Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to transfer parts of a WORD-document into a VFP-table. 7

Status
Not open for further replies.

german12

Programmer
Nov 12, 2001
563
DE
I have a WORD document which contains a lot of Chess games.
As an example I append a WORD document with only two games which looks like this:

Warkentin, Jurgen (2011)

Luco, Alain (2134)

Event: Fouesnant op 11th
Site: Fouesnant
Round: 8 Date: 10/28/2005
ECO: D00 Score: 1-0
1.d4 Nf6 2.Nc3 d5 3.f3 e6 4.Bg5 Be7 5.e3 c5 6.Bb5+ Nc6 7.f4 Bd7 8.Nf3 cxd4 9.exd4 h6 10.Bh4 Ne4 11.Bxe7 Qxe7 12.O-O Nxc3 13.bxc3 O-O 14.c4 dxc4 15.Bxc4 Na5 16.Bd3 Rac8 17.Qe1 b6 18.Ne5 Qd6 19.Rd1 Bc6 20.Kh1 f5 21.c4 Ba8 22.Qg3 Nc6 23.c5 bxc5 24.dxc5 Qc7 25.Bc4 Nxe5 26.Bxe6+ Nf7 27.Rd7 Qc6 28.Qg6 Kh8 29.Rxa7 Qxg2+ 30.Qxg2 Bxg2+ 31.Kxg2 Nd8 32.Bxc8

Stanek, Stanislav (2005)

Prokop, Petr (1620)

Event: Brno Dedek mem-B
Site: Brno
Round: 2 Date: ??/??/2005
ECO: D00 Score: 1-0
1.Nc3 d5 2.d4 Nf6 3.f3 e6 4.Bg5 Be7 5.e3 O-O 6.Nce2 c5 7.c3 b6 8.Ng3 Bb7 9.Bd3 Nbd7 10.f4 h6 11.Bxf6 Nxf6 12.Qf3 cxd4 13.exd4 Qc7 14.Nh3 a5 15.O-O Ba6 16.Bxa6 Rxa6 17.Rae1 b5 18.Re3 Rc6 19.Rfe1 Bd6 20.Ne2 Ne4 21.Nf2 Nd2 22.Qg4 f5 23.Qg6 Bxf4 24.Nxf4 e5 25.Nxd5 Rxg6 26.Nxc7 f4 27.Rd3 e4 28.Rxd2 e3 29.Rde2

What I mainly would like is to have the game in a VFP table, where each move has its own field:

Example for the first game (Warkentin versus Luca) (if Field-Name starts with W, it means a White moves, B means Black moves)

Fieldnames
W1 B1 W2 B2 ........etc. W32
d4 Nf6 Nc3 d5 ............. Bxc8

that means the VFP-table would have one record per game.
To see where a game starts is easy - it always starts with "1." (see bold formatted moves)

How would you do that?

Thanks in advance
Klaus

Attachment: WORD-FILE Chessgames.docx with two games





Peace worldwide - it starts here...
 
 https://files.engineering.com/getfile.aspx?folder=a0777115-fd96-4596-a7fa-7aba7946a132&file=Chessgames.docx
Hi Klaus,

Considering the whole discussion up to now, and especially Chriss's last remarks, a innocent question: why don't you simply copy and paste the data from the website into your VFP application as I did. It hardly takes 30 seconds for one full operation (copying/pasting Date, City, WP Name, BP Name and moves - please see row 2 of the grid on screenshot). You can then later do whatever you want with he moves saved in the memo field

Screenshot_2022-08-27_092640_s5juol.png


hth

MarK
 
Mark,

I think the answer to your question would be that Klaus wants to do this job programmatically, rather than a manual copy / paste.

That said, your suggestion is interesting. But you say you pasted from the website into a VFP application. What exactly is the target of your paste? In other words, what control or you pasting into? From your screen shot, it looks like a grid, but how can you paste text into a grid? Or could it be an edit box?

I'm not criticising your approach. I'm just asking out of curiosity.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Mike

I think the answer to your question would be that Klaus wants to do this job programmatically, rather than a manual copy / paste.

Maybe, but considering the detours he took, the unknown number (10, 100 or more than 1000?) of games he wants to save it might be easier for him to manually C&P

Furthermore you may remember that Klaus launched a similar thread in 2020

thread184-1807064

and at the time I drew a sketch of how his approach might look like (see code below).

You may also want to have a look at the chess internet site and see how easy it is to C&P from there into VFP

[link ][/url]

Screenshot_2022-08-27_110408_c3jh2c.png


Code:
PUBLIC go_Form

go_Form = CreateObject ("frmForm")
go_Form.Visible = .T.
go_Form.Show

READ Events

CLOSE ALL
CLEAR ALL

*****

DEFINE CLASS frmForm As Form
	Width = 600
	Height = 360
	MinWidth = This.Width
	MinHeight = This.Height
	AutoCenter = .T.
	Themes = .F.
	
	Add Object grdGames as Grid with;
		Top = 66, ;
		Left = 18, ;
		Height = 360 - 120, ;
		Width = 600 - 36, ;
		RowHeight = 60, ;
		AllowRowSizing = .F., ;
		DeleteMark = .F., ;
		Visible = .T., ;
		Anchor = 15, ;
		ColumnCount = -1, ;
		RecordSource = "csrChessGames"
    	
		PROCEDURE grdGames.Init()
			WITH This 
				.Column1.Header1.Caption = "Date"
				.Column1.Header1.FontBold = .T.
				.Column1.Width = 90

				.Column2.Header1.Caption = "City"
				.Column2.Header1.FontBold = .T.
				.Column2.Width = 90

				.Column3.Header1.Caption = "Player White"
				.Column3.Header1.FontBold = .T.
				.Column3.Width = 120

				.Column4.Header1.Caption = "Player Black"
				.Column4.Header1.FontBold = .T.
				.Column4.Width = 120
			ENDWITH 

			With This.Column5
				.Header1.Caption = "Moves"
				.Header1.FontBold = .T.
				.Width = This.Parent.Width - 456
				.NewObject("edtChessMoves","EditBox")
				.CurrentControl = "edtChessMoves"
				.edtChessMoves.Visible = .T.
				.Sparse = .F.
			ENDWITH    	
		ENDPROC 
    	
	ADD OBJECT lblSearch as LABEL WITH ;
		Top = 12, Left = 18, FontBold = .T., FontSize = 10, AutoSize = .T., ;
		Caption = "Search City, Players or Moves"
		
	ADD OBJECT txtSearch as Textbox WITH ;
		Top = 36, Left = 18, Width = 192, Format = "!", SpecialEffect = 0

	ADD OBJECT cmdSearch As CommandButton WITH;
		Width = 60, Height = 24, Left = 522, Top = 324, Anchor = 12, Caption = "Search"
		
		PROCEDURE cmdSearch.RightClick()
			ThisForm.txtSearch.Value = ""
			This.Click()
		ENDPROC 

		PROCEDURE cmdSearch.Click()
			IF !EMPTY(ALLTRIM(ThisForm.txtSearch.Value))
				SET Filter TO ;
					ATC(ALLTRIM(ThisForm.txtSearch.Value), cCity) !=  0 OR ;
					ATC(ALLTRIM(ThisForm.txtSearch.Value), cWhite) !=  0 OR ;
					ATC(ALLTRIM(ThisForm.txtSearch.Value), cBlack ) !=  0 OR ;
					ATC(ALLTRIM(ThisForm.txtSearch.Value), mMoves) !=  0
			ELSE
				SET Filter TO 
			ENDIF 

			LOCATE
			 
			ThisForm.Refresh()
		ENDPROC

	ADD OBJECT cmdExit As CommandButton WITH;
		Width = 60, Height = 24, Left = 18, Top = 324, Anchor = 6, Caption = "Exit"

		PROCEDURE cmdExit.Click()
			CLEAR Events
			ThisForm.Release
		ENDPROC

	ADD OBJECT cmdNew As CommandButton WITH;
		Width = 60, Height = 24, Left = 84, Top = 324, Anchor = 6, Caption = "New"
		
		PROCEDURE cmdNew.Click()
			go_FormAdd = CreateObject ("frmAdd")
			go_FormAdd.Visible = .T.
			go_FormAdd.Show
		ENDPROC 

	PROCEDURE Resize()
		WITH This.grdGames
			.Column5.Width = .Width - 456

		ENDWITH 
	ENDPROC 
	
	
	PROCEDURE Destroy()
		CLEAR Events
		ThisForm.Release
	ENDPROC
    
	PROCEDURE Load()
		Create Cursor csrChessGames (dDate D, cCity C(20), cWhite C(30), cBlack C(30), mMoves M)
		
		INSERT INTO csrChessGames VALUES ( {^2019/12/02}, "London", "Hosky", "Schmidt", "e2e3:e7e6 - d2d3:d7d5 - f2f4:f7f5 - since this is a Memo-Field you may add almost as much text as you'd like.")
		INSERT INTO csrChessGames VALUES ( {^2019/11/03}, "Paris", "Bauer", "Koenig", "e2e4:e7e5")
		INSERT INTO csrChessGames VALUES ( {^2018/09/03}, "Budapest", "Dame" ,"Turm", "1.d4 Nf6 2.Nc3 d5 3.f3 e6 4.Bg5 Be7 5.e3 c5 6.Bb5+ Nc6 7.f4 Bd7 8.Nf3 cxd4 9.exd4 h6" + ;
																						" 10.Bh4 Ne4 11.Bxe7 Qxe7 12.O-O Nxc3 13.bxc3 O-O 14.c4 dxc4 15.Bxc4 Na5 16.Bd3 Rac8" + ;
																						" 17.Qe1 b6 18.Ne5 Qd6 19.Rd1 Bc6 20.Kh1 f5 21.c4 Ba8 22.Qg3 Nc6 23.c5 bxc5 24.dxc5 Qc7 25.Bc4 Nxe5" + ; 
																						" 26.Bxe6+ Nf7 27.Rd7 Qc6 28.Qg6 Kh8 29.Rxa7 Qxg2+ 30.Qxg2 Bxg2+ 31.Kxg2 Nd8 32.Bxc8")
		INSERT INTO csrChessGames VALUES ( {^2018/06/18}, "Budapest", "Läufer", "Turm", "1.Nc3 d5 2.d4 Nf6 3.f3 e6 4.Bg5 Be7 5.e3 O-O 6.Nce2 c5 7.c3 b6 8.Ng3 Bb7 9.Bd3 Nbd7" + ;
																						" 10.f4 h6 11.Bxf6 Nxf6 12.Qf3 cxd4 13.exd4 Qc7 14.Nh3 a5 15.O-O Ba6 16.Bxa6 Rxa6" + ;
																						" 17.Rae1 b5 18.Re3 Rc6 19.Rfe1 Bd6 20.Ne2 Ne4 21.Nf2 Nd2 22.Qg4 f5 23.Qg6 Bxf4 24.Nxf4 e5 25.Nxd5 Rxg6" + ;
																						" 26.Nxc7 f4 27.Rd3 e4 28.Rxd2 e3 29.Rde2")
		
		LOCATE 
	ENDPROC

ENDDEFINE

*****

DEFINE CLASS frmAdd as Form 
	Width = 480
	Height = 240
	MinWidth = This.Width
	MaxWidth = This.Width
	MinHeight = This.Height
	MaxHeight = This.Height
	WindowType = 1
	AutoCenter = .T.
	Themes = .F.
	

	ADD OBJECT lblDate as Label WITH ;
		Top = 24, Left = 12, Caption = "Date"
		
	ADD OBJECT lblCity as Label WITH ;
		Top = 24, Left = 102, Caption = "City"

	ADD OBJECT lblWPName as Label WITH ;
		Top = 24, Left = 228, Caption = "WP Name"

	ADD OBJECT lblBPName as Label WITH ;
		Top = 24, Left = 354, Caption = "BP Name"

	ADD OBJECT lblMoves as Label WITH ;
		Top = 84, Left = 12, Caption = "Moves"

	ADD OBJECT txtDate as TextBox WITH ;
		Top = 48, Left = 12, Width = 78, Value = {}
		
	ADD OBJECT txtCity as TextBox WITH ;
		Top = 48, Left = 96, Width = 120, Value = ""
	
	ADD OBJECT txtWPName as TextBox WITH ;
		Top = 48, Left = 222, Width = 120, Value = ""

	ADD OBJECT txtBPName as TextBox WITH ;
		Top = 48, Left = 348, Width = 120, Value = ""

	ADD OBJECT edtMoves as EditBox WITH ;
		Top = 102, Left = 12, Width = 456, Value = ""
	
	ADD OBJECT cmdSave as CommandButton WITH ;
		Top = 204, Left = 12, Height = 24, BackColor = RGB(0, 240, 240), Caption = "Save"
		
		PROCEDURE cmdSave.Click()
			llSave = .T.
			
			FOR i = 1 TO ThisForm.ControlCount
				IF Thisform.Controls(i).BaseClass = "Textbox" OR ThisForm.Controls(i).BaseClass = "Editbox"
					IF EMPTY(ThisForm.Controls(i).Value)
						WAIT WINDOW + "Hi - an important field is still empty" TIMEOUT 1
						llSave = .F.			
					ENDIF 
				ENDIF
			ENDFOR
			
			IF llSave
				INSERT INTO csrChessGames VALUES (ThisForm.txtDate.Value, ThisForm.txtCity.Value, ThisForm.txtWPName.Value, ThisForm.txtBPName.Value, ThisForm.edtMoves.Value)
				
				ThisForm.Release()
			
                                go_Form.Show()
				
			ENDIF 
		ENDPROC 
ENDDEFINE 

*****

I'm not criticising your approach. I'm just asking out of curiosity.

No offense taken - I'm retired and playing with VFP just for fun and to keep my brain working

MarK
 
I earlier said:

myself said:
If you need to manually feed in the URLs to a program you write that then can extract the games, that's just defering the simple task to just copy out the game manually. So it only pays if you know a URL pattern...

Okay, you do have a pattern with

But I doubt you want to read in all games from 0 to somewhere between 4300000 and 4400000. You likely will hit limits. Mostly limits of how many of them, and which of them, are valuable to you to learn from them or have a good time replaying and analyzing them. The question remains, do you pick interesting games while you see them, get them recommended? If that's the way you go, I still say as I said before in my "put all the technological ideas aside" post, which MarK seconds, it may not be worth it to automate the parsing. And even if you get all these games, you won't even look at most of them in detail, you might only process them statistically.

Besides that, there is a button "Download games" on the game search page: It states you need be registered and be a supporter. You seem to be. I don't know how many games are in the download, but if it's all, then there is your whole work done and unnecessary.
Well, or you simply continue to use the database online, profit from it being extended with new, interesting games up to date and features programmed over time, search details you'd first need to implement yourself, even if you have all the data, etc.

I know, it would still be a nice problem to tackle simply for tackling the problem itself. Well, go ahead as you like.

Chriss
 
phh,
I really don't want to complicate what I want.

As you saw, it is possible to copy the notations for a chess game from the web site.
Of course, I don't want to have millions of chess games on my computer, just one very specific opening.

Let's assume it's the Richter-Veresow attack.
There are about 800 games that can be found on the web-page.

I can transfer these games manually - either to a WORD file or to a text file.

When I started my request, I dragged and dropped the game, just like Mark recommended into WORD
(The possibility of doing this via parsing or extracting in the htm file only came to me through tips from Mike, which of course requires programming work first but could have small advantage by automation).


Downloading the games only results in a new format (*.pgn)
which can be read by a chess program - but which does not make the notation visible.
(That's what I not want.)

What I want?
I just want an overview where I can see what was played in an overview
First possibility:
(sample for 2 different games:)

a)leave the copied games as I copied them


1.st game
1.d4 Nf6 2.Nc3 d5 3.Bg5 Bf5 4.f3 Nbd7 5.Qd2 c6 6.O-O-O h6 7.Bf4 e6 8.g4 Bg6 9.e3 Qa5 10.Bd3 Bxd3 11.cxd3 Bb4 12.Nge2 Nf8 13.h4 O-O-O 14.Kb1 Ng6 15.Bg3 h5 16.g5 Ne8 17.a3 Bd6 18.f4 Bc7 19.Ka2 Qa6 20.b4 Bd6 21.Qb2 Nc7 22.Qb3 Ne7 23.Na4 b5 24.Nc5 Bxc5 25.dxc5 Qb7 26.e4 g6 27.Nd4 dxe4 28.dxe4 Rhf8 29.Nf3 Rxd1 30.Rxd1 Rd8 31.Ne5 Rxd1 32.Qxd1 Ne8 33.Nxf7 Nd5 34.exd5 Qxf7 35.dxc6 e5+ 36.Qb3 Qxb3+ 37.Kxb3 e4 38.a4 a6 39.axb5 axb5 40.f5 gxf5 41.Kc3 Ng7 42.Kd4 Kd8 43.c7+ Kd7 44.Ke5 e3 45.Kf6 Ne8+ 46.Kxf5 Nxc7 47.g6 1-0

2.game

1.d4 Nf6 2.Nc3 d5 3.Bg5 Bf5 4.f3 c5 5.e4 dxe4 6.d5 Qa5 7.Bxf6 gxf6 8.fxe4 Bxe4 9.Bb5+ Kd8 10.Qd2 a6 11.Bf1 Bg6 12.Nge2 Nd7 13.Nf4 Qb4 14.O-O-O Kc8 15.g3 Kb8 16.Kb1 Bh6 17.a3 Qa5 18.Qf2 Rd8 19.Nd3 Bxd3 20.Bxd3 Ne5 21.d6 Rxd6 22.Ne4 Rd4 23.Qf5 Ka7 24.Qxh7 Bf8 25.Qf5 Rad8 26.Qf2 Ka8 27.Nc3 Nxd3 28.cxd3 Rxd3 29.Rxd3 Rxd3 30.Qf5 Qd8 31.Rf1 c4 32.Qc5 Rd4 33.Qf5 Bg7 34.Qh7 Bf8 35.Qxf7 Bh6 36.Rf5 Bd2 37.Nd5 Ba5 38.Ne3 c3 39.Nc4 Rd1+ 40.Ka2 c2 0-

b)create a vfp-table where with one line per game. (It is very seldom that games are longer than 40 to 60 moves - and if the line is too long - ignore it or restrict it.

You now can see better what happens
1.d4 Nf6 2.Nc3 d5 3.Bg5 Bf5 4.f3 Nbd7 5.Qd2 c6 6.O-O-O h6 7.Bf4 e6 8.g4 ............................................
1.d4 Nf6 2.Nc3 d5 3.Bg5 Bf5 4.f3 c5 5.e4 dxe4 6.d5 Qa5 7.Bxf6 gxf6 8.fxe4............................................

Imagine you have 10 games and I want to see 4th. move of Black - would it not much better to have 10 lines to view instead of 10 blocks of games?
Such a table would also be easy to handle and to evaluate with VFP.

That is all I want. (of course, if at the and of the line there would be a memo-field for information about players, date etc. ist would be fine, but the main
goal for me is to have a quick visible situation comparison lets say within the first 10 moves.

Therefore I would prefer possibility b) now.

Also, based after this discussion, I think it's easier
to take over the games with drag and drop instead of first
convert the file to htm and then read part of it with a program.




Thanks
Klaus









Peace worldwide - it starts here...
 
Hi Klaus

1.d4 Nf6 2.Nc3 d5 3.Bg5 Bf5 4.f3 Nbd7 5.Qd2 c6 6.O-O-O h6 7.Bf4 e6 8.g4 ............................................
1.d4 Nf6 2.Nc3 d5 3.Bg5 Bf5 4.f3 c5 5.e4 dxe4 6.d5 Qa5 7.Bxf6 gxf6 8.fxe4............................................

Imagine you have 10 games and I want to see 4th. move of Black - ...

As far as I understand you want to see the 4th move of B in games where moves 1 to 3 are IDENTICAL? If this assumption is correct you easily could

Code:
lcString2Search = "1.d4 Nf6 2.Nc3 d5 ..."

SELECT ... WHERE AT(lcString2Search, mMemoField) # 0 INTO ...

or

SELECT ... SUBSTR(mMemoField, 1, AT("5.", mMemoField) - 1) ... WHERE AT ... && if you only want to see the first 4 moves

and you'll have all you need

hth

MarK
 
So you do want to copy over all games of one search result?
And the download button does that?

Klaus said:
Downloading the games only results in a new format (*.pgn)
which can be read by a chess program - but which does not make the notation visible.

It will be totally possible to read out the moves from that format, too. Indeed, according to Wikipedia ( it is just a text format. A given example is
Code:
[Event "F/S Return Match"]
[Site "Belgrade, Serbia JUG"]
[Date "1992.11.04"]
[Round "29"]
[White "Fischer, Robert J."]
[Black "Spassky, Boris V."]
[Result "1/2-1/2"]

1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 {This opening is called the Ruy Lopez.}
4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. c3 O-O 9. h3 Nb8 10. d4 Nbd7
11. c4 c6 12. cxb5 axb5 13. Nc3 Bb7 14. Bg5 b4 15. Nb1 h6 16. Bh4 c5 17. dxe5
Nxe4 18. Bxe7 Qxe7 19. exd6 Qf6 20. Nbd2 Nxd6 21. Nc4 Nxc4 22. Bxc4 Nb6
23. Ne5 Rae8 24. Bxf7+ Rxf7 25. Nxf7 Rxe1+ 26. Qxe1 Kxf7 27. Qe3 Qg5 28. Qxg5
hxg5 29. b3 Ke6 30. a3 Kd6 31. axb4 cxb4 32. Ra5 Nd5 33. f3 Bc8 34. Kf2 Bf5
35. Ra7 g6 36. Ra6+ Kc5 37. Ke1 Nf4 38. g3 Nxh3 39. Kd2 Kb5 40. Rd6 Kc5 41. Ra6
Nf2 42. g4 Bd3 43. Re6 1/2-1/2

It does not only have the moves, you also have information about event, date, players, result. Why are you rejecting this, it actually seems the easiest way to me, as you get all the games. I don't know exactly what the download contains, I assume it would be a zip of several pgn files, but they are merely texts.

Chriss
 
Hi Klaus a.o.

I fine tuned my program a little bit. It allows to search
[ul]
[li]for a string - you enter "1.e4" (without the quotes) or "1.d4 Nf6 2.Nc3 d5" in the textbox "Search Moves"; every game containing this string will be displayed[/li]
[li]for a string up to a certain move - you enter "1.e4" or "1.d4 Nf6 2.Nc3 d5" or "2.Nc3 d5" in "Search Moves" and "10." in "... up to move"; every game containing this string will be displayed up to move 10 (excluded)[/li]
[li]for a move up to a certain move - you enter "2." and "21."; all moves between 2nd and 21st (excluded) will be displayed[/li][/ul]

Assumptions and requirements : the first move has to start with a space in your data, a game has no more than 60 moves and each move starts with a number followed by a dot e.g. "9.". If you add the chess field coordinates or the name of the piece, they follow without a space e.g. "9.N"

Code:
*!*	PUBLIC go_Form

go_Form = CreateObject ("frmForm")
go_Form.Visible = .T.
go_Form.Show

READ Events

CLOSE ALL
CLEAR ALL

RETURN 

*****

DEFINE CLASS frmForm As Form
	Width = 600
	Height = 360
	MinWidth = This.Width
	MinHeight = This.Height
	AutoCenter = .T.
	ShowTips = .T.
	Themes = .F.
	
	Add Object grdGames as Grid with;
		Top = 66, ;
		Left = 18, ;
		Height = 360 - 120, ;
		Width = 600 - 36, ;
		RowHeight = 60, ;
		AllowRowSizing = .F., ;
		DeleteMark = .F., ;
		Visible = .T., ;
		Anchor = 15, ;
		ReadOnly = .T., ;
		ColumnCount = -1, ;
		RecordSource = "tblChess"
    	
		PROCEDURE grdGames.Init()
			WITH This 
				.Column1.Header1.Caption = "Date"
				.Column1.Header1.FontBold = .T.
				.Column1.Width = 90

				.Column2.Header1.Caption = "City"
				.Column2.Header1.FontBold = .T.
				.Column2.Width = 90

				.Column3.Header1.Caption = "Player White"
				.Column3.Header1.FontBold = .T.
				.Column3.Width = 120

				.Column4.Header1.Caption = "Player Black"
				.Column4.Header1.FontBold = .T.
				.Column4.Width = 120
			ENDWITH 

			With This.Column5
				.Header1.Caption = "Moves"
				.Header1.FontBold = .T.
				.Width = This.Parent.Width - 456
				.NewObject("edtChessMoves","EditBox")
				.CurrentControl = "edtChessMoves"
				.edtChessMoves.Visible = .T.
				.Sparse = .F.
			ENDWITH    	
		ENDPROC 
		
	ADD OBJECT lblSearch as LABEL WITH ;
		Top = 12, Left = 18, FontBold = .T., FontSize = 10, AutoSize = .T., ;
		Caption = "Search Moves" + SPACE(42) + " ... up to move"
		
	ADD OBJECT txtSearch as Textbox WITH ;
		Top = 36, Left = 18, Width = 306, Format = "!", SpecialEffect = 0

	ADD OBJECT txtMove as Textbox WITH ;
		Top = 36, Left = 330, Width = 36, Format = "999", SpecialEffect = 0

	ADD OBJECT cmdSearch As CommandButton WITH;
		Width = 60, Height = 24, Left = 18, Top = 324, Anchor = 6, Caption = "Search", ToolTipText = "Right click to reset filter"
		
		PROCEDURE cmdSearch.RightClick()
			ThisForm.txtSearch.Value = ""
			ThisForm.txtMove.Value = ""
			SELECT tblChess
			This.Click()
		ENDPROC 

		PROCEDURE cmdSearch.Click()
			LOCAL lcString2Search, lcMove
			
			lcString2Search = " " + ALLTRIM(ThisForm.txtSearch.Value)
			lcMove = ALLTRIM(ThisForm.txtMove.Value)
			
			IF !EMPTY(lcString2Search)
				SELECT dDate, cCity, cWhite, cBlack, SUBSTR(mMoves, ATC(lcString2Search, mMoves, 1), IIF(EMPTY(lcMove), 480, AT(lcMove, mMoves) - ATC(lcString2Search, mMoves, 1))) ;
						FROM tblChess ;
						WHERE ATC(lcString2Search, mMoves, 1) # 0 ;
						INTO CURSOR csrFGames
				
				WITH ThisForm.grdGames
					.ColumnCount = -1
					.RecordSource = "csrFGames"
					.Init()

				ENDWITH     	
				
*!*				IF !EMPTY(ALLTRIM(ThisForm.txtSearch.Value))
*!*					
*!*					SET Filter TO ;
*!*						ATC(ALLTRIM(ThisForm.txtSearch.Value), cCity) !=  0 OR ;
*!*						ATC(ALLTRIM(ThisForm.txtSearch.Value), cWhite) !=  0 OR ;
*!*						ATC(ALLTRIM(ThisForm.txtSearch.Value), cBlack ) !=  0 OR ;
*!*						ATC(ALLTRIM(ThisForm.txtSearch.Value), mMoves) !=  0
			ELSE
			
				WITH ThisForm.grdGames
					.ColumnCount = -1
					.RecordSource = "tblChess"
					.Init()

				ENDWITH     	
			ENDIF 

			LOCATE
			 
			ThisForm.Refresh()
		ENDPROC

	ADD OBJECT cmdExit As CommandButton WITH;
		Width = 60, Height = 24, Left = 522, Top = 324, Anchor = 12, Caption = "Exit", BackColor = RGB(0, 240, 0)

		PROCEDURE cmdExit.Click()
			CLEAR Events
			ThisForm.Release
		ENDPROC

	ADD OBJECT cmdNew As CommandButton WITH;
		Width = 60, Height = 24, Left = 84, Top = 324, Anchor = 6, Caption = "New", BackColor = RGB(0, 240, 240)
		
		PROCEDURE cmdNew.Click()
			go_FormAdd = CreateObject ("frmAdd")
			go_FormAdd.Visible = .T.
			go_FormAdd.Show
		ENDPROC 
		
	ADD OBJECT cmdEdit as CommandButton WITH ;
		Width = 60, Height = 24, Left = 150, Top = 324, Anchor = 6, Caption = "Edit", Name = "cmdEdit"
		
		PROCEDURE cmdEdit.Click()
			IF ALIAS() = "TBLCHESS"
				IF This.Caption = "Edit"
					ThisForm.grdGames.ReadOnly = .F.
					This.Caption = "Save"
					
					FOR i = 1 TO ThisForm.ControlCount
						IF Thisform.Controls(i).BaseClass = "Commandbutton"
							IF ThisForm.Controls(i).Name = "CMDEDIT"
								ThisForm.Controls(i).Enabled = .T.
							ELSE 
								ThisForm.Controls(i).Enabled = .F.

							ENDIF 
						ENDIF
					ENDFOR

				ELSE 
					ThisForm.grdGames.ReadOnly = .T.
					This.Caption = "Edit"

					FOR i = 1 TO ThisForm.ControlCount
						IF Thisform.Controls(i).BaseClass = "Commandbutton"
								ThisForm.Controls(i).Enabled = .T.

						ENDIF
					ENDFOR
				ENDIF
			ELSE
				= MESSAGEBOX("You have to reset the filter before being able to change data.", 64 , "Changing data", 3000)
			ENDIF 
		ENDPROC 
			
	PROCEDURE Resize()
		WITH This.grdGames
			.Column5.Width = MAX(.Width - (.Column1.Width + .Column2.Width + .Column3.Width + .Column4.Width) - 36, 210)

		ENDWITH 
	ENDPROC 
	
	PROCEDURE Destroy()
		CLEAR Events
		ThisForm.Release
	ENDPROC
    
	PROCEDURE Load()
	
		IF !FILE("tblChess.dbf")
		
			Create Table tblChess (dDate D, cCity C(20), cWhite C(30), cBlack C(30), mMoves M)
			
			INSERT INTO tblChess VALUES ( {^2018/09/03}, "Budapest", "Dame" ,"Turm", " 1.d4 Nf6 2.Nc3 d5 3.f3 e6 4.Bg5 Be7 5.e3 c5 6.Bb5+ Nc6 7.f4 Bd7 8.Nf3 cxd4 9.exd4 h6" + ;
																							" 10.Bh4 Ne4 11.Bxe7 Qxe7 12.O-O Nxc3 13.bxc3 O-O 14.c4 dxc4 15.Bxc4 Na5 16.Bd3 Rac8" + ;
																							" 17.Qe1 b6 18.Ne5 Qd6 19.Rd1 Bc6 20.Kh1 f5 21.c4 Ba8 22.Qg3 Nc6 23.c5 bxc5 24.dxc5 Qc7 25.Bc4 Nxe5" + ; 
																							" 26.Bxe6+ Nf7 27.Rd7 Qc6 28.Qg6 Kh8 29.Rxa7 Qxg2+ 30.Qxg2 Bxg2+ 31.Kxg2 Nd8 32.Bxc8")
			
			INSERT INTO tblChess VALUES ( {^2018/06/18}, "Budapest", "Läufer", "Turm", " 1.Nc3 d5 2.d4 Nf6 3.f3 e6 4.Bg5 Be7 5.e3 O-O 6.Nce2 c5 7.c3 b6 8.Ng3 Bb7 9.Bd3 Nbd7" + ;
																							" 10.f4 h6 11.Bxf6 Nxf6 12.Qf3 cxd4 13.exd4 Qc7 14.Nh3 a5 15.O-O Ba6 16.Bxa6 Rxa6" + ;
																							" 17.Rae1 b5 18.Re3 Rc6 19.Rfe1 Bd6 20.Ne2 Ne4 21.Nf2 Nd2 22.Qg4 f5 23.Qg6 Bxf4 24.Nxf4 e5 25.Nxd5 Rxg6" + ;
																							" 26.Nxc7 f4 27.Rd3 e4 28.Rxd2 e3 29.Rde2")
		
		ELSE
		
			USE tblChess
		
		ENDIF 
		
		LOCATE 
		
	ENDPROC

ENDDEFINE

*****

DEFINE CLASS frmAdd as Form 
	Width = 480
	Height = 240
	MinWidth = This.Width
	MaxWidth = This.Width
	MinHeight = This.Height
	MaxHeight = This.Height
	WindowType = 1
	AutoCenter = .T.
	Themes = .F.
	

	ADD OBJECT lblDate as Label WITH ;
		Top = 24, Left = 12, Caption = "Date"
		
	ADD OBJECT lblCity as Label WITH ;
		Top = 24, Left = 102, Caption = "City"

	ADD OBJECT lblWPName as Label WITH ;
		Top = 24, Left = 228, Caption = "WP Name"

	ADD OBJECT lblBPName as Label WITH ;
		Top = 24, Left = 354, Caption = "BP Name"

	ADD OBJECT lblMoves as Label WITH ;
		Top = 84, Left = 12, Caption = "Moves"

	ADD OBJECT txtDate as TextBox WITH ;
		Top = 48, Left = 12, Width = 78, Value = {}
		
	ADD OBJECT txtCity as TextBox WITH ;
		Top = 48, Left = 96, Width = 120, Value = ""
	
	ADD OBJECT txtWPName as TextBox WITH ;
		Top = 48, Left = 222, Width = 120, Value = ""

	ADD OBJECT txtBPName as TextBox WITH ;
		Top = 48, Left = 348, Width = 120, Value = ""

	ADD OBJECT edtMoves as EditBox WITH ;
		Top = 102, Left = 12, Width = 456, Value = ""
	
	ADD OBJECT cmdSave as CommandButton WITH ;
		Top = 204, Left = 12, Height = 24, BackColor = RGB(0, 240, 240), Caption = "Save"
		
		PROCEDURE cmdSave.Click()
			LOCAL llSave
			
			llSave = .T.
			
			FOR i = 1 TO ThisForm.ControlCount
				IF Thisform.Controls(i).BaseClass = "Textbox" OR ThisForm.Controls(i).BaseClass = "Editbox"
					IF EMPTY(ThisForm.Controls(i).Value)
						WAIT WINDOW + "Hi - an important field is still empty" TIMEOUT 1
						llSave = .F.			
					ENDIF 
				ENDIF
			ENDFOR
			
			IF llSave
				INSERT INTO tblChess VALUES (ThisForm.txtDate.Value, ThisForm.txtCity.Value, ThisForm.txtWPName.Value, ThisForm.txtBPName.Value, ThisForm.edtMoves.Value)
				
				ThisForm.Release()

				go_Form.Show()
				
			ENDIF 
		ENDPROC 
ENDDEFINE 

*****

Enjoy

MarK
 
... and a further update. Now you may search for a W or B player or a City + the string/moves

Code:
*!*	PUBLIC go_Form

go_Form = CreateObject ("frmForm")
go_Form.Visible = .T.
go_Form.Show

READ Events

CLOSE ALL
CLEAR ALL

RETURN 

*****

DEFINE CLASS frmForm As Form
	Width = 600
	Height = 360
	MinWidth = This.Width
	MinHeight = This.Height
	AutoCenter = .T.
	ShowTips = .T.
	Themes = .F.
	
	Add Object grdGames as Grid with;
		Top = 66, ;
		Left = 18, ;
		Height = 360 - 120, ;
		Width = 600 - 36, ;
		RowHeight = 60, ;
		AllowRowSizing = .F., ;
		DeleteMark = .F., ;
		Visible = .T., ;
		Anchor = 15, ;
		ReadOnly = .T., ;
		ColumnCount = -1, ;
		RecordSource = "tblChess"
    	
		PROCEDURE grdGames.Init()
			WITH This 
				.Column1.Header1.Caption = "Date"
				.Column1.Header1.FontBold = .T.
				.Column1.Width = 90

				.Column2.Header1.Caption = "City"
				.Column2.Header1.FontBold = .T.
				.Column2.Width = 90

				.Column3.Header1.Caption = "Player White"
				.Column3.Header1.FontBold = .T.
				.Column3.Width = 120

				.Column4.Header1.Caption = "Player Black"
				.Column4.Header1.FontBold = .T.
				.Column4.Width = 120
			ENDWITH 

			With This.Column5
				.Header1.Caption = "Moves"
				.Header1.FontBold = .T.
				.Width = This.Parent.Width - 456
				.NewObject("edtChessMoves","EditBox")
				.CurrentControl = "edtChessMoves"
				.edtChessMoves.Visible = .T.
				.Sparse = .F.
			ENDWITH    	
		ENDPROC 
		
	ADD OBJECT lblSearch as LABEL WITH ;
		Top = 12, Left = 18, FontBold = .T., FontSize = 10, AutoSize = .T., ;
		Caption = "City or Player  ...  Moves" + SPACE(48) + " ... up to move"
		
	ADD OBJECT txtCityName as Textbox WITH ;
		Top = 36, Left = 18, Width = 96, Format = "!", SpecialEffect = 0

	ADD OBJECT txtSearch as Textbox WITH ;
		Top = 36, Left = 120, Width = 294, Format = "!", SpecialEffect = 0

	ADD OBJECT txtMove as Textbox WITH ;
		Top = 36, Left = 420, Width = 36, Format = "999", SpecialEffect = 0

	ADD OBJECT cmdSearch As CommandButton WITH;
		Width = 60, Height = 24, Left = 18, Top = 324, Anchor = 6, Caption = "Search", ToolTipText = "Right click to reset filter"
		
		PROCEDURE cmdSearch.RightClick()
			WITH ThisForm
				.txtCityName.Value = ""
				.txtSearch.Value = ""
				.txtMove.Value = ""
				
			ENDWITH 
			
			SELECT tblChess
			
			WITH ThisForm.grdGames
				.ColumnCount = -1
				.RecordSource = "tblChess"
				.Init()

			ENDWITH     	

		ENDPROC 

		PROCEDURE cmdSearch.Click()
			LOCAL lcString2Search, lcMove, lcCityName
				
			lcCityName = ALLTRIM(ThisForm.txtCityName.Value)
			lcString2Search = " " + ALLTRIM(ThisForm.txtSearch.Value)
			lcMove = ALLTRIM(ThisForm.txtMove.Value)
			
			IF EMPTY(lcString2Search)
				lcString2Search = " 1."
			
			ENDIF 

			SELECT dDate, cCity, cWhite, cBlack, SUBSTR(mMoves, ATC(lcString2Search, mMoves, 1), IIF(EMPTY(lcMove), 480, AT(lcMove, mMoves, 1) - ATC(lcString2Search, mMoves, 1))) ;
						FROM tblChess ;
						WHERE ;
							IIF(EMPTY(lcCityName) , .T. , ;
								(ATC(lcCityName, cCity) !=  0 OR ;
								ATC(lcCityName, cWhite) !=  0 OR ;
								ATC(lcCityName, cBlack ) !=  0)) ;
						AND ATC(lcString2Search, mMoves, 1) # 0 ;
						INTO CURSOR csrFGames
				
				WITH ThisForm.grdGames
					.ColumnCount = -1
					.RecordSource = "csrFGames"
					.Init()

				ENDWITH     	
				
			LOCATE
			 
			ThisForm.Refresh()
		ENDPROC

	ADD OBJECT cmdExit As CommandButton WITH;
		Width = 60, Height = 24, Left = 522, Top = 324, Anchor = 12, Caption = "Exit", BackColor = RGB(0, 240, 0)

		PROCEDURE cmdExit.Click()
			CLEAR Events
			ThisForm.Release
		ENDPROC

	ADD OBJECT cmdNew As CommandButton WITH;
		Width = 60, Height = 24, Left = 84, Top = 324, Anchor = 6, Caption = "New", BackColor = RGB(0, 240, 240)
		
		PROCEDURE cmdNew.Click()
			go_FormAdd = CreateObject ("frmAdd")
			go_FormAdd.Visible = .T.
			go_FormAdd.Show
		ENDPROC 
		
	ADD OBJECT cmdEdit as CommandButton WITH ;
		Width = 60, Height = 24, Left = 150, Top = 324, Anchor = 6, Caption = "Edit", Name = "cmdEdit"
		
		PROCEDURE cmdEdit.Click()
			IF ALIAS() = "TBLCHESS"
				IF This.Caption = "Edit"
					ThisForm.grdGames.ReadOnly = .F.
					This.Caption = "Save"
					
					FOR i = 1 TO ThisForm.ControlCount
						IF Thisform.Controls(i).BaseClass = "Commandbutton"
							IF ThisForm.Controls(i).Name = "CMDEDIT"
								ThisForm.Controls(i).Enabled = .T.
							ELSE 
								ThisForm.Controls(i).Enabled = .F.

							ENDIF 
						ENDIF
					ENDFOR

				ELSE 
					ThisForm.grdGames.ReadOnly = .T.
					This.Caption = "Edit"

					FOR i = 1 TO ThisForm.ControlCount
						IF Thisform.Controls(i).BaseClass = "Commandbutton"
								ThisForm.Controls(i).Enabled = .T.

						ENDIF
					ENDFOR
				ENDIF
			ELSE
				= MESSAGEBOX("You have to reset the filter before being able to change data.", 64 , "Changing data", 3000)
			ENDIF 
		ENDPROC 
			
	PROCEDURE Resize()
		WITH This.grdGames
			.Column5.Width = MAX(.Width - (.Column1.Width + .Column2.Width + .Column3.Width + .Column4.Width) - 36, 210)

		ENDWITH 
	ENDPROC 
	
	PROCEDURE Destroy()
		CLEAR Events
		ThisForm.Release
	ENDPROC
    
	PROCEDURE Load()
	
		IF !FILE("tblChess.dbf")
		
			Create Table tblChess (dDate D, cCity C(20), cWhite C(30), cBlack C(30), mMoves M)
			
			INSERT INTO tblChess VALUES ( {^2018/09/03}, "Budapest", "Dame" ,"Turm", " 1.d4 Nf6 2.Nc3 d5 3.f3 e6 4.Bg5 Be7 5.e3 c5 6.Bb5+ Nc6 7.f4 Bd7 8.Nf3 cxd4 9.exd4 h6" + ;
																							" 10.Bh4 Ne4 11.Bxe7 Qxe7 12.O-O Nxc3 13.bxc3 O-O 14.c4 dxc4 15.Bxc4 Na5 16.Bd3 Rac8" + ;
																							" 17.Qe1 b6 18.Ne5 Qd6 19.Rd1 Bc6 20.Kh1 f5 21.c4 Ba8 22.Qg3 Nc6 23.c5 bxc5 24.dxc5 Qc7 25.Bc4 Nxe5" + ; 
																							" 26.Bxe6+ Nf7 27.Rd7 Qc6 28.Qg6 Kh8 29.Rxa7 Qxg2+ 30.Qxg2 Bxg2+ 31.Kxg2 Nd8 32.Bxc8")
			
			INSERT INTO tblChess VALUES ( {^2018/06/18}, "Budapest", "Läufer", "Turm", " 1.Nc3 d5 2.d4 Nf6 3.f3 e6 4.Bg5 Be7 5.e3 O-O 6.Nce2 c5 7.c3 b6 8.Ng3 Bb7 9.Bd3 Nbd7" + ;
																							" 10.f4 h6 11.Bxf6 Nxf6 12.Qf3 cxd4 13.exd4 Qc7 14.Nh3 a5 15.O-O Ba6 16.Bxa6 Rxa6" + ;
																							" 17.Rae1 b5 18.Re3 Rc6 19.Rfe1 Bd6 20.Ne2 Ne4 21.Nf2 Nd2 22.Qg4 f5 23.Qg6 Bxf4 24.Nxf4 e5 25.Nxd5 Rxg6" + ;
																							" 26.Nxc7 f4 27.Rd3 e4 28.Rxd2 e3 29.Rde2")
		
		ELSE
		
			USE tblChess
		
		ENDIF 
		
		LOCATE 
		
	ENDPROC

ENDDEFINE

*****

DEFINE CLASS frmAdd as Form 
	Width = 480
	Height = 240
	MinWidth = This.Width
	MaxWidth = This.Width
	MinHeight = This.Height
	MaxHeight = This.Height
	WindowType = 1
	AutoCenter = .T.
	Themes = .F.
	

	ADD OBJECT lblDate as Label WITH ;
		Top = 24, Left = 12, Caption = "Date"
		
	ADD OBJECT lblCity as Label WITH ;
		Top = 24, Left = 102, Caption = "City"

	ADD OBJECT lblWPName as Label WITH ;
		Top = 24, Left = 228, Caption = "WP Name"

	ADD OBJECT lblBPName as Label WITH ;
		Top = 24, Left = 354, Caption = "BP Name"

	ADD OBJECT lblMoves as Label WITH ;
		Top = 84, Left = 12, Caption = "Moves"

	ADD OBJECT txtDate as TextBox WITH ;
		Top = 48, Left = 12, Width = 78, Value = {}
		
	ADD OBJECT txtCity as TextBox WITH ;
		Top = 48, Left = 96, Width = 120, Value = ""
	
	ADD OBJECT txtWPName as TextBox WITH ;
		Top = 48, Left = 222, Width = 120, Value = ""

	ADD OBJECT txtBPName as TextBox WITH ;
		Top = 48, Left = 348, Width = 120, Value = ""

	ADD OBJECT edtMoves as EditBox WITH ;
		Top = 102, Left = 12, Width = 456, Value = ""
	
	ADD OBJECT cmdSave as CommandButton WITH ;
		Top = 204, Left = 12, Height = 24, BackColor = RGB(0, 240, 240), Caption = "Save"
		
		PROCEDURE cmdSave.Click()
			LOCAL llSave
			
			llSave = .T.
			
			FOR i = 1 TO ThisForm.ControlCount
				IF Thisform.Controls(i).BaseClass = "Textbox" OR ThisForm.Controls(i).BaseClass = "Editbox"
					IF EMPTY(ThisForm.Controls(i).Value)
						WAIT WINDOW + "Hi - an important field is still empty" TIMEOUT 1
						llSave = .F.			
					ENDIF 
				ENDIF
			ENDFOR
			
			IF llSave
				INSERT INTO tblChess VALUES (ThisForm.txtDate.Value, ThisForm.txtCity.Value, ThisForm.txtWPName.Value, ThisForm.txtBPName.Value, ThisForm.edtMoves.Value)
				
				ThisForm.Release()

				go_Form.Show()
				
			ENDIF 
		ENDPROC 
ENDDEFINE 

*****

Enjoy

MarK
 
Chriss
Sorry that I answer later (vacation).

I have to agree with you.
When I open the games in pgn-format with an editor (not with a chess-program) it is clear visible text.

And really good is, that I can a variant download for all the games at onces.

as an example I did it for 3 (of 284 games) and it looks like on bottom of this text.

As you stated right the structure of each game is always identical.
The only problem is, when I want to see the games it would be better to see them in one line - so that I can easily see what happens in which move.

That would be in a table which looks like this (just for the first 10 moves by each player here only) other info (Players, Dates etc) could be in a 2nd.table :

1. d4 Nf6 2. Nc3 d5 3. Bg5 Nbd7 4. f3 e6 5. e4 dxe4 6. fxe4 Be7 7. Nf3 O-O 8. e5 Nd5 9. Nxd5 exd5 10. h4 f6.....
1. d4 Nf6 2. Nc3 d5 3. Bg5 Nbd7 4. f3 c5 5. dxc5 e6 6. e4 Qa5 7. Bb5 dxe4 8. Bxf6 gxf6 9. fxe4 Bxc5 10. Qf3 Ke7.....
1. d4 Nf6 2. Nc3 d5 3. Bg5 Nbd7 4. f3 c5 5. dxc5 e6 6. e4 Qa5 7. Qd2 Bxc5 8. exd5 exd5 9. Bxf6 Nxf6 10. Bb5+ Kf8.....

In this case I can see immediately what Black answered (or can answer) in the 4.th move (
This would be much more comfortable, then to have a look on e.g. 282 game-blocks.

My big problem is, that I do not know how to code that.
e.g in the 6.th move the string-length of that move differs between the games.
All what is equal is that every move has the same move-no in all games, and a move is always the difference between the move-nos.

Perhaps there is an idea?

Thanks
Klaus






--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

[Event "HUN-chT2 0203 Maroczy"]
[Site "Hungary"]
[Date "2003.02.02"]
[Round "6"]
[White "Bai, Attila"]
[Black "Demeter, Istvan"]
[Result "1-0"]
[WhiteElo "2242"]
[BlackElo "2190"]
[ECO "D01"]

1. d4 Nf6 2. Nc3 d5 3. Bg5 Nbd7 4. f3 e6 5. e4 dxe4 6. fxe4 Be7 7. Nf3 O-O 8. e5 Nd5 9. Nxd5 exd5 10. h4 f6 11. Bd3 Qe8 12. Bf4 fxe5 13. Bxe5 Nxe5 14. dxe5 Bg4 15. Be2 Bxf3 16. gxf3 Rd8 17. Qd4 c5 18. Qg4 Qf7 19. Rg1 Rde8 20. Bb5 Rd8 21. Ke2 a6 22. Bd3 c4 23. Bf5 Kh8 24. Be6 Qg6 25. Qxg6 hxg6 26. Rxg6 Rde8 1-0

[Event "Oberliga Ost-A 0203"]
[Site "Germany"]
[Date "2003.03.29"]
[Round "10.7"]
[White "Koksch, Guenther"]
[Black "Ahner, Andreas"]
[Result "0-1"]
[WhiteElo "2197"]
[BlackElo "2205"]
[ECO "D01"]

1. d4 Nf6 2. Nc3 d5 3. Bg5 Nbd7 4. f3 c5 5. dxc5 e6 6. e4 Qa5 7. Bb5 dxe4 8. Bxf6 gxf6 9. fxe4 Bxc5 10. Qf3 Ke7 11. Bxd7 Bxd7 12. Nge2 Qc7 13. Nf4 Bc6 14. O-O-O Rad8 15. Nd3 Bd4 16. Ne2 Qa5 17. Rhf1 f5 18. Nxd4 Rxd4 19. Qe3 Rxe4 20. Qg5+ Ke8 21. Nf4 h6 22. Qf6 Rg8 23. Nh5 Re2 24. Ng7+ Rxg7 25. Qxg7 Be4 26. Kb1 Bxc2+ 27. Ka1 Bxd1 28. Rxd1 Re1 29. Qd4 Rxd1+ 30. Qxd1 Qd5 31. Qe2 Qe4 32. Qd2 Qe5 0-1

[Event "Oberliga Ost-B 0203"]
[Site "Germany"]
[Date "2003.03.29"]
[Round "10.1"]
[White "Foetsch, Daniel"]
[Black "Taimanov, Mark E"]
[Result "0-1"]
[WhiteElo "2276"]
[BlackElo "2425"]
[ECO "D01"]

1. d4 Nf6 2. Nc3 d5 3. Bg5 Nbd7 4. f3 c5 5. dxc5 e6 6. e4 Qa5 7. Qd2 Bxc5 8. exd5 exd5 9. Bxf6 Nxf6 10. Bb5+ Kf8 11. Nge2 Be6 12. Nd4 Bb4 13. O-O Rc8 14. Qf4 Bc5 15. Bd3 Qc7 16. Qh4 h6 17. Nce2 g5 18. Qe1 Kg7 19. Kh1 Rhe8 20. Qd2 Bd7 21. c3 Re7 22. Bf5 Rce8 23. Ng3 Bxd4 24. Qxd4 Qe5 25. Bxd7 Qxd4 26. Nf5+ Kh7 27. Nxd4 Nxd7 28. Kg1 Ne5 29. Rfd1 Nc4 30. b3 Ne3 31. Rd3 f5 32. Kf2 f4 33. g3 a6 34. Rg1 Nc2 35. Rd2 Nxd4 36. cxd4 fxg3+ 37. hxg3 Rc8 38. Re1 Rxe1 39. Kxe1 Rc3 40. Kf2 Kg6 41. g4 h5 42. gxh5+ Kxh5 43. Kg2 g4 44. fxg4+ Kxg4 45. Rf2 Rg3+ 46. Kh2 Rd3 47. Rf7 Rxd4 48. Rxb7 Rd2+ 49. Kg1 Rxa2 50. Rf7 Rb2 51. Kf1 Rxb3 52. Ke2 a5 53. Rd7 Rb5 54. Kd3 Kf5 55. Re7 Rb4 56. Re8 a4 57. Kc3 Rc4+ 58. Kd3 Re4 59. Rf8+ Ke5 60. Re8+ Kd6 61. Rd8+ Kc6 62. Kc3 Rc4+ 63. Kd3 Rh4 64. Kc3 a3 65. Ra8 Rh3+ 66. Kd4 Kb5 67. Kxd5 Kb4 68. Kd4 Kb3 69. Rb8+ Kc2 70. Ra8 Kb2 0-1

Peace worldwide - it starts here...
 
Mark, your program works well. A good idea to gather/ show and present information via memo-fields.
A lot of coding work. (congratulation)
However as you can see above, there is still one problem remaining for me (see answer to Chriss)- which is the visibility of moves line by line - see example there.

Greetings
Klaus


Peace worldwide - it starts here...
 
Klaus (german12) said:
The only problem is, when I want to see the games it would be better to see them in one line - so that I can easily see what happens in which move.

The idea still is to extract the moves from the text into normalized data and then you can create a record for a game from that, there is the pivot table wizard, for example (menu Wizards-Pivot table), the basis still is normalized data, ie a record per move.

As I said above the normalized form is always better to do any statistics or other processing. But you're not stuck at just having the normalized form with moves in a column instead of a row, you can always pivot that or make any other transformation of the data you have into whatever form you want to view. The way you want to view data should still never determine how you want to store it.

You could create an excel sheet with automation and feed in the moves into an excel row, one by one in a scan loop, or show the pivot result in a grid and format the differences bold. But start with extracting the moves into a structure like this:

GameTable: Details (ID, whiteplayer, blackplayer, date, event, etc)
Moves ID, GameID, moveno, playernumber (1=white, 2=black), move

Chriss
 
Hi Klaus,

The only problem is, when I want to see the games it would be better to see them in one line - so that I can easily see what happens in which move.

Chris gave you quite a few hints.

But with a little bit of additional code I think I was able to sketch a picture of what you wish (see below). You may of course adapt it to your needs.

Code:
*!*	PUBLIC go_Form

go_Form = CreateObject ("frmForm")
go_Form.Visible = .T.
go_Form.Show

READ Events

CLOSE ALL
CLEAR ALL

RETURN 

*****

DEFINE CLASS frmForm As Form
	Width = 600
	Height = 360
	MinWidth = This.Width
	MinHeight = This.Height
	AutoCenter = .T.
	ShowTips = .T.
	Themes = .F.
	
	Add Object grdGames as Grid with;
		Top = 66, ;
		Left = 18, ;
		Height = 360 - 120, ;
		Width = 600 - 36, ;
		RowHeight = 60, ;
		AllowRowSizing = .F., ;
		DeleteMark = .F., ;
		Visible = .T., ;
		Anchor = 15, ;
		ReadOnly = .T., ;
		ColumnCount = -1, ;
		RecordSource = "tblChess"
    	
		PROCEDURE grdGames.Init()
			WITH This 
				.Column1.Header1.Caption = "Date"
				.Column1.Header1.FontBold = .T.
				.Column1.Width = 90

				.Column2.Header1.Caption = "City"
				.Column2.Header1.FontBold = .T.
				.Column2.Width = 90

				.Column3.Header1.Caption = "Player White"
				.Column3.Header1.FontBold = .T.
				.Column3.Width = 126

				.Column4.Header1.Caption = "Player Black"
				.Column4.Header1.FontBold = .T.
				.Column4.Width = 126
			ENDWITH 

			With This.Column5
				.Header1.Caption = "Moves"
				.Header1.FontBold = .T.
				.Width = This.Parent.Width - 432 - 36
				.NewObject("edtChessMoves","EditBox")
				.CurrentControl = "edtChessMoves"
				.edtChessMoves.Visible = .T.
				.Sparse = .F.
			ENDWITH    	
		ENDPROC 
		
	ADD OBJECT lblSearch as LABEL WITH ;
		Top = 12, Left = 18, FontBold = .T., FontSize = 10, AutoSize = .T., ;
		Caption = "City or Player" + SPACE(6) + "...  Moves" + SPACE(45) + " ... up to move"
		
	ADD OBJECT txtCityName as Textbox WITH ;
		Top = 36, Left = 18, Width = 96, Format = "!", SpecialEffect = 0

	ADD OBJECT txtSearch as Textbox WITH ;
		Top = 36, Left = 120, Width = 294, Format = "!", SpecialEffect = 0

	ADD OBJECT txtMove as Textbox WITH ;
		Top = 36, Left = 420, Width = 36, Format = "9", InputMask = "X9X", SpecialEffect = 0, ToolTipText = "Please enter value as 99."
		
	ADD OBJECT cmdSearch As CommandButton WITH;
		Width = 60, Height = 24, Left = 18, Top = 324, Anchor = 6, Caption = "Search", ToolTipText = "Right click to reset filter"
		
		PROCEDURE cmdSearch.RightClick()
			WITH ThisForm
				.txtCityName.Value = ""
				.txtSearch.Value = ""
				.txtMove.Value = ""
				
			ENDWITH 
			
			SELECT tblChess
			
			WITH ThisForm.grdGames
				.ColumnCount = -1
				.RecordSource = "tblChess"
				.Init()

			ENDWITH     	
		ENDPROC 

		PROCEDURE cmdSearch.Click()
			LOCAL lcString2Search, lcMove, lcCityName
				
			lcCityName = ALLTRIM(ThisForm.txtCityName.Value)
			lcString2Search = " " + ALLTRIM(ThisForm.txtSearch.Value)
			lcMove = ALLTRIM(ThisForm.txtMove.Value)
			
			IF BETWEEN(VAL(SUBSTR(lcMove, 1, 2)), 5 , 75)
				lcMove = TRANSFORM(VAL(SUBSTR(lcMove, 1, 2))) + "."

			ELSE
				ThisForm.txtMove.Value = ""
				
				lcMove = ""
			
			ENDIF
			
			IF EMPTY(lcString2Search)
				lcString2Search = " 1."
			
			ENDIF 

			SELECT dDate, cCity, cWhite, cBlack, SUBSTR(mMoves, ATC(lcString2Search, mMoves, 1), IIF(EMPTY(lcMove), 600, AT(lcMove, mMoves, 1) - ATC(lcString2Search, mMoves, 1))) as cMoves ;
						FROM tblChess ;
						WHERE ;
							IIF(EMPTY(lcCityName) , .T. , ;
								(ATC(lcCityName, cCity) !=  0 OR ;
								ATC(lcCityName, cWhite) !=  0 OR ;
								ATC(lcCityName, cBlack ) !=  0)) ;
						AND ATC(lcString2Search, mMoves, 1) # 0 ;
						INTO CURSOR csrFGames
				
				WITH ThisForm.grdGames
					.ColumnCount = -1
					.RecordSource = "csrFGames"
					.Init()

				ENDWITH     	
				
			LOCATE
			 
			ThisForm.Refresh()
		ENDPROC

	ADD OBJECT cmdExit As CommandButton WITH;
		Width = 60, Height = 24, Left = 522, Top = 324, Anchor = 12, Caption = "Exit", BackColor = RGB(0, 240, 0)

		PROCEDURE cmdExit.Click()
			CLEAR Events
			ThisForm.Release
		ENDPROC

	ADD OBJECT cmdNew As CommandButton WITH;
		Width = 60, Height = 24, Left = 84, Top = 324, Anchor = 6, Caption = "New", BackColor = RGB(0, 240, 240)
		
		PROCEDURE cmdNew.Click()
			go_FormAdd = CreateObject ("frmAdd")
			go_FormAdd.Visible = .T.
			go_FormAdd.Show
		ENDPROC 
		
	ADD OBJECT cmdEdit as CommandButton WITH ;
		Width = 60, Height = 24, Left = 150, Top = 324, Anchor = 6, Caption = "Edit", Name = "cmdEdit"
		
		PROCEDURE cmdEdit.Click()
			IF ALIAS() = "TBLCHESS"
				IF This.Caption = "Edit"
					ThisForm.grdGames.ReadOnly = .F.
					This.Caption = "Save"
					
					FOR i = 1 TO ThisForm.ControlCount
						IF Thisform.Controls(i).BaseClass = "Commandbutton"
							IF ThisForm.Controls(i).Name = "CMDEDIT"
								ThisForm.Controls(i).Enabled = .T.
							ELSE 
								ThisForm.Controls(i).Enabled = .F.

							ENDIF 
						ENDIF
					ENDFOR

				ELSE 
					ThisForm.grdGames.ReadOnly = .T.
					This.Caption = "Edit"

					FOR i = 1 TO ThisForm.ControlCount
						IF Thisform.Controls(i).BaseClass = "Commandbutton"
								ThisForm.Controls(i).Enabled = .T.

						ENDIF
					ENDFOR
				ENDIF
			ELSE
				= MESSAGEBOX("You have to reset the filter before being able to change data.", 64 , "Changing data", 3000)
			ENDIF 
		ENDPROC 

	ADD OBJECT cmdLBL as CommandButton WITH ;
		Width = 90, Height = 24, Left = 216, Top = 324, Anchor = 6, Caption = "Line By Line"
		
		PROCEDURE cmdLBL.Click()
			IF ALIAS() = "CSRFGAMES"
				go_FormLBL = CreateObject ("frmLiByLi")
				go_FormLBL.Visible = .T.
				go_FormLBL.Show
			ENDIF 
		ENDPROC 
				
			
	PROCEDURE Resize()
		WITH This.grdGames
			.Column5.Width = MAX(.Width - (.Column1.Width + .Column2.Width + .Column3.Width + .Column4.Width) - 36, 210)

		ENDWITH 
	ENDPROC 
	
	PROCEDURE Destroy()
		CLEAR Events
		ThisForm.Release
	ENDPROC
    
	PROCEDURE Load()
	
		IF !FILE("tblChess.dbf")
		
			Create Table tblChess (dDate D, cCity C(20), cWhite C(30), cBlack C(30), mMoves M)
			
			INSERT INTO tblChess VALUES ( {^2018/09/03}, "Budapest", "Dame" ,"Turm", " 1.d4 Nf6 2.Nc3 d5 3.f3 e6 4.Bg5 Be7 5.e3 c5 6.Bb5+ Nc6 7.f4 Bd7 8.Nf3 cxd4 9.exd4 h6" + ;
																							" 10.Bh4 Ne4 11.Bxe7 Qxe7 12.O-O Nxc3 13.bxc3 O-O 14.c4 dxc4 15.Bxc4 Na5 16.Bd3 Rac8" + ;
																							" 17.Qe1 b6 18.Ne5 Qd6 19.Rd1 Bc6 20.Kh1 f5 21.c4 Ba8 22.Qg3 Nc6 23.c5 bxc5 24.dxc5 Qc7 25.Bc4 Nxe5" + ; 
																							" 26.Bxe6+ Nf7 27.Rd7 Qc6 28.Qg6 Kh8 29.Rxa7 Qxg2+ 30.Qxg2 Bxg2+ 31.Kxg2 Nd8 32.Bxc8")
			
			INSERT INTO tblChess VALUES ( {^2018/06/18}, "Budapest", "Läufer", "Turm", " 1.Nc3 d5 2.d4 Nf6 3.f3 e6 4.Bg5 Be7 5.e3 O-O 6.Nce2 c5 7.c3 b6 8.Ng3 Bb7 9.Bd3 Nbd7" + ;
																							" 10.f4 h6 11.Bxf6 Nxf6 12.Qf3 cxd4 13.exd4 Qc7 14.Nh3 a5 15.O-O Ba6 16.Bxa6 Rxa6" + ;
																							" 17.Rae1 b5 18.Re3 Rc6 19.Rfe1 Bd6 20.Ne2 Ne4 21.Nf2 Nd2 22.Qg4 f5 23.Qg6 Bxf4 24.Nxf4 e5 25.Nxd5 Rxg6" + ;
																							" 26.Nxc7 f4 27.Rd3 e4 28.Rxd2 e3 29.Rde2")
		
		ELSE
		
			USE tblChess
		
		ENDIF 
		
		LOCATE 
		
	ENDPROC

ENDDEFINE

*****

DEFINE CLASS frmAdd as Form 
	Width = 480
	Height = 240
	MinWidth = This.Width
	MaxWidth = This.Width
	MinHeight = This.Height
	MaxHeight = This.Height
	WindowType = 1
	Caption = "Add Games"
	AutoCenter = .T.
	Themes = .F.
	

	ADD OBJECT lblDate as Label WITH ;
		Top = 24, Left = 12, Caption = "Date"
		
	ADD OBJECT lblCity as Label WITH ;
		Top = 24, Left = 102, Caption = "City"

	ADD OBJECT lblWPName as Label WITH ;
		Top = 24, Left = 228, Caption = "WP Name"

	ADD OBJECT lblBPName as Label WITH ;
		Top = 24, Left = 354, Caption = "BP Name"

	ADD OBJECT lblMoves as Label WITH ;
		Top = 84, Left = 12, Caption = "Moves"

	ADD OBJECT txtDate as TextBox WITH ;
		Top = 48, Left = 12, Width = 78, Value = {}
		
	ADD OBJECT txtCity as TextBox WITH ;
		Top = 48, Left = 96, Width = 120, Value = ""
	
	ADD OBJECT txtWPName as TextBox WITH ;
		Top = 48, Left = 222, Width = 120, Value = ""

	ADD OBJECT txtBPName as TextBox WITH ;
		Top = 48, Left = 348, Width = 120, Value = ""

	ADD OBJECT edtMoves as EditBox WITH ;
		Top = 102, Left = 12, Width = 456, Value = "" 
	
	ADD OBJECT cmdSave as CommandButton WITH ;
		Top = 204, Left = 12, Height = 24, BackColor = RGB(0, 240, 240), Caption = "Save"
		
		PROCEDURE cmdSave.Click()
			LOCAL llSave
			
			llSave = .T.
			
			FOR i = 1 TO ThisForm.ControlCount
				IF Thisform.Controls(i).BaseClass = "Textbox" OR ThisForm.Controls(i).BaseClass = "Editbox"
					IF EMPTY(ThisForm.Controls(i).Value)
						WAIT WINDOW + "Hi - an important field is still empty" TIMEOUT 1
						llSave = .F.			
					ENDIF 
				ENDIF
			ENDFOR
			
			IF llSave
				INSERT INTO tblChess VALUES (ThisForm.txtDate.Value, ThisForm.txtCity.Value, ThisForm.txtWPName.Value, ThisForm.txtBPName.Value, ThisForm.edtMoves.Value)
				
				ThisForm.Release()

				go_Form.Show()
				
			ENDIF 
		ENDPROC 
ENDDEFINE 

*****

[highlight #73D216]DEFINE CLASS frmLiByLi as Form 
	DIMENSION laMoves[1]
	
	Width = 900
	Height = 480
	MinWidth = This.Width
	MinHeight = This.Height
	MinButton = .F.
	MaxButton = .F.
	WindowType = 1
	Caption = "Line By Line"
	AutoCenter = .T.
	Themes = .F.
	
	ADD OBJECT grdMoves as Grid WITH ;
		Top = 12, ;
		Left = 12, ;
		Height = 480 - 24, ;
		Width = 900 - 24, ;
		Anchor = 15, ;
		ReadOnly = .T., ;
		ColumnCount = -1, ;
		RecordSource = "csrMoves"
    	
		PROCEDURE grdMoves.Init()
			LOCAL liFirstMove
			
			liFirstMove = VAL(SUBSTR(csrMoves.cM01, AT(".", csrMoves.cM01, 1) - 2, 2)) - 1
			
			FOR i = 1 TO This.ColumnCount
				WITH this 
					.Columns(i).Header1.Caption = "Move" + ALLTRIM(STR(liFirstMove + i))
					.Columns(i).Header1.FontBold = .T.
					.Columns(i).Width = 90

				ENDWITH 
			ENDFOR 
			
			FOR i = This.ColumnCount TO ALEN(ThisForm.laMoves) STEP -1
				This.DeleteColumn(i)
			ENDFOR 
		ENDPROC 
		
	PROCEDURE Load()
		LOCAL liDots
		
		CREATE CURSOR csrMoves (cM01 C(20), cM02 C(20), cM03 C(20), cM04 C(20), cM05 C(20), ;
								cM06 C(20), cM07 C(20), cM08 C(20), cM09 C(20), cM10 C(20), ;
								cM11 C(20), cM12 C(20), cM13 C(20), cM14 C(20), cM15 C(20), ;
								cM16 C(20), cM17 C(20), cM18 C(20), cM19 C(20), cM20 C(20))
		
		SELECT csrFGames
		
		SCAN
			liDots = OCCURS(".", csrFGames.cMoves)

			IF liDots > 0
			
				DIMENSION ThisForm.laMoves[liDots]
			
				FOR i = 2 to liDots
					ThisForm.laMoves[i - 1] = SUBSTR(csrFGames.cMoves, AT(".", csrFGames.cMoves, i - 1) - 2, AT(".", csrFGames.cMoves, i) - AT(".", csrFGames.cMoves, i - 1))
		
				ENDFOR 
				
				APPEND BLANK IN csrMoves
				Replace IN csrMoves from ARRAY ThisForm.laMoves
			ENDIF 
		ENDSCAN 
		
		SELECT csrMoves

		LOCATE 
		
	ENDPROC 
		
	PROCEDURE Destroy()
		USE IN csrMoves
		SELECT csrFGames		
		ThisForm.Release

	ENDPROC
ENDDEFINE[/highlight] 

*****

Enjoy

MarK

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top