1
\$\begingroup\$

I have some code in a particular coding language, and I am trying to clean it up by adding spaces around the variables. I wrote this code, and it works on small amounts of text and if I set a break point and run through it manually for large amounts of text. But when I try to run through it without frequently stopping the macro, Word stops responding and I have to restart the program. I think it is because the code is inefficient, but I don't have enough knowledge of vba to make it more efficient.

My code

Sub SpaceVarsAndEqns()

Dim i As Long
Dim paragraphIndex As Long
Dim characterIndex As Long
Dim isVar As Boolean
Dim varIndexBegin As Long
Dim varIndexEnd As Long
Dim Doc As Range
Dim Par As Range
Dim Char As Range

Set Doc = ActiveDocument.Range

For paragraphIndex = 1 To Doc.Paragraphs.Count

    Set Par = Doc.Paragraphs(paragraphIndex).Range
    isVar = False

    characterIndex = 1
    Do

        Set Char = Par.Characters(characterIndex)

        If isVar Then
            If Char.Text = "$" Then
                varIndexEnd = characterIndex

                If Not Par.Characters(varIndexEnd + 1).Text = " " Then
                    Par.Characters(varIndexEnd).InsertAfter (" ")
                    characterIndex = characterIndex + 1
                End If
                If Not Par.Characters(varIndexBegin - 1).Text = " " Then
                    Par.Characters(varIndexBegin).InsertBefore (" ")
                    characterIndex = characterIndex + 1
                End If

                varIndexBegin = 0
                varIndexEnd = 0
                isVar = False
            ElseIf Not (IsAlphaNumber(Char.Text) Or (Char.Text = ".")) Then
                varIndexBegin = 0
                varIndexEnd = 0
                isVar = False
            End If
        Else
            If Par.Characters(characterIndex).Text = "$" Then
                varIndexBegin = characterIndex
                isVar = True
            End If
        End If

        characterIndex = characterIndex + 1
    Loop While (characterIndex <= Par.Characters.Count)

Next paragraphIndex

End Sub

Text Before

\begin{bmatrix} $eval(($d$*$d.pmv$)/(|$d.et$|)*($d.et$*$xm$) + (($b$*-1)*$d.pmv$)/(|$d.et$|)*($d.et$*$ym$) + $dist5$,0.###)\\ $eval((((($a$*$d$)-$d.et$)/($b$))*$d.pmv$*-1)/(|$d.et$|)*($d.et$*$xm$) + ($a$*$d.pmv$)/(|$d.et$|)*($d.et$*$ym$)+ $dist6$,0.###) \end{bmatrix}

Text After

\begin{bmatrix} $eval(( $d$ * $d.pmv$ )/(| $d.et$ |)*( $d.et$ * $xm$ ) + (( $b$ *-1)* $d.pmv$ )/(| $d.et$ |)*( $d.et$ * $ym$ ) + $dist5$ ,0.###)\\ $eval((((( $a$ * $d$ )- $d.et$ )/( $b$ ))* $d.pmv$ *-1)/(| $d.et$ |)*( $d.et$ * $xm$ ) + ( $a$ * $d.pmv$ )/(| $d.et$ |)*( $d.et$ * $ym$ )+ $dist6$ ,0.###) \end{bmatrix}

I think it could be improved by using a find method to find two consecutive $ symbols, and checking if the characters in between are consistent with a variable. However, I don't know how I would add spaces doing it this way.

\$\endgroup\$
9
  • \$\begingroup\$ Not sure why this has DV's/CV's, totally on-topic. Code works, just not well. \$\endgroup\$ Commented Jun 23, 2017 at 18:09
  • \$\begingroup\$ @EBrown it's off-topic because OP looks for a specific solution he's apparently not able to implement. \$\endgroup\$
    – t3chb0t
    Commented Jun 23, 2017 at 19:05
  • \$\begingroup\$ Can you confirm that the macro works, uninterrupted, for a small document? If no test case works, then it might not be appropriate as a Code Review question. \$\endgroup\$ Commented Jun 23, 2017 at 19:22
  • \$\begingroup\$ @t3chb0t I'm inclined to say that's wrong because of the "I think..." bit. \$\endgroup\$ Commented Jun 23, 2017 at 19:33
  • 2
    \$\begingroup\$ @200_success The example text and resulting modification in the question body was modified by the macro and it worked. \$\endgroup\$ Commented Jun 23, 2017 at 20:51

1 Answer 1

1
\$\begingroup\$

Here's a version using Regular Expressions.

Option Explicit

Sub SpaceVarsAndEqns()

    Dim DocumentRange As Range, ParagraphRange As Range
    Dim i As Long, P As Paragraph
    Dim Pattern As String, Replace As String, RegEx As New RegExp
    Dim ParagraphText As String

    Pattern = "(?:\s?)\$[^$(]*\$(?:\s?)"
    Replace = " $& "

    With RegEx
        .Global = True
        .MultiLine = True
        .IgnoreCase = True
        .Pattern = Pattern
    End With

    Set DocumentRange = ActiveDocument.Range
    For i = 1 To DocumentRange.Paragraphs.Count
        Set P = DocumentRange.Paragraphs(i)
        ParagraphText = P.Range.Text
        If RegEx.Test(ParagraphText) Then
            P.Range.Text = RegEx.Replace(ParagraphText, Replace)
        End If

    Next

End Sub

Before:

\begin{bmatrix} $eval(($d$*$d.pmv$)/(|$d.et$|)*($d.et$*$xm$) + (($b$*-1)*$d.pmv$)/(|$d.et$|)*($d.et$*$ym$) + $dist5$,0.###)\\ $eval((((($a$*$d$)-$d.et$)/($b$))*$d.pmv$*-1)/(|$d.et$|)*($d.et$*$xm$) + ($a$*$d.pmv$)/(|$d.et$|)*($d.et$*$ym$)+ $dist6$,0.###) \end{bmatrix}

After:

\begin{bmatrix} $eval(( $d$ * $d.pmv$ )/(| $d.et$ |)*( $d.et$ * $xm$ ) + (( $b$ *-1)* $d.pmv$ )/(| $d.et$ |)*( $d.et$ * $ym$ ) + $dist5$ ,0.###)\\ $eval((((( $a$ * $d$ )- $d.et$ )/( $b$ ))* $d.pmv$ *-1)/(| $d.et$ |)*( $d.et$ * $xm$ ) + ( $a$ * $d.pmv$ )/(| $d.et$ |)*( $d.et$ * $ym$ )+ $dist6$ ,0.###) \end{bmatrix}


This requires adding a reference to the Microsoft VBScript Regular Expressions 5.5 by going to Tools > References and checking that box:

Adding a reference to Microsoft VBScript Regular Expressions 5.5

You can read more on Regular Expressions in VBA in this Stack Overflow answer.

\$\endgroup\$
2
  • \$\begingroup\$ For the record, the reason I used the i loop counter rather than For Each P in DocumentRange.Paragraphs directly was because the latter resulting in an infinite loop due to the paragraphs being edited during the loop. \$\endgroup\$
    – airstrike
    Commented Jul 5, 2017 at 21:04
  • \$\begingroup\$ Also I have no recollection of ever writing this code... \$\endgroup\$
    – airstrike
    Commented Mar 26, 2022 at 2:06

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