Documentation for components :
TFilterByForm Version 1.5
TQueryByForm Version 1.0
Created By :
Last Update :
Unit File Name :QryByFrm.Pas ( Contains both the components )
Dedication : To All Delphi Programmers
Note :
Written with Delphi-3. Should work in Delphi 1, 2 and 4 also.
Introduction
The aim of this Component is to provide the Delphi Programmers an easy way to implement QueryByForm sort of feature in their programs. That is, as the user works with a form designed by you a Delphi programmer, the user can on the fly during run-time see the data you present as per his requirements. For instance your form may provide employee-details . The user who is browsing through the data may want to see all the Male Employees from one particular Country. Usually you will have to provide for such Queries by providing some button and writing code. That too if the user has informed you while the program was being designed. If there are lets say 20 fields on the form the user should be able to Query any way he wants. The components TQueryByFormand TFilterByForm can help you do so without much effort just that by providing you 3 object methods. Now the user can query the employee data provided by you on the form in any way he pleases. Here are some examples. He may want to see the employee data in 1 of the following ways :
How To Use TQueryByForm Component ?
When the user clicks the button calling the GetCriteria method all the fields on the form connected to the same DataSource as the QBF DataSource gets cleared. This is the place where the user enters the Criteria he wants the query to work on. The user can avail the relational operators by clicking on the right mouse button. FilterByForm Version 1 used to put the DataSet into an Insert state to clear all the fields and get user criteria. This was fine in case of Tables. But in case of querys the BDE does not always return a Live Query. The query becomes ReadOnly. Thus not allowing us to put the Query into an Insert state. To overcome this problem a temporary In-Memory table is created and the DataSource’s DataSet property is changed to the temporary table. Thus all the fields get cleared and user Criteria can be collected. This solves the Live-Query problem. I have taken some care so that the user does not ( play with the ) Delete or Insert while he is in qsGetCriteria state by blocking the Insert and Delete features. I would recommend that you Disable such Buttons or DBNavigator to be on the safe side. You can enable them as soon as the ExecQuery method is called. When user activates the ExecQuery method the DataSet is changed back to our Query. The ExecQuery parses the SELECT query and seperates the Query into 6 parts. The SELECT-Part, FROM-Part, WHERE-Part, GROUPBY-Part, HAVING-Part and ORDERBY-Part. Now the user criteria is translated and added to the WHERE-Part or the HAVING-Part as per the requirement. ReSetQuery brings the Query to its original form.
Notes on the Origin Property of TField object :
The Origin property of the field objects (TFields) connected to the TQuery has a very important role to play in the working of TQueryByForm component. So it is necessary that the Delphi programmer understands it properly. TQueryByForm gets its field related information from this origin property. Paradox, Dbase, Interbase field-names are automatically put in the origin property by the Field-Editor. Calculated-Fields and Aggregate ( SUM,COUNT ) fields info are not properly put in the origin property. Microsoft Access fields info are also not properly put in the origin fields. Where ever the origin property is not in the way we want we have to manually correct it. Here are some instances...
the origin property should be "ANIMALS.DBF".NAME
the origin property should be "COUNTRY.DB".Name
the origin property should be "BIOLIFE.DB".Species No
the origin property should be COUNTRY.CountryID
the origin poperty should be [Air Freight].Station PrefixIn case of calculated fields the origin field should have the expression as the value. That is the expression as in the SELECT query should be Copy/Pasted into the origin property. For Example : ( Employee.Salary*0.30 )
Similarly incase of GROUP Expressions like SUM, COUNT, AVG, MAX, MIN, the expression to be put into the Origin property .
For Example : SUM( REC."AMOUNT" )
It is important to bear in mind that in case of GROUP Expressions, the expression should start with SUM, COUNT, AVG, MAX, MIN with out any spaces or any other characters.
Another important point to be noted is that the FieldKind property of the TField object should be changed to fkInternalCalc in case of calculated fields. All non-calculated fields should be of FieldKind fkData.
Properties :
- dtStandard - Paradox and Dbase ( default )
- dtAccess - Microsoft Access Database ( MDB)
- dtInterBase - Interbase
- qsInActive - Is when GetCriteria method is not called or after the ReSetQuery is called.
- qsGetCriteria - Is When GetCriteria method is called and before ExecQuery is called. It is in this state the user enters his criteria. He can also use the right-mouse button to select the relational operators and other functions while in a Data-Aware Control.
- qsExecuted - Is after the ExecQuery method is called. ReSetQuery method will change the state to qsInActive .
WHERE Address LIKE "%York%"
Will search for all data in the Address field containing York in it.
Since % is a wild card operator we can check whether % is a part of the field value by using this escape character. If you want to check whether a ‘%’ is there in the field, the wild card escape character can be used. If you want to search in a Character field named Discount for 20%.
WHERE Discount LIKE " %20@%%"
For more information refer to SQL LIKE documentaion.
| Relational Operators | Explanation |
| Equal To, Not Equal To,
Less Than, Greater Than |
No explanation required |
| Between & Not Between | The From part of the Between Range to be entered in the Field itself and when Between or Not Between is selected from the Relational Operator PopUpMenu the To part to be entered in the InputBox which pops up on selection. |
| Contains & Not Contains | If the string that is entered in the field is present in the field values of the table then it is shown. Actually here the LIKE reserved word is used with the Wild Card % automatically prefixed and suffixed. For example : If you want to see whether the field-value in the table contains a substring Rob, the user can enter Rob in the field and select Contains relational operator. It is automatically translated as %Rob% internally. So the user should not put the percentage sign. However the Wild Card underscore ( _ ) that is substitute for single character should be used whenever needed. |
| Like & Not Like | This is nothing but the LIKE operator of SQL SELECT statements and works exactly in the same way. Please note that the WildCardEscape property has the default ‘@’. This can be changed. Please refer to the SQL documentation for more details on Wild Card in LIKE operator. Even though the relational operator STARTING WITH is not provided – it can be easily emulated with the wild card %. For eg: if you want to all the names starting with 'Robert' you can enter Robert% in the field and select LIKE relational operator. |
| In & Not In | This is nothing but the SQL IN
operator in the WHERE clause. You do not have to enter anything
in the Field. When you select IN from the PopUpMenu an InputBox
pops up where you can enter all the values seperated by commas. If string
values are not entered in quotes a SQL error will be generated .For Example
:
In case of strings : "Jan","Feb","Mar" etc. In case of numbers : 10,20,30 For more details refer to SQL IN documentation. |
| Null & Is Not Null | No explanation is required |
FilterByForm component is just like QueryByForm except that it works on Table / Query Filter property. If you have existing programs using FilterByForm Ver 1.0, remember to change the QBFTable property and select the DataSource property. And also note that it supports only the Relational operators EqualTo, NotEqualTo, LessThan, GreaterThan , Between, NotBetween , ( New ) Null, (New) NotNull.
Please remove the old FilterByForm component and Install the unit QueryByForm which contains both the components.
Please note that the methods –
- CaseSensitive - Default is False. When False the filter set by the component will be case insensitive.
Important Note :
- AsteriskAsWildCard - Default is True. If you do not know the exact way the field value is you can use Asterisk as a Wild Card. For example you are not sure Smith is Smith or Smythe. You can enter Sm*. Please note ‘*’ can be used as a suffix only.
The state of Data Aware Controls are saved in Tag property of the Data Aware controls itself. So please do not use it or assign it while in qsGetCriteria and qsExecuted state. Use it after you call ReSetQuery ( or ReSetFilter in case of FilterByForm ) method. Also note that if you have anything stored in the Tag property before calling the GetCriteria method, it will be restored to you in the Tag property itself , when you call ReSetQuery method.
Known Problems :
When the temporary In-mem table is created it is of type ttDefault which is Paradox. You may have to distribute Paradox Driver along with your programs if it is using some other type of DataBase.
Conclusion :
If you have other Data Aware controls which you want to make QueryByForm aware you can add them to the object code. There are 4 places ( and 4 Places in FilterByForm ) where I have marked *TEMPLATE*. The code has been commented {}. Do not use this. Leave it in comments itself. Instead copy this commented code and paste just above the commented area. Replace the object TDBYourDataAwareControl to your object name. The source comes in only 1 Unit name QueryByForm.Pas. Demos are also enclosed in a Zip file. An Standard Alias named QBFDemoData to be created with the right DataPath.
I have tried both the components on Dbase, Paradox, Access and Interbase (Local). They work fine. I have not worked with them on the network. But I think that should be no problem.
I know it does not follow the true spirit of Object Oriented Programming. New features should be added by inheriting. But in the logic that I have used there a lot of type-casting of Data Aware controls. So I could not generalise the logic for all Data Aware Controls. May be somebody can come out with improvements. Please note that these components are not free. It is e-mail ware. That is if you try this component you have an obligation to inform me what you think of it, your suggestions, In what way you found it useful etc. Feedback is important. In no way should you try to sell this component or its idea. It is intended to be free. This component is a result of hours of hard work and imagination. So please do not forget to give me some credit in the applications you use the component. Feel free to copy and change the component as you like and you feel is better. But informing me about the changes is a must. I am not responsible for any problems you face as a result of using this component. You use it at your own risk. The component is limited by my Knowledge of Delphi, my working experience and my imagination. I will keep on improving this component and you will get the future updates if you respond to me. I would also be happy if you can share your components with me. You can send e-mails to my address jayan_chandra@hotmail.com or jayan@zajil.net.
To the relational operator list I would like to Add a Sounds Like (
Soundex ) feature. But neither Query nor Filter accepts User-Defined-functions.
In Interbase maybe stored-procedures would do the trick. I have
not tried this. That’s all folks. Keep on building components and share
your knowledge......Have lots of fun . Enjoy...............