Delphi - Get all column names of selected row from DBGrid - delphi

I'm using the following code to display the values of every column from a row I select in my DBGrid, to a Memo.
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
Memo1.Clear;
with DBGrid1 do
begin
for i:=0 to FieldCount-1 do
Memo1.Lines.Add(Fields[i].AsString);
end;
end;
Anyone have any ideas how to also get the column names, before the value?
For example 1st column is named ID, the 1st value shown on the memo is the ID value (let's say 15) - I'd like it to be ID:15 (column_name:column_value)

if you need column name and values
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
Memo1.Clear;
with DBGrid1 do
begin
for i:=0 to Columns.Count-1 do
Memo1.Lines.Add(Columns[i].FieldName+':'+ Columns[i].Field.AsString);
end;
end;

Related

How can I find the order of grid columns?

I have a grid on a form connected to a database table with 10 fields. The first field (hidden) is the ID. The second field is First_Name, the third Last_Name, etc. These columns are indexed 1 through 10. Now, if the user wants the Last_Name before the First_Name, he can grab that column and slide it over. First_Name now holds index 3 and Last_Name is at index 2.
I need to be able to read the order of the column indices so I can write them to an INI file. Then the next time the user opens the app, I can set the grid back to the preferred state.
I'm doing this with Lazarus 2.0.6 using a TRxDBGrid. I've tried several of its properties, but none of them show the grid column order.
I usually use Delphi rather than Lazarus and have been trying to install the RXDbGrid package into Lazarus 2.0.6 to check my suggested answer to this without any luck so far. However ...
TRxColumn descends from TColumn in the DBGrids source file.
TColumnhas a public property Index which is an integer, which is the index of the column into the GridColumns collection.
Because I can't get the RXDBGrid to install atm, the example below uses a normal TDBGrid, but should work fine with obvious detail changes.
The example has 3 fields, ID integer, Name String[20] and Value integer.
For simplicity, instead of saving and loading an IniFile, the Column order is saved to a TMemo, and to test the LoadColumnInfo you need to change the column order in the memo.
As you'll see, to reload the grid column order, it's easiest to save the column tit;es in left->right order and use a function ColumnByName to find the correct column when reloading the saved info.
uses
Classes, SysUtils, memds, db, Forms, Controls, Graphics, Dialogs, DBGrids,
StdCtrls;
type
TForm1 = class(TForm)
btnSaveColumns: TButton;
btnLoadColumns: TButton;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
MemDataset1: TMemDataset;
Memo1: TMemo;
procedure btnLoadColumnsClick(Sender: TObject);
procedure btnSaveColumnsClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
function ColumnByName(const AName: String): TColumn;
procedure LoadColumnInfo;
procedure SaveColumnInfo;
public
end;
[...]
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
var
i : integer;
begin
MemDataSet1.Open;
for i := 0 to 5 do
MemDataSet1.InsertRecord([i, 'Name' + IntToStr(i), i]);
end;
procedure TForm1.btnSaveColumnsClick(Sender: TObject);
begin
SaveColumnInfo;
end;
procedure TForm1.btnLoadColumnsClick(Sender: TObject);
begin
LoadColumnInfo;
end;
procedure TForm1.SaveColumnInfo;
var
i : Integer;
S : String;
begin
Memo1.Lines.Clear;
for i := 0 to DBGrid1.Columns.Count - 1 do begin
S := DBGrid1.Columns[i].Title.Caption;
Memo1.Lines.Add(S);
end;
end;
function TForm1.ColumnByName(const AName : String) : TColumn;
var
i : integer;
begin
for i := 0 to DBGrid1.Columns.Count - 1 do begin
Result := DBGrid1.Columns[i];
if CompareText(AName, Result.Title.Caption) = 0 then
exit;
end;
Result := Nil;
end;
procedure TForm1.LoadColumnInfo;
var
i : Integer;
Index : Integer;
Column : TColumn;
S : String;
begin
for i := 0 to Memo1.Lines.Count - 1 do begin
S := Memo1.Lines[i];
Column := ColumnByName(S);
Assert(Column <> Nil);
Column.Index := i;
end;
end;
end.

Key/Value pairs in ComboBox using Delphi Firemonkey

I would like to use an enumerator to populate a Combobox with Key/Value pairs. Its important that I hide the key from the user and display the value only. On selecting I would like to capture the key associated with the selected value.
The code looks something similar to this.
var
currentObj: ISuperObject;
enum: TSuperEnumerator<IJSONAncestor>;
while enum.MoveNext do
begin
currentObj := enum.Current.AsObject;
cboUserList.Items.Add(currentObj.S['key'],currentObj.S['value']);
end;
The key currentObj.S['key'] should be capture on user select of the value
currentObj.S['value'] which is visible to the user on the cboUserList dropdownlist.
Any ideas?
A simple cross-platform solution would be to use a separate TStringList to hold the keys, then display the values in the ComboBox and use its item indices to access the TStringList items.
var
currentObj: ISuperObject;
enum: TSuperEnumerator<IJSONAncestor>;
while enum.MoveNext do
begin
currentObj := enum.Current.AsObject;
userSL.Add(currentObj.S['key']);
cboUserList.Items.Add(currentObj.S['value']);
end;
var
index: Integer;
key: string;
begin
index := cboUserList.ItemIndex;
key := userSL[index];
...
end;
You can wrap your key in class, e.g.
type
TKey = class
S: string;
constructor Create(const AStr: string);
end;
constructor TKey.Create(const AStr: string);
begin
S := AStr;
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
ComboBox1.Items.AddObject('value', TKey.Create('key'));
end;
And then access it as
procedure TForm2.ComboBox1Change(Sender: TObject);
begin
Caption := (ComboBox1.Items.Objects[ComboBox1.ItemIndex] as TKey).S;
end;
just make sure to destroy these objects later

how to copy selected data from stringgrid

i couldn't find the way to copy selected cell data from a stringgrid, i want the selected data string to be copied to Edit box if possible.. many thanks in advance.
im using delphi xe8, firemonkey.
what i tried so far..
Private
A : Array of TValue;
procedure TForm1.Grid1GetValue(Sender: TObject; const Col, Row: Integer; var Value: TValue);
begin
// Gets the value from a cell in the first column
if Col = 0 then
Value := A[Row];
procedure TForm1.Button2Click(Sender: TObject);
begin
A[1] := Edit1.Text;
end;
//i spent hours just to figure it out,waste of TIME;//
Procedure Formx.StringGrid1SellectCell(Sender: TObject; const ACol,Arow: integer; var CanSellect: Boolean);
Var
Val: string;
begin
Val := StringGrid1.Cells[ACol, ARow];
Edit1.Text:= Val;

Have cxGrid expand current date

I made my grid group by date (grabbed the column name and dragged it to where it says 'group by that column'). However, when the grid is displayed all the dates are 'closed' so I must expand them to see data. That is OK but I wonder if it is possible to have current date expanded already (all other should remain closed !) so I do not have to click the expand cross?
try this, you can put the code in other event handler like a TButton for example
procedure TForm1.FormCreate(Sender: TObject);
begin
//aDBTableView1.ViewData.Expand(true); // this is how to expand all records
aDBTableView1.ViewData.Records[YourRecordNumber].Expand(true); // this is how to expand by a given record
end;
OK try the following
procedure TForm1.FormCreate(Sender: TObject);
begin
with cxGrid1DBTableView1 do
begin
DataController.DataSource.DataSet.Locate('YourDateFieldName',DateTimeToStr(Date),
[loPartialKey]);
ViewData.Records[DataController.FocusedRowIndex].Expand(True);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
intLoop,
vValue: Variant;
begin
for intLoop := 0 to self.cxGrid1DBTableView1.DataController.RowCount - 1 do
begin
if self.cxGrid1DBTableView1.ViewData.Rows[IntLoop] is TcxGridGroupRow then
begin
if TcxGridGroupRow(cxGrid1DBTableView1.ViewData.Rows[IntLoop]).Level = cxGrid1DBTableView1MyDate.GroupIndex then
begin
vValue:=TcxGridGroupRow(cxGrid1DBTableView1.ViewData.Rows[IntLoop]).Value ;
if vValue = Date() then
begin
TcxGridGroupRow(cxGrid1DBTableView1.ViewData.Rows[intLoop]).Expand(False);
end;
end;
end;
end;
end;

Copy all selected items from ListView1 to ListView2

How to copy multiple items from TListView to another. Right now im doing it like this:
procedure TForm1.CopyToRightClick(Sender: TObject);
var
selected: TListItem;
addItems: TListItem;
begin
saveChanges.Visible := false;
selected := deviceList.Selected;
addItems := selectedDevicesList.Items.Add;
addItems.Assign(selected);
end;
But this way only one selected item get copied. Is there a way to copy all selected items?
You can do
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
ListView2.Items.BeginUpdate;
try
for i := 0 to ListView1.Items.Count - 1 do
if ListView1.Items[i].Selected then
ListView2.Items.Add.Assign(ListView1.Items[i]);
finally
ListView2.Items.EndUpdate;
end;
end;
to copy every selected list view item in ListView1 to ListView2.
You can do
procedure TForm1.Button2Click(Sender: TObject);
var
i: Integer;
begin
ListView1.Items.BeginUpdate;
try
ListView2.Items.BeginUpdate;
try
for i := ListView1.Items.Count - 1 downto 0 do
if ListView1.Items[i].Selected then
begin
ListView2.Items.Add.Assign(ListView1.Items[i]);
ListView1.Items[i].Delete;
end;
finally
ListView2.Items.EndUpdate;
end;
finally
ListView1.Items.EndUpdate;
end;
end;
to move every selected list view item in ListView1 to ListView2.
(This works well in moderately-sized lists. In larger lists, when you need to do something for every selected item, iterating over all items and checking the Selected property is way too slow. Instead, you should use a while loop with GetNextItem with isSelected.)

Resources