Seite 1 von 1
[Gelöst] Excel erstellen mit mehreren Sheets
Verfasst: 18. August 2006 17:00
von rotsch
Ich versuche einen Excel-Export zu erstellen, welcher mehrere Sheets enthalten soll. Das heisst, ich laufe über eine Tabelle (REPEAT/UNTIL) und möchte jeden Record in einem einzelnen Sheet in Excel haben. Aber wie ich es auch anstelle, ich erhalte immer nur ein ausgefülltes Sheet mit dem letzten Record aus der Schleife. Die Daten werden immer in das selbe Sheet geschrieben, rsp. überschrieben.
Hat mir jemand einen Tipp?
Verfasst: 18. August 2006 17:20
von Michael Schumacher
hast du denn jeweils die Befehle zur erstellung eines neuen Sheets und das Aktivieren des Sheets eingebaut?
Verfasst: 18. August 2006 17:26
von Kowa
In Tabelle 370 Excel Buffer sind etliche Excel Funktionen. Für die Variable XlWrkSht kann man hier the Methode Activate wählen. Danach sollten die Daten eigentlich in das Sheet laufen. Bei VBA funktioniert das jedenfalls so.
Verfasst: 18. August 2006 18:01
von rotsch
Ich bin der Meinung, dass ich die nötigen Befehle eingebaut habe. Jedoch wird jedesmal pro Schleifendurchlauf ein neues Excel erstellt. Gerade habe ich aus dem TaskManager ein dutzend Instanzen rausgekippt. Mein Code sieht ungefähr so aus
- Code:
IF DocuObject.FIND('-') THEN BEGIN
TempExcelBuffer.DELETEALL;
TempExcelBuffer.CreateBook;
REPEAT
... füllen von ExcelBuffer...
TempExcelBuffer.CreateNewSheet(FORMAT(DocuObject.ID) +' - '+ DocuObject.Name,
FORMAT(DocuObject.ID) +' - '+ DocuObject.Name,
COMPANYNAME,
USERID);
UNTIL DocuObject.NEXT = 0;
END;
TempExcelBuffer.GiveUserControl;
Die Funktion CreateNewSheet habe ich selber erstellt. Darin wird jeweils ein neues Sheet erstellt, und dann die Standardfunktion aufgerufen
- Code:
XlWrkSht := XlWrkBk.Worksheets.Add;
CreateSheet(SheetName, '', CompanyName, UserID2);
Was auch nicht klappt, ist der Aufruf CreateBook am Anfang. Da motzt er mit einer fehlenden Instanz, und wenn ich CreateBook in die Schleife nehme, erhalte ich pro Durchgang ein neues Excel-File.
Verfasst: 19. August 2006 01:22
von Michael Schumacher
rotsch hat geschrieben:Was auch nicht klappt, ist der Aufruf CreateBook am Anfang. Da motzt er mit einer fehlenden Instanz, und wenn ich CreateBook in die Schleife nehme, erhalte ich pro Durchgang ein neues Excel-File.
Du hast vermutlich vorher Excel noch nicht gestartet, deswegen fehlende Instanz. Und CreateBook erzeugt ein neues Workbook also sozusagen eine neue Excel-Datei, so als wenn du in Excel auf Datei/Neu klickst.
Was steht denn in Deiner Funktion CreateNewsheet?
Und warum übergibst Du 2mal den Sheetnamen?
Ich vermute mal da fehlt noch der Worksheet.activate Befehl, deswegen schreibt der alles in das erste Sheet.
Verfasst: 19. August 2006 08:35
von rotsch
Wenn ich CreateBook for dem REPEAT aufrufe, erhalte ich den Fehler wegen der fehlenden Instanz. Wenn ich CreateBook aber direkt vor CreateNewSheet aufrufe erstellt mir Navision pro Durchlauf durch die Schleife eine neue Excel-Datei. Irgendwie beisst sich das immer.
Das mit dem Sheetnamen, der 2mal übergeben wird, ist noch Fehler meinerseits, hat aber keinen Einfluss.
Verfasst: 19. August 2006 09:06
von rotsch
Jetzt hat es funktioniert. Der Activate-Befehl war am falschen Platz, und ich habe die ExcelBuffer-Tabelle auf temporär umgestellt. Hier der Code, falls jemand etwas ähnliches machen muss:
Erstellen der Sheets:
- Code:
DocuObject.SETRANGE(Type, DocuObject.Type::Table);
IF DocuObject.FIND('-') THEN BEGIN
Line := 1;
TempExcelBuffer.DELETEALL;
TempExcelBuffer.CreateBook;
REPEAT
DocuObject.CALCFIELDS(Name);
EnterCell(Line, 1, FORMAT(DocuObject.ID) +' - '+ DocuObject.Name, true, italic, false);
Line := Line + 2;
EnterCell(Line, 1, 'Fieldlist', true, italic, false);
Line := Line + 2;
TempExcelBuffer.CreateNewSheet(FORMAT(DocuObject.ID) +' - '+ DocuObject.Name,
'Objectdocumeantion (Table)',
COMPANYNAME,
USERID);
TempExcelBuffer.DELETEALL;
Line := 1;
UNTIL DocuObject.NEXT = 0;
END;
TempExcelBuffer.GiveUserControl;
Neue Funktion 'CreateNewSheet' in der Excel-Buffer Tabelle
- Code:
XlWrkSht := XlWrkBk.Worksheets.Add;
CreateSheet(SheetName, '', CompanyName, UserID2);
XlWrkSht.Activate;
Danke für die Unterstützung
Verfasst: 21. August 2006 07:49
von rotsch
Eine kleine Unschönheit habe ich noch festgestellt.
Im erstellten Workbook befinden sich am Schluss jeweils 4 leere Sheets in der Reihenfolge Tabelle 4, Tabelle 1, Tabelle 2, Tabelle 3.
1 - 3 werden ja durch Excel automatisch erstellt, wenn man ein neues Workbook erstellt. Lässt sich das vermeiden?
Woher Tabelle 4 kommt, ist mir schleierhaft. Es sind alle benötigten Sheets vorhanden.
Verfasst: 21. August 2006 13:18
von Michael Schumacher
du könntest bei den Tabellen 1 bis 3 die vorhandenen Tabellen öffnen und umbenennen, und erst ab der 4. neue erstellen.
warum da aber noch ein weiteres Sheet kommt, ist mir ein Rätsel, es sei denn, in der Excelbuffer befindet sich ein leerer Datensatz....
Excel No of Sheets
Verfasst: 22. August 2006 15:44
von TomTom64
rotsch hat geschrieben:Eine kleine Unschönheit habe ich noch festgestellt.
Im erstellten Workbook befinden sich am Schluss jeweils 4 leere Sheets in der Reihenfolge Tabelle 4, Tabelle 1, Tabelle 2, Tabelle 3.
1 - 3 werden ja durch Excel automatisch erstellt, wenn man ein neues Workbook erstellt. Lässt sich das vermeiden?
Die Tabelle 1 bis 4 kommen aus einer Excel-Einstellung. Die Sheets 2-4 kannst Du auf jeden Fall mit einer Einstellung in Excel unterdrücken. Die Einstellung ist unter Allgemein und heiß Blätter in neuer Arbeitsmappe. Am besten auf 1 setzen.
Verfasst: 22. August 2006 16:39
von rotsch
Danke für den Tipp mit den Einstellungen. Leider hat das nicht geklappt. Jetzt habe ich anstatt 4 noch 2 leere Sheets (Tabelle 1 und Tabelle 2).
Gibt es eine Möglichkeit festzustellen, ob und wieviel leere Sheets vorhanden sind und diese dann explizit zu aktivieren, sodass diese zuerst gefüllt werden, bevor neue angelegt werden?
Verfasst: 23. August 2006 23:09
von Michael Schumacher
rotsch hat geschrieben:Gibt es eine Möglichkeit festzustellen, ob und wieviel leere Sheets vorhanden sind und diese dann explizit zu aktivieren, sodass diese zuerst gefüllt werden, bevor neue angelegt werden?
Ja, die Automation vom Typ worksheets oder so ähnlich (auf jeden Fall die Mehrzahl, nicht die Einzahl) enthält die Sheets in einer Auflistung.
ggf musst du mal in der VBA-Hilfe von Excel nachsehen, wie du darauf zugreifen kannst. Ich habe gerade keine vorliegen.....
Excel No. of sheets
Verfasst: 25. August 2006 10:07
von TomTom64
Ich habe es bei mir noch einmal nachgeschaut. Es bleibt max. 1 Sheet mit dem Namen Tabelle1 übrig. Wieviele Sheets hast Du denn wenn Du Excel ganz normal startest? Es muss wie in Mappe99 aussehen. Welche Office-Version vewendest Du?
Ich verwende Office 11 oder Office 10. Es kann aber sein, das ich die Automation Objekte für Office 9 verwende.
Wenn ich nur 1 Sheet benötige, sieht es bei mir so aus:
CREATE(Excel);
Excel.Visible(TRUE);
Book := Excel.Workbooks.Add;//(-4167);
Sheet := Excel.ActiveSheet;
Sheet.Name := 'Sheetname';
Ich habe dann nur 1 Tabellenblatt mit dem Namen Sheetname.
Wenn ich mehrere Tabellenblätter benötige kann dies so aussehen:
(Trigger1)
CREATE(Excel);
Book := Excel.Workbooks.Add;//(-4167);
Excel.Visible(FALSE);
(Trigger2)
Book.Sheets.Add;
Sheet := Excel.ActiveSheet;
Sheet.Name := Mandant.Name;
In diesem Fall bleibt natürlich 1 Tabellenblatt mit dem Name Tabelle1 übrig.
Verfasst: 26. August 2006 13:28
von rotsch
Hallo TomTom64,
Danke vielmals für deine Ausführungen. Das auf jeden Fall ein Sheet übrigbleibt, habe ich nicht gewusst.
Ich habe das Problem jetzt gefunden. Dein CodeBeispiel hat mich draufgebracht:
Ich habe ja eine eigene Funktion 'CreateNewSheet' erstellt, mit welcher ich neue Sheets anfüge. Das darf ich jedoch erst ab dem zweiten Durchlauf durch meine Routine tun, da CreatBook bereits ein Sheet erstellt.
Tja, am Schluss wars dann einfach, aber bis ich dahinter kam ein steiniger Weg. Ich war auf jedenfall froh um jeden Tipp hier.
Für alle, die sowas auch mal brauchen, hier der Code in gekürzter Fassung (sozusagen das Gerippe)
- Code:
IF Record.FIND('+') THEN BEGIN
FirstSheet := true;
TempExcelBuffer.DELETEALL;
TempExcelBuffer.CreateBook;
REPEAT
SheetName := 'Irgendwas';
... TempExcelBuffer füllen...
if FirstSheet then begin
// Standard aus ExcelBuffer
TempExcelBuffer.CreateSheet(SheetName, ReportHeader, COMPANYNAME, USERID);
FirstSheet := false;
end
else begin
// Eigene Routine
TempExcelBuffer.CreateSheet(SheetName, ReportHeader, COMPANYNAME, USERID);
end;
TempExcelBuffer.DELETEALL;
Line := 1;
UNTIL Record.NEXT(-1) = 0;
END;
TempExcelBuffer.GiveUserControl;
Excel erstellen mit mehreren Sheets
Verfasst: 28. August 2006 14:53
von TomTom64
Hi Roger,
es muß nicht automatisch ein Sheet übrigbleiben. Du mußt nur dafür sorgen, dass Du das Blatt mit dem Name Tabelle1 umbenennst oder löscht. Man kann zum Beispiel den 1. Durchlauf abfragen und dann anstatt ein neues Sheet anzulegen das aktive Sheet umbenennen.
Gruß Tom
- Code:
if FirstSheet then begin
Sheet := Excel.ActiveSheet;
Sheet.Name := companyname;
FirstSheet := false;
// Eigene Routine
end else begin
// Eigene Routine
TempExcelBuffer.CreateSheet(SheetName, ReportHeader, COMPANYNAME, USERID);
end;
Verfasst: 16. November 2006 15:12
von Otschko
Hallo,
kann ich da nochmal nachhaken?
Ich fasse mal zusammen, was ich mir nun erlesen habe.
1) Im ExcelBuffer eine neue Funktion "CreateNewSheet" mit dem Code von Rotsch
- Code:
XlWrkSht := XlWrkBk.Worksheets.Add;
CreateSheet(SheetName, '', CompanyName, UserID2);
XlWrkSht.Activate;
2) Im 1. Durchlauf die normale ExcelBuffer Funktion
CreateSheet(SheetName, ReportHeader, COMPANYNAME, USERID);
aufrufen.
3) In den folgenden Durchläufen dann die eigene Funktion
CreateNewSheet(SheetName, ReportHeader, COMPANYNAME, USERID);
aufrufen.
Habe ich das soweit richtig verstanden?
Bei mir wird halt am Ende nur 1 Excel Blatt mit dem letzten Sheet geöffnet, aber ich habe mehrere EXCEL.EXE Instanzen....
Was ich auch noch hinbekomme, ist x Excel Blätter zu öffnen, in denen jeweils das 1. Sheet gefüllt ist, auch nicht so schön...
Kann da jemand vllt. mal ein Fob zur Verfügung stellen?
Gruss, Otschko
Verfasst: 16. November 2006 17:40
von rotsch
Ich poste hier die Main-Routine, die ich erstellt habe. Damit bekomme ich wunderbar eine Excel-Datei mit mehreren Sheets.
- Code:
DocuObject.SETRANGE(Version, _ActVersion);
DocuObject.SETRANGE(Type, _ActType);
IF DocuObject.FIND('+') THEN BEGIN
Line := 1;
FirstObject := TRUE;
TempExcelBuffer.DELETEALL;
TempExcelBuffer.CreateBook;
REPEAT
DocuObject.CALCFIELDS(Name);
// Excel-Sheetname
SheetName := DELCHR(DocuObject.Name, '=', '/');
SheetName := DELCHR(SheetName, '=', '\');
SheetName := DELCHR(SheetName, '=', '*');
SheetName := DELCHR(SheetName, '=', '?');
SheetName := DELCHR(SheetName, '=', '[');
SheetName := DELCHR(SheetName, '=', ']');
SheetName := DELCHR(SheetName, '=', ':');
SheetName := FORMAT(DocuObject.ID) +' - '+ SheetName;
SheetName := COPYSTR(SheetName, 1, 31);
EnterCell(Line, 1, FORMAT(DocuObject.ID) +' - '+ DocuObject.Name, TRUE, FALSE, FALSE);
EnterCell(Line, 2, 'Version' +' '+ _ActVersion, TRUE, FALSE, FALSE);
Line := Line + 2;
// Generelle Bemerkungen ausgeben
DocuGeneralDesc.SETRANGE(Version, _ActVersion);
DocuGeneralDesc.SETRANGE(Type, DocuObject.Type);
DocuGeneralDesc.SETRANGE(ID, DocuObject.ID);
IF DocuGeneralDesc.FIND('-') THEN BEGIN
// Überschrift über Bemerkungen
EnterCell(Line, 1, 'Comments', TRUE, FALSE, FALSE);
Line := Line + 1;
REPEAT
EnterCell(Line, 1, DocuGeneralDesc.Description, FALSE, FALSE, FALSE);
Line := Line + 1;
UNTIL DocuGeneralDesc.NEXT = 0;
Line := Line + 1;
END;
// Felder ausgeben
DocuTableKey.SETRANGE(Version, _ActVersion);
DocuTableKey.SETRANGE(Type, DocuObject.Type);
DocuTableKey.SETRANGE(ID, DocuObject.ID);
IF DocuTableField.FIND('-') THEN BEGIN
// Überschrift über Keyliste
EnterCell(Line, 1, 'Keylist', TRUE, FALSE, FALSE);
Line := Line + 1;
// Titel für Keyliste
EnterCell(Line, 1, DocuTableKey.FIELDNAME("Creation Time"), TRUE, FALSE, FALSE);
EnterCell(Line, 2, DocuTableKey.FIELDNAME(Activity), TRUE, FALSE, FALSE);
EnterCell(Line, 3, DocuTableKey.FIELDNAME(Responsible), TRUE, FALSE, FALSE);
EnterCell(Line, 4, DocuTableKey.FIELDNAME("Key Fields"), TRUE, FALSE, FALSE);
EnterCell(Line, 5, DocuTableKey.FIELDNAME(SumIndexFields), TRUE, FALSE, FALSE);
Line := Line + 1;
REPEAT
EnterCell(Line, 1, FORMAT(DocuTableKey."Creation Time"), FALSE, FALSE, FALSE);
EnterCell(Line, 2, FORMAT(DocuTableKey.Activity), FALSE, FALSE, FALSE);
EnterCell(Line, 3, FORMAT(DocuTableKey.Responsible), FALSE, FALSE, FALSE);
EnterCell(Line, 4, FORMAT(DocuTableKey."Key Fields"), FALSE, FALSE, FALSE);
EnterCell(Line, 5, FORMAT(DocuTableKey.SumIndexFields), FALSE, FALSE, FALSE);
Line := Line + 1;
UNTIL DocuTableKey.NEXT = 0;
Line := Line + 1;
END;
// Keys ausgeben
DocuTableField.SETRANGE(Version, _ActVersion);
DocuTableField.SETRANGE(Type, DocuObject.Type);
DocuTableField.SETRANGE(ID, DocuObject.ID);
IF DocuTableField.FIND('-') THEN BEGIN
// Überschrift über Feldliste
EnterCell(Line, 1, 'Fieldlist', TRUE, FALSE, FALSE);
Line := Line + 1;
// Titel für Feldliste
EnterCell(Line, 1, DocuTableField.FIELDNAME("Creation Time"), TRUE, FALSE, FALSE);
EnterCell(Line, 2, DocuTableField.FIELDNAME(Activity), TRUE, FALSE, FALSE);
EnterCell(Line, 3, DocuTableField.FIELDNAME("Field No."), TRUE, FALSE, FALSE);
EnterCell(Line, 4, DocuTableField.FIELDNAME("Field Name"), TRUE, FALSE, FALSE);
EnterCell(Line, 5, DocuTableField.FIELDNAME(Responsible), TRUE, FALSE, FALSE);
EnterCell(Line, 6, DocuTableField.FIELDNAME(Description), TRUE, FALSE, FALSE);
EnterCell(Line, 7, DocuTableField.FIELDNAME("Data Type"), TRUE, FALSE, FALSE);
EnterCell(Line, 8, DocuTableField.FIELDNAME("Field Classe"), TRUE, FALSE, FALSE);
Line := Line + 1;
REPEAT
DocuTableField.CALCFIELDS("Field Name",
Caption,
"Data Type",
"Field Classe");
EnterCell(Line, 1, FORMAT(DocuTableField."Creation Time"), FALSE, FALSE, FALSE);
EnterCell(Line, 2, FORMAT(DocuTableField.Activity), FALSE, FALSE, FALSE);
EnterCell(Line, 3, FORMAT(DocuTableField."Field No."), FALSE, FALSE, FALSE);
EnterCell(Line, 4, DocuTableField."Field Name", FALSE, FALSE, FALSE);
EnterCell(Line, 5, DocuTableField.Responsible, FALSE, FALSE, FALSE);
EnterCell(Line, 6, DocuTableField.Description, FALSE, FALSE, FALSE);
EnterCell(Line, 7, DocuTableField."Data Type", FALSE, FALSE, FALSE);
EnterCell(Line, 8, FORMAT(DocuTableField."Field Classe"), FALSE, FALSE, FALSE);
Line := Line + 1;
UNTIL DocuTableField.NEXT = 0;
Line := Line + 1;
END;
// Globals ausgeben
ExportGlobals(DocuObject, _ActVersion);
// Textkonstanten ausgeben
ExportTextContants(DocuObject, _ActVersion);
// Funktionen ausgeben
ExportFunctions(DocuObject, _ActVersion);
// Trigger ausgeben
ExportTriggers(DocuObject, _ActVersion);
IF FirstObject THEN BEGIN
TempExcelBuffer.CreateSheet(SheetName,
'Documentation ('+ FORMAT(_ActType) +')',
COMPANYNAME,
USERID);
FirstObject := FALSE;
END
ELSE BEGIN
TempExcelBuffer.CreateNewSheet(SheetName,
'Documentation ('+ FORMAT(_ActType) +')',
COMPANYNAME,
USERID);
END;
TempExcelBuffer.DELETEALL;
Line := 1;
UNTIL DocuObject.NEXT(-1) = 0;
END;
TempExcelBuffer.GiveUserControl;
Verfasst: 13. September 2007 12:42
von Nachbaur
Hallo,
Die gefundene Lösung hat mir bisher noch sehr gut gefallen, jedoch stehe ich nun vor einem kleinen Problem.
Ich sollte Inhalte für verschiedene Sheets parallel (bzw. ein Eintrag für sheet1... einer für sheet2 dann wieder einer für sheet1 usw..) angeben können.
Bisher kann ich jedoch nur: Excelbuffer füllen - erstes sheet erstellen -> Excelbuffer leeren - nochmal füllen - zweites sheet erstellen.
Hat jemand einen Lösunsvorschlag für mich?
Danke
lg
Matthias