1

We are trying to automatically translate certain part of a string in each Excel cell automatically based on an VBA dictionary.

Original String examples:

1.Outer Fabric:2% EA, 44% WO, 54% PES; Lining:4% EA, 96% RY
Outside:2% EA, 98% WO
1.Outer Fabric:27% PA, 73% WV; 2.Lining:100% CO; 2.Outer Fabric:100% AOS

Regular expression is defined as:

Dim strPattern As String: strPattern = "(\d{1,3}\%\s+)(\w+)"

The dictionary is constructed from another excel spreasheet. The example key/value pairs are:

EA: Leather
WO: Cloth
PES: Polyester
RY: Other
...

But I cannot find a way to use those dictionary keys to replace the original string. Line 12 below is what I tested, but it cannot find the dictionary value...

Dim strPattern As String: strPattern = "(\d{1,3}\%\s+)(\w+)"
Dim strInput As String
Dim Myrange As Range

Set Myrange = ActiveSheet.Range("A2:A50")
With regex
    .Global = True
    .MultiLine = True
    .IgnoreCase = False
    .Pattern = strPattern
End With
Dim strReplace As String: strReplace = "$1" & IIf(Dict.Exists("$2"), Dict("$2"), "$2")

For Each cell In Myrange
    If strPattern <> "" Then
        strInput = cell.Value
        cell.Value = regex.replace(strInput, strReplace)
    End If
Next

Any guidance to get this problem resolved is greatly appreciated. Thanks!

1
  • You cannot replace all of the dictionary keys in one shot: you'd need to replace each one in turn. Use the pattern to get a Matches collection, then loop over that looking at the SubMatches for each one, running the replace as needed. Commented Aug 19, 2016 at 5:19

2 Answers 2

1

I don't think you need regex for this. When I translate I usually just use brute force with replace.

str = Replace ( str, "EA", "Leather")
str = Replace ( str, "WO", "Cloth")
str = Replace ( str, "PES", "Polyester")

Etc.
And once all replace has been done you know it has translated the abreviations that excist.
If WO is not in the string then the replace will fail and just continue with the next.

5
  • 1
    The problem with using replace for this scenario would not work. If the string contains "25% EA, 35% EA, 40%EA", and I want to replace EA with LEA, then the final string will have LLLEA
    – obvdso
    Commented Aug 19, 2016 at 4:43
  • In addition, the string to be replaced could be thousands of lines, to do this for every entry is tedious.
    – obvdso
    Commented Aug 19, 2016 at 4:58
  • 1
    LEA was not part of the scope. It's very important when you write a question that you don't "etc." when there is something that is important. But if you replace " EA" then you need a space first which will solve your problem. Tedious, yes. But that is what translations are. I have not seen any secure method that is not tedious. YMMV.
    – Andreas
    Commented Aug 19, 2016 at 5:33
  • 1
    How does "EA" become "LLEA"? Was not EA supposed to be Leather? Then it's impossible to become LLEA?
    – Andreas
    Commented Aug 19, 2016 at 5:38
  • 1
    I agree with this answer. A regex is useful if you can replace a pattern with a fixed string, but since you have pairs of Find/Replace strings then you might as well just do a bunch of Find/Replaces. I am also confused about how EA becomes LLLEA, so am maybe missing something. Commented Aug 19, 2016 at 5:43
1

Here's a basic outline:

Sub Tester()

    Dim regEx As Object, dict As Object
    Dim matches, m
    Dim c As Range
    Dim s As String, mat As String

    Set dict = CreateObject("scripting.dictionary")
    dict.Add "EA", "Leather"
    dict.Add "WO", "Cloth"
    dict.Add "PES", "Polyester"
    dict.Add "RY", "Leather"

    Set regEx = CreateObject("vbscript.regexp")
    regEx.Pattern = "(\d{1,3}\%\s+)(\w+)"
    regEx.Global = True
    regEx.IgnoreCase = True
    regEx.MultiLine = True

    For Each c In ActiveSheet.Range("A1:A10")
        s = c.Value
        Set matches = regEx.Execute(s)
        If Not matches Is Nothing Then
            'loop over each of the match objects
            For Each m In matches
                mat = m.submatches(1) '<<second submatch=material code
                If dict.Exists(mat) Then
                    s = Replace(s, m, Replace(m, mat, dict(mat)))
                End If
            Next m
        End If
        c.Offset(0, 1).Value = s
    Next c

End Sub
1
  • This works really well. Thank you very much, @tim-williams
    – obvdso
    Commented Aug 19, 2016 at 15:30

Not the answer you're looking for? Browse other questions tagged or ask your own question.