[SOLVED]index based on unknown field lazarus / 16-Databases ---------------------------------------------------------------------- micoudic · 2013-12-25 19:14 Hello, I just installed a debian 7.3.0 amd-64 and install lazarus. In a new project, I put a TDatasource and TDbf. I connect the datasource to dbf. I setup an existing dbf table. I do nothing more. When I want to make the active table, I get this message:   Code: [Select]index based on unknown field "+" Thanks ---------------------------------------------------------------------- howardpc · 2013-12-25 20:33 This error indicates that your existing dbf file has an expression index that cannot be parsed successfully. My guess is that you may have an index that tries to concatenate two or more field names and the syntax for the expression is not quite right (at least for the Lazarus TDBF implementation - the syntax may work in dbase or other dbf-aware database tools), so when the expression is parsed the "+" in the expression is considered a field name rather than a concatenation operator. You could try making a backup, then deleting the index and indexdefs to see if you get access to the data content. If so, you could then recreate the index(es) you want using Lazarus TDBF routines. ---------------------------------------------------------------------- micoudic · 2013-12-27 08:46 Hello, I'll try what you suggest But curiously, this file was created with Borland tools with Delphi. It should therefore be consistent with the standard? Moreover, with an older version of Lazarus, and TDbf third party component, it worked well ... Thanks ---------------------------------------------------------------------- BigChimp · 2013-12-27 09:00 "Consistent with the standard"? What standard? Clipper? DBaseIV? FoxPro? Some Borland BDE flavour perhaps? As you don't specify what version of Lazarus and FPC you are using (and which one used to work), what DBF format/tableleve, index file format (.mdx? something else) you are using, your complaining is not very useful, TBH. BTW: Lazarus/FPC use the "TDBF third party component".... so yes, there may be regressions in the implementation... or... you may remember things incorrectly. I'm happy to improve the FPC TDBF code in FPC trunk if we find the problem, but I'll need some solid information rather than vague descriptions, sorry. (Hint: why not attach the dbf and a sample project (code only), and provide the info) ---------------------------------------------------------------------- micoudic · 2013-12-28 07:48 - laraus V0.9.30.4 - fpc 2.6.0.9 I am under debian 7.3.0 amd64 The third party component is here http://tdbf.sourceforge.net/ I have nothing other than this: - Ask a TDatasource - Ask a TDbf - Connect the TDataSource to TDbf - Ask a TDBGrid and TDBNavigator and connect to TDatasource - Define an existing dbf table - Try to activate the current table, and it is at this time that the message comes. ---------------------------------------------------------------------- howardpc · 2013-12-28 10:21 Mixing use of two different classes with the same name - a third party TDBF, apparently last updated March 2007, and the Lazarus TDBF (currently maintained) - is basically a flawed decision. Never mind that the classes appear to have similar functionality and probably nearly identical sets of identically-named methods and properties. Whatever their history, they are now independent, and bound to give all sorts of problems if you attempt to use them together. Just one of the sources of incompatibility is that the Lazarus TDBF uses FCL db units which have been designed to be cross-platform. The third party TDBF is based on Windows-only code. ---------------------------------------------------------------------- BigChimp · 2013-12-28 11:42 What howardpc said. I'd suggest using the FPC-supplied TDBF. Additionally, FPC 2.6.2 has several fixes in TDBF; they may fix the situation (or not). FPC trunk has still more fixes. Quote from: bigchimpwhat DBF format/tableleve, index file format (.mdx? something else) you are using Quote from: bigchimpwhy not attach the dbf ---------------------------------------------------------------------- micoudic · 2014-01-04 20:25 Hello, I just installed a new distribution on a blank partition. Here is my setup: My PC moi[~]$ uname -a Linux rbs457 3.2.29-smp #2 SMP Mon Sep 17 13:16:43 CDT 2012 i686 AMD Athlon(tm) 64 Processor 3200+ AuthenticAMD GNU/Linux moi[~]$ cat /etc/slackware-version Slackware 14.0 (32 bits) Lazarus : 1.0.14 date 2013-11-16 FPC 2.6.2 Revision : SVN:43447 i386-linux-gtk 2 I tried a re-testing of TDbf component, with the same result. I looked on the side of the index file and made the following tests: I replaced the character "+" by another to see the result. I did not update components. I'll let you see what happens. http://imageshack.us/a/img845/9145/c9tl.jpg http://imageshack.us/a/img560/8222/4tmt.jpg http://imageshack.us/a/img543/9787/t0yw.jpg http://imageshack.us/a/img849/6422/qima.jpg My dbf file has a composite key ("APAYS" and "A_AKLE") NB: I prepared a dbf file and mdx index, but I do not know how to tie them. I do not know how to display my images ( [img] .... [/ img] does not work ) ---------------------------------------------------------------------- cdbc · 2014-01-04 21:01 Hi That looks like clipper compound indexes Just my 2 cents... Regards Benny ---------------------------------------------------------------------- micoudic · 2014-01-08 13:00 Hi, I made a copy of my file using "dbd32.exe" Borland ( under Windows ). I used this new file with Lazarus, and I no longer have the error when rendering the active table. But trying to display my data in a different order, via a different key, nothing happens (the display remains in the same state). After verification, the index were not copied to the new file. So I re-created multiple indexes, always with the dbd32.exe program Borland. Now Lazarus shows me the same error when I try to activate the table. I think a table generated with Borland product must conform to the standard dBase? ---------------------------------------------------------------------- BigChimp · 2014-01-08 13:12 Il n'y a pas "un" standard dBase. Il y a plusieurs. Voyez par exemple http://sourceforge.net/projects/tdbf/ "TDBF is a native dBASE III+, dBase IV and dBase 2k data access component for Delphi, BCB, Kylix, FreePascal" Pas de Clipper la. Si vous voulez, vous pouvez essayer d'ajouter support pour le format Clipper et ses indices. S'il vous plait, faites un patch contre la version de developpement actuelle de FPC (2.7.1/trunk). (Excusez-moi pour mon pauvre francais) edit: @benny: thanks! ---------------------------------------------------------------------- BigChimp · 2014-01-08 13:15 Quote from: micoudic on January 04, 2014, 09:25:51 pmNB: I prepared a dbf file and mdx index, but I do not know how to tie them. Do you mean you don't know how to upload them? Zip them and add them as an attachment to a post. See Attachments and other options below your message window when writing a new message. ---------------------------------------------------------------------- micoudic · 2014-01-10 21:23 Hi, A big thank you your efforts to write to me in French  (Maybe because my English is very bad ? ) My file was not created in Clipper, but with the BDE Borland. I downloaded TDBf and I'll install it to test. I attach the dbase file with its index file ---------------------------------------------------------------------- BigChimp · 2014-01-11 01:17 Well, I think your English is better than my French Quote from: micoudic on January 10, 2014, 10:23:39 pmMy file was not created in Clipper, but with the BDE Borland. Yes, YES, YES, but which dbase format did BDE create? DBase4, dbaseIII, Clipper, Foxpro, something else? Apparently it's clipper. Quote from: micoudic on January 10, 2014, 10:23:39 pmI downloaded TDBf and I'll install it to test. Don't download Tdbf if you're using Lazarus. It's built in. As Howardpc said, don't mix the various versions. If you're talking about using Tdbf with Delphi, sure, go ahead. ---------------------------------------------------------------------- micoudic · 2014-01-11 20:13 Quote from: BigChimp on January 11, 2014, 02:17:02 amWell, I think your English is better than my French Quote Google Quote from: micoudic on January 10, 2014, 10:23:39 pmMy file was not created in Clipper, but with the BDE Borland. Quote from: BigChimp on January 11, 2014, 02:17:02 amYes, YES, YES, but which dbase format did BDE create? DBase4, dbaseIII, Clipper, Foxpro, something else? Apparently it's clipper. Good question;) I created this file with Delphi5 (there a few years ago ...) but I do not know what format? I searched the net for information on the structure of dBase files, but definitions vary across sites found: ( I attach the header of my file. It seems that this is dBase IV with Memo (X8B Code). My file actually contains Memos. Quote from: micoudic on January 10, 2014, 10:23:39 pmI downloaded TDBf and I'll install it to test. Quote from: BigChimp on January 11, 2014, 02:17:02 amDon't download Tdbf if you're using Lazarus. It's built in. As Howardpc said, don't mix the various versions. If you're talking about using Tdbf with Delphi, sure, go ahead. OK, thanks ---------------------------------------------------------------------- BigChimp · 2014-01-11 20:42 1. Just tried ${fpcdir}\packages\fcl-db\examples\dbftool in trunk/2.7.1/development version of fpc. It cannot deal with the index file: Error reading file 0: Index based on unknown field "+". However, removing the mdx allowed for reading the dbf: Code: [Select]Database tablelevel: 4 Database codepage:   1252 tablelevel 4=>tdbf thinks this is a DBase IV file Code: [Select]*** Opening: D:\Cop\t\Membres.DBF Database tablelevel: 4 Database codepage:   1252 Record 1 Field A_AKLE has value: 10 Field ANOM has value: GILETTE Frank Field AADR1 has value: 42 rue Caban Field AADR2 is          ***NULL*** Field ACPOST has value: 45000 Field AVILLE has value: ORLEANS Field AEMAIL has value: monnom.prenom@monentreprise.fr Field AWEB is          ***NULL*** Field ASTATUS is          ***NULL*** Field ADATRAD is          ***NULL*** Field ANOTES is          ***NULL*** Field APAYS has value: FRANCE Field ADATEMAJ has value: 04/01/2014 Field ADATECREAT has value: 04/01/2014 Record 2 Field A_AKLE has value: 20 Field ANOM has value: LAMACHOIRE Roland Field AADR1 has value: 8 rue des sapins Field AADR2 is          ***NULL*** Field ACPOST has value: 33000 Field AVILLE has value: BORDEAUX Field AEMAIL is          ***NULL*** Field AWEB is          ***NULL*** Field ASTATUS is          ***NULL*** Field ADATRAD is          ***NULL*** Field ANOTES is          ***NULL*** Field APAYS has value: ALLEMAGNE Field ADATEMAJ is          ***NULL*** Field ADATECREAT has value: 04/01/2014 Record 3 Field A_AKLE has value: 30 Field ANOM has value: LEMARCHAND Serge Field AADR1 has value: 16 route departementale Field AADR2 is          ***NULL*** Field ACPOST has value: 03000 Field AVILLE has value: MOULINS Field AEMAIL is          ***NULL*** Field AWEB is          ***NULL*** Field ASTATUS is          ***NULL*** Field ADATRAD is          ***NULL*** Field ANOTES is          ***NULL*** Field APAYS has value: ITALIE Field ADATEMAJ is          ***NULL*** Field ADATECREAT has value: 05/01/2014 Record 4 Field A_AKLE has value: 40 Field ANOM has value: INTOSH Mac Field AADR1 has value: 6 street Elisabeth II Field AADR2 is          ***NULL*** Field ACPOST has value: 53800 Field AVILLE has value: LONDON Field AEMAIL is          ***NULL*** Field AWEB is          ***NULL*** Field ASTATUS is          ***NULL*** Field ADATRAD is          ***NULL*** Field ANOTES is          ***NULL*** Field APAYS has value: ANGLETERRE Field ADATEMAJ is          ***NULL*** Field ADATECREAT has value: 06/01/2014 You could remove the index file and recreate the index using tdbf; see here for details: http://wiki.lazarus.freepascal.org/Lazarus_Tdbf_Tutorial#How_to_add_in dexes_to_a_table ... then you can use Lazarus with the indexes from then on (don't remember by heart what format it uses - but it is quite probably compatible with the BDE in case you want that). 2. You may look into ADS; perhaps that can read the existing index file if you want to keep it: http://wiki.lazarus.freepascal.org/Databases#Advantage_TDataSet_Descen dant (No idea if it can, have never used it myself) ---------------------------------------------------------------------- micoudic · 2014-01-12 10:20 Quote from: BigChimp on January 11, 2014, 09:42:34 pm1. Just tried ${fpcdir}\packages\fcl-db\examples\dbftool in trunk/2.7.1/development version of fpc. It cannot deal with the index file: Error reading file 0: Index based on unknown field "+".his file is a file for testing (reduced to a single index or memo, just for testing) Quote from: BigChimp on January 11, 2014, 09:42:34 pmHowever, removing the mdx allowed for reading the dbf:Yes, I had noticed. But in this case I can't display my data in a different order. I'll do as you say: delete indexes, and then re - create with lazarus. I found a wiki in French http://wiki.freepascal.org/Lazarus_Tdbf_Tutorial/fr. many tanks ---------------------------------------------------------------------- BigChimp · 2014-01-12 10:28 Quote from: micoudic on January 12, 2014, 11:20:57 amQuote from: BigChimp on January 11, 2014, 09:42:34 pm1. Just tried ${fpcdir}\packages\fcl-db\examples\dbftool in trunk/2.7.1/development version of fpc. It cannot deal with the index file: Error reading file 0: Index based on unknown field "+".his file is a file for testing (reduced to a single index or memo, just for testing) That's why I decided to test it for you with FPC trunk in case you had not tested it with fpc trunk (I did understand it's a testing file; those email addresses and street names, as well as surnames, would be very unusual to see in a production database ) Quote from: micoudic on January 12, 2014, 11:20:57 amYes, I had noticed. But in this case I can't display my data in a different order. I'll do as you say: delete indexes, and then re - create with lazarus. I found a wiki in French http://wiki.freepascal.org/Lazarus_Tdbf_Tutorial/fr. many tanks Bonne chance ---------------------------------------------------------------------- micoudic · 2014-01-12 16:18 Is the copy of the file real, but empty of all his datas and I re- created a few registration only. I have not filled all the fields, only a few. After extensive research and testing, I finally found the syntax to create a multiple index.   Code: [Select]Dbf1.AddIndex('KNOMKLE', 'ANOM' + '+AADR1' , [ixCaseInsensitive]);When I visualise the mdx file, I see no difference in syntax. This works because both fields are of the same type. But I want to create an index with the fields "Name" and "A_AKLE" (String and SmallInt). I even can't do the translation of the key A_AKLE in a String field. StrToInt is rejected, and I found nothing else ---------------------------------------------------------------------- BigChimp · 2014-01-13 07:59 1. IIRC, there was a post recently about compound indexes with a solution. Nobody added anything to the wiki as usual, so I did it just now => http://wiki.lazarus.freepascal.org/Lazarus_Tdbf_Tutorial#Index _on_multiple_fields 2. Regarding inttostr, have you looked at the STR function (http://wik i.lazarus.freepascal.org)?/Lazarus_Tdbf_Tutorial#Index.2Ffilter_operat ors.2Ffunctions) 3. I would very much appreciate to see your additions/updates to the French dbf tutorial (and/or the English one).. I'll be happy to translate if needed (to English, that is ) ---------------------------------------------------------------------- micoudic · 2014-01-13 20:04 -I could nothing do with the STR function. -If I complete the name of the "A_AKLE" field with .asString (A_AKLE.AsString), I get an index name "ANOM10", 10 being the contents of the field A_AKLE of the 1st record in my file "Membres.dbf" -If I normally codifies the index, jobtiens the error cited in the title of this thread (Index based on unknown field "+") I'll leave it at that and return to my Delphi. Too bad. NB Code: [Select]Dbf1.AddIndex('KNOMKLE', 'ANOM+' + 'AADR1' , [ixCaseInsensitive]); is identical to Code: [Select]Dbf1.AddIndex('KNOMKLE', 'ANOM' + '+AADR1' , [ixCaseInsensitive]); I tested ---------------------------------------------------------------------- BigChimp · 2014-01-14 06:58 Hope it works for you with Delphi. Don't understand what your last remark about concatenated strings is supposed to mean... ---------------------------------------------------------------------- micoudic · 2014-01-14 08:41 Hi, Quote from: BigChimp on January 14, 2014, 07:58:42 amHope it works for you with Delphi. It works very well (application developed with Delphi5, and subsequent versions, hence my surprise that I can not do operate these indexes with Lazarus.) Quote from: BigChimp on January 14, 2014, 07:58:42 amDon't understand what your last remark about concatenated strings is supposed to mean... It was in connection with my previous thread and for information. I had so much trouble finding this syntax. ---------------------------------------------------------------------- BigChimp · 2014-01-14 16:59 Quote from: micoudic on January 14, 2014, 09:41:02 amIt works very well (application developed with Delphi5, and subsequent versions, hence my surprise that I can not do operate these indexes with Lazarus.) Hmm, I think there is a bug. Need to verify again but put it on the bugtracker as a reminder: http://bugs.freepascal.org/view.php?id=25533 ---------------------------------------------------------------------- micoudic · 2014-01-15 21:05 hello I looked at the sites for which you have provided me the links and I did other tests. Reminder: the "A_AKLE" field is of type SmallInt in the file "Membres.dbf" With this syntax, Code: [Select]DBf1.AddIndex('KNOMKLE', ('ANOM+' + IntToStr(Dbf1A_AKLE)),[]);the compiler sends to me following message: Code: [Select]/home/moi/Desktop/Lazarus_dbf/Test_Tris/Bis/utestdbf.pas (109,58) Error: Incompatible type for arg no. 1: Got "TSmallintField", expected "QWord" and with this syntax Code: [Select]DBf1.AddIndex('KNOMKLE', ('ANOM+' + Dbf1A_AKLE),[]);I get this message: Code: [Select]/home/moi/Desktop/Lazarus_dbf/Test_Tris/Bis/utestdbf.pas (109,37) Error: Operator is not overloaded: "Constant String" + "TSmallintField" === Since I can't create the index with a field of type smallint and the "IntToStr" function, I redid tests, by creating the table and indexes by program, but by choosing the type integer for the A_AKLE field, in order to test the IntToSTR function. With this syntax (A_AKLE is defined "integer") Code: [Select]AddIndex('KNOMKLE', 'ANOM', + '+A_AKLE', []); I get this message Code: [Select]unit1.pas(122,43) Error: Operator is not overloaded: + "Constant String" With this syntax Code: [Select]AddIndex('KNOMKLE', ('ANOM+' + IntToStr(A_AKLE)), []); I get this message Code: [Select]unit1.pas(122,50) Error: Identifier not found "A_AKLE" If I codifies "Dbf1A_AKLE", I get the same message: Code: [Select]unit1.pas(122,56) Error: Identifier not found "Dbf1A_AKLE" Lazarus 1.10.1 Date 2013/11/16 fpc 2.6.2 Revision : SVN 43447 i386-linux gtk2 Salix 14.0 (32bits) @ BigChimp I did not understand if I have to watch this link or if I have to ask the question again. In the latter case, I don't know how to do this ---------------------------------------------------------------------- BigChimp · 2014-01-16 09:54 Micoudic, no you do not have to ask your question again. I raised the bug because the solution I was looking was did not work. See the example code attached to the bug report. Perhaps I have trouble understanding but this: Code: [Select]DBf1.AddIndex('KNOMKLE', ('ANOM+' + IntToStr(Dbf1A_AKLE)),[]); you are trying to generate a string that contains the string 'ANOM+' andthe string representation of whatever fpc thinks Dbf1a_AKLE is You then pass this as the expression for index 'KNOMKLE' to the TDBF expression parser using the DBf1.AddIndex call. In other words: the inttostr part is more static: it is an Object Pascal function whose outcome is determined by the program at run time, not by the TDBF filtering engine when looking at the data. Fine if you want to do that, but I don't think this is your goal. Have a look at this example on the English wiki article: http://wiki.lazarus.freepascal.org/Lazarus_Tdbf_Tutorial#Index.2Ffilte r_on_TDateTimes where you use the TDBF expression parser DTOS() function to create an index expression. I think here you might be inserting a comma too mach after the 'ANOM' part... Code: [Select]AddIndex('KNOMKLE', 'ANOM', + '+A_AKLE', []); Haven't looked at the other examples. I haven't had my coffee yet so I hope this is clear... ---------------------------------------------------------------------- BigChimp · 2014-01-16 12:35 The "identifier not found" errors are because you are trying to use DBF field/column names, apply an FPC function to it and pass the result to the expression parser. FPC has no way of knowing what e.g. A_AKLE is... it may know about something like yourdbf.fields.fieldbyname('A_AKLE').asinteger but that will give only the value for the record you currently are in (if the dbf is even open) and will not help you. You should not be passing these field names to FPC, you should be passing them to the expression parser by including them inside the expression index string - e.g. Code: [Select]AddIndex('KNOMKLE', ('ANOM+' + IntToStr(A_AKLE)), []); would become Code: [Select]AddIndex('KNOMKLE', '(ANOM)+(IntToStr(A_AKLE))', []); ... if the dbf expression parser has an inttostr function, which it hasn't. I hope I have clarified instead of confused things... ---------------------------------------------------------------------- BigChimp · 2014-01-16 13:12 The demo program I used in my bug report was... buggy. Sorry. This code should demonstrate creating an index exoression built up out of: 1. a string field 2. an integer field ... and should give you an idea of how to adapt your code: ... I'm guessing something like: Code: [Select]NewDBF.AddIndex('IDXCOMPO','(A_PAYS)+(STR(A_AKLE))',[ixC aseInsensitive]); Please don't forget to 1. check you actually apply the index (MyDBF.IndexName:= in the code below) 2. and move to the first record before using it (see printrecords below). Code: [Select]program compoundindex2; { Demonstrates creating DBF tables, filling it with data, and setting multifield index, including numeric field Please delete any customer.dbf and customer.mdx if you have them in your directory so this program can recreate it. } {$mode objfpc}{$H+} uses {$IFDEF UNIX} {$IFDEF UseCThreads}   cthreads, {$ENDIF} {$ENDIF}   Classes,   SysUtils,   CustApp,   DB,   dbf,   dbf_fields,   dbf_common,   dateutils; type   { TDBFTool }   TDBFTool = class(TCustomApplication)   protected     procedure DoRun; override;   public     constructor Create(TheOwner: TComponent); override;     destructor Destroy; override;   end;   procedure CreateDemoDBFs(Directory: string);   // Creates dbase4 demonstration DBF in Directory   var     NewDBF: TDBF;     i: integer;   begin     NewDBF := TDBF.Create(nil);     try       if Directory = '' then         NewDBF.FilePath := '' { application directory}       else         NewDBF.FilePathFull := ExpandFileName(Directory) {full absolute path};       NewDBF.TableLevel := 4; //default to DBase IV       NewDBF.TableName := 'CUSTOMER.DBF';       writeln('Creating ', NewDBF.TableName, ' with table level ', NewDBF.TableLevel);       NewDBF.FieldDefs.Add('CUST_NO', ftInteger);       NewDBF.FieldDefs.Add('CUSTOMER', ftString, 25);       NewDBF.FieldDefs.Add('CITY', ftString, 25);       NewDBF.FieldDefs.Add('COUNTRY', ftString, 15);       NewDBF.CreateTable;       NewDBF.Exclusive:=true;       NewDBF.Open;       // Index on field customer (a string field) followed by the string value of integer field cust_no       NewDBF.AddIndex('IDXCOMPO','(CUSTOMER)+(STR(CUST_NO))',[ixCaseIn sensitive]);       // Another example: reverse sort on customer number:       //NewDBF.AddIndex('IDXCOMPO','-CUST_NO',[ixCaseInsensitive]);       // Compound index on the customer name followed by the customer number sorted backward.       // this doesn't seem to sort correctly on the customer number part though       //NewDBF.AddIndex('IDXCOMPO','CUSTOMER+(STR(CUST_NO*- 1))',[ixCaseInsensitive]);       NewDBF.Exclusive:=False;       NewDBF.Close;       NewDBF.Open;       for i := 1 to 5 do //keep size manageable until we have working files       begin         NewDBF.Append;         if (NewDBF.FieldDefs.Find('CUST_NO').DataType <> ftAutoInc) then           NewDBF.FieldByName('CUST_NO').AsInteger := i;         case i of           5:           begin             NewDBF.FieldByName('CUSTOMER').AsString := 'Michael Design';             NewDBF.FieldByName('CITY').AsString := 'San Diego';             NewDBF.FieldByName('COUNTRY').AsString := 'USA';           end;           4:           begin             NewDBF.FieldByName('CUSTOMER').AsString := 'Johnson';             NewDBF.FieldByName('CITY').AsString := 'San Ysidro';             NewDBF.FieldByName('COUNTRY').AsString := 'Mexico';           end;           3:           begin             NewDBF.FieldByName('CUSTOMER').AsString := 'Michael Design';             NewDBF.FieldByName('CITY').AsString := 'Dallas';             NewDBF.FieldByName('COUNTRY').AsString := 'USA';           end;           2:           begin             NewDBF.FieldByName('CUSTOMER').AsString := 'Johnson'; //same name as previous one, useful for sorting             NewDBF.FieldByName('CITY').AsString := 'Boston';             NewDBF.FieldByName('COUNTRY').AsString := 'USA';           end;           1:           begin             NewDBF.FieldByName('CUSTOMER').AsString := 'Zack Zucchini';             NewDBF.FieldByName('CITY').AsString := 'Manchester';             NewDBF.FieldByName('COUNTRY').AsString := 'England';           end;         end;         NewDBF.Post;       end;       NewDBF.Close;     finally       NewDBF.Free;     end;   end;   procedure GetDBFList(Results: TStringList);   // Gets list of all .dbf files in a directory and its subdirectories.   var     r: TSearchRec;   begin     results.Clear;     if FindFirst('*.dbf', faAnyFile - {$WARNINGS OFF}       faVolumeID - faSymLink {$WARNINGS ON}       , r) = 0 then     begin       repeat         if (r.Attr and faDirectory) <> faDirectory then         begin           results.add(expandfilename(r.Name));         end;       until (FindNext(r) <> 0);       findclose(r);     end;   end;   procedure PrintRecords(DBf: TDBf);   // Prints contents of available records to screen   var     i: integer;     RecordCount: integer;   begin     RecordCount:=0;     DBF.First;     while not (Dbf.EOF) do     begin       RecordCount := RecordCount + 1;       writeln('Record ' + IntToStr(RecordCount));       for i := 0 to DBf.Fields.Count - 1 do       begin         if DBF.fields[i].IsNull then           writeln('Field ', DBf.Fields[i].FieldName, ' is          ***NULL***')         else         if DBF.Fields[i].DataType in [ftVarBytes, ftBytes] then           writeln('Field ', DBF.Fields[i].FieldName, ' is          ***binary***.')         else           writeln('Field ', DBf.Fields[i].FieldName, ' has value: ' + DBf.fields[i].AsString);       end;       DBF.Next;       writeln('');     end;   end;   { TDBFTool }   procedure TDBFTool.DoRun;   var     DBFs: TStringList;     ErrorMsg: string;     FileNo: integer;     MyDbf: TDbf;   begin     DBFs := TStringList.Create;     try       try         CreateDemoDBFs('');       except         on E: Exception do         begin           writeln('*** Error creating demo databases: ' + E.Message);           Terminate;           Exit;         end;       end;       // Process all dbfs if no files specified       if DBFs.Count = 0 then         GetDBFList(DBFs);       if DBFs.Count = 0 then         writeln('Could not find any dbf files');       for FileNo := 0 to DBFs.Count - 1 do       begin         if not (fileexists(DBFs[FileNo])) then         begin           // for some reason, fpc trunk suddenly returns the directory as well...           //writeln('Sorry, file ',DBFs[FileNo],' does not exist.');           break;         end;         MyDbf := TDbf.Create(nil);         try           try             MyDbf.FilePath := ExtractFilePath(DBFs[FileNo]);             MyDbf.TableName := ExtractFileName(DBFs[FileNo]);             MyDbf.ReadOnly := true;             writeln('*** Opening: ' + DBFs[FileNo]);             MyDbf.Open;             writeln('Database tablelevel: ' + IntToStr(MyDbf.TableLevel));             writeln('Database codepage:   ' + IntToStr(MyDBF.CodePage));             MyDBF.IndexName:='IDXCOMPO';             PrintRecords(MyDBF);             MyDbf.Close;           except             on E: Exception do             begin               writeln('*** Error reading file ', FileNo, ': ', E.Message);             end;           end;         finally           MyDbf.Free;         end;       end;     finally       DBFs.Free;     end;     // stop program loop     Terminate;   end;   constructor TDBFTool.Create(TheOwner: TComponent);   begin     inherited Create(TheOwner);     StopOnException := true;   end;   destructor TDBFTool.Destroy;   begin     inherited Destroy;   end; var   Application: TDBFTool; begin   Application := TDBFTool.Create(nil);   Application.Title := 'DBFTool';   Application.Run;   Application.Free; end. ---------------------------------------------------------------------- micoudic · 2014-01-18 19:04 Quote from: BigChimp on January 16, 2014, 02:12:44 pmPerhaps I have trouble understanding but this: Code: [Select]DBf1.AddIndex('KNOMKLE', ('ANOM+' + IntToStr(Dbf1A_AKLE)),[]); you are trying to generate a string that contains     the string 'ANOM+' and     the string representation of whatever fpc thinks Dbf1a_AKLE is I have found that TDC accepts indexes multiples only if the fields are of the same type. That is why I thought this function "IntToStr" ...  (1) Quote from: BigChimp on January 16, 2014, 02:12:44 pmI think here you might be inserting a comma too mach after the 'ANOM' part... Code: [Select] AddIndex('KNOMKLE', 'ANOM', + '+A_AKLE', []);The missing comma is due to a bad transcript (2). She was well in my source, and the message is good. Quote from: BigChimp on January 16, 2014, 02:12:44 pmThis code should demonstrate creating an index exoression built up out of: 1. a string field 2. an integer field ... and should give you an idea of how to adapt your code: ... I'm guessing something like: Code: [Select]NewDBF.AddIndex('IDXCOMPO','(A_PAYS)+(STR(A_AKLE))',[ixC aseInsensitive]); YES, impeccable. I almost give up to work with Lazarus. A big thank you (1) I am not a professional, but an autodidact. I know that I certainly commit errors (2) I prepared my answers in French, then I translated them with G... but the syntax is sometimes modified. I then corrects directly in my reply on the forum, which explains this typo.. ---------------------------------------------------------------------- BigChimp · 2014-01-19 11:24 Excellent. Glad it works! ---------------------------------------------------------------------- micoudic · 2014-01-20 18:38 My second key field is numeric. He became alpha in the index. Thus, the key "15" and larger than the "135" key (framing to left, as the alpha) To recap: -you have an application that uses the file dBase (xxxxxxxx.dbf) -you have created these files with the Borland Database (dbd32.exe) module -you have the index multiples with different type fields(char and num) This works well with Borland's Delphi, but not with Lazarus Solution: You keep your .dbf files, but we must re-create the index programmatically in Lazarus. ---------------------------------------------------------------------- BigChimp · 2014-03-10 08:49 Quote from: BigChimp on January 14, 2014, 05:59:02 pmHmm, I think there is a bug. Need to verify again but put it on the bugtracker as a reminder: http://bugs.freepascal.org/view.php?id=25533 Blush... totally irrationally, I had expected sorting to work numerically and even partially (i.e. BILL-10 is higher than BILL-11) while TDBF does a regular alphanumerical sort. Thanks for helping me, as usual, Lacak2 With current FPC trunk, the test code in the bug report works fine, just sorts in a way that idealists like me may not want