Delphi TDBGrid selected row get value - delphi

I would like to retrieve a value from a TDBGrid the selected row, how can I do?
procedure TForm7.Button2Click(Sender: TObject);
var
i, j: Integer;
s: string;
begin
if DBGrid1.SelectedRows.Count>0 then
with DBGrid1.DataSource.DataSet do
for i:=0 to DBGrid1.SelectedRows.Count-1 do
begin
GotoBookmark(DBGrid1.SelectedRows.Items[i]);
for j := 0 to FieldCount-1 do
begin
if (j>0) then s:=s+', ';
s := s + FindField(Fields.Fields[j].FieldName).AsString;
end;
Listbox1.Items.Add(s);
s:= '';
end;
end;

The code below fixes a few problems with yours.
The main problems were the fact that you weren't correctly initialising s and your way of getting the fields for the selected row(s) was flawed.
The calls to DataSet.Disable/EnableControls and ListBox1.Items.BeginUpdate/EndUpdate are to speed the process up.
Also, avoid the with construct like the plague. As you can see, my use of a local DataSet variable instead involves minimal extra typing and avoids all sorts of accidental problems that can arise when you use with.
procedure TForm1.GetSelected;
var
i,
J : Integer;
s : String;
DataSet : TDataSet;
begin
if DBGrid1.SelectedRows.Count>0 then begin
DataSet := DBGrid1.DataSource.DataSet;
// with DBGrid1.DataSource.DataSet do
try
ListBox1.Items.BeginUpdate;
DataSet.DisableControls;
for i:=0 to DBGrid1.SelectedRows.Count-1 do
begin
DataSet.GotoBookmark(Pointer(DBGrid1.SelectedRows.Items[i]));
s := '';
for j := 0 to DataSet.FieldCount - 1 do
begin
if (j>0) then s:=s+', ';
s := s + DataSet.Fields[j].AsString;
//s := s + FindField(Fields.Fields[j].FieldName).AsString;
end;
Listbox1.Items.Add(s);
//s:= '';
end;
finally
DataSet.EnableControls;
ListBox1.Items.EndUpdate;
end;
end;
end;
**Update: **
You can set the current grid row as selected like this
DBGrid1.SelectedRows.CurrentRowSelected := True;
Update #2
The grid's selected rows are stored in a TBookmarkList named SelectedRow. To clear the current selections, all you need do is to call its Clear method, like so:
procedure TForm1.btnClearSelectedClick(Sender: TObject);
begin
DBGrid1.SelectedRows.Clear;
end;
Equally, if you want to clear your ListBox, you just call its Clear method, as in:
procedure TForm1.btnClearListBoxClick(Sender: TObject);
begin
ListBox1.Clear;
end;
If you are having trouble getting my code to work, try this:
In the Object Inspector, set the DBGrid Options property dgMultiSelect to True.
Place a button on your form and in its OnClick handler call GetSelected.
Compile and run. Click a row in the grid and then the button. Nothing happens. The reason is that clicking the button moves focus away from the DBGrid, so that as far as it is concerned, none of its rows is selected. Then try step 3.
Run the app again. This time press and hold the Ctrl key while you click the grid then the button. This time the selected row appears in the ListBox. With the Ctrl button still down, click another row in the grid, then the button. This time, both rows are added to the ListBox.

only a single line call is needed to retrieve a value when you know the column number. The system will automatically return values from the current row, or last line clicked or double-clicked in a grid list.
var colidx : integer; ss : string;
..
ss := DBGrid1.Fields[colidx].AsString;

this is my method to retrieve the key
procedure TfrmArticle.Button2Click(Sender: TObject);
begin
op:='M';
with frmajtArticlee do
begin
Edit1.text:=dm.ADOQueryArticle.fieldbyname('ID_prod').Value;
Edit2.text:=dm.ADOQueryArticle.fieldbyname('ref_art').Value;
Edit3.text:=dm.ADOQueryArticle.fieldbyname('code_barre').Value;
Edit4.text:=dm.ADOQueryArticle.fieldbyname('marque').asstring;
Edit5.text:=dm.ADOQueryArticle.fieldbyname('qts_art').Value;
Edit6.text:=dm.ADOQueryArticle.fieldbyname('designation').asstring;
Edit7.text:=dm.ADOQueryArticle.fieldbyname('prix_achats_ht').Value;
Edit8.text:=dm.ADOQueryArticle.fieldbyname('prix_vente_faciliter').Value;
Edit9.text:=dm.ADOQueryArticle.fieldbyname('prix_vente_cache').Value;
val_mod:=dm.ADOQueryArticle.fieldbyname('ID_prod').asstring;
val_mod:string "declare it in public "

IF YOU'RE NEED TO FIND HOW TO GET DATA OF A SELECTED ROW IN THE DBGRID, I HAD THE HINT. I USE DBGRID.SelectedField TO GET THE SELECTED FIELD AND CONVERT THE FIELD TO BE SELECTED TO BOOKMARK BY DB_GRID.SelectedField.DataSet.Bookmark
AND USE DATASET.GOTOBOOKMART TO GO TO THE SELECTED RECORD FIELD IN DBGRID DB_DATA.DataSet.GotoBookmark (DB_GRID.SelectedField.DataSet.Bookmark);

Related

Delphi ComboBox Access violation on combobox

I get Access violation error, but I know the code is correct, so where could be the problem? I'm trying to fill a ComboBox whit data from a local AccessDB.
var i : integer;
x : string;
begin
with DataModule3.ADOTable1 do begin
if RecordCount > 0 then
for i := 1 to RecordCount do begin
RecNo := i;
x := FieldByName('Teacher').AsString;
ComboBox1.Items.Add(x);
end;
end;
end;
I have tried lots of things and nothing works, I have tried lots of combobox typed but still doesn't work the only time a combobx showed value was when I selected a row in table then it showed in combobox the rows value by which I need to filter...
Access Violation is raised most probably because you have forgot to instantiate your datamodule DataModule3. Verify this by calling Assigned function.
begin
with DataModule3.ADOTable1 do
if Active then
while not Eof do
begin
ComboBox1.Items.Add(FieldByName('Teacher').AsString);
Next;
end;
end;

cxGrid clear columns on form close

I have a grid that I use to display few query results (cxGrid1.ActiveLevel.GridView := cxGrid1DBTableView1; etc ...). On form close, I close the queries as well.
However, the former columns that were last displayed remain visible (when I return to that form again) How can I eliminate these traces of columns as well? I would like empty grid when I return to the form.
Edit : This is the query that I run :
procedure TForm2.cxRadioGroup1Click(Sender: TObject);
begin
case cxRadioGroup1.ItemIndex of
0: begin
with Form1.UniQuery3 do begin
Close;
sql.Clear;
sql.Add('select * from program_log');
Open;
cxGrid1.ActiveLevel.GridView := cxGrid1DBTableView1;
end;
end;
1: begin
with Form1.UniQuery4 do begin
Close;
sql.Clear;
sql.Add('select * from guests_log');
Open;
cxGrid1.ActiveLevel.GridView := cxGrid1DBTableView2;
end;
end;
end;
end;
Calling
cxGrid1DBTableView1.ClearItems;
Removes all traces of columns which are then unavailable if I want to run the query again.
The easiest way to accomplish this is to create another cxgridlevel > cxGrid1dbtableview. Then just call set this level on form show:
procedure TForm2.FormShow(Sender: TObject);
begin
cxGrid1.ActiveLevel.GridView := cxGrid1DBTableView3;
end;
Since it is assigned to nothing so will the grid display empty.
Calling cxGrid1DBTableView1.ClearItems will remove all columns. Just call it in your FormClose event handler. To recreate columns call cxGrid1DBTableView1.DataController.CreateAllItems function.

Proper Validation on TPageControl in Delphi

I'm working with Delphi 7 code to ensure that comments are entered on a tab have been saved before users can switch tabs.
The tabs are located on a TPageControl, and this code is triggered OnExit
procedure TfCallerInfo.tsChaplainExit(Sender: TObject);
begin
{ Compare the saved DB value with the text in the comments field }
if (dmMain.qChaplainCOMMENTS.AsString <> dbmChapComments.Text) then
begin
ShowMessage ('Please save the comments before proceeding.');
pcDetail.ActivePage := tsChaplain; // Remain on the Current Page
tsChaplain.SetFocus;
end;
end;
When users click on another tab tsInfoRequest for instance, the validation does trigger, but the Active Page becomes tsInfoRequest instead of remaining tsChaplain.
Any idea what I'm doing wrong?
There's probably a better way to do what you're trying to do. Use the TPageControl.OnPageChanging event instead.
procedure TfCallerInfo.pcDetailPageChanging(Sender: TObject;
NewPage: TTabSheet; var AllowChange: Boolean);
begin
if pc.ActivePage = tsChaplain then
begin
AllowChange := (dmMain.qChaplainCOMMENTS.AsString = dbmChapComments.Text);
if not AllowChange then
ShowMessage(...);
end;
end;
By the way, a better test might be
AllowChange := not dmMain.gChaplainCOMMENTS.Modified;
TField.Modified is set to True when the content of the field is changed when it's DataSet is in dsEdit or dsInsert mode, and set to False when it's state changes back to dsBrowse.

Strange filter behavior in DevExpress grid

I have a form with 2 grids showing records selected using master-detail option on Devart UniQuery. This working very nice showing the wanted records in detail that relates to master.
I have the option to select records (companies) using a filter. This is done by 30 buttons with a letter on each and then when pressing one I set the filter with this code
procedure TfrmJsCompanies.ButtonClick(Sender: TObject);
var
ButtonValue: char;
FilterString: string;
begin
ButtonValue := (Sender as TcxButton).Caption[1];
FilterString := ButtonValue + '%';
with grdCompaniesView1.DataController.Filter.Root do
begin
Clear;
BoolOperatorKind := fboOr;
AddItem(colCompany_Name, foLike, FilterString, FilterString);
end;
grdCompaniesView1.DataController.Filter.Active := True;
grdCompaniesView1.FilterRow.Visible := False;
ActiveControl := grdCompanies;
end;
If I do this i get the result I expect unless I first press a button that gives me master records that has detail records and there after press a button that gives me no master records - in this case the detail records from the previous selection are still shown in my detail grid
What can I do to get rid of this?
This behavior is caused by the fact that filtering is executed on the cxGrid level, but not on the DataSet level and, as a result, the DataSet is not filtered.
One way to deal with that could be:
procedure TForm1.DetailViewFilterRecord(ADataController: TcxCustomDataController; ARecordIndex: Integer;
var Accept: Boolean);
begin
Accept := MasterView.DataController.FilteredRecordCount >0;
end;
procedure TForm1.MasterViewDataControllerFilterChanged(Sender: TObject);
begin
DetailView.DataController.Refresh
end;

How do you update TStringGrid cells in Delphi XE3, Firemonkey2

I've seen this question asked as part of another question before, so know it can't just be me...if I open a new FireMonkey2 HD app, add a TButton and TStringGrid, then add this to the button on click event, NOTHING happens in the grid when I click the button!
procedure TForm33.Button1Click(Sender: TObject);
var
i: Integer;
begin
for i:= 0 to 6 do
begin
StringGrid1.Cells[0,i] := 'Row:' + IntToStr(i);
end;
stringgrid1.UpdateColumns;
stringgrid1.SetFocus;
end;
Any ideas ?
PS I've also tried using TStringGrid.OnGetValue and it still won't show anything in the StringGrid.
Having looked further into the TStringGrid source code, C is nil so the Cells are never being set.
procedure TStringGrid.SetValue(Col, Row: Integer; const Value: TValue);
var
C: TColumn;
begin
C := Columns[Col];
if Assigned(C) then
begin
C.UpdateRowCount(RowCount);
C.SetCells(Row, Value);
end;
I appears there are no Columns in the "virgin" StringGrid, so how do you add them ? There is a r+w RowCount property but ColCount is readonly...
You must add at least a column to the TStringGrid in order to add data to the cells, you can do this in runtime
StringGrid1.AddObject(TStringColumn.Create(Self));
or in design time using the Items Designer

Resources