英文:
How to remove any () and their contents from a string variable in Excel VBA without regex
问题
我有一个预定义的函数,它在数据库中查找字符串,并返回一个对象。我需要从工作表中提取一个字符串,删除括号内的内容(以及括号本身),然后将其传递给这个函数。然而,我无法让替换函数找到括号之外的内容。
我尝试了以下代码:
Set feederType = Cells(i, 5)
feederCode = Replace(feederType, "()", "")
feederID = getFeeder(feederCode).ID
其中i是一个循环变量,feederType是一个范围,getFeeder()接受一个字符串并返回一个带有ID属性的对象。我还尝试过将feederType作为字符串来使用,但结果相同。
这只对直接替换"()"有效,并且实际上不会替换括号内的任何内容。有没有办法在字符串变量中进行这种替换,而不涉及正则表达式?
编辑:我已经找到了适用于我的特定用例的解决方案,使用InStr()和Left(),因为括号只出现在我的输入的末尾。然而,我仍然很好奇,是否已经存在用于字符串变量的通配符替换函数。
英文:
I have a pre-defined function that looks up a string in a database, and returns an object. I need to pull a string from a worksheet, remove anything in parentheses(as well as the parentheses), and then pass it to this function. However, I can't get the Replace function to find more than just the parentheses themselves.
I tried the code:
Set feederType = Cells(i, 5)
feederCode = Replace(feederType, "(*)", "")
feederID = getFeeder(feederCode).ID
Where i is a looping variable, feederType is a range, and getFeeder() takes a string and returns an object with the ID property. I have also tried this with feederType as a string, to the same result.
This only works for a direct substitution of "(*)", and does not actually replace anything in parentheses. Is there a way to do this replacement in a string variable without getting into regex?
EDIT: I have found a solution that works for my specific use case using InStr() and Left() since parentheses only appear at the end of my inputs. I am still curious, however, if any wildcard substitution functions already exist for string variables.
答案1
得分: 2
假设只有一组括号,我们可以找到开括号和闭括号的位置,获取子字符串,然后从原始字符串中删除它。对于更复杂的模式,我会使用正则表达式。
Function RemoveParentheses(ByVal Text As String) As String
Dim Result As String
Dim OpeningParenPos As Long
OpeningParenPos = InStr(Text, "(")
Dim ClosingParenPos As Long
ClosingParenPos = InStr(Text, ")")
If OpeningParenPos > 0 And ClosingParenPos > 0 Then
Result = Replace(Text, Mid(Text, OpeningParenPos, ClosingParenPos - OpeningParenPos + 1), "")
Else
Result = Text
End If
Result = Trim(Result)
RemoveParentheses = Result
End Function
英文:
Assuming that there is only one set of parenthesis we can find the position of the opening and closing parentheses, get the substring, and remove it from the original string. I would use RegEx for more complex patterns.
Function RemoveParentheses(ByVal Text As String) As String
Dim Result As String
Dim OpeningParenPos As Long
OpeningParenPos = InStr(Text, "(")
Dim ClosingParenPos As Long
ClosingParenPos = InStr(Text, ")")
If OpeningParenPos > 0 And ClosingParenPos > 0 Then
Result = Replace(Text, Mid(Text, OpeningParenPos, ClosingParenPos - OpeningParenPos + 1), "")
Else
Result = Text
End If
Result = Trim(Result)
RemoveParentheses = Result
End Function
答案2
得分: 2
以下是您要翻译的内容:
"While I see no point in explicitly not using regular expressions, it can of course be done, but not with a one-liner (at least I cannot think of any).
The easy case is that you have only one pair of parentheses. Search for the leftmost opening and the rightmost closing parentheses.
Function removeParenthesesVersion1(s As String) As String
Dim p1 As Long, p2 As Long
p1 = InStr(s, "(")
p2 = InStrRev(s, ")")
If p1 > 0 And p2 > 0 Then
removeParenthesesVersion1 = Left(s, p1 - 1) & Mid(s, p2 + 1)
Else
removeParenthesesVersion1 = s
End If
End Function
However, if you have more than one pair of parentheses, you need to be a little bit more sophisticated. The following function loops over the string until no more pairs of parentheses can be found. In opposite to the first function, it looks for the leftmost closing parentheses.
Function removeParenthesesVersion2(ByVal s As String) As String
Dim p1 As Long, p2 As Long
Do While True
p1 = InStr(s, "(")
p2 = InStr(s, ")")
If p1 > 0 And p2 > 0 and p2 > p1 Then
removeParenthesesVersion2 = removeParenthesesVersion2 & Left(s, p1 - 1)
s = Mid(s, p2 + 1)
Else
Exit Do
End If
Loop
removeParenthesesVersion2 = removeParenthesesVersion2 & s
End Function
To test this:
Sub test()
Const s1 = "Lorem(xyz)Ipsum"
Const s2 = "Lorem(xyz)Ipsum(123)Dolor Sit"
Debug.Print removeParenthesesVersion1(s1)
Debug.Print removeParenthesesVersion1(s2)
Debug.Print removeParenthesesVersion2(s1)
Debug.Print removeParenthesesVersion2(s2)
End Sub
results in
LoremIpsum
LoremDolor Sit
LoremIpsum
LoremIpsumDolor Sit
It gets even more tricky if you have nested loops and the like, but for this you first need to define what exactly you need as output before starting to code."
英文:
While I see no point in explicitly not using regular expressions, it can of course be done, but not with a one-liner (at least I cannot think of any).
The easy case is that you have only one pair of parentheses. Search for the leftmost opening and the rightmost closing parentheses.
Function removeParenthesesVersion1(s As String) As String
Dim p1 As Long, p2 As Long
p1 = InStr(s, "(")
p2 = InStrRev(s, ")")
If p1 > 0 And p2 > 0 Then
removeParenthesesVersion1 = Left(s, p1 - 1) & Mid(s, p2 + 1)
Else
removeParenthesesVersion1 = s
End If
End Function
However, if you have more than one pair of parentheses, you need to be a little bit more sophisticated. The following function loops over the string until no more pairs of parentheses can be found. In opposite to the first function, it looks for the leftmost closing parentheses.
Function removeParenthesesVersion2(ByVal s As String) As String
Dim p1 As Long, p2 As Long
Do While True
p1 = InStr(s, "(")
p2 = InStr(s, ")")
If p1 > 0 And p2 > 0 and p2 > p1 Then
removeParenthesesVersion2 = removeParenthesesVersion2 & Left(s, p1 - 1)
s = Mid(s, p2 + 1)
Else
Exit Do
End If
Loop
removeParenthesesVersion2 = removeParenthesesVersion2 & s
End Function
To test this:
Sub test()
Const s1 = "Lorem(xyz)Ipsum"
Const s2 = "Lorem(xyz)Ipsum(123)Dolor Sit"
Debug.Print removeParenthesesVersion1(s1)
Debug.Print removeParenthesesVersion1(s2)
Debug.Print removeParenthesesVersion2(s1)
Debug.Print removeParenthesesVersion2(s2)
End Sub
results in
LoremIpsum
LoremDolor Sit
LoremIpsum
LoremIpsumDolor Sit
It gets even more tricky if you have nested loops and the like, but for this you first need to define what exactly you need as output before starting to code.
答案3
得分: 1
' 更快一些:
' 从字符串中移除括号内的内容
Function RemoveParenthContent(s As String) As String
Dim openPar As Long, closePar As Long
Const Lpar = "(", Rpar = ")"
openPar = InStr(1, s, Lpar)
If openPar > 0 Then
closePar = InStr(openPar, s, Rpar)
If closePar > openPar Then
RemoveParenthContent = Left$(s, openPar - 1) & Mid$(s, closePar + 1)
Exit Function
End If
End If
RemoveParenthContent = s
End Function
' 对于任何一组()
Function RemoveParenthContent(s As String) As String
Dim openPar As Long, closePar As Long
Const Lpar = "(", Rpar = ")"
Do
openPar = InStr(1, s, Lpar)
If openPar > 0 Then
closePar = InStr(openPar, s, Rpar)
If closePar > openPar Then
s = Left$(s, openPar - 1) & Mid$(s, closePar + 1)
Else
Exit Do
End If
Else
Exit Do
End If
Loop
RemoveParenthContent = s
End Function
英文:
A little faster:
Function RemoveParenthContent(s As String) As String
Dim openPar As Long, closePar As Long
Const Lpar = "(", Rpar = ")"
openPar = InStr(1, s, Lpar)
If openPar > 0 Then
closePar = InStr(openPar, s, Rpar)
If closePar > openPar Then
RemoveParenthContent = Left$(s, openPar - 1) & Mid$(s, closePar + 1)
Exit Function
End If
End If
RemoveParenthContent = s
End Function
'for any group of ()
Function RemoveParenthContent(s As String) As String
Dim openPar As Long, closePar As Long
Const Lpar = "(", Rpar = ")"
Do
openPar = InStr(1, s, Lpar)
If openPar > 0 Then
closePar = InStr(openPar, s, Rpar)
If closePar > openPar Then
s = Left$(s, openPar - 1) & Mid$(s, closePar + 1)
Else
Exit Do
End If
Else
Exit Do
End If
Loop
RemoveParenthContent = s
End Function
答案4
得分: 1
以下是代码部分的翻译:
Function removeParanthesisAndContent(strP As String) As String
Dim arr1, arr2, i As Long, strTxt As String
arr1 = Split(strP, "(")
If UBound(arr1) = 0 Then
removeParanthesisAndContent = strP
Else
strTxt = arr1(0)
For i = 1 To UBound(arr1)
arr2 = Split(arr1(i), ")")
strTxt = strTxt & arr2(1)
Next i
removeParanthesisAndContent = strTxt
End If
End Function
请注意,我已经将 "
替换为引号字符 "
,以便代码在正常的编程环境中运行。
英文:
Even if the question has been answered, please also try the next function using arrays:
Function removeParanthesisAndContent(strP As String) As String
Dim arr1, arr2, i As Long, strTxt As String
arr1 = Split(strP, "(")
If UBound(arr1) = 0 Then
removeParanthesisAndContent = strP
Else
strTxt = arr1(0)
For i = 1 To UBound(arr1)
arr2 = Split(arr1(i), ")")
strTxt = strTxt & arr2(1)
Next i
removeParanthesisAndContent = strTxt
End If
End Function
It is able to process a string with as many parenthesis pairs as you want and it can be tested in the next way:
Sub ReplaceParanthesisAndInBetween()
Const s = "Lorem Ipsum"
Const s1 = "Lorem(abcd) Ipsum"
Const s2 = "Lorem(abc) Ipsum(ssss) dolor sit"
Const s3 = "Lorem (xyz)Ipsum(123) dolor sit(321) amet"
Const s4 = "Lorem (xyz)Ipsum(123) dolor sit(321) amet(xyz)"
Debug.Print removeParanthesisAndContent(s)
Debug.Print removeParanthesisAndContent(s1)
Debug.Print removeParanthesisAndContent(s2)
Debug.Print removeParanthesisAndContent(s3)
Debug.Print removeParanthesisAndContent(s4)
End Sub
答案5
得分: 0
以下是翻译好的部分:
只是为了看到 FilterXML
的威力,请测试下面的函数。它应该非常快速和紧凑(只有一行代码...):
Function removeParXML(txt As String) As String
With Application
removeParXML = Join(.Transpose(.FilterXML("<t><s>" & VBA.Replace(VBA.Replace(txt, "(", "</s><p>"), ")", "</p><s>") & "</s></t>", "//s[count(node())>0]")))
End With
End Function
您可以使用以下方式进行测试:
Sub testRemoveParXML()
Const strText = "Lorem (xyz)Ipsum(123) dolor sit(321) amet(qwerty)"
Debug.Print removeParXML(strText)
End Sub
由于无法添加清晰的注释以便易于理解函数,我将放置另一个函数,将其拆分为较小的部分,以便进行注释和理解(我认为):
Function removeParXMLDetails(txt As String) As String
Dim strXML As String: strXML = "<t><s>" & VBA.Replace(VBA.Replace(txt, "(", "</s><p>"), ")", "</p><s>") & "</s></t>"
Debug.Print strXML '创建一个XML字符串,其中包含主根标签<t></t>和节点<s></s>,用于保留字符串和
'用于括号内容的<p></p>标签(不要提取)。在即时窗口中查看它
Dim arrXML: arrXML = Application.FilterXML(strXML, "//s[count(node())>0]") '它返回所有非空<s></>节点的二维(一列)数组!
'如果字符串不包含最后的括号对,
'返回一个空节点,'XPath查询字符串'(第二个参数)
'只能是"//s"以返回所有节点(而不是"//s[count(node())>0]")...
'为了连接数组内容,需要对其进行转置(以变为一维类型):
removeParXMLDetails = Join(Application.Transpose(arrXML))
End Function
为了测试它,您只需要在上面的测试子过程的末尾添加以下代码行:
Debug.Print removeParXMLDetails(strText)
非常感谢 @T.M.,他引发了我对于理解自Excel 2013版本以来存在的FilterXML
的强大功能的兴趣和挑战!
英文:
Just to see the power of FilterXML
, please test the next function. It should be very fast and compact (only a code line...):
Function removeParXML(txt As String) As String
With Application
removeParXML = Join(.Transpose(.FilterXML("<t><s>" & VBA.Replace(VBA.Replace(txt, "(", "</s><p>"), ")", "</p><s>") & "</s></t>", "//s[count(node())>0]")))
End With
End Function
You can test it using:
Sub testRemoveParXML()
Const strText = "Lorem (xyz)Ipsum(123) dolor sit(321) amet(qwerty)"
Debug.Print removeParXML(strText)
End Sub
Not being possible to place eloquent comments to easily understand the function, I will place another one, split in smaller slices able to be commented and understood (I think):
Function removeParXMLDetails(txt As String) As String
Dim strXML As String: strXML = "<t><s>" & VBA.Replace(VBA.Replace(txt, "(", "</s><p>"), ")", "</p><s>") & "</s></t>"
Debug.Print strXML 'it creates a XML string having the main root tag <t></t> and nodes <s></s> for strings to REMAIN and
'<p></p> tag for paranthesis content (to NOT be extracted). See it in Immediate Window
Dim arrXML: arrXML = Application.FilterXML(strXML, "//s[count(node())>0]") 'it returns a 2D (one column) array of all NOT EMPTY <s></> nodes!
'If the string would not contain a last parenthesis pair,
'returning an EMPTY NODE, 'XPath query string' (second parameter)
'can only be "//s" to return ALL nodes (instead of "//s[count(node())>0]")...
'In order to join the array contents it needs to be Transposed (to become 1D type):
removeParXMLDetails = Join(Application.Transpose(arrXML))
End Function
In order to test it, you should only add at the end of the above testing sub the next code line:
Debug.Print removeParXMLDetails(strText)
Many thanks to @T.M. who raised in me the interest and challenge of understanding the power of FilterXML
, existing in Excel since 2013 version!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论