lichess.org
Donate

Reversing the order of games in PGN download using SCID vs PC

AnalysisSoftware Development
Simple Excel VBA macro

When one exports historical games from a Lichess profile, the default order of games is chronologically reversed, i.e. the most recent game appears first and the oldest one last in the PGN download file. This makes it difficult to add later games to a SCID vs PC database.

One can, of course, sort the SCID vs PC database in date order, but this doesn't work properly when there are many games with the same date (e.g. bullet binge on a Saturday).

Here's a simple Excel macro that will add a reverse counter as an additional PGN "Round" record, which is an unused field in the Lichess PGN download. After importing the converted PGN file as a SCID vs PC database, one can then sort the database using the "Round" field, followed by compaction to make it permanent. The order of games in the database will then be chronological, i.e. the oldest game is first and the most recent game last in the list.

To use the macro, create a new Excel file, and paste the code below into a new macro, change the input and output file names and run the macro.

Hope this helps!
'--------------------------------------------------------------------------------------------------------
Sub ReverseParsePGN()
'DevObes 2022-03-01
'This macro reads in a Lichess PGN games file, using the default reverse order, i.e. most recent games first.
'which creates a problem when appending more recent games incrementally.
'Simple solution: Add our own reverse counter as a PGN Round record, then use SCID vs PC to sort it on Round

'All Records$ are separated by LF only, hence read entire file and split it at LF.
'Then add [Round "reversenumber"] at the start of each game and output as new file.
'where reversenumber = 1 for the last game in the input file and N for the first game. N = total number of games

'Afterwards:
'Use SCID vs PC, to sort on Round, then compact the database
'Result: Games listed chronologically, i.e. oldest games first, most recent one last.
'Thereafter, add games incrementally, for any date ranges after the first batch
'Note: For adding incrementally, change the GameOffset& variable to the last game number already on SCID vs PC database.
'---------------------------------------------------------------------------------------------------------------
'Define input and output files
pgnfile$ = "C:\Lichess\lichess_JoeDoe_2022-03-01.pgn"
outfile$ = "C:\Lichess\lichess_JoeDoe(2)_2022-03-01.pgn"
GameOffset& = 0 'Change this when adding incrementally to a previous database
'Read entire input file into a buffer string
Open pgnfile$ For Input As 1
FileBuffer$ = Input$(LOF(1), #1)
Close 1

'Split the buffer at Line Feeds, into string array Records$()
Dim Records$()
Records$ = Split(FileBuffer$, vbLf)

'Run through all the Records$ to identify number of games, using Event record as the start of each game
ngames& = 0
For i = 0 To UBound(Records$)
If Left$(Records$(i), 6) = "[Event" Then
ngames& = ngames& + 1
End If
Next

'Export the Records$ to output file
Open outfile$ For Output As #2
counter& = ngames& 'Set up a reverse counter
'The first game in the original PGN file will have the last number e.g. [Round "140151"]
For i = 0 To UBound(Records$)
outrecord$ = Records$(i) + vbLf 'Add the LF
If Left$(outrecord$, 6) = "[Event" Then
AddRound$ = "[Round " + Chr$(34) + Format$(counter& + GameOffset&) + Chr$(34) + "]" + vbLf
Print #2, AddRound$; 'Insert a new record to add the decreasing counter as the Round number
counter& = counter& - 1 'Decrease the Round counter. Thus the very last game should be [Round "1"]
End If
Print #2, outrecord$; 'export the original record as is with LF terminator
Next
Close 2
MsgBox "Added Reverse Round for " + Format$(ngames&) + " games"
End Sub