StringGrid-Inhalt nach Excel exportieren
Oft kommt es vor, dass Daten, die in einer eigenen Anwendung verwaltet werden, zusammengefasst und ausgewertet werden sollen. Dazu bietet sich die Verwendung von Standardsoftware wie Excel an. Excel bietet hierzu eine Schnittstelle zur Automatisierung an. Details können auch im Tutorial OLE-Automation von MS Office nachgelesen werden.Folgendes Code-Beispiel exportiert den Inhalt eines StringGrids in ein Excel-Sheet.
uses ComObj, Math, SysUtils, Variants; //Hilfsfunktionen function StringToVariant(const SourceString : string) : Variant; var FloatValue : Extended; begin if TryStrToFloat(SourceString, FloatValue) then Result := FloatValue else Result := SourceString; end; function RefToCell(Col, Row : Integer) : string; var Pos : Integer; begin //Spalte bestimmen Result := ''; while Col > 0 do begin Pos := Col mod 26; if Pos = 0 then begin Pos := 26; Dec(Col); end; Result := Chr(Ord('A') + Pos - 1) + Result; Col := Col div 26; end; //Spalte und Zeile zusammenführen Result := Result + IntToStr(Row); end; //Inhalt eines TStringGrid nach Excel exportieren und anzeigen function ExportStringGridToExcel(StringGrid : TStringGrid) : Boolean; var Col : Integer; Data : OleVariant; ExcelApp : OleVariant; MaxCol : Integer; MaxRow : Integer; Range : OleVariant; Row : Integer; Workbook : OleVariant; Worksheet : OleVariant; Value : OleVariant; begin Result := False; //Verbindung zu Excel herstellen ExcelApp := CreateOleObject('Excel.Application'); try if not VarIsNull(ExcelApp) then begin //Neues Workbook öffnen Workbook := ExcelApp.Workbooks.Add; if not VarIsNull(Workbook) then begin //Maximalen Bereich bestimmen MaxCol := Min(StringGrid.ColCount, ExcelApp.Columns.Count); MaxRow := Min(StringGrid.RowCount, ExcelApp.Rows.Count); if (MaxRow > 0) and (MaxCol > 0) then begin //Worksheet auswählen Worksheet := Workbook.ActiveSheet; //Bereich auswählen Range := Worksheet.Range[RefToCell(1, 1), RefToCell(MaxCol, MaxRow)]; if not VarIsNull(Range) then begin //Daten aus Grid holen Data := VarArrayCreate([1, MaxRow, 1, MaxCol], varVariant); for Row := 0 to Pred(MaxRow) do begin for Col := 0 to Pred(MaxCol) do begin Value := StringToVariant(StringGrid.Cells[Col, Row]); Data[Succ(Row), Succ(Col)] := Value end; end; //Daten dem Excelsheet übergeben Range.Value := Data; Range.Columns.AutoFit; //Excel anzeigen Workbook.Activate; ExcelApp.Visible := True; Result := True; end; end; end; end; finally Value := UnAssigned; Data := UnAssigned; Range := UnAssigned; Workbook := UnAssigned; ExcelApp := UnAssigned; end; end;
Ein Worksheet kann je nach Excel-Programmversion nur eine bestimmte Anzahl von Spalten und Zeilen aufnehmen. Deshalb kann es erforderlich sein, dass die Daten des TStringGrid auf mehrere Workbooks und Worksheets aufgeteilt werden müssen. Wie das funktionieren kann, zeigt das folgende Code-Beispiel.
//Inhalt eines TStringGrid in Excel-Dateien speichern function WriteStringGridToExcelFiles(StringGrid : TStringGrid; const Directory : string) : Boolean; var Col : Integer; Data : OleVariant; ExcelApp : OleVariant; FileName : string; GridCol : Integer; GridRow : Integer; MaxCol : Integer; MaxRow : Integer; Range : OleVariant; Row : Integer; Value : OleVariant; Workbook : OleVariant; WorkbookCount : Integer; WorkbookIndex : Integer; Worksheet : OleVariant; WorksheetCount : Integer; WorksheetIndex : Integer; begin Result := False; //Verbindung zu Excel herstellen ExcelApp := CreateOleObject('Excel.Application'); try if not VarIsNull(ExcelApp) then begin Result := True; //Maximalen Bereich bestimmen Workbook := ExcelApp.Workbooks.Add; MaxCol := Min(StringGrid.ColCount, ExcelApp.Columns.Count); MaxRow := Min(StringGrid.RowCount, ExcelApp.Rows.Count); Workbook.Close; //Anzahl Worksheets und Workbooks bestimmen WorkbookCount := (StringGrid.RowCount div MaxRow); if StringGrid.RowCount mod MaxRow > 0 then Inc(WorkbookCount); WorksheetCount := (StringGrid.ColCount div MaxCol); if StringGrid.ColCount mod MaxCol > 0 then Inc(WorkbookCount); //Variantes Array zur Datenübergabe erstellen Data := VarArrayCreate([1, MaxRow, 1, MaxCol], varVariant); for WorkbookIndex := 0 to Pred(WorkbookCount) do begin //Neues Workbook öffnen Workbook := ExcelApp.Workbooks.Add; if not VarIsNull(Workbook) then begin //überzählige Worksheets entfernen while Workbook.Sheets.Count > 1 do WorkBook.Sheets.Delete; for WorksheetIndex := 0 to Pred(WorksheetCount) do begin //Neues Worksheet öffnen if WorkSheetIndex = 0 then WorkSheet := Workbook.ActiveSheet else Worksheet := Workbook.Sheets.Add(After := Workbook.ActiveSheet); if not VarIsNull(Worksheet) then begin //Bereich auswählen Range := Worksheet.Range[RefToCell(1, 1), RefToCell(MaxCol, MaxRow)]; if not VarIsNull(Range) then begin //Daten aus Grid holen for Row := 0 to Pred(MaxRow) do begin for Col := 0 to Pred(MaxCol) do begin GridCol := Col + (MaxCol * WorksheetIndex); GridRow := Row + (MaxRow * WorkbookIndex); if (GridCol < StringGrid.ColCount) and (GridRow < StringGrid.RowCount) then begin Value := StringToVariant(StringGrid.Cells[GridCol, GridRow]); Data[Succ(Row), Succ(Col)] := Value; end else Data[Succ(Row), Succ(Col)] := ''; end; end; //Daten dem Excelsheet übergeben Range.Value := Data; Range.Columns.AutoFit; end; end; end; end; //Workbook schließen und speichern FileName := Format('%s%.2d', [StringGrid.Name, Succ(WorkbookIndex)]); FileName := Directory + FileName; Workbook.Close(SaveChanges := True, Filename := FileName); Result := Result and (FileExists(FileName + '.xls') or FileExists(FileName + '.xlsx')); end; //Excel beenden ExcelApp.DisplayAlerts := False; ExcelApp.Quit; end; finally Value := UnAssigned; Data := UnAssigned; Range := UnAssigned; Workbook := UnAssigned; Worksheet := UnAssigned; ExcelApp := UnAssigned; end; end;
procedure TTestDialog.ExportButtonClick(Sender: TObject); begin ExportStringGridToExcel(DataStringGrid); end; procedure TTestDialog.SaveButtonClick(Sender: TObject); begin if WriteStringGridToExcelFiles(DataStringGrid, 'C:Test') then MessageDlg('Tabelle wurde gespeichert.', mtInformation, [mbOk], 0) else MessageDlg('Tabelle konnte nicht gespeichert werden', mtError, [mbOk], 0); end;
Weitere Informationen zur OLE-Automation von Excel können auch im Tipp Excel mit OLE-Automation steuern nachgelesen werden.