我正在尝试编写一个非常大的宏来从一张表中提取数据并将其解析并转换为不同的表。
其他一切都很好。但是,我坚持 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
另外,我不太擅长正则表达式。字符串中有多个模式。 有些行有货币符号,有些则没有。有些具有“高于”的值,而另一些具有 > 的值。无法弄清楚如何解释这些变化。
如果你们能提供帮助,我将不胜感激。
此解决方案使用多个正则表达式来匹配各种模式。您可以在没有正则表达式的情况下轻松挑选出各个国家/地区的行,但是如果没有它,每行中的某些字段将很困难。您不妨使用正则表达式变得更好。你会发现它在未来很有用。
这段代码没有错误检查;这取决于你。另外,我相信您可以将输出写入工作表,所以我也将把它留给您。我已经在输出代码所属的 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
另一种方式....
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 值。
子里有三个循环
代码假定每行的第一个和第二个“单词”总是用一个空格分隔。
第一个循环是将循环的行字符串中的第一个单词放入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
.