Возврат различных типов из функции - PullRequest
0 голосов
/ 05 июня 2019

Итак, у меня есть функция, которую я написал, которая проверяет, является ли данная строка истинной, ложной или чем-то еще. Если это True, я хочу, чтобы он возвращал логическое значение true, если это false, я хочу вернуть логическое значение false, и если это что-то еще, я хочу, чтобы он продолжал возвращать строку.

Public Function ConvertToBoolean(InputString As String) As Variant
Dim TempResults As Variant


    If InputString = "True" Then
        TempResults = True
    ElseIf InputString = "False" Then
        TempResults = False
    Else
        TempResults = InputString
    End If

    ConvertToBoolean = TempResults


End Function

Тем не менее, он по умолчанию остается строкой. Я мог бы затемнить его как логическое значение, но тогда обычные строки возвращались бы как ИСТИНА, а не как строка.

Как заставить / заставить работать преобразование типов функций? Вероятно, это нужно в операторе if, но я не знаю, как это сделать.

Не могу затемнить внутри if (Хотя, возможно, я смогу затемнить? Собираюсь проверить)

Редактировать: Дальнейшее тестирование показывает, что большую часть времени возвращается логическое значение - но иногда вместо этого он возвращает строку, со всеми связанными проблемами, которые я пытался исправить в первую очередь. Поэтому мой вопрос остается прежним:

Как я могу явно объявить функцию (или переменную) для возврата того или иного данного типа?

Редактировать 2: Поскольку люди, кажется, не верят, что код не всегда работает идеально или одинаково каждый раз:

enter image description here enter image description here enter image description here enter image description here

Ответы [ 3 ]

3 голосов
/ 06 июня 2019

Ради будущих читателей:

Основной проблемой была чувствительность к регистру, решаемая путем обеспечения сравнения на Text, а не Binary

Вот доказательства

enter image description here

Обратите внимание, что логические значения отображают верхний регистр по центру. Строковые значения в оригинальном регистре, выровненные по левому краю, номера выровненные по правому краю.

Вот версия, оптимизированная для обработки ошибок, чисел и самодостаточности для текстовых тестов (это была , а не версия, использованная в тестах ниже, поскольку она содержит дополнительные функции)

Public Function ConvertToBoolean(Val As Variant) As Variant
    If IsError(Val) Then
        ConvertToBoolean = Val
    ElseIf IsEmpty(Val) Then
        ConvertToBoolean = vbNullString
    ElseIf StrComp(Trim$(Val), "True", vbTextCompare) = 0 Then
        ConvertToBoolean = True
    ElseIf StrComp(Trim$(Val), "False", vbTextCompare) = 0 Then
        ConvertToBoolean = False
    Else
        ConvertToBoolean = Val
    End If
End Function

Тесты были основаны на этом коде

Option Explicit
Option Compare Text

Public Function ConvertToBoolean1a(InputString As String) As Variant
    Dim TempResults As Variant

    If InputString = "True" Then
        TempResults = True
    ElseIf InputString = "False" Then
        TempResults = False
    Else
        TempResults = InputString
    End If

    ConvertToBoolean1a = TempResults
End Function

Public Function ConvertToBoolean2a(InputString As String) As Variant
    Dim IsBoolean As Boolean
    Dim ReturnString As String
    Dim ReturnBoolean As Boolean

    If InputString = "True" Then
        IsBoolean = True
        ReturnBoolean = True
    ElseIf InputString = "False" Then
        IsBoolean = True
        ReturnBoolean = False
    Else
        IsBoolean = False
        ReturnString = InputString
    End If

    If IsBoolean Then
        ConvertToBoolean2a = ReturnBoolean
    Else
        ConvertToBoolean2a = ReturnString
    End If
End Function

И в отдельном модуле (я немного изменил версию Davids, чтобы дать справедливое сравнение. Его оригинальная версия обрабатывает начальные / конечные пробелы, но это дополнительная функция и стоит времени)

Option Explicit

Public Function ConvertToBoolean1b(InputString As String) As Variant
    Dim TempResults As Variant

    If InputString = "True" Then
        TempResults = True
    ElseIf InputString = "False" Then
        TempResults = False
    Else
        TempResults = InputString
    End If

    ConvertToBoolean1b = TempResults
End Function

Public Function ConvertToBoolean2b(InputString As String) As Variant
    Dim IsBoolean As Boolean
    Dim ReturnString As String
    Dim ReturnBoolean As Boolean

    If InputString = "True" Then
        IsBoolean = True
        ReturnBoolean = True
    ElseIf InputString = "False" Then
        IsBoolean = True
        ReturnBoolean = False
    Else
        IsBoolean = False
        ReturnString = InputString
    End If

    If IsBoolean Then
        ConvertToBoolean2b = ReturnBoolean
    Else
        ConvertToBoolean2b = ReturnString
    End If
End Function

Public Function ConvertToBoolean3(Val As String) As Variant
    If StrComp(Val, "True", vbTextCompare) = 0 Then
        ConvertToBoolean3 = True
    ElseIf StrComp(Val, "False", vbTextCompare) = 0 Then
        ConvertToBoolean3 = False
    Else
        ConvertToBoolean3 = Val
    End If
End Function


Public Function ConvertToBoolean4(Val As Variant) As Variant
    Dim s As String
    s = UCase$(Val)
    Select Case s
        Case "TRUE", "FALSE"
            ConvertToBoolean4 = CBool(s)
        Case Else
            ConvertToBoolean4 = Val
    End Select
End Function

Я также провел тест скорости для сравнения производительности, используя этот код

Sub Test()
    Dim n As Long, i As Long, j As Long
    Dim T1 As Single, T2 As Single, T3 As Single, T4 As Single
    Dim res As Variant

    Dim Dat2(1 To 5) As String
    Dat2(1) = "true"
    Dat2(2) = "false"
    Dat2(3) = "   true"
    Dat2(4) = "zx"
    Dat2(5) = ""
    Dim cl As Range

    Application.Calculation = xlCalculationManual

    n = 1000000

    T1 = Timer()
    For i = 1 To n
        For j = 1 To 5
            res = ConvertToBoolean1a(Dat2(j))
        Next
    Next
    T2 = Timer()

    T3 = Timer()
    For i = 1 To n
        For j = 1 To 5
            res = ConvertToBoolean2a(Dat2(j))
        Next
    Next
    T4 = Timer()

    'Verion 1a OP 1
    [F22] = (T2 - T1) / n * 1000000#
    'Verion 2a OP 2
    [H22] = (T4 - T3) / n * 1000000#


    n = n / 100

    Set cl = [f10:f15]
    T1 = Timer()
    For i = 1 To n
        cl.Calculate
    Next
    T2 = Timer()

    Set cl = [h10:h15]
    T3 = Timer()
    For i = 1 To n
        cl.Calculate
    Next
    T4 = Timer()

    'Verion 1a OP 1 UDF
    [F23] = (T2 - T1) / n * 1000000#
    'Verion 2a OP 1 UDF
    [H23] = (T4 - T3) / n * 1000000#

End Sub

И

Sub Test2()
    Dim n As Long, i As Long, j As Long
    Dim T1 As Single, T2 As Single, T3 As Single, T4 As Single
    Dim res As Variant

    Dim Dat2(1 To 5) As String
    Dat2(1) = "true"
    Dat2(2) = "false"
    Dat2(3) = "   true"
    Dat2(4) = "zx"
    Dat2(5) = ""
    Dim cl As Range

    Application.Calculation = xlCalculationManual

    n = 1000000
    T1 = Timer()
    For i = 1 To n
        For j = 1 To 5
            res = ConvertToBoolean3(Dat2(j))
        Next
    Next
    T2 = Timer()

    T3 = Timer()
    For i = 1 To n
        For j = 1 To 5
            res = ConvertToBoolean4(Dat2(j))
        Next
    Next
    T4 = Timer()

    'Verion 3 mine
    [J22] = (T2 - T1) / n * 1000000#
    'Verion 4 david
    [K22] = (T4 - T3) / n * 1000000#


    n = n / 100
    Set cl = [j10:j15]
    T1 = Timer()
    For i = 1 To n
        cl.Calculate
    Next
    T2 = Timer()

    Set cl = [K10:K15]
    T3 = Timer()
    For i = 1 To n
        cl.Calculate
    Next
    T4 = Timer()

    'Verion 3 mine  UDF
    [J23] = (T2 - T1) / n * 1000000#
    'Verion 4 david UDF
    [K23] = (T4 - T3) / n * 1000000#


End Sub

3 голосов
/ 06 июня 2019

Если я что-то упустил:

Public Function ConvertToBoolean(InputString As String) As Variant
Dim s As String
Dim ret
    s = Trim$(UCase$(InputString))
    Select Case s
        Case "TRUE", "FALSE"
            ret = CBool(s)
        Case Else
            ret = InputString
    End Select
    ConvertToBoolean = ret
End Function

enter image description here

0 голосов
/ 06 июня 2019

Огромное спасибо @MathieuGuindon за то, что он объяснил мне, как именно работают варианты, и указал мне правильный путь.

Теперь мой код:

Option Compare Text
Public Function ConvertToBoolean(InputString As String) As Variant
Dim IsBoolean As Boolean
Dim ReturnString As String
Dim ReturnBoolean As Boolean


If InputString = "True" Then
    IsBoolean = True
    ReturnBoolean = True
ElseIf InputString = "False" Then
    IsBoolean = True
    ReturnBoolean = False
Else
    IsBoolean = False
    ReturnString = InputString
End If

If IsBoolean Then
    ConvertToBoolean = ReturnBoolean
Else
    ConvertToBoolean = ReturnString
End If


End Function

Конечно, как упомянул @MathieuGuindon, если вы хотите, чтобы этот код НАЧИНАЛ РАБОТУ (в отличие от упражнения типа «принудительный тип»), вам нужно добавить StrComp () (Preferable) или Option Сравнить текст (менее предпочтительно, по-видимому, глючит)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...