Ok, I understand that sorting in the underlying sheet directly would be preferred. It would involve a lot more work. Because TCustomDrawGrid already does the most work I did create the two functions needed to do this in the grid itself. The grid would always have to sort the underlying sheet because otherwise you would need two sheet in memory. StringGrid also sorts its underlying data. Comparing it to something like a dataset is not fair because in that case you would need to create a real database engine which could sort "on the fly" (and leave the memory structure intact).
A sort routine in the spreadsheet itself would also need to receive a complete range (from/to column/rows) to sort and an index in that range (like you select a range in Excel and sort according to the 3th selected column or row). In TCustomDrawGrid.SortColRow the complete row (or column) gets sorted. I don't think you can adjust the range to sort (columns when sorting rows and rows when sorting columns).
So something like this:
TsWorksheet.SortSheet("E", "D10:J28") sorting range D10:J28 taking values from column E or
TsWorksheet.SortSheet("12", "D10:J28") sorting range D10:J28 taking values from row 12 or
TsWorksheet.SortSheet("12", "D:J") sorting range D:J taking values from row 12 or
TsWorksheet.SortSheet("A", "") sorting complete sheet taking values from column A
Here is my implementation for TCustomDrawGrid.SortColRow so far: (which we can throw in the bin because we need to implement this in TsWorksheet itself)
TsWorksheetGrid = class(TsCustomWorksheetGrid)
// ...
protected
// ...
procedure ColRowExchanged(IsColumn: boolean; index, WithIndex: integer); override;
function DoCompareCells(Acol, ARow, Bcol, BRow: integer): integer; override;
// ...
end;
procedure TsWorksheetGrid.ColRowExchanged(IsColumn: boolean; index, WithIndex: integer);
var
iCol, iRow: integer;
cell1: PCell;
cell2: PCell;
procedure SwapCell(C1, C2: PCell);
var
cell0: PCell;
Row1, Col1: integer;
Row2, Col2: integer;
begin
Row1 := C1^.Row;
Col1 := C1^.Col;
Row2 := C2^.Row;
Col2 := C2^.Col;
New(cell0);
cell0^ := cell1^;
cell1^ := cell2^;
cell2^ := cell0^;
cell1^.Row := Row1;
cell1^.Col := Col1;
cell2^.Row := Row2;
cell2^.Col := Col2;
Dispose(cell0);
end;
begin
if IsColumn then
begin
for iRow := HeaderCount to RowCount - 1 do
begin
cell1 := Worksheet.GetCell(iRow - HeaderCount, index - HeaderCount);
cell2 := Worksheet.GetCell(iRow - HeaderCount, Withindex - HeaderCount);
SwapCell(cell1, cell2);
end;
end
else { IsColumn }
begin
for iCol := HeaderCount to ColCount - 1 do
begin
cell1 := Worksheet.GetCell(index - HeaderCount, iCol - HeaderCount);
cell2 := Worksheet.GetCell(Withindex - HeaderCount, iCol - HeaderCount);
SwapCell(cell1, cell2);
end;
end;
end;
function TsWorksheetGrid.DoCompareCells(Acol, ARow, Bcol, BRow: integer): integer;
var
A, B: string;
cell1: PCell;
cell2: PCell;
begin
if Assigned(OnCompareCells) then
Result := inherited DoCompareCells(Acol, ARow, Bcol, BRow)
else
begin
cell1 := Worksheet.GetCell(ARow - HeaderCount, ACol - HeaderCount);
cell2 := Worksheet.GetCell(BRow - HeaderCount, BCol - HeaderCount);
A := Worksheet.ReadAsUTF8Text(cell1);
B := Worksheet.ReadAsUTF8Text(cell2);
Result := UTF8CompareText(A,B);
if SortOrder = soDescending then
Result := -Result;
end;
end;