Einzelnen Beitrag anzeigen

pero.s

Registriert seit: 6. Feb 2005
Ort: Konstanz
4 Beiträge
 
Delphi 2006 Professional
 
#1

Excel aus einem Thread fernsteuern

  Alt 8. Apr 2005, 13:53
Hallo allerseits.

Ich habe mir ein kleines Programm geschrieben, das mir Daten in eine Excel-Tabelle schiebt und formatiert. Das hat dann auch alles wunderbar funktioniert. Und, da alles funktioniert wollte ich als letzten Schritt die Routine, die den Export tätigt, in einen separaten Thread bauen, da ich nicht unnötig das Hauptformular auslasten möchte.

Die Routine ist:
Delphi-Quellcode:
uses
  Windows, ExcelXP, OleServer;

(* - Im Objekt deklariert
    ExclApp: TExcelApplication;
    ExclDoc: TExcelWorkbook;
    ExclSht: TExcelWorksheet;
*)


procedure TFormMain.ActionExpsExecute(Sender: TObject);
var lcid, i, j: LongInt;
    EAP: _Application;
    EWB: _Workbook;
    EWS: _Worksheet;
    EFM, ECL: OleVariant;
begin
  lcid := LOCALE_USER_DEFAULT;
  ActionStop.Enabled := ListView.Items.Count > 0;
  ActionScan.Enabled := not ActionStop.Enabled;
  ActionExps.Enabled := ActionScan.Enabled;
  if ActionStop.Enabled
  then begin
    PBarRow.Position := 0;
    PBarRow.Max := ListView.Items.Count - 2;
    PBarAll.Position := 0;
    PBarAll.Max := ListView.Columns.Count - 1;
    Refresh;
    ExclApp.Connect;
    ExclApp.Visible[lcid] := True;
    EWB := ExclApp.Workbooks.Add('', lcid);
    ExclDoc.ConnectTo(EWB);
    ExclDoc.Activate;
    EWS := ExclDoc.Activesheet as _Worksheet;
    ExclSht.ConnectTo(EWS);
    i := 1;
    while i < ListView.Columns.Count
    do begin
      PBarAll.Position := i;
      PBarAll.Refresh;
      ECL := Chr(64 + i);
      if (Length(ListView.Columns[i].Caption) = 0) or (LowerCase(ListView.Columns[i].Caption) = 'text')
      then EFM := NS_AT else EFM := ListView.Columns[i].Caption;
      ExclSht.Range[ECL + '1', ECL + IntToStr(ListView.Items.Count)].NumberFormat := EFM;
      j := 0;
      while j < ListView.Items.Count
      do begin
        if i <= ListView.Items[j].SubItems.Count
        then begin
          PBarRow.Position := j;
          PBarRow.Refresh;
          ECL := WideString(Chr(64 + i) + IntToStr(j + 1));
          EFM := WideString(ListView.Items[j].SubItems[i - 1]);
          ExclSht.Range[ECL, ECL].Value2 := EFM;
        end;
        j := j + 1;
      end;
      ECL := Chr(64 + i);
      //ExclSht.Range[ECL, ECL].AutoFit;
      i := i + 1;
    end;
    (*try
      Exporter := TTrExExps.Create(not ActionStop.Enabled);
      Exporter.FreeOnTerminate := ActionStop.Enabled;
      Exporter.OnTerminate := TrExOnTerminate;
    except
    end;*)

  end;
end; //ActionExpsExecute
Wie man sehen kann, ist die Routine voll in das Programm mit anderen Komponenten integriert und ich habe gegen Ende der Routine den Start des Threads auskommentiert.

Wenn ich nun diese Routine in einen Thread integriere und die drei Elemente ExclApp, ExclDoc und ExclSht manuell mit
  ExclApp := TExcelApplication.Create(FormMain); //Beispiel erzeuge und dann irgendeinen Aufruf via ExclApp starte, bekomme ich einen Laufzeitfehler der besagt, dass CoInitialize nicht aufgerufen wurde.
Ich habe das Ganze auch ohne die drei Elemenete ExclApp, ExclDoc und ExclSht versucht, indem ich nur über _Application, _Workbook und _Worksheet mit
Delphi-Quellcode:
procedure ...
var Unknown: IUnknown;
    OleRes: HRESULT;
begin
  OleRes := GetActiveObject(CLASS_ExcelApplication, nil, Unknown);
  if OleRes = MK_E_UNAVAILABLE
  then EAP := CoExcelApplication.Create
  else begin
    OleCheck(OleRes);
    OleCheck(Unknown.QueryInterface(_Application, EAP));
  end;
end; //...
gegangen bin - mit selbem Ergebnis.

Was mache ich falsch?

P.S.: Wenn Interesse am ganzen Projekt besteht, so kann ich das hier mit hereinstellen.
Pero S.
  Mit Zitat antworten Zitat