I have a delphi form with TFDConnection, TFDQuery, TDataSource and TDBGrid. I want to show the data that my query gets (select * from table_1) and put it in my DBGrid.
I've made all the connections between the components, but after I launch my query (which returns 12 rows) in my DBGrid are shown 12 rows but they are empty. Apparentely I forgot something that prevents me from seeing my data in my DBGrid. Can you help me what I'm missing in my actions ?
1- Adding all components to the form.
2- Connect FDQuery with FDConnection, TDataSource with FDQuery, DBGrid with TDataSource.
3- Connection parameters succed in testing (the problem is not in my connection parameters)
4- The number of rows are placed in my DBGrid (12), but with no information visible.
5- If I loop through my FDQuery I can see all the information I need but that doesn't help me populate my DBGrid.
Can you try this:
Make your TFDQuery active explicitly in your OnShow code of your Form. Like this,
procedure TForm.FormShow(Sender: TObject);
begin
FDQuery.Active:= True;
end;
It works for me and hope it helps.
You would get the behaviour that you would see the correct number of rows in the DBGrid, but the grid's cells are empty, if the DBGrid's DefaultDrawing property is set to False. if that's the case for your DBGrid, obviously just set DefaultDrawing to True.
To fix this problem (which I had the same), after you open the query, set:
datasource.dataset := Query
and the problem will be resolved.
I know the topic is old, but maybe it can help someone. In my case, the solution was: Deleting all the DBGrid columns that was created in design time, OR match the column's (TColumn) FieldName property to the EXACT field names as they named in the database tables.
For anyone else with this problem, here's the fix: make sure that the column names (not the Title) in the grid control match the field names in the query. Once they're matched they should behave properly.
Related
I have a DBGrid that is updated on a button click. Once updated I have it check each row vs an XML file. If the fields in that row match the data in the XML file, I want to delete that row from the dbgrid only.
The DBgrid is loaded from ADOconnection / Query / Datasource . The main connection is to a DB which is linked to an excel file. The XML file is just a report we get each month. Normally we have to check to make sure all the machines on the excel file is also on the report given to us.. With hundreds of machines I am trying to auto detect any difference.
but I cant figure out how to delete the row in the grid only when it finds a match Thus only the non-Matched items are in the grid.
You can't delete rows from a DBGrid. You delete them from the dataset to which the DBGrid is connected. A DBGrid simply displays the data from a dataset. If you want the row deleted, delete it from that dataset using it's .Delete method.
After reading the edit you made, it looks to me like you should be loading the query data into a TClientDataSet (CDS), and then attaching that CDS to the DBGrid's DataSource. You can then do whatever you want to that CDS without affecting the original data, as long as you don't call the CDS's ApplyUpdates method.
What Ken White says in his answer is 100% correct, but I think there is something else
maybe worth pointing out, especially as you mention XML.
Unlike some other TDataSet descendants, both TClientDataSet and the more modern FireDAC datasets implement the UpdateStatus
property of the dataset and this reflects what has happened to the current record
in the dataset - see the Online Help for details. It is an enumeration [1] declared as
type
TUpdateStatus = (usUnmodified, usModified, usInserted, usDeleted);
You say you want to compare the records with what you have in an XML file and delete
the records which have not been updated "from the DBGrid", which as Ken has said is
not meaningful per se.
However there is another way of going about what you seem to want. If you can load the
data displayed in the dataset feeding the grid from the XML file. then you know
that until you update the dataset, the records must match the XML. So, once the
records have been updated in your app, rather than comparing all the records in the dataset
with their XML counterparts, you could simply delete (from the dataset) the records
whose UpdateStatus is usUnmodified. This is trivial to do using a method like this:
procedure TForm1.DeleteUnmodifiedRecords;
begin
ClientDataSet1.DisableControls;
try
ClientDataSet1.First;
while not ClientDataSet1.Eof do begin
if ClientDataSet1.UpdateStatus = usUnModified then
ClientDataSet1.Delete
else
ClientDataSet1.Next;
end;
finally
ClientDataSet1.EnableControls;
end;
end;
and this will, of course, remove the records from the DBGrid.
Of course, this assumes that you can load the XML data into a TClientDataSet
or a FireDAC dataset, eithe directly or by transforming the XML into a form that
either of these can load using a TXmlTransform component but I won't go
into the details of that here.
[1]: A point to beware of is that usModified does not seem to be the exact logical negation of usUnmodified. This has the slightly surprising consequence that if you
apply a StatusFilter of [usModified] to a CDS, records that have been changed can appear twice, once in their original form and once in their changed form - see fig 6.5 of Cary Jensen's "Delphi in Depth: ClientDataSets", 1st edition.
One option to make rows/records vanish from a dbGrid and other data aware controls is to use the TDataSet's OnFilterRecord and return false for rows you no longer want seen. It does not have any effect on the underlying data - it just filters out what is visible.
procedure TDM1.FDQueryTopicListFilterRecord(DataSet: TDataSet; var Accept: Boolean);
begin
// Check if the row should be shown - set Accept to true if it should, false if not
end;
I am using a TClientDataset, connected to a DBGrid, with a couple of Aggregate Fields, for calculating the SUM of an other couple of Float Fields. All fields have been created in Design time.
Everything is working as expected, until the time that the IndexName of the ClientDataset changes with a custom Index, in order to sort the Grid. After that, the Aggregate Fields don't calculate their value properly, and they are set with Null value.
The problem occurs in Delphi XE7.
I have google about it and i found a solution that worked for me here
There is a bug at TCustomClientDataSet.SetIndex method that is declared in the DBClient unit.
The solution propose to replace the following code
if FAggregatesActive then
begin
FAggFieldsInit := False;
ResetAllAggs(FAggregatesActive);
with the next one
if FAggregatesActive then
begin
CloseAggs;
ResetAllAggs(FAggregatesActive);
As far as i understand, the replacement of FAggFieldsInit := False with CloseAggs, force the Aggregates to be released and then recalculate with the new index.
As i said this solution worked for me, and i haven't notice any unwanted behavior.
The credit goes to AndreyZ for the original solution.
I have a form which has a cxGrid on it and connects to a database table via TADQuery (FireDAC).
I've also added a TEdit box to the same form. When a user starts typing into the TEdit box, can I make the grid start to filter the results based on what the user is typing (preferably for more than one field in the table)?
If so, your thoughts/examples would be appreciated.
Thanks.
In your FDQuery, you might have a sort of query like this :
SELECT * FROM MyTable
WHERE ColumnA LIKE :paramA
This would apply to a string column, but any other logical comparison would work. I presume you know how to write your query.
You would of course need to add the parameter, either programmatically or via the Parameters property in the design-time Object Inspector, being sure to match the parameter's name with that used in the query. I presume also that you know how to do this.
In the OnChange handler of your TEdit, then, you could do something like:
procedure TForm1.Edit1Change(Sender: TObject);
begin
FDQuery1.Params.ParamByName('paramA').Value := Format('%%%s%%',[Edit1.Text]);
FDQuery1.Refresh;
end;
This, naturally, braces the search term with % SQL wildcards, narrowing the returned records to those which contain the substring typed by the user into the edit box.
If you are querying a large dataset where the .Refresh operation is long-running you can instead use a timer to delay refreshing the dataset until the user has stopped typing for a given interval of time.
Use the KeyDown event in the TEdit Field to start a timer. With the Timer-Event you check if the Text is still changing (User is still typing) - A Intervall for the timer of maybe 500 ms - 1 sek is engough between the checks.
If the Text did not change in the meantime requery your cxGrid using the Text in the Edit-Field. On top of this you could use a thread to requery your Grid.
The slower the user types and the lager the Table you are quering the longer your intervall should be.
Better use filter
procedure TForm4.Edit1Change(Sender: TObject);
begin
if trim(edit1.Text)>'' then
begin
adoquery1.Filter:='field1 like '+quotedstr(trim(edit1.Text)+'%');
adoquery1.Filtered:=true
end
else adoquery1.Filtered:=false
end;
I am facing a very strange problem in one of my programs. I have a TSQLConnection followed by two TSQLQUery, TDataSetProvider, TClientDataSet and TDataSource. Its a Master-Detail structure.
The TDataSource of the detail query has an additional column with one lookup property of the master query. (Think of something like 'ProductID, ProductName, GroupName' where GroupName comes from the master query)
Then I have a DBGrid which has the TDataSource of the detail query as Source. It diplays most parts correctly, but the field that is a lookup from the master-query, sometimes does not show. Sometimes means in this case, i scroll down in the DBGrid, and up again, then its gone. I scroll down and up one more time, and its shown.
For debugging I added a TDBLookupComboBox with the same source as the DBGrid, but the ComboBox always shows the correct value for this field.
Thanks for any help on this problem.
Try changing the LookupCash property of the lookup column to true, I think this will solve the problem.
I have a DBLookupComboBox that lists values from 1 table that I'm selecting a value from.
When the value is selected, I want the 2 DBMemo Boxes I have to be able to input/edit into to insert/update into another table.
But They don't allow me to enter into them. I assume because it's state is dsInactive.
How do I do this?
Thanks!
If the state is dsInactive, that means that the dataset isn't active, so it can't be edited. In your setup code, try saying MyDataset.Active := true;. This will fire its query and load the results into the dataset for you to view and edit.