Columbo 1 Posted November 28, 2023 (edited) I’m trying to learn Delphi 7 and at the moment I am trying to figure out how to access and retrieve data from a SQLite database. I found a short pdf tutorial and I followed the instructions but it is flagging a Undeclared identifier: ‘ShowSelectResults’. I have gone over the code several times comparing it to the code in the pdf tutorial and I can’t find anything different. The line that is highlighted in Delphi is ShowSelectResults(); I assumed that it might be something wrong in the procedure TDatabaseTutorial.ShowSelectResults(); but if it is I can’t figure out where, unless there is an error in the tutorial. Can anyone give me a hint as to what is causing this? Here is my code: unit DatabaseTutorial_u; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DBXpress, FMTBcd, DB, SqlExpr, StdCtrls; type TfrmDatabaseTutorial = class(TForm) btnConnect: TButton; btnExecute: TButton; SQLConnection1: TSQLConnection; memOutput: TMemo; SQLQuery1: TSQLQuery; procedure btnConnectClick(Sender: TObject); procedure btnExecuteClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var frmDatabaseTutorial: TfrmDatabaseTutorial; implementation {$R *.dfm} procedure TfrmDatabaseTutorial.btnConnectClick(Sender: TObject); begin SQLConnection1.Params.Add('D:\Borland Delphi\Test Projects\Database Tutorial\Data\Dat2.sqlite'); try //Establish the connection SQLConnection1.Connected := true; btnExecute.Enabled := true; memOutput.Text := 'Connection Established!'; except on E: EDatabaseError Do ShowMessage('Exception raised with message' + E.Message); end; end; procedure TfrmDatabaseTutorial.btnExecuteClick(Sender: TObject); var query : String; begin memOutput.ClearSelection; //Set up a Query query := 'SELECT * FROM hline1;'; try //Assign the query to the object SQLQuery1 SQLQuery1.SQL.Text := query; SQLQuery1.Active := true; except on E: Exception Do memOutput.Text := 'Exception raised with message:' + E.Message; end; //Show the result of the query in memOutput ShowSelectResults(); end; procedure TDatabaseTutorial.ShowSelectResults(); var headline : TStringList; i : integer; currentField: Tfield; currentLine : string; begin If not SQLQuery1.IsEmpty Then begin SQLQuery1.First; headline := TStringList.Create; try SQLQuery1.GetFieldNames(headline); While not SQLQuery1.Eof Do begin currentLine := "; for i := 0 to hline1.Count -1 Do begin currentField := SQLQuery1.FieldByName(headline(i)); currentLine := currentLine + ' ' + currentField.AsString; end; memOutput.Lines.Add(currentLine); SQLQuery1.Next; end; headline.Free; end; end; end. Edited November 28, 2023 by Columbo typo Share this post Link to post
edbored 0 Posted November 28, 2023 You have to add ShowSelectedResults to the class definition. Simplest is to throw it in the public declaration section public { Public declarations } procedure ShowSelectedResults; It's likely you need to change hline1 to headline below too: for i := 0 to hline1.Count -1 Do Share this post Link to post
Columbo 1 Posted November 28, 2023 I made the changes that you suggested but it still flags the same error, Undeclared identifier: ‘ShowSelectResults’. Here is the change that I made: unit DatabaseTutorial_u; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DBXpress, FMTBcd, DB, SqlExpr, StdCtrls; type TfrmDatabaseTutorial = class(TForm) btnConnect: TButton; btnExecute: TButton; SQLConnection1: TSQLConnection; memOutput: TMemo; SQLQuery1: TSQLQuery; procedure btnConnectClick(Sender: TObject); procedure btnExecuteClick(Sender: TObject); private { Private declarations } public { Public declarations } procedure ShowSelectedResults; end; I also changed hline1 to headline as you suggested. Share this post Link to post
Serge_G 87 Posted November 28, 2023 4 hours ago, Columbo said: I’m trying to learn Delphi 7 and at the moment I am trying to figure out how to access and retrieve data from a SQLite database. Can I make two suggestions? First one, if you absolutely want to keep Delphi 7 use, try to install ZEOSLIB (aka ZEOSDBO) and use this data access component suite instead of DBExpress Second, try Delphi 11 community, with his Firedac components, Share this post Link to post
Columbo 1 Posted November 28, 2023 (edited) Thanks Serge_G. Delphi 7 actually belongs to my son so I am using his computer to see if I can learn Delphi before making such a purchase. I looked at Delphi 11 Community and downloaded it but it won't install. I am still using Windows 7 Professional on my computer, (I'm not a fan of Windows 10 or 11). I am pretty sure that the Delphi web site said that Delphi 11 was compatible with Windows 7 but it won't install. When I enter the Serial number that they emailed to me it says that the Serial number is invalid. I tried 3 times uninstalling and reinstalling but continue to have the same problem. One thing that I don't understand is that at one point a dialog came up saying that I was using Windows 6.1 which I have never heard of. I gave up on trying to install it. I will Google ZEOSDBO and try that as you kindly suggested. Since I posted this I have downloaded ZeosLib but any instructions that I have found about installing and using it seems to always refer to Firebird. I want to use it for SQLite. Edited November 28, 2023 by Columbo Share this post Link to post
Tom Chamberlain 47 Posted November 28, 2023 The problem is the procedure is declared to a class that does not exist: Quote procedure TDatabaseTutorial.ShowSelectResults(); Should be: procedure TfrmDatabaseTutorial.ShowSelectResults(); Share this post Link to post
Columbo 1 Posted November 28, 2023 Thanks Tom, I replaced the line procedure TDatabaseTutorial.ShowSelectResults(); with procedure TfrmDatabaseTutorial.ShowSelectResults(); but error still exists. Share this post Link to post
ioan 45 Posted November 28, 2023 You need to make the names match: procedure TfrmDatabaseTutorial.ShowSelectedResults(); Selected not Select Share this post Link to post
Columbo 1 Posted November 28, 2023 (edited) 48 minutes ago, ioan said: You need to make the names match: procedure TfrmDatabaseTutorial.ShowSelectedResults(); Selected not Select I tried that but it now flags an error at private { Private declarations } public { Public declarations } procedure TfrmDatabaseTutorial.ShowSelectedResults(); end; The actual procedure is: procedure TDatabaseTutorial.ShowSelectResults(); If I change the actual procedure to match the change in the Public delarations using 'ShowSelectedResults' I still get the error in the Public declarations. Edited November 28, 2023 by Columbo Share this post Link to post
Gary 18 Posted November 28, 2023 It's easy to get confused at first. What ioan is saying the procedure "ShowSelectResults" or "ShowSelectedResults" you decide has to match. However, in the implementation section at the top inside your class TfrmDatabaseTutorial in the public section you do not use the class name just public { Public declarations } procedure ShowSelectedResults; Down below in the implementation section where you write your code you need the class name then a period then the procedure with exact spelling procedure TDatabaseTutorial.ShowSelectedResults(); begin //code end; If you get rid of the class name from the implementation section and just leave "procedure ShowSelectedResults;" then with your cursor on the line press ctrl + shift + c Delphi will create the implementation section for you and you don't have to worry about spelling. Share this post Link to post
Gary 18 Posted November 28, 2023 look at the event handlers Delphi created btnConnectClick(Sender: TObject) and btnExecuteClick(Sender: TObject) to see this. You can use ctrl + shift + up or down arrow to toggle between interface and implementation sections. Also it doesn't hurt but the () are not needed if you have no parameters. Share this post Link to post
Columbo 1 Posted November 28, 2023 Thanks Gary. In the declaration section I put the following code: private { Private declarations } public { Public declarations } procedure TfrmDatabaseTutorial.ShowSelectResults; end; and in the implementation I put the following code: procedure TfrmDatabaseTutorial.ShowSelectResults; var headline : TStringList; ... but I am still getting the error flagged on the line in the Public declarations saying 'Undeclared Identifier: 'TfrmDatabaseTutorial'. Share this post Link to post
Remy Lebeau 1403 Posted November 28, 2023 (edited) 16 minutes ago, Columbo said: In the declaration section I put the following code: ... and in the implementation I put the following code: ... but I am still getting the error flagged on the line in the Public declarations saying 'Undeclared Identifier: 'TfrmDatabaseTutorial'. REMOVE 'TfrmDatabaseTutorial.' from the DECLARATION! public { Public declarations } procedure ShowSelectResults; // <-- NO TfrmDatabaseTutorial here! end; It belongs only in the IMPLEMENTATION: procedure TfrmDatabaseTutorial.ShowSelectResults; // <-- ONLY here! var headline : TStringList; ... end; Edited November 28, 2023 by Remy Lebeau Share this post Link to post
Gary 18 Posted November 28, 2023 Yes! What Remy said! Your form is your class and defined in the interface section of the file. This is just the description or declaration of the class, you write the code later in the implementation section type TfrmDatabaseTutorial = class(TForm) //<- Class name btnConnect: TButton; btnExecute: TButton; SQLConnection1: TSQLConnection; memOutput: TMemo; SQLQuery1: TSQLQuery; procedure btnConnectClick(Sender: TObject); //<- procedures of your class no need for TfrmDatabaseTutorial procedure btnExecuteClick(Sender: TObject); //<- procedures of your class no need for TfrmDatabaseTutorial private { Private declarations } public { Public declarations } procedure ShowSelectedResults;//<- procedures of your class no need for TfrmDatabaseTutorial end; // <- Definition of your class ends here When you write your code the unit needs to know what class your procedure belongs to since you can have multiple classes, so you need it here: implementation TDatabaseTutorial needs to be here so compiler knows what class the procedure belongs to. Multiple classes can have the same procedure names and often do so you have to distinguish them. procedure TDatabaseTutorial.ShowSelectResults; begin //code end; Share this post Link to post
Columbo 1 Posted November 29, 2023 That has got me past the error. Thank you very much guys. I've only been playing with Delphi 7 for 3 days and it is somewhat confusing at times. And now,... on to the next error. 🙂 Trying to assign an empty string to a variable. Thanks to all for your help and patience. Very much appreciated. Share this post Link to post
Gary 18 Posted November 29, 2023 Coding Boot Camp 2022 – Learn to Program (learndelphi.org) This was great for beginners. Delphi must be used in schools in South Africa, many of the sessions were from instructors there and referred often to this book: Dr Kevin R Bond on Delphi-Books.com Share this post Link to post
Columbo 1 Posted November 29, 2023 (edited) Thanks Gary. Actually I did watch Gerhard's videos. What I like about his videos is that he takes his time and explains everything. I found that a lot of videos that I had looked at previously, the teacher went too fast for a beginner to keep up. They know what they are doing so they have the cursor moving all over the place clicking this and clicking that and I find it difficult to follow. Gerhard is not like that and takes his time. I still have a few of his videos to watch yet but I didn't see any that dealt with databases. I used to program in dBaseIII and Clipper back in 1997 and I wrote a program where you enter someone's name, the day, month and year of their birth and the program would do a printout showing their birthstone, birth flower, astological sign, planet and element, 3 newspaper headlines that appeared on their birthday, the Stanley cup winner for that year, The Greay Cup winner, the Academy Award best Actor and actress, best movie, the U.S President at that time, the Canadian Prime Minister, and the price of a loaf of bread, quart of milk, a dozen eggs, a pound of butter, average price of a home, average price of an automobile and the average price of gas. I wanted to try writing the same program in Delphi so I have to get to know how to manipulate databases in Delphi. I took my .DBF database files and converted them to SQLite so I still have the data for all birth dates from the year 1900 to 1997. I will have to add the data from 1998 to present. A lot of work and research but fun in the end. Besides, I'll be 82 in January so, hopefully, it will help to keep my mind sharp. Thanks again Gary. You have been very helpful. Edited November 29, 2023 by Columbo Share this post Link to post
Columbo 1 Posted November 29, 2023 Thanks, Die Hollander. I have bookmark that web site. Share this post Link to post
Gary 18 Posted November 29, 2023 I started with Lotus Approach and dBase files 🙂 Just wondering, you know while your project is great for learning Delphi you can do the same thing with components and hardly any code? That's what got me interested in Delphi in the beginning. Drop a TDBGrid and TDataSource on the form, connect the Grids DataSource property to the TDataSource, set the DataSource's DataSet property to your Query and when you open the Query it populates the Grid automatically including FielNames as headers. Share this post Link to post
Stano 143 Posted November 29, 2023 Personally, I think it would be easier to use Firebird. I don't even use another one. I also tried SQLite, but quickly dismissed it. 1 Share this post Link to post
Columbo 1 Posted November 30, 2023 5 hours ago, Gary said: I started with Lotus Approach and dBase files 🙂 Interesting that you started with dBase as well. I don't know much about Lotus Approach although I knew of it back in the day. I am assuming that TDBGrid gives you a MS Access style layout? The program that I wrote in Clipper was called "This Day In History" and it did not display anything. It uses 7 databases and once the person's name and birth date is entered it goes directly to the printer and prints out the data for that date in history. I did another program in Purebasic called "Prehistoric Life" and it uses a lot of text fields, a memo field, 2 image boxes and a few buttons. It displays data and pictures on 112 animals and sea creatures that lived in prehistoric times. That might also be a good program to learn Delphi with. I did the same program when I was learning Python. Share this post Link to post
Columbo 1 Posted November 30, 2023 Hi stano, I don't know anything about Firebird but I will look into it. I seen it mentioned a number of times in posts related to FireDAC. Share this post Link to post
Serge_G 87 Posted November 30, 2023 (edited) Agree @Stano Firebird SQL is a very good RDBMS, all my pro GPAO suite use it. SQLite has also some advantages for mono-station programs On 11/28/2023 at 4:58 PM, Columbo said: Since I posted this I have downloaded ZeosLib but any instructions that I have found about installing and using it seems to always refer to Firebird. I want to use it for SQLite. ZeosLib can be used with many database system, not only firebird ones Quote The ZeosLib is a set of database components for MySQL, MariaDB, PostgreSQL, Interbase, Firebird, MS SQL Server, SAP Adaptive Server Enterprise and Adaptive Server Anywhere (previously Sybase), Oracle and SQLite for Delphi You have only to change Zconnection.protocol parameter to sqlite (or sqlite-3). If you find more doc ZEOSDBO+Firebird you can apply all (or at least a good part of) the doc to SQlite as well. Effectively when I wrote (never finished, but on the web) a (French) tutorial about ZEOS components my samples was Firebid ones also Edited November 30, 2023 by Serge_G Share this post Link to post