В Excel VBA я не мог изменить все вхождения между {MyText} на нижний регистр.
Я просматривал весь столбец A и B, и каждый раз, когда я находил текст между {}, я меняю его на нижний регистр.
Код, который у меня был, работает только с первым вхождением, но когда в ячейке есть несколько вхождений, я не смог бы изменить их все на строчные.
как напр. в ячейке у нас было "Bla Bla Bla {Abc} bla bla {xYz} и {HELLO}"
У меня было бы в результате "Бла Бла Бла {abc} бла бла {xYz} и {HELLO}"
Однако я ожидаю, что это будет так:
"Бла-бла-бла {abc} бла-бла {xyz} и {привет}"
Даже если я снова запускаю код, он применяется только в первом случае, ниже приведен VBA, который у меня был:
Set MyRange = Worksheets("Sheet1").Range("G:G,H:H")
Dim temp As String
For Each c In MyRange
If c.Value Like "*{*" Then
temp = Split(c.Value, "{")(1)
temp = Split(temp, "}")(0)
c.Value = Replace(c.Value, temp, LCase(temp))
Else
End If
Next c
End Sub
Привет, BigBen. К сожалению, я раньше не работал, не могли бы вы помочь во всем этом? Спасибо.
Пример шаблона RegEx, который вы могли бы использовать: https://regex101.com/r/1gP1Ms/1


Простое решение без RegEx может работать следующим образом:
Sub test()
Debug.Print LowerCaseBrackets("Bla Bla Bla {Abc} bla bla {xYz} and {HELLO}")
End Sub
Public Function LowerCaseBrackets(ByVal InputString As String) As String
Dim SplitStarts() As String
SplitStarts = Split(InputString, "{")
Dim iStart As Variant
For iStart = LBound(SplitStarts) + 1 To UBound(SplitStarts)
Dim EndPos As Long
EndPos = InStr(SplitStarts(iStart), "}")
SplitStarts(iStart) = LCase(Left$(SplitStarts(iStart), EndPos - 1)) & Mid$(SplitStarts(iStart), EndPos)
Next iStart
LowerCaseBrackets = Join(SplitStarts, "{")
End Function
Split разобьет строку на следующие части:
Bla Bla Bla
Abc} bla bla
xYz} and
HELLO}
Поскольку первая часть всегда находится за пределами первой открывающей скобки, мы опускаем ее и начинаем со следующей.
For iStart = LBound(SplitStarts) + 1
Перебираем следующие части строки и ищем положение концевой скобки в этой части
EndPos = InStr(SplitStarts(iStart), "}")
Затем мы берем левое искусство, преобразуем его в нижний регистр.
LCase(Left$(SplitStarts(iStart), EndPos - 1))
и добавьте остальные с
& Mid$(SplitStarts(iStart), EndPos)
После этого цикла наш массив SplitStarts выглядит так:
Bla Bla Bla
abc} bla bla
xyz} and
hello}
И присоединяем его с помощью открывающей скобки
LowerCaseBrackets = Join(SplitStarts, "{")
чтобы получить нашу последнюю строку
Bla Bla Bla {abc} bla bla {xyz} and {hello}
Другим альтернативным решением может быть
Public Function LowerCaseBrackets(ByVal InputString As String) As String
Dim Pos As Long
Do While InStr(Pos + 1, InputString, "{")
Dim EndPos As Long
EndPos = InStr(Pos + 1, InputString, "}")
Mid(InputString, Pos + 1, EndPos - 1) = LCase(Mid(InputString, Pos + 1, EndPos - 1))
Pos = EndPos
Loop
LowerCaseBrackets = InputString
End Function
Regex - хороший способ. Однако, если вы ищете решение VBA, попробуйте следующее. Код учитывает неправильный ввод, как показано в тестовых примерах:
Option Explicit
Private Sub Test()
Debug.Print Lowercase("Bla Bla Bla {Abc} bla bla {xYz} and {HELLO}")
Debug.Print Lowercase("Bla Bla Bla bla bla ")
Debug.Print Lowercase("Bla Bla Bla and {HELLO")
End Sub
Private Function Lowercase(ByVal Value As String) As String
Dim i As Integer
Dim j As Integer
j = 1
Do
If j > 0 Then
i = InStr(j, Value, "{")
If i > 0 Then
j = InStr(i, Value, "}")
If j > 0 Then Mid(Value, i + 1, j - i - 1) = LCase(Mid(Value, i + 1, j - i - 1))
End If
End If
Loop While i > 0 And j > 0
Lowercase = Value
End Function
Вау, я на самом деле очень удивлен, что Mid(Value, i + 1, j - i - 1) = LCase(Mid(Value, i + 1, j - i - 1)) работает. Никогда бы не подумал, что это вообще что-то заменит в Value.
Возможно, немного удивительно, но это в официальная документация.
А как насчет этого подхода?
Я предлагаю вам следить за тем, чтобы быть внутри или вне "региона" фигурных скобок, используя логическое значение, что-то вроде (±псевдокод):
dim b_inside as Boolean;
dim Line as string; ' this is the text you're going to manipulate
for (int i = 0, i < Line.Length, i++):
if Line[i] == "{" then b_inside = True;
if Line[i] == "}" then b_inside = False;
if b_inside and
(Line[i] >= "A") and
(Line[i] <= "Z")
then Line[i] = LowerCase(Line[i])
next i
Я бы пропустил (Line[i] >= "A") and (Line[i] <= "Z") и вставил все символы от b_inside до LCase(Line[i]), потому что есть иностранные языки, в которых есть буквы, отличные от A-Z, которые нужно преобразовать в немецкие ÄÜÖ. • Теперь было бы интересно, какой из трех подходов быстрее ;)
Моя версия ответа анализирует строку, потому что вы можете заменить тот же текст, но НЕ заключенный в "{}":
Option Explicit
Sub test()
Dim origText As String
Dim lowerText As String
origText = "Bla Abc Bla {Abc} bla bla {xYz} and {HELLO}"
lowerText = MakeItLower(origText)
Debug.Print "original text: " & origText
Debug.Print " lower text: " & lowerText
End Sub
Function MakeItLower(ByVal text As String) As String
Dim result As String
Dim pos0 As Long
Dim pos1 As Long
Dim pos2 As Long
pos0 = 1
pos1 = InStr(1, text, "{", vbTextCompare)
Do While pos1 > 0
result = result & Mid$(text, pos0, pos1 - pos0 + 1)
pos2 = InStr(pos1, text, "}", vbTextCompare)
If pos2 > 0 Then
Dim textToReplace As String
textToReplace = Mid$(text, pos1 + 1, pos2 - pos1 - 1)
result = result & LCase(textToReplace) & "}"
pos0 = pos2 + 1
End If
pos1 = InStr(pos2, text, "{", vbTextCompare)
Loop
MakeItLower = result
End Function
Regex может быть здесь хорошим.