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.
-
\$\begingroup\$ Not sure why this has DV's/CV's, totally on-topic. Code works, just not well. \$\endgroup\$Der Kommissar– Der Kommissar2017年06月23日 18:09:11 +00:00Commented 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– t3chb0t2017年06月23日 19:05:13 +00:00Commented 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\$200_success– 200_success2017年06月23日 19:22:30 +00:00Commented Jun 23, 2017 at 19:22
-
\$\begingroup\$ @t3chb0t I'm inclined to say that's wrong because of the "I think..." bit. \$\endgroup\$Der Kommissar– Der Kommissar2017年06月23日 19:33:06 +00:00Commented 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\$Jacob Bischoff– Jacob Bischoff2017年06月23日 20:51:19 +00:00Commented Jun 23, 2017 at 20:51
1 Answer 1
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.
-
\$\begingroup\$ For the record, the reason I used the
i
loop counter rather thanFor 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– airstrike2017年07月05日 21:04:46 +00:00Commented Jul 5, 2017 at 21:04 -
\$\begingroup\$ Also I have no recollection of ever writing this code... \$\endgroup\$airstrike– airstrike2022年03月26日 02:06:53 +00:00Commented Mar 26, 2022 at 2:06
Explore related questions
See similar questions with these tags.