Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Excel speichern (https://www.delphipraxis.net/216521-excel-speichern.html)

vesila 11. Jan 2025 15:57

Excel speichern
 
Hallo liebe Gemeinschaft,

habe beim abspeichern einer Exceldatei aus Delphi6 Schwierigkeiten.
beim Aufruf der Speicherroutine Workbook.saveAs(dateiname) erscheint die Fehlermeldung
Im Projekt ist eine Exception der Klasse EOleError aufgetreten: Meldung 'Variante referenziert kein Automatisierungsobjekt'.Prozefl wurde angehalten.
Auch beim Aufruf der Speicherroutine mit Excel.Workbook.saveAs(dateiname) erscheint die gleiche Fehlermeldung.
Excel und Woorkbook sind global als variant deklariert.
Was läuft da falsch?

DaCoda 11. Jan 2025 22:12

AW: Excel speichern
 
Ich habe eine kleine Unit als "Helper" für meine Projekte, wo ich Excel-Sheets brauche.
Da kannst du ja mal schauen ob du da was mit anfangen kannst.

Delphi-Quellcode:
unit tbOfficeUtils;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.StdCtrls,
  System.Win.ComObj;

const
  xlWBATChart = -4109;
  xlWBATExcel4IntlMacroSheet = 4;
  xlWBATExcel4MacroSheet = 3;
  xlWBATWorksheet = -4167;

type
  TExcelFile = class(TObject)
  private
    FApplication: OLEVariant;
    FWorkBook: OLEVariant;
    FWorkSheet: OLEVariant;
    FVisible: Boolean;
    FDisplayAlerts: Boolean;
    FActWorkSheetIdx: Integer;

    procedure SetVisible(Visible: Boolean);
    procedure SetDisplayAlerts(DisplayAlerts: Boolean);
  public
    constructor Create; virtual;
    destructor Destroy; override;

    function Open: Boolean;
    procedure Close;
    function ExportFile(FileName: TFileName): Boolean;
    function SelectWorkSheet(Index: Integer): Boolean;
    function AddWorkSheet: Integer;

    property Application: OLEVariant read FApplication;
    property WorkBook: OLEVariant read FWorkBook;
    property WorkSheet: OLEVariant read FWorkSheet write FWorkSheet;
    property Visible: Boolean read FVisible write SetVisible;
    property DisplayAlerts: Boolean read FDisplayAlerts write SetDisplayAlerts;
    property ActWorkSheetIdx: Integer read FActWorkSheetIdx;
  end;

implementation

uses
  tbUtils;

constructor TExcelFile.Create;
begin
  inherited Create;
  FApplication := NULL;
  FWorkBook := NULL;
  FWorkSheet := NULL;
  FVisible := False;
  FDisplayAlerts := False;
end;

destructor TExcelFile.Destroy;
begin
  if not VarIsNull(FWorkSheet) then begin
    FWorkSheet := NULL;
  end;

  if not VarIsNull(FWorkBook) then begin
    FApplication.Workbooks.Close;
    FWorkBook := NULL;
  end;

  if not varIsNull(Fapplication) then begin
    FApplication.Quit;
    FApplication := NULL;
  end;
  inherited Destroy;
end;

function TExcelFile.Open: Boolean;
begin
  Result := False;
  try
    FApplication := CreateOleObject('Excel.Application');
    if not VarIsNull(FApplication) then begin
      if not VarIsNull(FApplication) then begin
        FApplication.Visible := FVisible;
        FApplication.DisplayAlerts := FDisplayAlerts;
        try
          FWorkBook := FApplication.WorkBooks.Add(xlWBATWorksheet);
          if not VarIsNull(FWorkBook) then begin
            Result := True;
          end;
        except
          ErrorDialog('Die Arbeitsmappe konnte nicht erzeugt werden!');
          FWorkBook := NULL;
        end;
      end;
    end;
  except
    FApplication := NULL;
    ErrorDialog('Excel konnte nicht geöffnet werden!');
  end;
end;

function TExcelFile.AddWorkSheet: Integer;
begin
  Result := -1;
  if not VarIsNull(WorkBook) then begin
    Workbook.Worksheets.Add(After := Workbook.Worksheets[Workbook.Worksheets.Count]);
    Result := Workbook.Worksheets.Count;
  end;
end;

function TExcelFile.SelectWorkSheet(Index: Integer): Boolean;
begin
  Result := False;
  WorkSheet := WorkBook.Sheets[Index];
  if not VarIsNull(WorkSheet) then begin
    WorkSheet.Activate;
    FActWorkSheetIdx := Index;
    Result := True;
  end;
end;

function TExcelfile.ExportFile(FileName: TFileName): Boolean;
begin
  Result := False;
  if not VarIsNull(FWorkBook) then begin
    try
      SelectWorkSheet(1);
      FWorkbook.SaveAs(FileName);
      Result := True;
    except
      ErrorDialog('Die Arbeitsmappe: ' + QuotedStr(FileName) + ' konnte nicht gespeichert werden!');
    end;
  end;
end;

procedure TExcelFile.Close;
begin
  if not VarIsNull(FWorkSheet) then begin
    FWorkSheet := NULL;
  end;

  if not VarIsNull(FWorkBook) then begin
    FApplication.Workbooks.Close;
    FWorkBook := NULL;
  end;

  if not varIsNull(Fapplication) then begin
    FApplication.Quit;
    FApplication := NULL;
  end;
end;

procedure TExcelfile.SetVisible(Visible: Boolean);
begin
  FVisible := Visible;
end;

procedure TExcelFile.SetDisplayAlerts(DisplayAlerts: Boolean);
begin
  FDisplayAlerts := DisplayAlerts;
end;

end.
Benutzen kann man es Beispielsweise so:

Delphi-Quellcode:
procedure TForm1.btnTestClick(Sender: TObject);
var
  Excel: TExcelFile;
begin
  Excel := TExcelFile.Create;
  try
    with Excel do begin
      Visible := False;
      DisplayAlerts := False;
      if Open then begin
        if SelectWorkSheet(1) then begin
          WorkSheet.Name := 'Erstes Blatt';
          WorkSheet.Columns.Columns[1].ColumnWidth := 150;
          WorkSheet.Cells[1, 1] := 123.456;
          WorkSheet.Cells[1, 1].NumberFormat := '0,00';
          WorkSheet.Cells[2, 1] := 456;
          WorkSheet.Cells[3, 1] := 123;
          WorkSheet.Cells[1, 3] := 'Erstes Blatt';

          WorkSheet.Cells[1, 1].Interior.Color := clRed;
          WorkSheet.Cells[2, 1].Interior.Color := clLime;
          WorkSheet.Cells[3, 1].Interior.Color := clYellow;

          WorkSheet.Cells[1, 1].Font.Name := 'Arial';
          WorkSheet.Cells[1, 1].Font.Size := 20;
          WorkSheet.Cells[1, 1].Font.Bold := True;
          WorkSheet.Cells[1, 1].Font.Color := clYellow;

          WorkSheet.Range['A6', 'A6'].Formula := '=Sum(A1:A3)';

          if AddWorkSheet > -1 then begin;
            if SelectWorkSheet(2) then begin
              Worksheet.Name := 'Zweites Blatt';
              WorkSheet.Cells[1, 5] := 0.815;
              WorkSheet.Cells[1, 5].NumberFormat := '0,00';
              WorkSheet.Cells[1, 5].Font.Name := 'Aial';
              WorkSheet.Cells[1, 5].Font.Size := 6;
              WorkSheet.Cells[1, 5].Font.Bold := True;
              WorkSheet.Cells[1, 5].Font.Color := clRed;

              WorkSheet.Cells[2, 5] := 311264;
              WorkSheet.Cells[3, 5] := 270664;
              WorkSheet.Cells[1, 3] := 'Zweites Blatt';
              WorkSheet.Cells[1, 1].Interior.Color := clMaroon;
              WorkSheet.Cells[2, 1].Interior.Color := clGray;
              WorkSheet.Cells[3, 1].Interior.Color := clWhite;
            end;
          end;
        end;
        ExportFile(System.SysUtils.ExtractFilePath(Vcl.Forms.Application.ExeName) + 'Produktionsberichte.xlsx');
        Close;
      end;
    end;
  finally
    FreeAndNil(Excel);
  end;
end;

vesila 12. Jan 2025 17:09

AW: Excel speichern
 
Guten Abend DaCoda,

vielen Dank für die umfangreiche Unterstützung.
In meiner Delphi Version fehlen die in der uses Anweisung aufgeführten Komponenten bzw die dcu Dateien.
Kann ich mit einer anderen Schreibweise das Problem lösen also statt Winapi.Windows nur Windows, denn diese
sind in der Library vorhanden.
Desweiteren wird eine Unit tbUtils benötigt. wo kann ich die finden .

Viele Grüße und noch einen schönen Sonntag
vesil

DaCoda 12. Jan 2025 17:29

AW: Excel speichern
 
Durch eine andere Schreibweise, wie zum Beispiel Windows, statt Winapi.Windows müsste es gehen. Die tbUtils werden im Beispiel nicht gebraucht, kannst du weglöschen.

Gutes Gelingen...

LG
Thorsten

vesila 14. Jan 2025 18:19

AW: Excel speichern
 
Guten Abend DaCoda,

ich habe die Anwendung in einem separaten Projekt getestet und wie zu erwarten,
funtioniert sie.

Die unit tbofficeUtils habe ich dann in meine Anwendung eingebunden und entsprechend zugewiesen var ExcFile: TExcelFile; um auf die Prozeduren zugreifen zu können.

Mit nachfolender Prozedur lese ich die Exceltabelle ein.
Delphi-Quellcode:
procedure TVermkal.DateiOeffnenAccept(Sender: TObject);
 var
      DatSatzname :String;
begin
DatSatzName := DateiOeffnen.Dialog.FileName;
Statbar(DatSatzName);
excel := CreateOleObject('Excel.Application');// Excel ˆffnen
wb := excel.Workbooks.Open(DatSatzName);
excel.visible :=true;
ladeflg:= true;
testpfad :=DatSatzName;
end;
Mit dieser Prozedur will die aktualisierte Datei speichern
Delphi-Quellcode:
procedure TVermkal.SpeichernAccept(Sender: TObject);

begin
 testpfad:=Speichern.Dialog.FileName;  
 Excfile.ExportFile(testpfad);
end;
In der Zeile
Delphi-Quellcode:
 if not VarIsNull(FWorkbook) then begin
wird eine Exception der Klasse EAccessViolation aufgerufen
Zugriffsverletzung an Adresse xxxx Lesen von Adresse xxxx.

Wie muss ich den Aufruf Excfile.ExportFile(testpfad); in die
SpeichernAccept Prozedur einbinden.

Viele Grüße und einen schönen Wochenanfang
Vesila

Blup 15. Jan 2025 09:10

AW: Excel speichern
 
FWorkBook wird nicht korrekt zugewiesen.
Delphi-Quellcode:
FWorkBook := FApplication.WorkBooks.Add(xlWBATWorksheet);
..
Ersetzen durch
Delphi-Quellcode:
{fügt das neue WorkBook am Anfang der Liste ein:}
FApplication.WorkBooks.Add(xlWBATWorksheet);
FWorkBook := FApplication.Workbooks[1];
..

DaCoda 16. Jan 2025 07:51

AW: Excel speichern
 
So wie Blup schrieb. Hast du einfach nur die korrekte Zuweisung vergessen.

Und ein paar TRY...EXCEPT Blöcke für die Fehlerbehandlung wären auch gut...

Viel Erfolg mit deinem Projekt.

LG
Thorsten


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:09 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz