Arrays 带数学属性的Excel VBA字符串转换

Arrays 带数学属性的Excel VBA字符串转换,arrays,excel,string,vba,special-characters,Arrays,Excel,String,Vba,Special Characters,我的好奇心激起了我的兴趣,也难住了我。我有一种情况,我有一堆字符串,一些带有数学符号,一些只是字符。这些字符串中有些很长,有些不长,但是,我想在任何具有数学符号(特别是+)的字符串的完整字符串之后添加一个Chr10,然后继续读取下一个数学符号的字符串,并在其前面插入一个Chr10 最终结果应该如下所示: 10+20+30+40 50+60+70+80 123a 123 123b 345 123c 123 123d 123 90+100+110+120 123 123 231 123 Conve

我的好奇心激起了我的兴趣,也难住了我。我有一种情况,我有一堆字符串,一些带有数学符号,一些只是字符。这些字符串中有些很长,有些不长,但是,我想在任何具有数学符号(特别是+)的字符串的完整字符串之后添加一个Chr10,然后继续读取下一个数学符号的字符串,并在其前面插入一个Chr10

最终结果应该如下所示:

10+20+30+40 50+60+70+80 123a 123 123b 345 123c 123 123d 123 90+100+110+120 123 123 231 123

Converts to: 

10+20+30+40  
50+60+70+80 
123a 123 123b 345 123c 123 123d 123 
90+100+110+120 
123 123 231 123
在方程没有空格的情况下,普通字母可以是数字的混合体,字母可以有空格,但在找到数学符号时会分开

我在网上寻找一些线索,我想我很快就能找到答案了。这似乎是一个分裂,合并,或右,左,然后Len函数是答案

 If Len(SearchString) = "+" Or Len(SearchString) = "-" Then
    SearchString = Left(SearchString, Chr(10))
 End If

然而,这不起作用。我可能不太理解Len、Left和Right函数,但我非常肯定SearchString是正确的做法。还值得注意的是,我提供的If/End If语句确实起作用,它不会返回任何错误,但它并没有做我希望它做的事情。

粗略地说,它做了您需要的事情

sentence() = Split(10+20+30+40 50+60+70+80 123a 123 123b 345 123c 123 123d 123 90+100+110+120 123 123 231 123)

 For i = 0 To UBound(sentence)
  acu_str = sentence(i)
   If InStr(sentence(i), "+") = 0 And InStr(sentence(i), "-") = 0 Then
    Do While InStr(sentence(i + 1), "+") = 0 And InStr(sentence(i + 1), "-") = 0
    On Error GoTo ErrorHandling
     acu_str = acu_str + " " + sentence(i + 1)
    i = i + 1
    Loop
   ErrorHandling:
  End If
 Debug.Print acu_str & vbCr
 Next i

在一个粗糙的方式,它做你需要的

sentence() = Split(10+20+30+40 50+60+70+80 123a 123 123b 345 123c 123 123d 123 90+100+110+120 123 123 231 123)

 For i = 0 To UBound(sentence)
  acu_str = sentence(i)
   If InStr(sentence(i), "+") = 0 And InStr(sentence(i), "-") = 0 Then
    Do While InStr(sentence(i + 1), "+") = 0 And InStr(sentence(i + 1), "-") = 0
    On Error GoTo ErrorHandling
     acu_str = acu_str + " " + sentence(i + 1)
    i = i + 1
    Loop
   ErrorHandling:
  End If
 Debug.Print acu_str & vbCr
 Next i

因此,这并不理想,而是使用正则表达式进行中断

Option Explicit
Public Sub TEST()
    Dim tests(), i As Long
    tests = Array("10+20+30+40 50+60+70+80 123a 123 123b 345 123c 123 123d 123 90+100+110+120 123 123 231 123")
    For i = LBound(tests) To UBound(tests)
        Debug.Print ReplaceString(tests(i))
    Next
End Sub

Public Function ReplaceString(ByVal inputString As String) As String
Dim matches As Object, match As Object
  With CreateObject("VBScript.RegExp")
            .Global = True
            .MultiLine = True
            .Pattern = "(\w+\+|\-)+(\w)+"
            If .TEST(inputString) Then
              Set matches = .Execute(inputString)
              For Each match In matches
                  inputString = Replace$(Replace$(inputString, Chr$(32) & match, Chr$(10) & match), match & Chr$(32), match & Chr$(10))
              Next
              ReplaceString = Trim$(inputString)
            Else
              ReplaceString = inputString
            End If
  End With
End Function
第一个捕获组\w+\+|\-+

\+量词-在一次和无限次之间匹配,尽可能多地匹配,根据需要返回

第一个备选方案\w+\+

\w+匹配任何等于[a-zA-Z0-9_]的字字符

\+量词-在一次和无限次之间匹配,尽可能多地匹配,根据需要返回

\+匹配字符+区分大小写

第二种选择\- \-匹配字符-字面上区分大小写

第二捕获组\w+

\+量词-在一次和无限次之间匹配,尽可能多地匹配,根据需要返回

\w匹配任何等于[a-zA-Z0-9_]的字字符

试试看


感谢@RonRosenfeld帮助我改进了正则表达式。

所以这并不理想,但使用正则表达式来进行破坏

Option Explicit
Public Sub TEST()
    Dim tests(), i As Long
    tests = Array("10+20+30+40 50+60+70+80 123a 123 123b 345 123c 123 123d 123 90+100+110+120 123 123 231 123")
    For i = LBound(tests) To UBound(tests)
        Debug.Print ReplaceString(tests(i))
    Next
End Sub

Public Function ReplaceString(ByVal inputString As String) As String
Dim matches As Object, match As Object
  With CreateObject("VBScript.RegExp")
            .Global = True
            .MultiLine = True
            .Pattern = "(\w+\+|\-)+(\w)+"
            If .TEST(inputString) Then
              Set matches = .Execute(inputString)
              For Each match In matches
                  inputString = Replace$(Replace$(inputString, Chr$(32) & match, Chr$(10) & match), match & Chr$(32), match & Chr$(10))
              Next
              ReplaceString = Trim$(inputString)
            Else
              ReplaceString = inputString
            End If
  End With
End Function
第一个捕获组\w+\+|\-+

\+量词-在一次和无限次之间匹配,尽可能多地匹配,根据需要返回

第一个备选方案\w+\+

\w+匹配任何等于[a-zA-Z0-9_]的字字符

\+量词-在一次和无限次之间匹配,尽可能多地匹配,根据需要返回

\+匹配字符+区分大小写

第二种选择\- \-匹配字符-字面上区分大小写

第二捕获组\w+

\+量词-在一次和无限次之间匹配,尽可能多地匹配,根据需要返回

\w匹配任何等于[a-zA-Z0-9_]的字字符

试试看


感谢@RonRosenfeld帮助我改进正则表达式。

这里是使用正则表达式的另一种方法。我使用.Replace方法

如何应用这将取决于您的数据设置;检查你的原始数据,然后把结果吐到某个地方

分离器 选项:不区分大小写^$在换行时不匹配

?:?:\w++[+-]++\w+?=\s|$ ?:?:\w+[+-]+\w+ ?:?:\w++-]++ + ?:\w+[+-]+ + \w+ + [+-] + - \w+ + ?=\s|$ \ \ $ $ ?:^ |\s?:\w++\s++\w++?=\s|$ ?:^|\s ^ ^ \ \ ?:\w++\s++\w+ ?:\w+\s++ + \w+ + \+ + \w+ + ?=\s|$ \ \ $ $ 一元二元

␊ $1 $2
使用

创建这里是使用正则表达式的另一种方法。我使用.Replace方法

如何应用这将取决于您的数据设置;检查你的原始数据,然后把结果吐到某个地方

分离器 选项:不区分大小写^$在换行时不匹配

?:?:\w++[+-]++\w+?=\s|$ ?:?:\w+[+-]+\w+ ?:?:\w++-]++ + ?:\w+[+-]+ + \w+ + [+-] + - \w+ + ?=\s|$ \ \ $ $ ?:^ |\s?:\w++\s++\w++?=\s|$ ?:^|\s ^ ^ \ \ ?:\w++\s++\w+ ?:\w+\s++ + \w+ + \+ + \w+ + ?=\s|$ \ \ $ $ 一元二元

␊ $1 $2
使用InStr和InStrRev创建的应能够处理拆分

Option Explicit    

Function splitString(str As String)

    Dim a As Long, b As Long

    a = InStr(1, str, Chr(32))
    b = InStr(1, str, Chr(43))

    Do While a > 0 And b > 0

        If b > a Then
            a = InStrRev(str, Chr(32), b)
        End If

        Mid(str, a, 1) = Chr(10)

        b = InStr(a, str, Chr(43))
        a = InStr(a, str, Chr(32))

    Loop

    splitString = str

End Function

InStr和InStrRev应能够处理拆分

Option Explicit    

Function splitString(str As String)

    Dim a As Long, b As Long

    a = InStr(1, str, Chr(32))
    b = InStr(1, str, Chr(43))

    Do While a > 0 And b > 0

        If b > a Then
            a = InStrRev(str, Chr(32), b)
        End If

        Mid(str, a, 1) = Chr(10)

        b = InStr(a, str, Chr(43))
        a = InStr(a, str, Chr(32))

    Loop

    splitString = str

End Function

您的正则表达式假设在带有算术运算符的字符串中永远不会有非数字。可能是问题,也可能不是问题。但是如果一个子串是50+60+70a+80b…我会用\wDoh替换[0-9]!美好的谢谢,如何使选项显式地在宏中工作?我有一个不同的子程序,我也在和它一起运行?你只需要把它放在每个模块的顶部,然后再做其他事情。或者将其作为.visualbasic编辑器>工具>选项>检查要求变量声明打开。我建议启用该选项。它迫使您编写更好的代码。您的正则表达式假定s中永远不会有非数字

用算术运算符尝试。可能是问题,也可能不是问题。但是如果一个子串是50+60+70a+80b…我会用\wDoh替换[0-9]!美好的谢谢,如何使选项显式地在宏中工作?我有一个不同的子程序,我也在和它一起运行?你只需要把它放在每个模块的顶部,然后再做其他事情。或者将其作为.visualbasic编辑器>工具>选项>检查要求变量声明打开。我建议启用该选项。它迫使您编写更好的代码。我有多个范围需要处理,所以我可以简单地用范围替换句子=吗?当然,将其放在拆分函数中。我有多个范围需要处理,所以我可以简单地用范围替换句子=吗?当然,将它放在分割函数中。这正是我所希望的。谢谢!这是一种迂回的方式,我不理解Option显式函数,但是这实现了我的目标,非常感谢!我后来才意识到我必须在单元格中键入hahaIt,这绝对是我所需要的,但我想知道如何在循环中添加第三个变量,如-sign?我尝试使用or函数,结果好坏参半,一半的行会被分割,但其他行会给出一个值错误?如果您正在更改问题的条件,使当前答案无效,那么您应该按“原样”结束此问题,并发布一个带有新条件的新问题,新的样本数据和新的预期结果,这正是我所希望的,谢谢!这是一种迂回的方式,我不理解Option显式函数,但是这实现了我的目标,非常感谢!我后来才意识到我必须在单元格中键入hahaIt,这绝对是我所需要的,但我想知道如何在循环中添加第三个变量,如-sign?我尝试使用or函数,结果好坏参半,一半的行会被分割,但其他行会给出一个值错误?如果您正在更改问题的条件,使当前答案无效,那么您应该按“原样”结束此问题,并发布一个带有新条件的新问题,新的样本数据和新的预期结果,谢谢你回答了我的问题!最后,我选择了胡安·梅德尔(Juan Medel)的明确答案,因为这是我最容易理解的!谢谢所有这些回答了我的问题!最后,我选择了胡安·梅德尔(Juan Medel)的明确答案,因为这是我最容易理解的!