TDBF.Filter and TDBF.Found lazarus / 16-Databases ---------------------------------------------------------------------- tshumak · 2013-07-12 08:33 I'm trying to search a TDBF dataset using Filter, and checking for results using Found.  I'm having trouble getting Filter to work. EX: TDBF.Filtered := False; TDBF.Filter := 'FieldName=intValue'; -or- TDBF.Filter := 'FieldName="strValue"'; TDBF.Filtered := True; //Now check to see if we have results If TDBF.Found then  // some code here  -or If TDBF.FindFirst then // some code here -or- TDBF.First; If Not TDBF.EOF then // some code here TDBF.Found and TDBF.FindFirst return false.  TDBF.EOF returns what I would expect, but the dataset is not filtered. Also the comparison operators and be either <, <=, >=, > as well.  I also have OnFilterRecord event returning Accept := True.  I know I'm not doing something right. The dataset seems to be acting as if I did not apply a filter. Could some one be good enough to iterate or offer suggestions?  I hope this post makes sense to somebody.  Thanks for reading. Heres my code. Code: [Select]// Function Find. // Locates first occurance in a record based on // information supplied. And returns whether or // not the dataset was able to able to locate the // information. // // Parameters: //   V : String //     The value to be searched for. //   CS : String //     Compare String.  Used to build filter string //     to supplied to Field.dataset.filter property. //   F : TField. //     Field to be used compare with. // // Variables: //   DS : TDBF //     Dataset derived from the field passed to this //     function. //   N : String //     Name of the field derived from the field //     passed to this function Function TDM.Find(V, CS : String; F : TField) : Boolean; var   //DS^ : TDataSet;   N : String;   ft : TFieldType; Begin   //DS := F.^DataSet;   N := F.FieldName;   ft := F.DataType;   with (TDBF(F.DataSet)) do   begin     Filtered := False;     if ft = ftString then       Filter := N + CS + '"' + V + '"'     else       Filter := N + CS + V;     Filtered := True;     Refresh;     // If Found then   // begin // check first char in CS to determine direction of search.       if POS('<', CS) > 0 then       begin         Result := FindLast;   //      Result := Found;   //      Result := not BOF;       end       else       begin         Result := FindFirst;   //      Result := Found;   //      Result := not EOF;       end;   //end   //else   //      Result := False;   end; End; ---------------------------------------------------------------------- BigChimp · 2013-07-12 08:51 Have you checked the documentation to see if your filter text is supported? https://sourceforge.net/projects/tdbf/files/TDbf%20documentation/TDbf% 20documentation%201.1/ Also, wouldn't the filtered records just "disappear", leaving only the found records - i.e. you wouldn't need to use .Found or .FindFirst? ---------------------------------------------------------------------- tshumak · 2013-07-13 01:44 Thank you for your reply and the link.  Yes, I've read it.  It talks a little about FindFirst Not so much for Found.  Ive read through almost every related post here and on sourceforge as well.  There does not seem to be good examples for Found, or FindFirst. What is a good method of verifying that Filter was successful other than visually through DBGrid or the like?  I'm also thinking that my problem may be related to object passing to functions.  Are objects passed by reference or by value?  I think I tried to put the 'var' modifier in the parameter declaration clause, but the compiler complained of some sort of pointer issue or error. ---------------------------------------------------------------------- tshumak · 2013-07-13 02:50 Hi BigChimp, Sorry, I did not catch the second sentence of your post.  Well I'm looking for a method to verify if Filter was successful at locating records that match the filter string.  Tonight I think I might look at RecordCount as an option. ---------------------------------------------------------------------- BigChimp · 2013-07-13 11:35 FYI, here is an example that uses filtering: http://wiki.lazarus.freepascal.org/Lazarus_Tdbf_Tutorial#Searching_and _Displaying_a_data_set_by_using_filters ---------------------------------------------------------------------- tshumak · 2013-07-14 00:30 Good, thank you, however I read this one as well.  I did a little more work last night.  I found that I for some reason needed to set an index against some of the tables.  I thought .Filter did not need indexes.  I also see FilterOptions being set.  Does FilterOptions need to be set?  I'm not setting the options.  I was going ask another question, I forgot what it was.  Sorry.  I'll either reply here or start a new thread when I remember. ---------------------------------------------------------------------- tshumak · 2013-07-14 02:01 Al-right I remember now!  Is the TDBF component included with Lazarus/FPC the same as the component available on sourceforge?  Should I be using the sourceforge component instead? Is it better? ---------------------------------------------------------------------- BigChimp · 2013-07-14 03:05 The FPC one was copied from the sourceforge one. We recently improved a lot of code in the FPC version (in FPC trunk), so I wouldn't use the SourceForge one. We're planning to try and pass the fixes on to the sourceforge version. ---------------------------------------------------------------------- BigChimp · 2013-07-14 03:06 Quote from: tshumak on July 14, 2013, 02:30:44 amI did a little more work last night.  I found that I for some reason needed to set an index against some of the tables.  I thought .Filter did not need indexes.  I also see FilterOptions being set.  Does FilterOptions need to be set?  I'm not setting the options.  TBH, no idea. Haven't looked at the filtering part yet (have been fixing Visual FoxPro support and streams). ---------------------------------------------------------------------- tshumak · 2013-07-15 19:58 Yesterday I did a lot more work on this subject.  I have a test app I originally built to test the indexes.  So I modified it to test filtering.  I found that .Filter does work and does not need indexes.  My problem was in my table data being so scrambled, when I applied my filter, the table view came back and looked as if it was unfiltered.  When I applied an index, there was the record I was looking for on the top!  I also needed to set .FilterOptions := [foCaseInsensitive];. Anyway, .Found and .FindFirst still do not return True.  So I'm still looking for a method to determine if .Filter found records and maybe how many.  I suppose I could use found := .BOF = True and .EOF = False, however I think (.BOF and .EOF) = True still could mean 0 or 1 record found. ---------------------------------------------------------------------- BigChimp · 2013-07-16 08:21 Perhaps .RecordCount could work (don't know if it takes filtering into account). ---------------------------------------------------------------------- tshumak · 2013-07-17 02:36 More testing last night.  I should be able to use found := not (.BOF and .EOF);.  And .RecordCount displays the total number of records in the currently set index and does not change with a filter applied.  Maybe I could do a hidden DBGrid and look at the Rows.Count property.  FindFirst and FindLast don't do anything. Thanks again BigChimp for your suggestions.  If I figure out something for FilteredRecordCount, I'll post back here. BTW - Is the DBF component in Lazarus/FPC the same as the one on sourceforge?  If not, which one is better? ---------------------------------------------------------------------- BigChimp · 2013-07-17 07:58 Quote from: tshumak on July 17, 2013, 04:36:05 amBTW - Is the DBF component in Lazarus/FPC the same as the one on sourceforge?  If not, which one is better? Already answered: http://forum.lazarus.freepascal.org/index.php/topic,21497.msg125826.ht ml#msg125826 ---------------------------------------------------------------------- tshumak · 2013-07-17 19:26 Ok, sorry about this.  I missed your post in this thread.  I'll stick with FPC.  Thanks again. ---------------------------------------------------------------------- OzeCode · 2013-07-18 00:06 Lazarus 1.0.10 and FPC 2.6.2 on Windows 64 bit I have been using different Methods for the RecordCount... Code: [Select]// counts ALL records in Table even if it is the Detail Table // TOTAL RECORDS in TABLE DM.Series.Last;  id := DM.Series.PhysicalRecordCount; // get number of records in the Detail Table // where master detail exists // TOTAL RECORDS in Filtered TABLE DM.Series.Last;  NumRecs := DM.Series.ExactRecordCount; That might be what you can use... ---------------------------------------------------------------------- BigChimp · 2013-07-18 06:17 Quote from: tshumak on July 17, 2013, 09:26:48 pmOk, sorry about this.  I missed your post in this thread.  I'll stick with FPC.  Thanks again. No problem. BTW, if you'd want to contribute to/correct the wiki article on tdbf: http://wiki.lazarus.freepascal.org/Lazarus_Tdbf_Tutorial be my guest ---------------------------------------------------------------------- timcs · 2013-07-18 08:01 I have been using the DBFRecordFilter function (I think that is what is it called, do not have the code in front of me) this works on the basis that when you set dbf1.filtered:=true  , it looks at this function to do the searching. You may want to try this method as I have been using it while doing a recent project myself. Cheers Tim ---------------------------------------------------------------------- tshumak · 2013-07-18 19:12 OzeCode - Hi,  I'm familliar with .RecordCount and .ExactRecordCount, but I did not know about .PhysicalRecordCount.  I'll have to look back at the DBF components inner workings to learn more.  Thanks for the tip. ---------------------------------------------------------------------- tshumak · 2013-07-18 19:21 BigChimp - Thank you for the invitation to the wiki article.  I might just add my two cents where appropriate. ---------------------------------------------------------------------- tshumak · 2013-07-18 19:48 So I've been re-writing my project to move away from the .Filter function.  When trying to synchronize 9 tables the application seems to be slow.  I've moved towards setting indexes and using .Next and .Prior methods.  Hence TDBF currently does not support referential integrity, I'm also going to look at .Locate and .Lookup functions. .Filter is good for Greater than, Less than searching, where as .Locate and .Lookup seem to allow for exact matches. ---------------------------------------------------------------------- BigChimp · 2013-07-19 06:30 Thanks for your post. In the longer term, I'd be interested in adding referential integrity features into tdbf if possible (haven't looked at that aspect yet)... which would make it a lot more usable IMO... but that time isn't here yet... ---------------------------------------------------------------------- timcs · 2013-07-19 15:56 As per my previous post where this is the logic behind using the Dbf1FilterRecord Function :   accept := (DateOf(Dataset.FieldByName('dateon').AsDateTime)=DateOf(now))  This will give you, as an example any records using the dateon field in the DBF file , all records as of today Thanks TimCS ---------------------------------------------------------------------- tshumak · 2013-07-24 07:19 OzeCode - I looked at ExactRecordCount, this seems to be something I've been looking for.  Thanks. Using a for loop to iterate through the records found from Filter.