Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Daten in Excel übertragen (https://www.delphipraxis.net/187253-daten-excel-uebertragen.html)

zeras 11. Nov 2015 18:01

Daten in Excel übertragen
 
Hallo,

Ich habe ein Programm geschrieben, was auch schon einige Male verkauft wurde.
Nun fragen Kunden an, die dort angezeigten Daten ins Excel exportieren zu können.
Mit einigen privaten Programm habe ich das schon gemacht. Das läuft auch soweit.
Nun könnte ich die Routinen nutzen, um die Daten auch in meinem kommerziellen Programm zu exportieren.
Was ist genau zu beachten wegen der verschiedenen Excelversionen (2003, 2010, 201x), Windowsversionen etc.?
Ich möchte hier nicht ständig nachbessern.
Die Funktionen sind teilweise von hier und auch von Swissdelphi.

punktl 11. Nov 2015 19:43

AW: Daten in Excel übertragen
 
Hallo,

also ich exportiere Daten nach Excel 2000, 2002/3/7/10/13 mit immer der gleichen Routine. Vorgehen nach http://www.djpate.freeserve.co.uk/AutoExcl.htm (Late Binding).
Das führt hier zu keinen Problemen mit den unterschiedlichen Versionen, wobei ich zusätzlich zum reinen Export noch Zellen formatiere (färben, Linien, Schriftformatierung) und Formeln einfüge.

hth
Peter

zeras 12. Nov 2015 18:50

AW: Daten in Excel übertragen
 
Danke für die Info.
Werde das mal mit deinen Infos so angehen.

Chemiker 12. Nov 2015 20:20

AW: Daten in Excel übertragen
 
Hallo zeras,

welche und wie viele Daten sollen nach EXCEL übertragen werden, davon sollte man die Methode abhängig machen wie man die Daten überträgt.

Bis bald Chemiker

zeras 12. Nov 2015 21:40

AW: Daten in Excel übertragen
 
Zitat:

Zitat von Chemiker (Beitrag 1321362)
Hallo zeras,

welche und wie viele Daten sollen nach EXCEL übertragen werden, davon sollte man die Methode abhängig machen wie man die Daten überträgt.

Bis bald Chemiker

Ich denke, so zwischen 100 und 200 Zellen sollen eingetragen werden. Muss nicht sonderlich schnell sein, aber wie schon gesagt, ich möchte keine Probleme beim Endanwender haben, dass etwas nicht geht mit den verschiedenen Excelversionen. Ich habe nur Excel 2010 und kann daher nur mit dieser Version testen. Die Kunden haben aber alles. Das kennt ihr besser als ich.

Pfaffe 13. Nov 2015 08:35

AW: Daten in Excel übertragen
 
Ich kann mit gutem Gewissen die Komponente von Ondřej Pokorný empfehlen:
http://www.kluug.net/xlsx-ods-delphi.php

frankyboy1974 13. Nov 2015 09:02

AW: Daten in Excel übertragen
 
Hallo,

wenn ich wirklich nur Daten nach Excel übertragen möchte, würde ich diese einfach als CSV-Datei exportieren. Dann kannst du diese wahrscheinlich auch noch in hundert Jahren mit Excel importieren.

mfg

ps.: Aber warum auch einfach, wenn's .....

zeras 13. Nov 2015 18:03

AW: Daten in Excel übertragen
 
Zitat:

Zitat von frankyboy1974 (Beitrag 1321392)
Hallo,

wenn ich wirklich nur Daten nach Excel übertragen möchte, würde ich diese einfach als CSV-Datei exportieren. Dann kannst du diese wahrscheinlich auch noch in hundert Jahren mit Excel importieren.

mfg

ps.: Aber warum auch einfach, wenn's .....

Die Übertragung der Daten soll beim Kunden erfolgen. Ich glaube nicht, dass alle Kunden wissen, was ein CSV File ist, wie man die Daten dann exportiert und wieder importiert. So wollte ich das für den Kunden einfacher machen.

Eine Frage habe ich noch.
Ich möchte dem Kunden die Möglichkeit bieten, dass er die Werte, die übertragen werden sollen, selber beeinflussen kann. So war meine Idee, dass er in meinem Programm auf eine Zelle in einem Grid klickt, dann einen Button drückt, der aussagt, dass dieser Wert übertragen werden soll, dann in einen offenen Excelsheet eine Zelle anklickt und diese Zelle dann als Ziel gilt.
So könnte sich der Kunde sein eigenes Formular zusammenklicken. Diese Funktion wird dann aufgezeichnet und mann kann diese Kopiererei dann automatisch ausführen lassen.
So kann sich der Kunde sein Excelformular selber zusammenbauen (mit seinen Logos etc.) und trotzdem die Daten aus meinem Programm bekommen.
Ist das verständlich?

BUG 14. Nov 2015 12:50

AW: Daten in Excel übertragen
 
Zitat:

Zitat von zeras (Beitrag 1321467)
Ich glaube nicht, dass alle Kunden wissen, was ein CSV File ist, wie man die Daten dann exportiert und wieder importiert. So wollte ich das für den Kunden einfacher machen.

Das ist ja verständlich und durchaus löblich.

Zitat:

Zitat von zeras (Beitrag 1321467)
Diese Funktion wird dann aufgezeichnet und mann kann diese Kopiererei dann automatisch ausführen lassen.

Dieses automatisierte Klicken und Kopieren klingt nach einer monströsen Fehlerquelle :pale:
Dabei kann so viel schief-gehen (zwischendurch aufploppende Fenster, usw.).

Zitat:

Zitat von zeras (Beitrag 1321467)
So kann sich der Kunde sein Excelformular selber zusammenbauen (mit seinen Logos etc.) und trotzdem die Daten aus meinem Programm bekommen.

Anderseits kann man davon ausgehen, dass ein Nutzer, der sich Formulare in Excel zusammenbaut, im Prinzip alles mit Excel macht und sich auch entsprechend auskennt.
Im Prinzip würde es für so einen Nutzer reichen, wenn er irgendwie alle Daten in einen Reiter bekommt. Das Herauspicken kann er dann über Formeln/Referenzen selbst in Excel in seiner gewohnten Arbeitsumgebung machen.

zeras 14. Nov 2015 13:06

AW: Daten in Excel übertragen
 
Ich wollte das so machen, dass der Kunde sich ein eigenes Formular erstellt mit seinem Logo, Adresse etc. und mein Programm bringt dann die Daten.
Es gibt zwar in meinem Programm ein Drucken der Daten, aber verschiedene Kunden möchten die Daten in einem eigenen Formular.

Heute habe ich mal einiges probiert.
Auf dem Source Grid mache ich Drag und auf dem Excelformular dann Drop.
Mit einigem Aufwand sollte ich doch wissen, wo die Daten herkommen und wo sie hingegangen sind. Wenn ich dann direkt das Excelformular ansteuere, sollten doch keine aufopppenden Fenster etc. ein Problem darstellen beim Ablegen der Daten. Wie gesagt, die Idee funktioniert im Prinzip, aber es könnte natürlich noch Sachen geben, die ich derzeit nicht überblicken kann.

Chemiker 14. Nov 2015 14:31

AW: Daten in Excel übertragen
 
Hallo zeras,

wenn Du das so aufbauen willst, kann der Kunden doch einfach mit Kopieren und Einfügen die Daten in das Excel-Formular eintragen. Meiner Erfahrung nach ist es immer sehr Fehleranfällig wenn der Benutzer selbstständig ohne Programmführung zwischen 2 unabhängige Programme agieren soll.
Am besten ist wenn der Benutzer nicht eingreifen kann. Ich würde ein Formular in Excel gestalten und die Adresse und Logo usw. vom Kunden im eigenen Programm ablegen lassen. Beim Aufrufen der Excel-Funktion würde ich dann das Excel-Formular aufrufen und die Kunden spezifische Daten an die dafür vorgesehen stellen eintragen, mit den zuvor ausgesuchten Daten. Anschließend würde ich den Kunden das Formular abspeichern lassen(oder auch ausdrucken), ohne das er überhaupt Excel gesehen hat. Er kann dann, wenn er will diese Excel-Datei selber nochmal in Excel aufrufen und individuell anpassen.

Bis bald Chemiker

p80286 14. Nov 2015 15:00

AW: Daten in Excel übertragen
 
Leider kenne ich mich in Excel nicht so gut aus, darum denke ich bei Formular zunächst an Word und Bookmarks um die Daten abzulegen.
In Excel sollten dann die Daten in spez. Felder abgelegt werden, d.h. Dein Programm benötigt die Information über die Zielfelder um die Daten dort abzulegen.

Gruß
K-H

zeras 14. Nov 2015 15:37

AW: Daten in Excel übertragen
 
Zitat:

Zitat von Chemiker (Beitrag 1321487)
Am besten ist wenn der Benutzer nicht eingreifen kann.

Da gebe ich dir vollkommen Recht. Deshalb versuche ich ja, über euch noch die beste Lösung zu finden.

Zitat:

Zitat von Chemiker (Beitrag 1321487)
Ich würde ein Formular in Excel gestalten und die Adresse und Logo usw. vom Kunden im eigenen Programm ablegen lassen.

Das Excel Grundformular sollte der Kunde selber gestalten können. Da aber jeder Kunde sein eigenes Logo hat, wollte ich das auch vom Kunden mit implementieren lassen.

Zitat:

Zitat von Chemiker (Beitrag 1321487)
Beim Aufrufen der Excel-Funktion würde ich dann das Excel-Formular aufrufen und die Kunden spezifische Daten an die dafür vorgesehen stellen eintragen, mit den zuvor ausgesuchten Daten.

Das ist ja das, was ich will. Das Problem hier ist, dass jeder Kunde ein eigenes Formular haben will. Das bedeutet, dass Kunde 1 einen Wert in Zeile 1, Spalte 1 haben will, der Kunde 2 einen Wert in Zeile 2, Spalte 2 haben will, usw.
Die Kunden haben teilweise aus der Vergangenheit selbst ein Formular entworfen und möchten dass nun mehr oder weniger automatisiert füllen. Aber jeder Kunde hat seine eigenen Ideen in das Formular gebracht.

Zitat:

Zitat von Chemiker (Beitrag 1321487)
Anschließend würde ich den Kunden das Formular abspeichern lassen(oder auch ausdrucken), ohne das er überhaupt Excel gesehen hat. Er kann dann, wenn er will diese Excel-Datei selber nochmal in Excel aufrufen und individuell anpassen.

Da gehe ich auch mit.

Mein eigentliches Problem wäre dann, wie der Kunde sein Formular aufbaut und wie ich an die entsprechenden Zellen komme. Ich könnte auch die Zellen benennen lassen, aber das macht auch viel Arbeit.
Deshalb dachte ich an einen "Teach Modus". Der Kunde markiert mit Drag eine Zelle aus meinem Grid. Dann legt er es mit Drop auf die entsprechende Zelle im Excel. Dies dann mit allen gewünschten Werten. So hat der Kunde einmalig die Arbeit. Beim nächsten Mal starte ich per Makro die Werte des Teach-Modus und das Formular füllt sich mit den Werten automatisch. Ich muss nur die Drags und Drops merken und wieder abspielen.
Ich hoffe, das ist einigermaßen verständlich rumgekommen.

Das Übertragen klappt nun auch soweit, nur habe ich noch nicht herausgefunden, wie man sicherstellen kann, dass die Daten auch im Excel angekommen sind.

Mit
Delphi-Quellcode:
var
  WS: OleVariant;
  Content : OleVariant;

begin
  Memo1.Lines.Add('Grid3OleDragStop'+ Format('OLEEffect=%d',[OLEEffect]));

  ExcelApplication1.Connect;
  ExcelWorkbook1.ConnectTo(ExcelApplication1.ActiveWorkbook);
  ExcelWorksheet1.ConnectTo(ExcelApplication1.ActiveSheet as _Worksheet);
  WS := ExcelApplication1.ActiveSheet as _Worksheet;

  ShowMessage(Format('%d, %d',[ExcelApplication1.ActiveCell.Column, ExcelApplication1.ActiveCell.Row]));

end;
bekomme ich auch schon die Zelldaten raus, aber damit ist nicht sichergestellt, dass diese auch im Excel gelandet sind.
Da bräuchte ich noch eine Idee.

nahpets 14. Nov 2015 17:20

AW: Daten in Excel übertragen
 
Hallo zeras,

mal so unkoordiniert dahingedacht:

In Excel kann man ja in einer Datei mehrere Tabellen haben.

Wie wäre es damit:

In der ersten Tabelle ist das vom Kunden erstellte Formular.
In die zweite Tabelle bringst Du die Daten.

Der Kunde kann nun aus deinen Daten innerhalb von Excel, per Formel, die von ihm gewünschten Informationen an die Stelle der ersten Tabelle (also seines Formulares) bringen, ohne dass Du wissen muss, wo er welche Daten hinhaben möchte.
(Wenn er sein Formular ändert, muss Du das nicht wissen, er ändert einfach die Verknüpfungen zwischen Tabelle 1 und Tabelle 2 und gut isssss...)

Sollte die "Fernsteuerung" von Excel (warum auch immer) nicht funktionieren, so könntest Du die Daten aus Deinem Programm in einen tabulatorseparierten Text packen, diesen in die Zwischenablage kopieren und dann den Anwender bitten, er möge in Excel auf die zweite Tabelle gehen und dort die Daten aus der Zwischenablage einfügen. Das wäre quasi ein "halbautomatisches" Copy&Paste.

Vor Jahr(zehnt)en musst ich mal aus dem StringGrid eines Programmes eine Exceltabelle erstellen, die aber (leider) einen anderen Aufbau hatte, als die Daten im StringGrid, so dass eine 1:1-Übernahme nicht möglich war. Außerdem sollte die Exceltabelle auch noch ein bisserl "schöner" werden.

Den Quelltext dazu hab' ich noch (gefunden):
Delphi-Quellcode:
// Exceltabelle füllen
procedure TfmDaten.acExcelExecute(Sender: TObject);
Var
          i              : Integer;
          k              : Integer;
          l              : Integer;
          sDirName       : String;
          sFileName      : String;
          iRecordCount   : Integer;
          sEMessage      : String;
          iErrorCode     : Word;
          iExcelIndex    : Integer;
          ea             : TExcelApplication;
          ewb            : TExcelWorkbook;
          ews1            : TExcelWorkSheet;
          lcid           : Integer;
          sRange         : String;
          sRange2         : String;

begin
  // Schalter für "Excel arbeitet" einschalten.
  bExcelActive    := True;
  // Variabeln für die Verbindung zu Excel initialisieren
  ea              := TExcelApplication.Create(Self);
  ewb             := TExcelWorkbook.Create(Self);
  ews1             := TExcelWorksheet.Create(Self);
  // Verbindungsart zu Excel festlegen.
  ea.ConnectKind  := ckNewInstance;
  ewb.ConnectKind := ckNewInstance;
  ews1.ConnectKind := ckNewInstance;
  // Diese ID wird zur Komunikation mit Excel benötigt.
  lcid            := LOCALE_USER_DEFAULT;
  Try
    // Excel soll unsichtbar arbeiten.
    ea.Visible[lcid] := False;
    // Comboboxen synchronisieren.
    If cbNamen.ItemIndex < 0 Then cbNamen.ItemIndex := cbEMail.ItemIndex
    Else If cbEMail.ItemIndex < 0 Then cbEMail.ItemIndex := cbNamen.ItemIndex
    Else cbEMail.ItemIndex := cbNamen.ItemIndex;
    // Über die MitarbeiterID aus ProgInfo den Dateipfad holen.
    fmDataBase.qryDOIT.Close;
    fmDataBase.qryDOIT.SQL.Clear;
    fmDataBase.qryDOIT.SQL.Text := fmDataBase.fnGetSQL(99);
    fmDataBase.qryDOIT.ParamByName('MITARBEITERID').AsInteger := DatenTabelle.Mitarbeiter.MitarbeiterID;
    fmDataBase.fnOpenSQL(fmDataBase.qryDOIT,-1,iRecordCount,sEMessage,iErrorCode,0);
    sDirName := fmDataBase.qryDOIT.Fields[0].AsString;
    // Dateinamen zusammenbauen.
    sFileName := sDirName + '\Daten.' + Trim(DatenTabelle.Mitarbeiter.Name) + ' ' + IntToStr(DatenTabelle.Mitarbeiter.Jahr) + '.xls';
    // Verbindung zu Excel herstellen.
    ea.Connect;
    // Falls die Datei schon existiert, müssen wir sie löschen, da wir sonst
    // mit ferngesteuertem Excel keine neue Datei erstellen können,
    // bzw. Excel zeigt einen Dialog an, zum Überschreiben der Datei oder Speichern
    // unter einem anderen Namen, dies ist auch der Fall, wenn die Datei noch offen ist.
    If FileExists(sFileName) Then Begin
      If Not DeleteFile(sFileName) Then Begin
        // hier haben wir dann ein Problem
        ShowMessage('Die Excel-Tabelle ' + sFileName + ' ist bereits geöffnet.'
        + #13 + 'Bitte schließen Sie diese Datei in Excel, andernfalls kann das Programm nicht korrekt weiter arbeiten.');
      End;
    End;
    // Neue Arbeitsmappe aufmachen.
    ea.Workbooks.Add(EmptyParam,lcid);
    // Verbindung zur aktiven Arbeitsmappe herstellen.
    ewb.ConnectTo(ea.ActiveWorkbook);
    // Verbindung zur ersten Tabelle aufbauen.
    ews1.ConnectTo(ea.Worksheets.Item[1] As _WorkSheet);
    // Tabelle aktivieren.
    ews1.Activate;
    // Der Tabelle einen neuen Namen geben.
    ews1.Name := DatenTabelle.Mitarbeiter.Name + ',' + DatenTabelle.Mitarbeiter.Vorname;
    // Seitenlayout festlegen
    Try
      ews1.PageSetup.Orientation := xlLandscape;    // Querformat
      ews1.PageSetup.FitToPagesTall := 1;           // Größe automatisch anpassen
      ews1.PageSetup.FitToPagesWide := 1;           // Größe automatisch anpassen
      ews1.PageSetup.CenterHorizontally := True;
      ews1.PageSetup.CenterVertically := True;
      ews1.PageSetup.PaperSize := xlPaperA4;
      ews1.PageSetup.Zoom := False;
      // Kopf- und Fusszeile erstellen
      ews1.PageSetup.LeftHeader := '';
      ews1.PageSetup.CenterHeader := '';
      ews1.PageSetup.RightHeader := 'Datum: ' + DateTimeToStr(Now);
      ews1.PageSetup.LeftFooter := '';
      ews1.PageSetup.CenterFooter := '';
      ews1.PageSetup.RightFooter := 'Programmversion: ' + fmAbout.lbVersion.Caption + #13 + 'vom: ' + fmAbout.lbDatum.Caption;
    Except
      // on e : Exception do ShowMessage(e.Message);
    End;
    // Der linke Index sind die Zeilen, der rechte Index die Spalten.
    // Tabelle mit Daten füllen.
    // Namen,
    ews1.Range['A3', 'A3'].Value := DatenTabelle.Mitarbeiter.Name + ', ' + DatenTabelle.Mitarbeiter.Vorname;
    ews1.Range['A3', 'A3'].Font.FontStyle := 'Fett';
    // Mindestumsatz - Text,
    ews1.Range['D4', 'D4'].Value := 'MinU';
    ews1.Range['D4', 'D4'].Font.FontStyle := 'Fett';
    // Faktor - Text,
    ews1.Range['A5', 'A5'].Value := 'Faktor';
    ews1.Range['A5', 'A5'].Font.FontStyle := 'Fett';
    // Faktor - Zahl,
    ews1.Range['B5', 'B5'].Value := DatenTabelle.Mitarbeiter.Faktor / 100;
    ews1.Range['B5', 'B5'].NumberFormat := '0,00%';
    // Zielumsatz - Text,
    ews1.Range['D5', 'D5'].Value := 'ZielU';
    ews1.Range['D5', 'D5'].Font.FontStyle := 'Fett';
    // Quartalsüberschriften
    ews1.Range['D3', 'D3'].Value := 'Quartal';
    ews1.Range['D3', 'D3'].Font.FontStyle := 'Fett';
    ews1.Range['E3', 'E3'].Value := 1;
    ews1.Range['E3', 'E3'].NumberFormat := '0';
    ews1.Range['E3', 'E3'].Font.FontStyle := 'Fett';
    ews1.Range['F3', 'F3'].Value := 2;
    ews1.Range['F3', 'F3'].NumberFormat := '0';
    ews1.Range['F3', 'F3'].Font.FontStyle := 'Fett';
    ews1.Range['G3', 'G3'].Value := 3;
    ews1.Range['G3', 'G3'].NumberFormat := '0';
    ews1.Range['G3', 'G3'].Font.FontStyle := 'Fett';
    ews1.Range['H3', 'H3'].Value := 4;
    ews1.Range['H3', 'H3'].NumberFormat := '0';
    ews1.Range['H3', 'H3'].Font.FontStyle := 'Fett';
    // Mindestumsatz - Zahl,
    ews1.Range['E4', 'E4'].Value := DatenTabelle.Quartal[1].MindestUmsatzDaten;
    ews1.Range['E4', 'E4'].NumberFormat := '#.###.##0,00';
    ews1.Range['F4', 'F4'].Value := DatenTabelle.Quartal[2].MindestUmsatzDaten;
    ews1.Range['F4', 'F4'].NumberFormat := '#.###.##0,00';
    ews1.Range['G4', 'G4'].Value := DatenTabelle.Quartal[3].MindestUmsatzDaten;
    ews1.Range['G4', 'G4'].NumberFormat := '#.###.##0,00';
    ews1.Range['H4', 'H4'].Value := DatenTabelle.Quartal[4].MindestUmsatzDaten;
    ews1.Range['H4', 'H4'].NumberFormat := '#.###.##0,00';
    // Zielumsatz - Zahl.
    ews1.Range['E5', 'E5'].Value := DatenTabelle.Quartal[1].ZielUmsatzDaten;
    ews1.Range['E5', 'E5'].NumberFormat := '#.###.##0,00';
    ews1.Range['F5', 'F5'].Value := DatenTabelle.Quartal[2].ZielUmsatzDaten;
    ews1.Range['F5', 'F5'].NumberFormat := '#.###.##0,00';
    ews1.Range['G5', 'G5'].Value := DatenTabelle.Quartal[3].ZielUmsatzDaten;
    ews1.Range['G5', 'G5'].NumberFormat := '#.###.##0,00';
    ews1.Range['H5', 'H5'].Value := DatenTabelle.Quartal[4].ZielUmsatzDaten;
    ews1.Range['H5', 'H5'].NumberFormat := '#.###.##0,00';

    // Die Zeilen des Stringgrids in die Exceltabelle übernehmen.
    // Da wir in der Exceltabelle nicht in der ersten Zeile anfangen, sondern in
    // der sechsten, wird auf den Index immer 6 addiert.
    iExcelIndex := 6;

    l := sgDaten.RowCount; // sgDaten ist ein Stringgrid.
    For i := 0 to l Do Begin // Einmal für jede Zeile,
      For k := 0 to sgDaten.ColCount - 1 Do Begin // einmal für jede Spalte,
        If (i = 0) And (k > sgDaten.ColCount - 3) Then Continue; // diese Zeile ignorieren.
        If (i = 1) And (k > sgDaten.ColCount - 3) Then Continue; // diese Zeile ignorieren.
        If (i = 2) And (k > sgDaten.ColCount - 3) Then Continue; // diese Zeile ignorieren.
        If (i = 3) And (k < sgDaten.ColCount - 2) Then Continue; // diese Zeile ignorieren.
        // Namen der Zelle erstellen -> k = Spalte -> i = Zeile
        sRange := GetExcelRange(k) + IntToStr(i + iExcelIndex);
        If ((i < 3) And (k < sgDaten.ColCount - 2))
        Or ((i = 3) And (k = sgDaten.ColCount - 2))
        Or ((k in [0, sgDaten.ColCount - 2])) Then Begin
          ews1.Range[sRange,sRange].Value := Trim(sgDaten.Cells[k,i]);
        End Else Begin
          If (i in [4..7,9..12,14..17,19..22])
          Or (i in [3,8,13,18]) And (k in [sgDaten.ColCount - 1]) Then Begin
            ews1.Range[sRange,sRange].Value       := fnStrToExcelFloat(sgDaten.Cells[k,i]);
            ews1.Range[sRange,sRange].NumberFormat := '#.###.##0,00';
          End Else
        End;
        ews1.Range[sRange,sRange].BorderAround(xlContinuous,xlThin,0,0);
      End; // For k := 0 to sgDaten.ColCount - 1 Do Begin // Einmal für jede Spalte.
    End; // Ende For i := 0 to sgDaten.RowCount - 1 do begin.

    // Die Formeln für die Spalten "Summe Umsatz" und "Summe Umsatz für Verrechnung"
    // müssen erstellt werden.
    // Sie kommen in die Zeilen 4, 5, 6, 9, 10, 11, 14, 15, 16, 19, 20 und 21
    // der viertletzten und drittletzten Spalte.

    // Hier wird berücksichtigt, ob ein Umsatz verrechnungswirksam ist oder nicht.
    // Dies erkennt man an der Farbe der fünfletzten Spalte.
    // Ist diese clWindow oder clKommentar, dann ist's wirksam, sonst nicht.
    k := sgDaten.ColCount - 5;
    For i := 4 To 21 Do Begin
      If i in [7,8,12,13,17,18] Then Continue; // Diese Zeilen brauchen wir nicht.
      // Formeln für die Spalte "Summe Umsatz"
      sRange := GetExcelRange(k + 1) + IntToStr(i + iExcelIndex);
      ews1.Range[sRange,sRange].Formula := '=SUM(' + Chr(64 + 5) + IntToStr(i + iExcelIndex)
                                             + ':' + GetExcelRange(k - 2) + IntToStr(i + iExcelIndex) + ')';

      // Formeln für die Spalte "Summe Umsatz für Verrechnung"
      If (sgDaten.ColorCell[k,i] <> clKommentar)
      And (sgDaten.ColorCell[k,i] <> clWindow) Then Begin
        // Umsätze sind nicht verrechnungswirksam.
        // Wenn kein Anspruch besteht schreiben wir keine Formel, sondern den Wert 0.
        sRange := GetExcelRange(k + 4) + IntToStr(i + iExcelIndex);
        ews1.Range[sRange,sRange].Value := 0;
        // Entsprechenden Kommentar in die Tabelle schreiben.
        sRange := GetExcelRange(sgDaten.ColCount + 1) + IntToStr(i + iExcelIndex);
        ews1.Range[sRange,sRange].Value          := 'nicht verrechnungswirksam';
        ews1.Range[sRange,sRange].Font.FontStyle := 'Fett';
        ews1.Range[sRange,sRange].Font.Size      := 10;
        ews1.Range[sRange,sRange].Font.ColorIndex := 3;
      End Else Begin
        sRange := GetExcelRange(k + 2) + IntToStr(i + iExcelIndex);
        ews1.Range[sRange,sRange].Formula := '=' + Chr(64 + 4) + IntToStr(i + iExcelIndex)
                                           + '+' + GetExcelRange(k + 1) + IntToStr(i + iExcelIndex);
      End;
    End;

    // Jetzt müssen wir die Formeln für die Gesamtzeilen erstellen.
    // Diese kommen in die Zeilen 7, 12, 17 und 22.
    // Die Summen müssen für die Spalten 1 bis ColCount - 3 erstellt werden.
    i := 7;
    Repeat
      For k := 1 To sgDaten.ColCount - 3 Do Begin
        sRange := GetExcelRange(k) + IntToStr(i + iExcelIndex);
        ews1.Range[sRange,sRange].Formula := '=SUM(' + GetExcelRange(k) + IntToStr(i - 3 + iExcelIndex)
                                               + ':' + GetExcelRange(k) + IntToStr(i - 1 + iExcelIndex) + ')';
      End;
      i := i + 5;
    Until i > 22;

    // Nun muß der Anspruch für das Quartal berechnet werden.
    // Der Anspruch steht in den Zeilen 4, 9, 14 und 19 in der letzten Spalte.
    i := 4;
    k := sgDaten.ColCount - 1;
    sRange2 := GetExcelRange(k - 2); // Spaltenbuchstabe der Summe für die Verrechnungsberechnung.
    sRange := GetExcelRange(k) + IntToStr(i + iExcelIndex);
    ews1.Range[sRange,sRange].Formula := '=If(' + sRange2 + '13>E4,(' + sRange2 + '13-E4)*B5,0)';
    i := 9;
    sRange := GetExcelRange(k) + IntToStr(i + iExcelIndex);
    ews1.Range[sRange,sRange].Formula := '=If(' + sRange2 + '18>F4,(' + sRange2 + '18-F4)*B5,0)';
    i := 14;
    sRange := GetExcelRange(k) + IntToStr(i + iExcelIndex);
    ews1.Range[sRange,sRange].Formula := '=If(' + sRange2 + '23>G4,(' + sRange2 + '23-G4)*B5,0)';
    i := 19;
    sRange := GetExcelRange(k) + IntToStr(i + iExcelIndex);
    ews1.Range[sRange,sRange].Formula := '=If(' + sRange2 + '28>H4,(' + sRange2 + '28-H4)*B5,0)';

    // Jetzt werden die Vorauszahlungen aus den Gesamtzeilen übernommen.
    // Sie kommen in die Zeilen 5, 10, 15 und 20 in der letzten Spalte.
    i := 5;
    Repeat
      sRange := GetExcelRange(k) + IntToStr(i + iExcelIndex);
      ews1.Range[sRange,sRange].Formula := '=' + GetExcelRange(k - 4) + IntToStr(i + 2 + iExcelIndex);
      i := i + 5;
    Until i > 20;

    // Die Abschlagszahlungen müssen ebenfalls aus den Gesamtzeilen übernommen werden.
    // Sie kommen in die Zeilen 6, 11, 16, und 21 der letzten Spalte.
    i := 6;
    Repeat
      sRange := GetExcelRange(k) + IntToStr(i + iExcelIndex);
      ews1.Range[sRange,sRange].Formula := '=' + GetExcelRange(k - 5) + IntToStr(i + 1 + iExcelIndex);
      i := i + 5;
    Until i > 21;

    // Nun benötigen wir noch die Restansprüche.
    // Sie stehen in den Zeilen 7, 12, 17 und 22 der letzten Spalte
    // und werden aus den vier davor stehenden Zeilen berechnet.
    i := 7;
    Repeat
      sRange := GetExcelRange(k) + IntToStr(i + iExcelIndex);
      ews1.Range[sRange,sRange].Formula := '=' + GetExcelRange(k) + IntToStr(i - 4 + iExcelIndex)
                                         + '+' + GetExcelRange(k) + IntToStr(i - 3 + iExcelIndex)
                                         + '-' + GetExcelRange(k) + IntToStr(i - 2 + iExcelIndex)
                                         + '-' + GetExcelRange(k) + IntToStr(i - 1 + iExcelIndex);
      i := i + 5;
    Until i > 22;

    // Jetzt brauchen wir noch die Quartalsüberträge. Diese werden aus der
    // vorhergehenden Zeile übernommen und zwar in die Zeilen 8, 13 und 18;
    i := 8;
    Repeat
      sRange := GetExcelRange(k) + IntToStr(i + iExcelIndex);
      ews1.Range[sRange,sRange].Formula := '=' + GetExcelRange(k) + IntToStr(i - 1 + iExcelIndex);
      i := i + 5;
    Until i > 18;

    // Damit das Ganze jetzt noch ein bisserl Farbe bekommt:
    // Die Zeilen 0 bis 2, 7, 12, 17 und 22 werden grau hinterlegt und fett.
    For i := 0 To 22 Do Begin
      If i in [0..2,7,12,17,22] Then Begin
        For k := 0 To sgDaten.ColCount - 1 Do Begin
          sRange := GetExcelRange(k) + IntToStr(i + iExcelIndex);
          ews1.Range[sRange,sRange].Font.FontStyle     := 'Fett';
          ews1.Range[sRange,sRange].Interior.ColorIndex := 15;
          ews1.Range[sRange,sRange].Interior.Pattern   := xlSolid;
          ews1.Range[sRange,sRange].BorderAround(xlContinuous,xlThin,0,0);
        End;
      End;
    End;

    // Spaltenbreite auf optimale Breite bringen.
    ews1.Cells.Select;
    ews1.Cells.EntireColumn.AutoFit;
    // Cursor positionieren.
    ews1.Range['A1','A1'].Select;
    Try
      // Gibts die Datei schon, dann löschen.
      If FileExists(sFileName) Then DeleteFile(sFileName);
      // Exceldatei speichern.
      ewb.SaveAs(sFilename,xlNormal,'','',False,False,xlNoChange,xlLocalSessionChanges,False,'','',lcid);
    Except
      // Wenn's Speichern der Exceltabelle schief ging,
      // die Tabelle ist in Excel geöffnet und kann vom Anwender
      // manuell gespeichert werden.
      On E : Exception Do Begin
        MessageDlg('Fehler beim Speichern der Excel-Tabelle ' + sFileName + '.'
        + #13 + e.Message,mtError,[mbok],0);
        // Excel soll sichtbar arbeiten.
        ea.Visible[lcid] := True;
      End;
    End;
    Try
      // Workbook schließen
      // Excel fragt nach, ob Änderungen gespeichert werden sollen
      ea.Workbooks.Close(lcid);
      ea.Quit;
    Except
      On E : Exception Do Begin
        MessageDlg('Fehler beim Schließen der Excel-Tabelle ' + sFileName + '.'
        + #13 + e.Message,mtError,[mbok],0);
        // Excel soll sichtbar arbeiten.
        ea.Visible[lcid] := True;
      End;
    End;
  Finally
    // Verbindung zu Excel trennen.
    ews1.Disconnect;
    ewb.Disconnect;
    ea.Disconnect;
    ews1.Free;
    ewb.Free;
    ea.Free;
  End;
  // Uns selbst in den Vordergrund bringen.
  BringToFront;
  // Schalter für "Excel arbeitet" ausschalten.
  bExcelActive := False;
end;

// Excel benötigt anstelle von Punkten Kommas und an Stelle von Kommas Punkte.
Function fnStrToExcelFloat(sInput : String) : String;
Var
         f : Extended;
         s : String;
Begin
  sInput := Trim(sInput);
  While Pos('.',sInput) <> 0 Do Delete(sInput,Pos('.',sInput),1);
  If (sInput <> '') Then Begin
    Try
      f := StrToFloat(sInput);
      s := FloatToStr(f);
      If Pos(',',s) <> 0 Then While Pos(',',s) <> 0 Do s[Pos(',',s)] := '.';
      Result := s;
    Except
      On e : Exception Do Begin
        MessageDlg('Ungültige Eingabe' + #13 + e.Message,mtError,[mbok],0);
        Result := '0';
      End;
    End;
  End Else Result := '0';
End;

function GetExcelRange(iColumn : Integer) : String;
begin
  Case iColumn Of
    0..25 : Result := Chr(64 + iColumn + 1);
  else
    begin
      Result := Chr(64 + (iColumn DIV 26)) + Chr(64 + (iColumn MOD 26) + 1);
    end;
  end;
end;
Das ist noch aus meinen Delphianfängen (Delphi 4 und Excel 97). Vielleicht kannst Du damit ja was anfangen (so als Ideenklauvorlage ;-))

BUG 14. Nov 2015 17:24

AW: Daten in Excel übertragen
 
Zitat:

Zitat von nahpets (Beitrag 1321490)
In der ersten Tabelle ist das vom Kunden erstellte Formular.
In die zweite Tabelle bringst Du die Daten.

Der Kunde kann nun aus deinen Daten innerhalb von Excel, per Formel, die von ihm gewünschten Informationen an die Stelle der ersten Tabelle (also seines Formulares) bringen, ohne dass Du wissen muss, wo er welche Daten hinhaben möchte.

Zitat:

Zitat von BUG (Beitrag 1321485)
Im Prinzip würde es für so einen Nutzer reichen, wenn er irgendwie alle Daten in einen Reiter bekommt. Das Herauspicken kann er dann über Formeln/Referenzen selbst in Excel in seiner gewohnten Arbeitsumgebung machen.

Erster :tongue: :mrgreen:

zeras 15. Nov 2015 08:29

AW: Daten in Excel übertragen
 
Danke euch beiden mit der Idee vom 2. Reiter. Darauf war ich noch nicht gekommen.
Dann spare ich mir die Aufzeichnung der Übertragung, der Kunde kann alles selber entscheiden und designen.


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

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