В VBA я написал это

Function SPLITTER(data As String, delimiter As String) As String()
    SPLITTER = Split(data, delimiter)
End Function

Что отлично работает для меня

enter image description here

Однако SPLITTER возвращает строки, но я буду использовать его исключительно для чисел. Теперь, когда я возвращаю его As String (), использование любого другого типа мне не помогло. Я предполагаю, что это мешает функции Split

Я использую эту функцию для автоматизации вещей, так как преобразование значений ячеек в числа вручную у меня не работает. Есть ли способ разрешить функции возвращать значения как десятичные?

Извините, если я ошибаюсь в своей терминологии, но я новичок в VBA.

3
Kuehlschrank 6 Июл 2021 в 09:26

4 ответа

Лучший ответ

Либо вы используете формулу VALUE, как предлагает @norie, либо вам нужно изменить функцию, чтобы она преобразовывала строки, которые вы получаете от формы Split, в значения Double.

Обратите внимание, что это невозможно сделать для всего массива сразу, и вам нужно преобразовать каждое значение. Это может быть немного медленнее (при большом объеме данных или широком использовании функции), чем при использовании формулы VALUE. Для небольших данных вы не увидите разницы.

Option Explicit

Public Function SPLITTER(ByVal Data As String, ByVal Delimiter As String) As Variant()
    ' split strings
    Dim SplittedStrings() As String
    SplittedStrings = Split(Data, Delimiter)
    
    ' create variant array of the same size (variant so we can return errors)
    Dim Values() As Variant
    ReDim Values(LBound(SplittedStrings) To UBound(SplittedStrings)) As Variant
    
    ' convert each value into double
    Dim i As Long
    For i = LBound(Values) To UBound(Values)
        If IsNumeric(SplittedStrings(i)) Then
            ' return value as double
            Values(i) = CDbl(SplittedStrings(i))
        Else
            ' return #VALUE! error if a value is not numeric
            Values(i) = CVErr(xlErrValue)
        End If
    Next i
    
    SPLITTER = Values
End Function

Обратите внимание, что возвращаемый массив определяется как As Variant(), а не As Double(), поэтому в случае, если какая-либо из разделенных строк не является числовой, он может вернуть ошибку #VALUE! для этого одного значения и по-прежнему выводить другие . Если вы этого не сделаете, вся функция завершится ошибкой и выдает #VALUE! для всех значений, даже если только одно не может быть преобразовано.


Поскольку вы все равно переписываете весь массив, вы даже можете привести его в правильном направлении: выводить как строку или как столбец:

Option Explicit

Public Function SPLITTER(ByVal Data As String, ByVal Delimiter As String, Optional ByVal OutputAsRow As Boolean = False) As Variant()
    ' split strings
    Dim SplittedStrings() As String
    SplittedStrings = Split(Data, Delimiter)
    
    ' create variant array of the same size (variant so we can return errors)
    Dim Values() As Variant
    If OutputAsRow Then
        ' 2-dimensional array with 1 row and n columns
        ReDim Values(1 To 1, LBound(SplittedStrings) To UBound(SplittedStrings)) As Variant
    Else
        ' 2-dimensional array with n rows and 1 column
        ReDim Values(LBound(SplittedStrings) To UBound(SplittedStrings), 1 To 1) As Variant
    End If
    
    ' convert each value into double
    Dim i As Long
    For i = LBound(SplittedStrings) To UBound(SplittedStrings)  ' for each value in the input string string
        Dim RetVal As Variant
        If IsNumeric(SplittedStrings(i)) Then  ' check if it is a number
            ' return value as double
            RetVal = CDbl(SplittedStrings(i))
        Else
            ' return #VALUE! error if a value is not numeric
            RetVal = CVErr(xlErrValue)
        End If
        
        If OutputAsRow Then
            Values(1, i) = RetVal  ' fill columns
        Else
            Values(i, 1) = RetVal  ' fill rows
        End If
    Next i

    SPLITTER = Values
End Function

Таким образом, =SPLITTER($A$1,";") или =SPLITTER($A$1,";",0) выведут его как столбец, а =SPLITTER($A$1,";",1) - как строку.

3
Pᴇʜ 6 Июл 2021 в 09:10

Вы можете возвращать числа, не изменяя функцию, добавив VALUE к формуле.

=VALUE(TRANSPOSE(SPLITTER(D5,";")))
3
Pᴇʜ 6 Июл 2021 в 06:37

Кажется, у вас есть разбросанный диапазон значений, который указывает на то, что вы используете Microsoft 365. Я бы посоветовал даже не использовать UDF, если он не нужен (и вместо этого сохранить файл .xlsx):

=FILTERXML("<t><s>"&SUBSTITUTE(A1,";","</s><s>")&"</s></t>","//s")

Затем это «разделит» вашу строку на допустимые выражения xml / xpath, и excel автоматически распознает числа.

3
JvdV 6 Июл 2021 в 07:15

Расширение решения JvdV

Предполагая, что содержимое ячейки BV71 содержит нечисловые токены, вы можете даже ограничить все содержимое узла xml только числовыми элементами через XPath "//s[.*0=0]":

    =FILTERXML("<t><s>"&SUBSTITUTE(A8,";","</s><s>")&"</s></t>","//s[.*0=0]")

Объяснение: выражение XPath для поиска всех s узлов (на любом уровне иерархии) получает дополнительное условие в скобках []. Умножение содержимого узла (обозначенного .) на ноль (*0) и проверка того, равен ли результат числу (например, =0), позволяет получить только числа, так как это умножение не выполняется со строками .

Примечание , что региональные настройки даты с разделителями-точками могут интерпретировать такие токены, как 8.2, как дату, что потребует дополнительных преобразований.

1
T.M. 6 Июл 2021 в 20:24