【问题标题】:VBA SPLIT by different delimiterVBA SPLIT 按不同的分隔符
【发布时间】:2021-04-14 06:15:46
【问题描述】:

我有一个相当棘手的问题。我正在尝试拆分并声明字符串的不同部分以供进一步使用。显然,我有不同的分隔符来做到这一点。

假设我想将标准螺钉代码:DIN912M6x10A2 拆分为不同的部分,因为该代码的每个部分都意味着特定的东西。

ScreHead 保留到第一个“M”,不带分隔符 = DIN912

ScrewThickness 是“M”,最多包含“x”,不包括 = M5

ScrewLenght 被“x”排除到“A”被排除 = 10

ScrewMaterial 是“A”,直到“”,或者如果没有“”,那么直到字符串的末尾 = A2

到目前为止,我在代码方面拥有的是(我在第 5 列工作):

Dim ScrewHead As Long
ScrewHead = Split(Cells(i, 5), "M"-1)

Dim ScrewDiameter As Long
ScrewDiameter =Split(i,5),"M", "x"-1)

Dim ScrewLenght As Long
ScrewLenght =Split(i,5),"x"-1, "A"-1)

Dim ScrewMaterial As Long
ScrewMaterial =Split(i,5),"A", " ")

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 当字符串为M6 时,您是如何获得M5 的。你是从结果中减去 1 吗?
  • 旁注:捕获的变量声明为长。除了“ScrewLenght”之外,它们不是数字。

标签: excel vba split


【解决方案1】:

老实说,当您可以捕获自己组中的所有部分时,对于正则表达式来说,这听起来不错。例如通过:

^(.+?)(M\d+)x(\d+)(.+?)(?:\s.*)?$

在线查看demo

  • ^ - 起始线锚点。
  • (.+?) - 第一个捕获组,最多可容纳 1 个以上(惰性)字符;
  • (M\d+) - 第二个捕获组,带有文字“M”,后跟 1+(贪婪)数字。
  • x - 文字“x”。
  • (\d+) - 持有 1+(贪婪)数字的第三个捕获组。
  • (.+?) - 第 4 个捕获组,最多包含 1+ 个(惰性)字符;
  • (?:\s.*)? - 包含 0+ 个(贪婪)字符的空格字符的可选非捕获组。
  • $ - 结束线锚。

下面是一个用于检索这些组的快速代码:

Sub Test()

Dim str As String: str = "DIN912M6x10A2 test"
With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = "^(.+?)(M\d+)x(\d+)(.+?)(?:\s.*)?$"
    If .Test(str) = True Then
        For Each Match In .Execute(str)(0).Submatches
            Debug.Print Match
        Next
    End If
End With

End Sub

更广泛的代码示例以便更好地理解:

Sub Test()

Dim str As String: str = "DIN912M6x10A2 test"
Dim ScrewHead As String, ScrewDiameter As String, ScrewLenght As Long, ScrewMaterial As String
Dim matches

With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = "^(.+?)(M\d+)x(\d+)(.+?)(?:\s.*)?$"
    If .Test(str) = True Then
        Set matches = .Execute(str)
        ScrewHead = matches(0).Submatches(0)
        ScrewDiameter = matches(0).Submatches(1)
        ScrewLenght = matches(0).Submatches(2)
        ScrewMaterial = matches(0).Submatches(3)
    End If
End With

End Sub

【讨论】:

  • 这段代码对我来说似乎很混乱,M5也可能是M100。这就是我写下绝对限制的原因,因为每个部分的长度可能会有所不同。我将如何以方便的方式进一步引用这些部分?如果我像在原始帖子中那样使每个部分变暗 - 用人类语言引用它们很方便,例如 If ScrewThickness.value>60 那么。你知道我的意思吗?
  • 首先,M100 捕获不是问题。试一试。关于你的第二点;不幸的是,我们无法在 VBA 的正则表达式对象中使用命名的捕获组,但是如果要将它们的值分配给变量,则可以单独引用每个子匹配。例如:Screwhead = .Execute(str)(0).Submatches(0)ScrewDiameter = .Execute(str)(0).Submatches(1)。您还可以设置“匹配”对象并引用它,而无需多次执行模式。
  • 感谢您提供额外的代码。不太清楚为什么会有 IF 函数?因为我不想找到匹配项。我只是想在第 5 列中声明值的不同部分,并在同一个 sub 的其他函数中使用该暗淡。 IE。我需要进一步比较我正在评估的项目是否比规定值厚或螺丝头是否不是 DIN912 等等。
  • 这只是一个内置安全性,因为如果找不到有效匹配,Set matches = .Execute(str) 将返回错误。 .Test(str) 可以解决这个问题,如果找不到匹配项,则跳过整个分配。
  • @Eduards,它只是作为字符串分配的替代品,是的。只是为了展示。
【解决方案2】:

这是一个简单的基于 VBA 的大锤方法。您可以采用符合您要求的代码。

Public Sub GetDiffPartsofString()
    Dim strInput As String, strScrewHead As String, strScrewThck As String, strScrewLeng As String, strScrewMatl As String
    Dim i As Long, j As Long
    strInput = "DIN912M6x10A2"
    j = 1
    For i = 1 To Len(strInput)
        Select Case Mid(strInput, i, 1)
        Case "M"
            strScrewHead = Mid(strInput, j, i - 1)
            j = i
        Case "x"
            strScrewThck = Mid(strInput, j, i - j)
            j = i
        Case "A"
            strScrewLeng = Mid(strInput, j + 1, i - j - 1)
            strScrewMatl = Mid(strInput, i, Len(strInput))
        End Select
    Next i
    Debug.Print strScrewHead, strScrewThck, strScrewLeng, strScrewMatl
End Sub

【讨论】:

  • 谢谢,但这对于这项任务来说仍然显得过于混乱和复杂。因为我需要做的是使第 5 列中值的不同部分变暗,并在同一个 sub 的进一步功能中使用该变暗。 IE。我需要进一步比较我正在评估的项目是否比规定值厚,或者螺丝头是否不是 DIN912 等等。
  • @Eduards 模式匹配本身就是一项相当复杂的任务......因此解决方案很可能也相当复杂
  • 请注意此处可能出现的尾随空格(和文本)。
  • @shrivallabha.redij 我的意思是尾随空格按照 OP 在“ScrewMaterial”部分的要求。在需要拆分的文本之后可以有尾随空格。例如,检查我在答案中使用的输入。顺便说一句,这只是积极的反馈而不是批评=)
  • @JvdV,我绝对认为这是冒犯 :) 开个玩笑!我测试了一个像DIN912 M6 x10 A2 test test and this is one more test 这样的样本,它似乎也可以工作,因为我使用了整个字符串的长度来捕获最后一部分。
【解决方案3】:

通过Val() 进行的棘手拆分方法

另一条通往罗马的路

Sub AnalyzeID()
    Dim s As String: s = "DIN912M6x10A2 test"
    Dim parts: parts = Split(Replace(Replace(s, "M", "x"), " ", "x"), "x")
    'adjust split elements
    parts(1) = "M" & parts(1)
    parts(3) = Split(parts(2), Val(parts(2)))(1)  ' (don't change code line order!)
    parts(2) = Val(parts(2))
    Debug.Print Join(parts, "|")    ' ~~> DIN912|M6|10|A2
End Sub

在 VB 编辑器的即时窗口中输出

    DIN912|M6|10|A2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    • 2013-02-01
    • 1970-01-01
    • 2011-12-13
    • 2013-05-22
    • 2014-07-31
    相关资源
    最近更新 更多