【问题标题】:String to Decimial with Split function使用拆分功能将字符串转换为十进制
【发布时间】:2021-09-16 18:58:33
【问题描述】:

我在 VBA 中写了这个

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

这对我很有效

但是,SPLITTER 返回字符串,但我将专门用于数字。我现在返回它As String (),但使用任何其他类型对我不起作用。我猜它会干扰Split 功能

我使用该功能自动化将单元格的值手动转换为数字对我不起作用。有没有办法让函数以十进制返回值?

抱歉,我的术语可能不正确,但我是 VBA 新手。

【问题讨论】:

    标签: excel vba string split


    【解决方案1】:

    您可以通过在公式中添加 VALUE 来返回数字而不更改函数。

    =VALUE(TRANSPOSE(SPLITTER(D5,";")))
    

    【讨论】:

      【解决方案2】:

      您可以按照@norie 的建议使用VALUE 公式,或者您需要更改您的函数,以便它将您从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! 错误,并且仍然输出其他值。如果你不这样做,整个函数就会失败,并且会为 all 值输出#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) 将输出为行。

      【讨论】:

      • @Kuehlschrank 如果您对此代码有任何疑问,请告诉我。
      【解决方案3】:

      您似乎有一个溢出的值范围,这表明您使用的是 Microsoft 365。如果不需要,我建议您甚至不要使用 UDF(并保留一个 .xlsx 文件):

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

      然后,这将通过有效的 xml/xpath 表达式“拆分”您的字符串,excel 将自动识别数字。

      【讨论】:

      • @Kuehlschrank FILTERXML 函数返回的数字节点值将立即解释为数字是有益的。 - 建议阅读 JvdV 关于Extracting substrings via FilterXML 的近乎百科全书式的帖子以了解更多背景信息。
      • fyi 发布了对有效解决方案的扩展,将令牌限制为仅限数字元素 :-)
      【解决方案4】:

      JvdV 解决方案的扩展

      假设单元格内容 BV71 包含非数字标记,您甚至可以通过 XPath "//s[.*0=0]" 将所有 xml 节点内容限制为 仅限数字元素

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

      解释:用于搜索所有s 节点的XPath 表达式(在任何层次结构级别)[] 括号中获得一个附加条件。将节点内容(由. 表示)乘以零(*0)并检查结果是否等于数字(即=0)只允许获得数字,因为这种乘法会因字符串而失败。

      注意 带有点分隔符的区域日期设置可能会将8.2 等标记解释为日期,这需要进一步转换。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-09
        • 2018-03-09
        • 1970-01-01
        相关资源
        最近更新 更多