Small Microsoft Word macro
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

I need a Word macro that reformats a string of text into two columns. The text string will be a chess game in PGN format and the output will be successive rows of White and Black moves.

Before Example:
——————————————
[Event "Game #1"]
[Date "2019.03.18"]
[White "Me"]
[Black "You"]
[Result "1-0"]

  1. e4 e5 2. Nf3 { First comment } Nc6 3. Bb5 a6 { Second comment } 4. Ba4 Nf6 1-0

After Example:
——————————————
[Event "Game #1"]
[Date "2019.03.18"]
[White "Me"]
[Black "You"]
[Result "1-0"]

  1. e4 e5
  2. Nf3 { First comment } Nc6
  3. Bb5 a6 { Second comment }
  4. Ba4 Nf6 1-0

Notes:
1) Each pair of moves should start on a new line with the move number first.
2) A tab character should be inserted before the Black move. The move coordinates always starts with a letter [A-Z, a-z].
3) Any text inside [brackets], {braces}, and (parens) should be ignored.

awarded to Wuddrum

Crowdsource coding tasks.

2 Solutions

Winning solution

Hey, this should do:

Sub ChessSplit()
    Dim regExp As Object
    Set regExp = CreateObject("vbscript.regexp")

    With regExp
        .Pattern = " (\d*[13579]\. )(?![^{[(]*[}\]\)])"
        .Global = True
        ActiveDocument.Content.Text = .Replace(ActiveDocument.Content.Text, vbNewLine & "$1")
    End With

    With regExp
        .Pattern = " (\d*[02468]\. )(?![^{[(]*[}\]\)])"
        .Global = True
        ActiveDocument.Content.Text = .Replace(ActiveDocument.Content.Text, vbNewLine & vbTab & "$1")
    End With
End Sub

I tested it on the PGN found on https://en.wikipedia.org/wiki/Portable_Game_Notation#Example and everything was formatted as you requested.

Edit: You should try to do as @svipal has commented, first, to see if that works with the original code, before trying this alternative code:

Sub ChessSplit()
    With ActiveDocument.Content.Find
        .Text = " ([13579]. )"
        .Replacement.Text = "^p\1"
        .Forward = True
        .MatchWildcards = True
        .Execute Replace:=wdReplaceAll
    End With

    With ActiveDocument.Content.Find
        .Text = " ([02468]. )"
        .Replacement.Text = "^p^t\1"
        .MatchWildcards = True
        .Execute Replace:=wdReplaceAll
    End With

    With ActiveDocument.Content.Find
        .Text = " ([0-9]@[13579]. )"
        .Replacement.Text = "^p\1"
        .Forward = True
        .MatchWildcards = True
        .Execute Replace:=wdReplaceAll
    End With

    With ActiveDocument.Content.Find
        .Text = " ([0-9]@[02468]. )"
        .Replacement.Text = "^p^t\1"
        .MatchWildcards = True
        .Execute Replace:=wdReplaceAll
    End With
End Sub

Since the default wildcard searching in word documents is not as powerful as default Regular Expressions, this has one caveat - if game info or comments contains a number that looks like a new step (e.g " 12. "), it will still break the line on that number, breaking the game info or comment in two lines.

Hi Wuddrum, thanks for your solution. I get a VBA error on this line: Set regExp = CreateObject("vbscript.regexp") "Runtime error 429: ActiveX component can't create object". I suspect the problem is that ActiveX is not supported in Mac Word. I looked in References for the library and didn't see anything. If you don't have a fix or workaround, I will attempt to run it on my PC Word, but I prefer a Mac solution.
CuriousMynd 3 months ago
Ah shoot, I spent way too much time on this. Good job Wuddrum. @CuriousMynd : if you go into Tools -> References you should be able to find 'Microsoft VBScript Regular Expressions 5.5'. If you enable that you can just do Dim regEx as New RegExp Instead of Dim regExp As Object Set regExp = CreateObject("vbscript.regexp")
svipal 3 months ago
Success! I tried both the revised version from @svipal and the second solution from @Wuddrum and they both seem to work well on my PC Word 2016. I'll try the second solution on my Mac soon, but I think I'm good to go for now. Thank you both!
CuriousMynd 3 months ago
@svipal Please re-post your comment as solution #2 so that I can award you a tip for your efforts. Thanks.
CuriousMynd 3 months ago
Thank you !
svipal 3 months ago

If you go into Tools -> References you should be able to find 'Microsoft VBScript Regular Expressions 5.5'.

If you enable that you can just do

Dim regEx as New RegExp

Instead of

Dim regExp As Object

Set regExp = CreateObject("vbscript.regexp")

View Timeline