I have found many solutions online but they aren't working becaue the StringGrid1.ColumnCount peoperty is read only. I am using Delphi 10 Seattle.
I have a StringGrid1 and I need to add columns at runtime. To be specific I have to add columns according to the size of a TList. In particular:
var a: TList<double>;
begin
//fill the TList...
for i := 0 to a.Count - 1 do
begin
StringGrid1.AddColumn(); //how can I do this?
end;
end;
I find this very easy on Lazarus (but it has FPC of course) but on Delphi I really don't know what to do. I am working on Firemonkey.
Use the grid's AddObject() or InsertObject() method to add an object instance of the desired TColumn-derived class, like TStringColumn. The column object will get added to the grid's Columns array. The ColumnCount property simply returns the number of columns in the array, that is why it is read-only.
I solved my problem but I need to know why this problem raised to me ?!
I write a project that load file to listBox then delete the strings one by one,
but when I delete listBox strings this exception raised to me!
list index out of bounds (5) !
I type this for loop to read list box and delete strings:
for i := 0 to ListBox3.Count -1 do
begin
ShowMessage(ListBox3.Items[i]);
ListBox3.items.Delete(i);
end;
and my problem solved by do a little change in for-loop statement
for i := ListBox3.Items.Count - 1 downto 0 do
begin
ShowMessage(ListBox3.Items[i]);
ListBox3.items.Delete(i);
end;
Why the first statement raised an exception, and the second one work fine ?
By deleting items moving forward, you're cutting the branch off that you're standing on. :-) The upper bounds of the loop is only evaluated once, before the loop begins, and if you delete items there are now fewer in the list than there were when the bound was calculated.
Loop limit is evaluated (for example, List.Count - 1 = 5). Valid indexes into it are [0..4]
The loop starts, and you retrieve List[0] and delete it. List Count = 4,
bounds is still 5
The index is incremented, you retrieve and delete List[1]. List Count = 3, bounds is still 5
The index is incremented, you retrieve and delete List[2]. List Count = 2, bounds is still 5.
The index is incremented, you retrieve List[3] - Oops! There are only 2 items in the list, now at indexes [0..1] - List index out of bounds(3).
By iterating backwards, even though the bounds is still only calculated at the beginning, you're removing the items from the end and decrementing the count at the same time.
Bounds is 5, and you retrieve List[4] and delete it. Count is now 4, bounds is still 5
Index is decremented, and you retrieve List[3] and delete it. Count is now 3, bounds is still 5
Index is decremented, and you retrieve List[2] and delete it. Count is now 2, bounds is still 5.
Index is decremented, and you retrieve and delete List[1]. Count is now 1, bounds is still 5.
Index is decremented, and you retrieve and delete List[0]. List is now empty, but we've reached the terminating condition of the loop (downto 0) and the loop exits safely.
Each time you delete an item from the list, the list contains one less item. However, the for statement copies the list count at the beginning, and is not updated upon each iteration. Therefore, by the time you get halfway through the list, the counter i becomes larger than the current (new) list count, even though the list no longer contains the original number of items.
As an alternative, you could also do a loop like this:
while ListBox3.Items.Count > 0 do begin
ShowMessage(ListBox3.Items[0]);
ListBox3.items.Delete(0);
end;
There may be situation when you DO NOT delete certain items. Then the generic approach would be
i := 0;
while i < ListBox3.Items.Count do
begin
ShowMessage(ListBox3.Items[i]);
if <wantToDelete> then // some condition there
ListBox3.Items.Delete(i)
else
Inc(i);
end;
Anyone can help what is the best way to compare two stringlist and get difference from them?
For example if I have AList and BList like
AList
ABC
CDE
EFG
KLM
STA
LMO
TKJ
BList
ABC
CDE
EFG
KLM
STA
LMO
TKJ
FGJ
FGJ
ARE
IJE
If I compare them like
for i := 0 to BList.count-1 do
if AList.indexof(BList[i]) < 0 then
ResultList.Add(BList[i]);
Result is:
FGJ
FGJ
ARE
IJE
I need elements only once. How can I avoid multiple items? Is there a better solution than to make a procedure that remove multiple items from the List? Sorry for my English and thanks for the help!
The TStringList has a property Duplicates which controls what should happen when duplicates are attempted to be added to a sorted list.
From the documentation:
dupIgnore Ignore attempts to add duplicate strings to the list.
dupError raise an EStringListError exception when an attempt is made
to add duplicate strings to the sorted list.
dupAccept Permit duplicate strings in the sorted list.
So, set
ResultList.Sorted := True;
ResultList.Duplicates := dupIgnore;
I'm using a TcxGrid with Grouping. I want to find out how many grouped rows there are but I can't seem to find the right property. There is a <mytableview>.GroupedItemCount but that just refers to how many columns the grid is getting grouped by.
Basically I just want to know if all the groups are collapsed. I could keep a count of expanded groups by watching the GroupRowExpanded and GroupRowCollapsed events but it feels like there should be a better way.
My current plan is to compare the group count with <mytableview>.ViewData.RowCount. If they are different then I must have an expanded group.
I'm guessing the answer is simple.. but the TcxGrid has so many options that I'm not having much luck finding the right one.
I think you are looking for:
level0GroupCount := gridview.DataController.Groups.ChildCount[-1];
This is the number of data groups at level 0.
To check if every groups are full collapsed:
function AreGridGroupsCollapsed(_gridView : TcxGridDBTableView): Boolean;
var
level0GroupCount : Integer;
begin
level0GroupCount := _gridView .DataController.Groups.ChildCount[-1];
Result := groupCount = _gridView.ViewData.RowCount;
end;
I have a TDbGrid, and I can easily tell how many columns are in it at runtime with the FieldCount property, but there doesn't seem to be a corresponding RowCount property to display how many records are being displayed. How can I find this out?
Both RowCount and VisibleRowCount are protected properties in TCustomGrid that are not exposed in TDBGrid. But you can get round that doing the following:
type
TDummyGrid = class(TDBGrid);
RowCount := TDummyGrid(MyDBGrid).RowCount;
VisibleRowCount := TDummyGrid(MyDBGrid).VisibleRowCount;
Be warned that this includes the header.
You could try:
DBGrid1.DataSource.DataSet.RecordCount
Maybe there are better solutions. But this worked for me.
I would use
TDbGrid.ApproxCount