At work we use a tool called FNT command for planning and documentation of cabling, server racks, network infrastructure and so on. It can export planned connections to an excel file but its filled with so much junk that its about 90% junk text that doesn't matter to the engineer executing the task.
I'm not a software engineer but i was able to get something together to address this using copilot and basic regex knowledge. The script replaces junk text with nothing or a semicolon (used as a delimiter for "text to columns" in another script).
I keep getting the runtime error 5020 at one of my loops so im hoping someone can have a look. Additionally, chances are good that my script is bloated or in other ways improvable, even if i get it to work. If there are better methods to do the task please do share your ideas.
Set matches = regexUmpatchen.Execute(cell.Value)
is the line that gets tagged when I click "debugging" after trying to run the script. I removed the last ElseIf loop with comments, which causes the script to run fine. Online research idicates the issue is about the regex pattern but ive tested it in regex101 and found no issues.
Here is an example of 2 cells on which that part of the script should work:
And this is my script:
Sub CleanupAndInsertSemicolon2()
Dim ws As Worksheet
Dim cell As Range
Dim regexVerbindung1 As Object
Dim regexVerbindung2 As Object
Dim regexKarte1 As Object
Dim regexKarte2 As Object
Dim regexUmpatchen As Object
Dim regexUmpatchen2 As Object
Dim regexNach As Object
Dim regexCleanup As Object
Dim regexLineBreaks As Object
Dim regexCondition As Object
Dim matches As Object
Dim match As Object
Dim beschreibungColumn As Range
' Set the worksheet to the active sheet
Set ws = ActiveSheet
' Create regex objects for pattern matching later in the script.
Set regexVerbindung1 = CreateObject("VBScript.RegExp")
regexVerbindung1.pattern = "^.+?(und|nach)"
Set regexVerbindung2 = CreateObject("VBScript.RegExp")
regexVerbindung2.pattern = "Kabel.+\nVon: "
Set regexKarte1 = CreateObject("VBScript.RegExp")
regexKarte1.pattern = "Objekttyp.+"
Set regexKarte2 = CreateObject("VBScript.RegExp")
regexKarte2.pattern = "Standort: "
Set regexUmpatchen = CreateObject("VBScript.RegExp")
regexUmpatchen.pattern = "mit.+\nVon: "
Set regexUmpatchen2 = CreateObject("VBScript.RegExp")
regexUmpatchen.pattern = "(Umpatchen.\(Datenkabel\).in"
Set regexCondition = CreateObject("VBScript.RegExp")
regexCondition.pattern = "(Verbindung|Patchen).\(Datenkabel\)"
Set regexNach = CreateObject("VBScript.RegExp")
regexCondition.pattern = "Nach: "
Set regexPlatzieren = CreateObject("VBScript.RegExp")
regexCondition.pattern = "platzieren."
' Find the "Beschreibung" column and save it as 'beschreibungColumn' so that we can quickly reference this column.
Set beschreibungColumn = ws.Rows(1).Find("Beschreibung", LookIn:=xlValues, LookAt:=xlWhole).EntireColumn
' We now loop through each cell in the "Beschreibung" column, looking for regex patterns and replacing matches with the things I want. A cell is ignored if the previous column does not have a specified string that describes the action that the engineer has to do with the cable or optic module. (Umpatchen - connect elsewhere, Verbinden - Connect, lösen - remove connection and so on)
For Each cell In beschreibungColumn.Cells
If Not IsEmpty(cell.Value) Then
If InStr(1, cell.Value, "Neuer Patch", vbTextCompare) > 0 Or InStr(1, cell.Value, "Neues Bündelkabel", vbTextCompare) > 0 Or InStr(1, cell.Value, "lösen", vbTextCompare) > 0 Then
Set matches = regexVerbindung1.Execute(cell.Value)
For Each match In matches
cell.Value = Replace(cell.Value, match.Value, "")
Next match
Set matches = regexVerbindung2.Execute(cell.Value)
For Each match In matches
cell.Value = Replace(cell.Value, match.Value, ";")
Next match
ElseIf InStr(1, cell.Value, "platzieren", vbTextCompare) > 0 Then
Set matches = regexKarte1.Execute(cell.Value)
For Each match In matches
cell.Value = Replace(cell.Value, match.Value, "")
Next match
Set matches = regexKarte2.Execute(cell.Value)
For Each match In matches
cell.Value = Replace(cell.Value, match.Value, "")
Next match
Set matches = regexPlatzieren.Execute(cell.Value)
For Each match In matches
cell.Value = Replace(cell.Value, match.Value, ";")
Next match
ElseIf InStr(1, cell.Value, "Umpatchen", vbTextCompare) > 0 Then
Set matches = regexUmpatchen.Execute(cell.Value)
For Each match In matches
cell.Value = Replace(cell.Value, match.Value, ";")
Next match
Set matches = regexUmpatchen2.Execute(cell.Value)
For Each match In matches
cell.Value = Replace(cell.Value, match.Value, "")
Next match
Set matches = regexNach.Execute(cell.Value)
For Each match In matches
cell.Value = Replace(cell.Value, match.Value, ";")
Next match
End If
End If
Next cell
End Sub
Update: Example of "Aktion/Beschreibung" content where the script is working (New script by @taller is being used/discussed about from here on)
About the tables: (\n) → newline should be there but was replaced due to limitations of the markdown format regarding text that exceeds one line
Umlaut characters have been replaced with their base letter (Ü-U Ö-O Ä-A)
Bold text indicates that the word is intended to be found by the script, causing it to perform the regex-replace operations for the corresponding cell in the Beschreibung column.
Aktion | Beschreibung |
---|---|
Einfache Verbindung losen | Junktext und ValidInfo1(\n)Junktext(\n)Von: ValidInfo2 Nach: ValidInfo3 |
Umpatchen (einfach) | Junktext in ValidInfo1 mit Junktext(\n)Von: ValidInfo2 Nach: ValidInfo3 |
Non-functional cell content
Aktion | Beschreibung |
---|---|
Neuer Patch (einfach) | Junktext und ValidInfo1(\n)Junktext(\n)Von: ValidInfo2 Nach: ValidInfo3 |
Neues Bundelkabel | Junktext und ValidInfo1(\n)Junktext(\n)Von: ValidInfo2 Nach: ValidInfo3 |
Where the Aktion column has either Neuer Patch or Neues Bundelkabel it seems like the script doesn't find a match and skips them. Since neither the term Neues nor Neuer appears in any other type of Aktion cell, we can even shorten the text that has to be present in Aktion to only those terms but the regex-replacement still does not happen upon executing the script.
Here are some updates to the script:
RegExp
object instead of creating multiple instances.RegExp
for replacements.Note: it's untesed script
Sub CleanupAndInsertSemicolon2()
Dim ws As Worksheet
Dim cell As Range
Dim regexObj As Object
Dim matches As Object
Dim beschreibungColumn As Range
Dim dataArray As Variant
Dim i As Long
Dim lastRow As Long
' Set the worksheet to the active sheet
Set ws = ActiveSheet
' Create a single RegExp object
Set regexObj = CreateObject("VBScript.RegExp")
regexObj.Global = True ' Important for Replace method
' Find the "Beschreibung" column
Set beschreibungColumn = ws.Rows(1).Find("Beschreibung", LookIn:=xlValues, LookAt:=xlWhole)
' Find the last used row in the "Beschreibung" column
lastRow = ws.Cells(ws.Rows.Count, beschreibungColumn.Column).End(xlUp).Row
' Load cell values into an array, using only the used range
Dim dataRng As Range: Set dataRng = beschreibungColumn.Offset(1).Resize(lastRow - 1)
dataArray = dataRng.Value
' Loop through the array and perform replacements
For i = 1 To UBound(dataArray, 1)
If Not IsEmpty(dataArray(i, 1)) Then
If InStr(1, dataArray(i, 1), "Neuer", vbTextCompare) > 0 Or _
InStr(1, dataArray(i, 1), "Neues", vbTextCompare) > 0 Or _
InStr(1, dataArray(i, 1), "lösen", vbTextCompare) > 0 Then
' Pattern 1
regexObj.Pattern = "^.+?(und|nach)"
dataArray(i, 1) = regexObj.Replace(dataArray(i, 1), "")
' Pattern 2
regexObj.Pattern = "Kabel.+\nVon: "
dataArray(i, 1) = regexObj.Replace(dataArray(i, 1), ";")
ElseIf InStr(1, dataArray(i, 1), "platzieren", vbTextCompare) > 0 Then
' Pattern 3
regexObj.Pattern = "Objekttyp.+"
dataArray(i, 1) = regexObj.Replace(dataArray(i, 1), "")
' Pattern 4
regexObj.Pattern = "Standort: "
dataArray(i, 1) = regexObj.Replace(dataArray(i, 1), "")
' Pattern 5
regexObj.Pattern = "platzieren."
dataArray(i, 1) = regexObj.Replace(dataArray(i, 1), ";")
ElseIf InStr(1, dataArray(i, 1), "Umpatchen", vbTextCompare) > 0 Then
' Pattern 6
regexObj.Pattern = "mit.+\nVon: "
dataArray(i, 1) = regexObj.Replace(dataArray(i, 1), ";")
' Pattern 7
regexObj.Pattern = "(Umpatchen.\(Datenkabel\).in)"
dataArray(i, 1) = regexObj.Replace(dataArray(i, 1), "")
' Pattern 8
regexObj.Pattern = "Nach: "
dataArray(i, 1) = regexObj.Replace(dataArray(i, 1), ";")
End If
End If
Next i
' Write array back to the worksheet
dataRng.Value = dataArray ' Ensure write back to the same used range
Set regexObj = Nothing
End Sub
Update: Modify the script based on the sample data in the original post. Changes in the script are marked with *Change
.
Option Explicit
Sub CleanupAndInsertSemicolon2()
Dim ws As Worksheet
Dim cell As Range
Dim regexObj As Object
Dim matches As Object
Dim beschreibungColumn As Range
Dim dataArray As Variant
Dim i As Long
Dim lastRow As Long
' Set the worksheet to the active sheet
Set ws = ActiveSheet
' Create a single RegExp object
Set regexObj = CreateObject("VBScript.RegExp")
regexObj.Global = True ' Important for Replace method
' Find the "Beschreibung" column
Set beschreibungColumn = ws.Rows(1).Find("Beschreibung", LookIn:=xlValues, LookAt:=xlWhole)
' Find the last used row in the "Beschreibung" column
lastRow = ws.Cells(ws.Rows.Count, beschreibungColumn.Column).End(xlUp).Row
' Load cell values into an array, using only the used range
' *Change: Aktion column is used in the If clause, dataRng should include TWO columns
Dim dataRng As Range: Set dataRng = beschreibungColumn.Offset(1, -1).Resize(lastRow - 1, 2)
dataArray = dataRng.Value
' Loop through the array and perform replacements
' *Change: all replacement should be applied on the 2nd column (Beschreibung)
For i = 1 To UBound(dataArray, 1)
If Not IsEmpty(dataArray(i, 1)) Then
' *Change: InStr doesn't support wildcard, change to Like operator
If InStr(1, dataArray(i, 1), "Neuer", vbTextCompare) > 0 Or _
InStr(1, dataArray(i, 1), "Neues", vbTextCompare) > 0 Or _
dataArray(i, 1) Like "*l?sen*" Then
' Pattern 1
regexObj.Pattern = "^.+?(und|nach)"
dataArray(i, 2) = regexObj.Replace(dataArray(i, 2), "")
' Pattern 2
' *Change: line break in a cell is Chr(10) instead of \n (ASCII is 13)
regexObj.Pattern = "Kabel.+" & Chr(10) & "Von: "
dataArray(i, 2) = regexObj.Replace(dataArray(i, 2), ";")
ElseIf InStr(1, dataArray(i, 1), "platzieren", vbTextCompare) > 0 Then
' Pattern 3
regexObj.Pattern = "Objekttyp.+"
dataArray(i, 2) = regexObj.Replace(dataArray(i, 2), "")
' Pattern 4
regexObj.Pattern = "Standort: "
dataArray(i, 2) = regexObj.Replace(dataArray(i, 2), "")
' Pattern 5
regexObj.Pattern = "platzieren."
dataArray(i, 2) = regexObj.Replace(dataArray(i, 2), ";")
ElseIf InStr(1, dataArray(i, 1), "Umpatchen", vbTextCompare) > 0 Then
' Pattern 6
regexObj.Pattern = "mit.+" & Chr(10) & "Von: "
dataArray(i, 2) = regexObj.Replace(dataArray(i, 2), ";")
' Pattern 7
regexObj.Pattern = "(Umpatchen.\(Datenkabel\).in)"
dataArray(i, 2) = regexObj.Replace(dataArray(i, 2), "")
' Pattern 8
regexObj.Pattern = "Nach: "
dataArray(i, 2) = regexObj.Replace(dataArray(i, 2), ";")
End If
End If
Next i
' Write array back to the worksheet
dataRng.Value = dataArray ' Ensure write back to the same used range
Set regexObj = Nothing
End Sub