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.. :pGruss , 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?