通过使用正则表达式提取值从单元格中的字符串创建表格

问题描述 投票:0回答:2

我正在尝试编写一个非常大的宏来从一张表中提取数据并将其解析并转换为不同的表。

其他一切都很好。但是,我坚持 1 部分。

我在单元格中有多行文本(本例中为 11 行,但可以是动态的)

下面是我尝试构建代码的示例文本(各行由空格分隔,每行最后一个字符后按 Alt+Enter):

Flat where a figure is quoted but theshold based on the following lanes
IL STD  $5.00 above $75.00 USD 
SG STD  $11 above SGD400 
TR STD  $3 above €30 EUR 
AU EXP $2 for value>AUD 1000
IL EXP $2 for value>USD 75
JP EXP $2 for value>USD 65
NZ EXP $2 for value>NZD 400
PH EXP $2 for value>USD 165
SG EXP $2 for value>SGD 400
TW EXP $2 for value>TWD 2000

我的要求是将这段文字解析成如下表格:

我开始的逻辑是我将计算换行符/回车符的数量,然后使用循环创建数组来计算行数。

但是我没能做到这一点

我尝试了以下代码变体以获得否。行,但输出始终为 0。

Sub tresholds()

Dim strTest As String
Dim NewLines As Long

strTest = ThisWorkbook.Sheets("Rate Card").Range("D10").Text
NewLines = UBound(Split(strTest, Chr(32) & vbCrLf))
'NewLines = UBound(Split(strTest, " " & vbCrLf))
'NewLines = UBound(Split(strTest, vbCrLf))
'NewLines = UBound(Split(strTest, vbLf))
'NewLines = UBound(Split(strTest, Chr(32) & vbLf))

Debug.Print NewLines

End Sub

另外,我不太擅长正则表达式。字符串中有多个模式。 有些行有货币符号,有些则没有。有些具有“高于”的值,而另一些具有 > 的值。无法弄清楚如何解释这些变化。

如果你们能提供帮助,我将不胜感激。

excel vba string extract
2个回答
0
投票

此解决方案使用多个正则表达式来匹配各种模式。您可以在没有正则表达式的情况下轻松挑选出各个国家/地区的行,但是如果没有它,每行中的某些字段将很困难。您不妨使用正则表达式变得更好。你会发现它在未来很有用。

这段代码没有错误检查;这取决于你。另外,我相信您可以将输出写入工作表,所以我也将把它留给您。我已经在输出代码所属的 sub 中注明了。

如果你需要正则表达式方面的帮助,请在评论中提出具体问题。

Sub ParseThreshold()
    Dim rngInput As Range, regexMatch As RegExp, strPattern As String, strInput As String, vntRc As Variant, strPartLine As String
    Dim nCount As Integer, nIndex As Integer, vntMatches As Variant, arstrItems() As String, strCountry As String, strSE As String
    Dim dblDollars As Double, dblThreshold As Double
    
    Set regexMatch = New RegExp
    Set rngInput = ActiveSheet.Range("a1")
    strInput = rngInput.Value
    
    ' Define the regex pattern to match each country's line
    strPattern = "^[A-Z]{2} *(STD|EXP) *\$[0-9.]* (above|for value>[A-Z]{3}).*$"
    
    With regexMatch
        .Pattern = strPattern
        .Global = True
        .MultiLine = True
        nCount = .Execute(strInput).Count
    End With
    
    Set vntMatches = regexMatch.Execute(strInput)
    
    If nCount > 0 Then
        ReDim arstrItems(0 To nCount - 1)
        
        For nIndex = 0 To nCount - 1 '
            arstrItems(nIndex) = vntMatches(nIndex)
            strCountry = Left(arstrItems(nIndex), 2)
            strSE = Mid(arstrItems(nIndex), 4, 3)
            
            dblDollars = DollarAmount(arstrItems(nIndex))
            dblThreshold = Threshold(arstrItems(nIndex))
            
            ' Output the values to your table here
        Next nIndex
    End If
    
End Sub  ' ParseThreshold


Function DollarAmount(strInput As String)
    Dim regexMatch As RegExp, strPattern As String, vntRc As Variant
    
    strPattern = "(STD|EXP) *\$[0-9.]*"
    Set regexMatch = New RegExp
    
    With regexMatch
        .Pattern = strPattern
        .Global = False
        .MultiLine = False
        nCount = .Execute(strInput).Count
    End With
    
    Set vntMatches = regexMatch.Execute(strInput)
    If nCount > 0 Then
        vntRc = vntMatches(0)
        vntRc = Replace(vntRc, "STD ", "")
        vntRc = Replace(vntRc, "EXP ", "")
        vntRc = Replace(vntRc, "$", "")
        vntRc = Trim(vntRc)
    End If
    
    DollarAmount = vntRc
    
End Function  ' DollarAmount


Function Threshold(strInput As String)
    Dim regexMatch As RegExp, strPattern As String, vntRc As Variant, nLength As Integer, vntMatches As Variant
    
    nLength = Len(strInput)
    Set regexMatch = New RegExp
    
    strPattern = "[0-9.]+"
    strTarget = "above"
    nPosition = InStr(strInput, strTarget)
    If nPosition > 0 Then
        strPartLine = Mid(strInput, nPosition + Len(strTarget) + 1, nLength)
    Else
        strTarget = "value>"
        nPosition = InStr(strInput, strTarget)
        If nPosition > 0 Then
            strPartLine = Mid(strInput, nPosition + Len(strTarget) + 1, nLength)
        End If
    End If
    
    With regexMatch
        .Pattern = strPattern
        .Global = False
        .MultiLine = False
        nCount = .Execute(strPartLine).Count
        Set vntMatches = .Execute(strPartLine)
    End With
    
    If nCount > 0 Then
        vntRc = vntMatches(0)
    End If
    
    Threshold = vntRc
    
End Function  ' Threshold

0
投票

另一种方式....

Sheet1 单元格 A1 值就像您的样本数据

Sub test()
Dim rslt As Range, cnt As Integer, splitVal as String
Dim i As Integer, j As Integer, k As Integer, arr
Dim bol as Boolean

Set rslt = Sheet2.Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
arr = Split(Sheet1.Range("A1").Value, Chr(10))

For i = 1 To UBound(arr)
    rslt.Value = Split(arr(i), " ")(0)
    rslt.Offset(0, 1).Value = Split(arr(i), " ")(1)
    Set rslt = rslt.Offset(0, 2)
    bol = True
    For j = 2 To UBound(Split(arr(i), " "))
        splitVal = Split(arr(i), " ")(j)
        If splitVal Like "*#*" Then
            For k = 1 To Len(splitVal)
                If Mid(splitVal, k, 1) = "." Then Exit For
                If Mid(splitVal, k, 1) >= "0" And Mid(splitVal, k, 1) <= "9" Then rslt.Value = rslt.Value & Mid(splitVal, k, 1)
            Next k
        If bol Then Set rslt = rslt.Offset(0, 1): bol = False Else Exit For
        End If
    Next j
    Set rslt = Sheet2.Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
Next i

End Sub

rslt 是将放置结果的范围变量。在这种情况下,结果将放在 sheet2 中,从单元格 A2 开始。

arr 变量的值来自用换行符分割的 sheet1 单元格 A1 值。

子里有三个循环

  1. 每行循环
  2. 循环每行中用空格分隔的“单词”
  3. 循环“单词”中的每个字符

代码假定每行的第一个和第二个“单词”总是用一个空格分隔。

第一个循环是将循环的行字符串中的第一个单词放入sheet2的A列,将第二个单词作为i变量放入sheet2的B列。然后它将 rslt 设置为 offset(0,2) 并创建布尔变量作为 bol.

在第二个循环中,它循环到循环行中的每个单词。由于不再需要第一个单词和第二个单词,因此它从 2 开始作为 j 变量。并将循环后的词放入splitVal变量中,检查splitVal值是否包含数字,然后进入第三个循环。

在第三个循环中,它检查 splitVal(循环词)值的每个字符作为 k 变量。如果循环字符是“。”然后它退出循环--->这将忽略十进制值(因为我假设您不需要结果的小数)。

然后检查循环字符是否 >= 0 和 <=9, it put the result to sheet2 column C (the rslt variable). Then it flag the bol as false (this is to let the code go to the ELSE in the if) and set rslt offset(0,1) so the next result will be put in column D.

请注意,代码将失败:

  • 如果循环的单词是这样的
    SGD.400
    (数字前面有一个点)
  • 如果第一个词和第二个词用一个以上的空格隔开。
    例如:
    SG  STD
    .
  • 如果第一个单词以空格开头,例如
     SG
    .
© www.soinside.com 2019 - 2024. All rights reserved.