Pattern modeling engine / function in Visual Basic for Applications

A common use of VBA in my company is to create source code based on the information entered into Excel spreadsheets. Given the built-in VBA string manipulation, the code that does this is tedious to write and not very readable.

A simple example (they become more complex):

Print #fileIdentifier, SSpace(9) & "update_" & print_string & "[" & CStr(j) & "] <= 1'b0;"
Print #fileIdentifier, SSpace(9) & print_string & "_ack_meta" & "[" & CStr(j) & "] <= 1'b0;"
Print #fileIdentifier, SSpace(9) & print_string & "_ack_sync" & "[" & CStr(j) & "] <= 1'b0;"

I am looking for a solution in VBA that will allow me to indicate this using a “text template”, so define a text that will look something like this.

    update_@name@[@bit@] <= 1'b0;
    @name@_ack_meta[@bit@] <= 1'b0;
    @name@_ack_sync[@bit@] <= 1'b0;

and have a function / method call, passing the values ​​@name @ and @bit @, replacing all instances of @name @ and @bit @ with the corresponding values.

+4
source share
2 answers

The main insert function:

Function insert(template As String, ParamArray inserts() As Variant) As String
    Dim i As Long
    For i = 0 To UBound(inserts)
        template = Replace$(template, "%" & i + 1 & "%", inserts(i))
    Next

    '// some special cases perhaps
    template = Replace$(template, "%SSPACE%", SSpace(9))
    template = Replace$(template, "\r\n", VbCrLf)

    insert = template
End Function

For

?insert("Foo %1% Bar %2% Qux %3% (%1%)", "A", "B", "C")

Foo A Bar B Qux C (A)

( Microsoft Scripting Runtime):

Dim col As New Scripting.Dictionary
col("name") = "bob"
col("age") = 35

MsgBox insert2("Hello %name% you are %age%", col)

...

Function insert2(template As String, map As Scripting.Dictionary) As String
    Dim name
    For Each name In map.Keys()
        template = Replace$(template, "%" & name & "%", map(name))
    Next
    insert2 = template
End Function
+5

., .

( , , )

Function FillTemplateGeneric(template As Variant, map As Scripting.Dictionary) As String
    Dim name
    Dim out_text As String

    ' Handle multiple ways of receiving the template string
    If VarType(template) = vbString Then
        out_text = template
    ElseIf VarType(template) = vbArray Then
        out_text = Join(template, vbCrLf)
    ElseIf TypeName(template) = "String()" Then
        out_text = Join(template, vbCrLf)
    ElseIf TypeName(template) = "Variant()" And TypeName(template(LBound(template, 1))) = "String" Then
        out_text = Join(template, vbCrLf)
    Else
        MsgBox "Unknown Var Type passed to FillTemplateGeneric as first argument:" & vbCrLf & TypeName(template)
        Err.Raise vbObjectError + 513, "FillTemplateGeneric", "Unknown Var Type passed to FillTemplateGeneric as first argument:" & vbCrLf & TypeName(template)
    End If

    For Each name In map.Keys()
        out_text = Replace$(out_text, "%" & name & "%", map(name))
    Next
    FillTemplateGeneric = out_text
End Function

:

' Common dictionary for expansion
Dim col As New Scripting.Dictionary
col("name") = print_string

' Using inline text for template
MsgBox FillTemplateGeneric("test text with %name% name - just string", col)

' Using a multi-line string
Dim template As String
templ_text = "         update_%name% <= 1'b0; // 1 - manual multi-line string" & _
    vbCrLf & "         %name%_ack_meta <= 1'b0; // " & _
    vbCrLf & "         %name%_ack_sync <= 1'b0; // "
MsgBox FillTemplateGeneric(templ_text, col)

' Using an array of strings
Dim ttext(1 To 3) As String
ttext(1) = "         update_%name% <= 1'b0; // 2 - manual array of strings"
ttext(2) = "         %name%_ack_meta <= 1'b0; // "
ttext(3) = "         %name%_ack_sync <= 1'b0; // "
MsgBox FillTemplateGeneric(ttext, col)

' Using an inline array of strings 
MsgBox FillTemplateGeneric(Array( _
    "         update_%name% <= 1'b0; // 3 - immediate array of strings", _
    "         %name%_ack_meta <= 1'b0; // ", _
    "         %name%_ack_sync <= 1'b0; // " _
    ), col)
+2

Source: https://habr.com/ru/post/1545842/


All Articles