Excel und Diagramme mittels OLE



  • Hallo, zusammen

    ich kann mit dem BCB6.x Excel öffnen, Tabelle anlegen usw. Alles kein Problem. Aber: Egal was ich mit Diagrammen (Charts bzw. ChartsObjects) versuche, endet in einer Fehlermeldung. Nach etlichen Stunden und Recherchen im Netz bin ich mit meinem Latein am Ende und hoffe auf einen Tip (der ausgemarkerte Quellcode ziemlich am Ende ist mein Problem):

    void __fastcall TForm21::frm21_btnExcelClick(TObject *Sender)
    {try {                                                                          // Fehllerroutine Start
     Integer iRow,iCol,iSumme; AnsiString z1,z2,zFile;                              // Vars definieren
     Variant Excel,vSheet,vChart,vFont,vCell,vCol,vRange;                           // Vars definieren
    
     if(FileExists(zExcel)==false) {                                                // Pfad falsch
      ShowMessage("MS Excel Pfadangabe nicht korrekt bzw. Programm nicht gefunden.\rBitte geben Sie den korrekten Pfad an.\r\r=> "+zExcel); // Info geben
      frm21_btnAuswahlClick(0);                                                     // und Auswahl ermöglichen
      return;                                                                       // und raus
     }                                                                              // ende if(FileExists
    
     z1="Statistik "+frm21_cbStatistik->Text;                                       // Bezeichnung Arbeitsmappe
     zFile=Form1->PrgPfad+"Ablage\\excel_"+z1+".xls";                               // Filename erzeugen
    
     Excel=CreateOleObject("Excel.Application");                                    // Excel OLE anmelden
     Excel.OlePropertySet("Visible",Form1->PrgComp);                                // Excel noch nicht sichtbar machen (im IDE sofort)
    
     Excel=Excel.OlePropertyGet("Workbooks");                                       // Zugriff auf die Workbooks
     Excel.OleFunction("Add");                                                      // 1. Arbeitsblatt erstellen
     vSheet=Excel.OlePropertyGet("Item",1);                                         // Zugriff auf das erste Worksheet
     vSheet=vSheet.OlePropertyGet("Worksheets");                                    // und
     vSheet.OlePropertyGet("Item",1).OlePropertySet("Name",z1.c_str());             // Dem Worksheet einen Namen geben
    
     vSheet=vSheet.OlePropertyGet("Item",1);                                        // Zugriff auf das erste Worksheet
    
     iCol=frm21_grdStatistik->ColCount;                                             // Anzahl Spalten
     iRow=frm21_grdStatistik->RowCount;                                             // Anzahl Zeilen
     for (int i1=0;i1<iRow;i1++) {                                                  // alle Zeilen
      for (int i0=0;i0<iCol;i0++) {                                                 // alle Spalten
       z1=frm21_grdStatistik->Cells[i0][i1];                                        // Text auslesen
       vCell=vSheet.OlePropertyGet("Cells").OlePropertyGet("Item",i1+2,i0+2);       // Zelle ermitteln
       vCell.OlePropertySet("Value", z1.c_str());                                   // Zelle beschreiben
    
       if(i1==0) {                                                                  // ÜBERSCHRIFT
        vFont=vCell.OlePropertyGet("Font");                                         // Fontzugriff übergeben
        vFont.OlePropertySet("Name", WideString("Arial"));                          // Schriftname
        vFont.OlePropertySet("Size", 10);                                           // Schriftgrösse
        vFont.OlePropertySet("Bold" ,true);                                         // Fontstil
        vFont.OlePropertySet("Color",clBlue);                                       // Farbe des Textes
       }                                                                            // ende if(i1==0
    
      }                                                                             // ende for(int i0
     }                                                                              // ende for(int i1
     z1="Summen"; z2=IntToStr(frm21_grdChart->Tag);                                 // z2=Summe Anzahl
     vSheet.OlePropertyGet("Cells").OlePropertyGet("Item",iRow+3,2).OlePropertySet("Value", z1.c_str()); // Summenzeile 1. Spalte
     vSheet.OlePropertyGet("Cells").OlePropertyGet("Item",iRow+3,3).OlePropertySet("Value", z2.c_str()); // Summenzeile 2. Spalte
     vSheet.OlePropertyGet("Cells").OlePropertyGet("Item",iRow+3,4).OlePropertySet("Value", "100");      // Summenzeile 3. Spalte
    
     vCol=vSheet.OlePropertyGet("Columns","C");                                     // Spalte C
     vCol.OlePropertySet("HorizontalAlignment",alRight);                            // rechtsbündig ausrichten
     vCol=vSheet.OlePropertyGet("Columns","D");                                     // Spalte D
     vCol.OlePropertySet("HorizontalAlignment",alRight);                            // rechtsbündig ausrichten
    
     vCol=vSheet.OlePropertyGet("Columns","B");                                     // Spalte B
     vCol.OlePropertySet("ColumnWidth",30);                                         // Breite einstellen
     vCol.OleFunction("Autofit");                                                   // autom. Breite
    
     z1="B3:D"+IntToStr(iRow+1);                                                    // Tabellenwerte (ausser Kopfzeile und Summenzeile)
     vRange=vSheet.OlePropertyGet("Range",z1.c_str());                              // auswählen
     vRange.OleFunction("Select");                                                  // und markieren
    
     // DIAGRAMM ERZEUGEN MIT DEN SELEKTIERTEN BEREICH vRange ???
     //vSheet=vSheet.OlePropertyGet("Charts");                                        // und
     //vSheet.OleFunction("Add");                                                     // 1. Diagramm erstellen
     //vSheet.OlePropertySet("ChartType",51); //xlColumnClustered=51                          // Diagrammtyp
     //vSheet.OlePropertySet("SetSourceData",z1.c_str());                             // Wertebereich zuordnen
     //vSheet.OlePropertySet("Left",10);                                              // linker Rand
     //vSheet.OlePropertySet("Top",10);                                               // oberer Rand
    
     //Excel.OlePropertySet("Visible",true);                                          // Excel jetzt sichtbar machen
    
     Excel=Unassigned;                                                              // und auflösen
    
     } catch(...) { ShowMessage("TForm21::frm21_btnExcelClick()"); }                // Fehler anzeigen
    }
    

    Danke für jeden Tipp!

    Habe auch in Excel schon versucht, über die Makros weiterzukommen,
    leider auch ohne Erfolg... Denke mal, ich mache einen grundsätzlichen
    Fehler mit der Diagrammerzeugung. 😕

    Hinweis am Rande für alle: Die Werte für die Tabelle stehen bei mir in
    einem TStringGrid (frm21_grdStatistik).

    Gruss Stefan



  • Stefan7124 schrieb:

    Egal was ich mit Diagrammen (Charts bzw. ChartsObjects) versuche, endet in einer Fehlermeldung.

    So so, eine Fehlermeldung.



  • Ok, Wink mit dem Zaunpfahl verstanden:

    ---------------------------
    Benachrichtigung über Debugger-Exception
    ---------------------------
    Im Projekt NetCat_Finder_3.exe ist eine Exception der Klasse EOleSysError aufgetreten. Meldung: 'Unbekannter Name'. Prozeß wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
    ---------------------------
    OK Hilfe
    ---------------------------

    War davon ausgegangen, daß hier der Aufruf des Diagrammes von seiner Art her falsch ist und die Fehlermeldung als solches daher nicht relevant ist (was falsch aufgerufen wird kann logischerweise nicht funktionieren 😉

    MfG Stefan Scholz



  • In welcher Zeile tritt die Exception auf, schon in 64?
    Ist "Charts" valid? Wie sieht das im entsprechenden Makro aus?



  • Hallo, Jansen

    schon in der ersten Zeile:

    vSheet=vSheet.OlePropertyGet("Charts");
    

    ..schon in 64... verstehe ich leider nicht 😕

    Im Excel-Makro sieht es so aus:
    *'
    ' Makro1 Makro
    ' Makro am 25.10.2006 von Stefan Scholz aufgezeichnet
    '

    '
    Charts.Add
    ActiveChart.ChartType = xlLine
    ActiveChart.SetSourceData Source:=Sheets("Tabelle1").Range("B3:C9"), PlotBy _
    :=xlColumns
    ActiveChart.Location Where:=xlLocationAsObject, Name:="Tabelle1"
    End Sub
    *

    Im internet habe ich auch OLE gefunden mit ChartsObjects; geht aber auch nicht...

    Was mich insofern wundert, da alle anderen Makrobefehle super funktionieren.
    Vermute daher, das mein Bezugspunkt zum Makro falsch ist; habe hier aber
    auch alles mögliche probiert, also mit Excel. vSheet. usw.

    Habe es auch auf verschiedenen Excel- und Windowsversionen probiert, ebenfalls negativ. Daher meine Vermutung das ich zur Erzeugung einen generellen Fehler mache bzw. irgendwas wichtiges fehlt

    Und Excel selbst kommt nach obigen Bsp. einwandfrei zustande, Tabelle, Werte, Formatierung, keinerlei Fehlermeldung. Irgendwas stört also den BCB gewaltig, oder?

    Gruss, Stefan



  • ...dann probiert man halt weiter und kommt zumindest einen Schritt weiter:

    vSheet=vSheet.OlePropertyGet("ChartObjects");                                  // und Object vorbereiten
     vChart=vSheet.OleFunction("Add");                                                     // 1. Diagramm erstellen
     //vChart=Excel.OlePropertyGet("Item",1);                                         // Zugriff auf das erste Diagramm
     vChart.OlePropertySet("ChartType",51); //xlColumnClustered=51                  // Diagrammtyp
     vChart.OlePropertySet("SetSourceData",z1.c_str());                             // Wertebereich zuordnen
     vChart.OlePropertySet("Left",10);                                              // linker Rand
     vChart.OlePropertySet("Top",10);                                               // oberer Rand
    

    Damit kommt nun in der 2. Zeile

    vChart=vSheet.OleFunction("Add");
    

    die Meldung: Parameter nicht Optional

    Mit dem Key "ChartObjects" ist nun zumindest der Begriff klar (Danke Mikrosoft, daß wieder einmal mehr nicht einheitlich gearbeitet wurde; die anderen Begriffe sind in den Makros nämlich identisch; Charts dagegen nicht, hier muss man ChartObjects angeben 😡 )

    Wenn jemand weiss, wie hier der Add Befehl oder ähnlich aussehen würde....
    👍

    Gruss Stefan



  • eventuell solltest du das mal überdenken:

    [b]vSheet[/b]=[b]vSheet[/b].OlePropertyGet("ChartObjects");
    

    weiter gehts dann mit:

    vChart.OleProcedure("Add");
    //oder
    vChart.OleProcedure("Add",10,10,100,100);
    


  • Erstmal Danke für Deine Antwort; ich komme jetzt einen Schritt weiter.

    // DIAGRAMM ERZEUGEN MIT DEN SELEKTIERTEN BEREICH vRange ???
     vChart=vSheet.OlePropertyGet("ChartObjects");                                  // und Diagramm anmelden
     vChart.OleProcedure("Add",350,50,300,300);                                     // 1. Diagramm erstellen
    
     vChart.OleProcedure("SetSourceData",vRange);                             // Wertebereich zuordnen
     vChart.OlePropertySet("ChartType",51);                                         // Diagrammtyp einstellen
     //vChart.OleFunction("Autofit");                                                   // autom. Breite
     //vChart.OleProcedure("ChartType",51); //xlColumnClustered=51                          // Diagrammtyp
     //vChart.OleProcedure("SetSourceData",z1.c_str());                             // Wertebereich zuordnen
    

    Leider finde ich im Internet einfach keine eindeutige Beschreibung;
    wieso auf einmal OleProcedure statt wie bei den anderen Funktionen
    OleFunktion.. bzw. wann OleFunction, OleProcedure usw..

    Mit dem SetSoruceData (lt Makro) klappt es nicht; hast Du noch
    einen Tipp für mich, wann ich welchen Befehl anwenden muss? Irgendwie
    schnall ich das beim Diagramm nicht; obwohl ich es bei den anderen
    Dingen hinbekomme habe... *grummel*

    Habe es auch mit

    vChart.OleProcedure("SetSourceData",z1.c_str());
    

    usw probiert (z1 z.B. ="B3:F10"), ging aber leider auch nicht

    Gruss Stefan Scholz



  • versuch mal das:

    vChart=vSheet.OlePropertyGet("ChartObjects");
    	vChart.OlePropertyGet("Add");
    	Variant chart  = vChart.OlePropertyGet("Item",1);
    	Variant series = chart.OlePropertyGet("SeriesCollection");
    	series.OleProcedure("Add",vRange);
    

    [Edit] Hier noch ein Link wo alle Diagrammeinstellungen über den "ChartWizard" gemacht werden



  • Hei, Linnea

    vielen Dank für Deine Infos; jetzt habe ich endlich einen
    Anhaltspunkt bzw. kapiere es ein bisschen mehr.

    // DIAGRAMM ERZEUGEN MIT DEN SELEKTIERTEN BEREICH vRange ???
     vChart=vSheet.OlePropertyGet("ChartObjects");                                  // und Object vorbereiten
     vChart.OleProcedure("Add",350,25,400,400);                                     // und Diagramm erstellen
    
     vDiagram=vChart.OlePropertyGet("Item",1);                                      // Diagrammzuordnung holen
     vSeries=vDiagram.OlePropertyGet("SeriesCollection");                           // Datencollection holen
    
     //vDiagram.OleProcedure("SetSourceData",z1.c_str());                             // Wertebereich zuordnen
    

    Die Zeile mit SeriesCollection mag er nicht, aber ich schau mal bei
    Deinem extern Link nach bzw. werde durch probieren und studieren
    versuchen da weiterzukommen und das Ergebnis hier posten. Immerhin kommt
    jetzt schon ein weisses Viereck... Und mühsam ernährt sich das
    Eichhörnchen.. :p

    Gruss , Stefan Scholz



  • An der Stelle ein dickes Danke an Linnea!
    Sein Link auf eine spanische (?) Seite war Gold wert...

    Nach etlichem Tüfteln hier eine aktzeptable Lösung: Wer neue Parameter rausfindet im Bereich iChart (Art des Diagramms) kann es ja hier posten. Der Parameter zExcel (AnsiString) dient nur dazu, das der Anwender überhaupt Excel hat (falls sich einer wundert, ich brauche es noch für direkte Exportfunktionen 😉

    -----------------------------------------------
    Items anlegen in eine Combobox für Chartstypen:
    00 Kein Diagramm erstellen
    02 Balken vertikal (2D)
    03 Balken horizontal (2D)
    05 Torte (2D)
    11 Balken horizontal (3D)
    13 Torte (3D)
    -----------------------------------------------

    void __fastcall TForm21::frm21_cbChartChange(TObject *Sender)
    {Integer i2; AnsiString z1,z2;                                                  // Vars definieren
    
     i2=frm21_cbChart->ItemIndex;                                                   // Auswahl vorhanden
     if(i2==-1) { iChart=0; return; }                                               // ggfs. Fehler abfangen
    
     z1=frm21_cbChart->Items->Strings[i2];                                          // und Auswahl auslesen
     z2=z1.SubString(1,2);                                                          // 1+2. Stelle
     iChart=StrToIntDef(z2,0);                                                      // als Int ermitteln
    }
    

    Excel Tabelle erstellen:
    --------------------------------------------------------------
    Button frm21_btnExcel startet das Erstellen der Excel Tabelle,
    Werte liegen in einem TStringGrid frm21_grdStatistik
    1. Spalte = Bezeichnungen, 2. Spalte = Anzahl Werte
    --------------------------------------------------------------

    void __fastcall TForm21::frm21_btnExcelClick(TObject *Sender)
    {try {                                                                          // Fehllerroutine Start
     Integer iRow,iCol,iSumme; AnsiString z1,z2,zFile;                              // Vars definieren
     AnsiString zTitel,zAchseX,zAchseY;                                             // Vars definieren
     Variant Excel,vSheet,vChart,vFont,vCell,vCol,vRange,vDiagram,vDiagData,vSeries;// Vars definieren
    
     if(FileExists(zExcel)==false) {                                                // Pfad falsch
      ShowMessage("MS Excel Pfadangabe nicht korrekt bzw. Programm nicht gefunden.\rBitte geben Sie den korrekten Pfad an.\r\r=> "+zExcel); // Info geben
      frm21_btnAuswahlClick(0);                                                     // und Auswahl ermöglichen
      return;                                                                       // und raus
     }                                                                              // ende if(FileExists
    
     z1="Statistik "+frm21_cbStatistik->Text;                                       // Bezeichnung Arbeitsmappe
     zFile=Form1->PrgPfad+"Ablage\\excel_"+z1+".xls";                               // Filename erzeugen
    
     Excel=CreateOleObject("Excel.Application");                                    // Excel OLE anmelden
     Excel.OlePropertySet("Visible",Form1->PrgComp);                                // Excel noch nicht sichtbar machen (im IDE sofort)
    
     Excel=Excel.OlePropertyGet("Workbooks");                                       // Zugriff auf die Workbooks
     Excel.OleFunction("Add");                                                      // 1. Arbeitsblatt erstellen
     vSheet=Excel.OlePropertyGet("Item",1);                                         // Zugriff auf das erste Worksheet
     vSheet=vSheet.OlePropertyGet("Worksheets");                                    // und
     vSheet.OlePropertyGet("Item",1).OlePropertySet("Name",z1.c_str());             // Dem Worksheet einen Namen geben
    
     vSheet=vSheet.OlePropertyGet("Item",1);                                        // Zugriff auf das erste Worksheet
    
     iCol=frm21_grdStatistik->ColCount;                                             // Anzahl Spalten
     iRow=frm21_grdStatistik->RowCount;                                             // Anzahl Zeilen
     for (int i1=0;i1<iRow;i1++) {                                                  // alle Zeilen
      for (int i0=0;i0<iCol;i0++) {                                                 // alle Spalten
       z1=frm21_grdStatistik->Cells[i0][i1];                                        // Text auslesen
       vCell=vSheet.OlePropertyGet("Cells").OlePropertyGet("Item",i1+2,i0+2);       // Zelle ermitteln
       vCell.OlePropertySet("Value", z1.c_str());                                   // Zelle beschreiben
    
       if(i1==0) {                                                                  // ÜBERSCHRIFT
        vFont=vCell.OlePropertyGet("Font");                                         // Fontzugriff übergeben
        vFont.OlePropertySet("Name", WideString("Arial"));                          // Schriftname
        vFont.OlePropertySet("Size", 10);                                           // Schriftgrösse
        vFont.OlePropertySet("Bold" ,true);                                         // Fontstil
        vFont.OlePropertySet("Color",clBlue);                                       // Farbe des Textes
       }                                                                            // ende if(i1==0
    
      }                                                                             // ende for(int i0
     }                                                                              // ende for(int i1
     z1="Summen"; z2=IntToStr(frm21_grdChart->Tag);                                 // z2=Summe Anzahl
     vSheet.OlePropertyGet("Cells").OlePropertyGet("Item",iRow+3,2).OlePropertySet("Value", z1.c_str()); // Summenzeile 1. Spalte
     vSheet.OlePropertyGet("Cells").OlePropertyGet("Item",iRow+3,3).OlePropertySet("Value", z2.c_str()); // Summenzeile 2. Spalte
     vSheet.OlePropertyGet("Cells").OlePropertyGet("Item",iRow+3,4).OlePropertySet("Value", "100");      // Summenzeile 3. Spalte
    
     vCol=vSheet.OlePropertyGet("Columns","C");                                     // Spalte C
     vCol.OlePropertySet("HorizontalAlignment",alRight);                            // rechtsbündig ausrichten
     vCol=vSheet.OlePropertyGet("Columns","D");                                     // Spalte D
     vCol.OlePropertySet("HorizontalAlignment",alRight);                            // rechtsbündig ausrichten
    
     vCol=vSheet.OlePropertyGet("Columns","B");                                     // Spalte B
     vCol.OlePropertySet("ColumnWidth",30);                                         // Breite einstellen
     vCol.OleFunction("Autofit");                                                   // autom. Breite
    
     z1="B3:C"+IntToStr(iRow+1);                                                    // Tabellenwerte (ausser Kopfzeile und Summenzeile)
     vRange=vSheet.OlePropertyGet("Range",z1.c_str());                              // auswählen
     //vRange.OleFunction("Select");                                                  // und markieren
    
     if(iChart==0) { goto KeinDiagramm; }                                           // kein Diagramm erstellen
    
     vDiagram=vSheet.OlePropertyGet("ChartObjects");                                // Neues Chartobject
     vDiagram.OleProcedure("Add",350,25,300,300);                                   // erzeugen
     vDiagData=vDiagram.OlePropertyGet("Item",1);                                   // und Zugriff auf Daten holen
    
     zTitel=frm21_cbStatistik->Text;                                                // Titel des Diagramms
     zAchseX="Bezeichnung";                                                         // Beschriftung Achse X
     zAchseY="Anzahl";                                                              // Beschriftung Achse Y
    
     vDiagData.OlePropertyGet("Chart").OleProcedure("ChartWizard",                  // Start Chartfunktionsaufruf
     vRange,                                                                        // Bereich Daten z.B. B3:D20
     iChart,                                                                        // Balken horizontal 2D (2) / Balken vertikal 2D (3) / Torte 2D (5) / Balken 3D (11) / Torte 3D (13)
     6,                                                                             // 6 (Beschriftung X) / 7 (mit Beschriftung X/Y)
     2,                                                                             // ??
     1,                                                                             // Anzahl Spalten/Zeilen im Range für Achse X
     0,                                                                             // Anzahl Spalten/Zeilen im Range für Achse Y
     0,                                                                             // ohne Legende (0) / mit Legende (1)
     zTitel.c_str(),                                                                // Titel des Diagrams
     zAchseX.c_str(),                                                               // Beschriftung Achse X
     zAchseY.c_str());                                                              // Beschriftung Achse Y
    
     KeinDiagramm:                                                                  // Sprungmarke
     //Excel.OlePropertySet("Visible",true);                                          // Excel jetzt sichtbar machen
    
     Excel=Unassigned;                                                              // und auflösen
    
     } catch(...) { ShowMessage("TForm21::frm21_btnExcelClick()"); }                // Fehler anzeigen
    }
    

    Gruss, Stefan Scholz 🕶

    P.S. Verstehe immer noch nicht, warum es nirgends ein
    lauffähiges Demo gibt/gab ....??? Wer das hier nichts
    fürs FAQ? 👍


Anmelden zum Antworten