Da muß ich ein wenig wiedersprechen.
Fakt ist man muß eine Konvertierung machen, ob StringGrid, VST oder sonstwas.
Da unser Export mit unterschiedlichen "Grids" arbeiten können soll, habe ich eine "Wrapper"-Klasse geschrieben, damit die eingentliche Exportklasse übersichtlich bleibt.
Hier ein paar Ansätze:
Delphi-Quellcode:
procedure TExcelServer.WriteRange(Row, Col, RowCount, ColCount: integer; Values: OleVariant);
begin
ExcelWorksheet.Range[
TranslateCell(Row + 1, Col + 1),
TranslateCell(Row + RowCount, Col + ColCount)].Value := Values;
end;
Das ist die schnellste Variante GROSSE Datenmengen an Excel zu senden. (TranslateCell macht aus Integer die Excel Spalten/Zeilen-bezeichnungen)
Der OleVariant wird in der "Wrapper"-Klasse erzeugt:
Delphi-Quellcode:
function TDataWrapper.GetDataOle : OleVariant;
var
i, iRow, iCol : Longint;
bm : TBookmark;
FNodeData : PGridTreeData;
FNode : PVirtualNode;
begin
Result := VarArrayCreate([0, RowCount - 1,
0, ColCount - 1], varVariant);
{$REGION 'FAdvStringGridLink'}
if Assigned(FAdvStringGridLink) then
begin
for iCol := 0 to ColCount - 1 do
begin
for iRow := 0 to RowCount - 1 do
begin
Result[iRow, iCol] := FAdvStringGridLink.Cells[iRow, iCol];
end;
end;
end;
{$ENDREGION}
{$REGION 'FVirtualStringTreeLink'}
if Assigned(FVirtualStringTreeLink) then
begin
with FVirtualStringTreeLink do
begin
FNode := GetFirst;
for iRow := 0 to RowCount - 1 do
begin
FNodeData := GetNodeData(FNode);
for iCol := 0 to ColCount - 1 do
begin
Result[iRow, iCol] := FNodeData^.Columns[iCol];
end;
FNode := GetNext(FNode);
end;
end;
end;
{$ENDREGION}
{$REGION 'FDataSourceLink'}
if Assigned(FDataSourceLink) then
begin
with FDataSourceLink.DataSet do
begin
DisableControls;
bm := GetBookmark;
First;
iRow := 0;
while (not Eof) do
begin
i := 0;
for iCol := 0 to FieldCount - 1 do
begin
if Fields[iCol].Visible then
begin
Result[iRow, i] := Fields.Fields[iCol].AsString;
inc(i);
end;
end;
Next;
inc(iRow);
end;
GotoBookmark(bm);
FreeBookmark(bm);
EnableControls;
end;
end;
{$ENDREGION}
end;
RowCount und ColCount wird auch so ermittelt.
Der OleVariant aus GetDataOle kann wie ein Stringgrid benutzt werden, was ich für zusätzliche Formatierungen ausnutze. z.B.:
Delphi-Quellcode:
...
{$REGION 'Werte ggf. formatieren und dann einfügen —————————————————————————————'}
if iMonat > -1 then
begin
for iRow := 0 to AData.RowCount - 1 do
OleGrid[iRow, iMonat] := '01.' + OleGrid[iRow, iMonat];
end;
if (FExcelServer.Version.Major >= 11) then
begin
if iDatum > -1 then
begin
OleGrid[iRow, iDatum] := StrToDateTime(OleGrid[iRow, iDatum]);
end;
end;
...
{$REGION 'Daten schreiben ——————————————————————————————————————————————————————'}
FExcelServer.WriteRange(FStartRow,
FStartCol,
AData.RowCount,
AData.ColCount,
OleGrid);
{$ENDREGION}
...
Ich benutzt übrigens Early-binding um wenigstens ein bisschen Kontrolle zu behalten. (Sollte man bei solchen Problemen immer dazu sagen, erleichter das Verständnis ungemein)
Um jetzt auf das Wiedersprechen zu kommen:
man kann natürlich die Werte einzeln nach Excel schreibe:
Delphi-Quellcode:
{$REGION 'FVirtualStringTreeLink'}
if Assigned(FVirtualStringTreeLink) then
begin
with FVirtualStringTreeLink do
begin
FNode := GetFirst;
for iRow := 0 to RowCount - 1 do
begin
FNodeData := GetNodeData(FNode);
for iCol := 0 to ColCount - 1 do
begin
Result[iRow, iCol] := FNodeData^.Columns[iCol]; // Hier kann man statt den Variant zu füllen auch gleich Excel füttern
end;
FNode := GetNext(FNode);
end;
end;
end;
{$ENDREGION}
Diese Variante ist aber um
mehrere Größenordnungen langsamer!
Gruß David