Aus PB Excel-Datei mit mehreren Tabellenblättern erstellen?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
dysti
Beiträge: 656
Registriert: 10.02.2006 18:34
Wohnort: Schlicktown

Beitrag von dysti »

Achtung: bei Verwendung des Codes muß die Funktion "XLGetCellsValue" mit zum Code von @schic (auf Seite 2) hinzugefügt werden.

Hier der Code:

Code: Alles auswählen

IncludeFile "exelwrapper.pb"

was$=InputRequester("Exel","Bitte geben Sie ' L ' für Lesen ein,keine Eingabe: Schreiben","")

If UCase(was$)="L"
lesen=1
Else
schreiben=1
EndIf

File$="C:\tmp\test.xls"

;ActiveX-Script zum öffnen
;Set pXlApp = CreateObject ("Excel.Application")     
;Set pXlBooks = pXlApp.Workbooks.Open(Ex_Datei)
;set pXlSheets = pXlApp.ActiveWorkBook.WorkSheets("Tabelle1")' Name des 1. Tabellenblattes 

;ActiveX-Script zum schreiben
;Set pxlApp = CreateObject("Excel.Application")
;Set pxlBooks = pxlApp.Workbooks.Add
;Set pxlSheets = pxlBooks.Worksheets.Add
;pxlSheet.Cells(1, 1).Value = "hello"

;ActiveX-Script zum schliessen
;pxlSheet.SaveAs "test.xls"
;pxlBook.Close
;pxlApp.Quit

;Exel_Object erzeugen
pXlApp.IDispatch = SetAppObj("Excel.Application") ; create the object Excel -> Set pXlApp = Excel.Application
If pXlApp = 0
  Debug LastMessage
  End
EndIf


;Exel sichtbar machen
Dim varArr.VARIANT(1)
varArr(0)\vt = #VT_I4 ;Variant-Value
varArr(0)\lVal = 1    ;for TRUE (=1)
AutoWrap(#DISPATCH_PROPERTYPUT, pXlApp, "Visible", 1); put the value "TRUE" to the property Visible -> pXlApp.Visible = True
VariantClear_(varArr(0))

;Datei / Workbooks_Object erzeugen
pXlBooks.IDispatch = SetComObj(pXlApp, "Workbooks", 0)

If lesen=1 ; Datei öffnen
File$ = "C:\tmp\test.xls"
varArr(0)\vt = #VT_BSTR
varArr(0)\bstrVal = Ansi2Uni(File$);File$=xls-Datei
AutoWrap(#DISPATCH_METHOD, pXlBooks, "Open", 1)  
VariantClear_(varArr(0)) 
EndIf

If schreiben=1   ;Daten in Exel schreiben
;Methode Workbooks.Open ausführen
pXlBooks.IDispatch
pvResult.VARIANT
VariantInit_(@pvResult);
AutoWrap(#DISPATCH_PROPERTYGET, pXlBooks, "Add", 0)
pXlBooks = pvResult\pdispVal


;Blatt / Worksheet_Object erzeugen
pxlSheets.IDispatch = SetComObj(pXlBooks, "Worksheets", 0)

;Methode Blatt hinzufügen
pxlSheets.IDispatch 
pvResult.VARIANT
VariantInit_(@pvResult);
AutoWrap(#DISPATCH_PROPERTYGET, pxlSheets, "Add", 0)
pxlSheets = pvResult\pdispVal

;Eintrag in einer Zelle
XLPutCellsStrValue(pXlSheets, 1, 3, "blabla")
EndIf
PB5 / Spiderbasic / WB14 / Win7 / Win8.1 / Win10 / Debian 9
Benutzeravatar
dysti
Beiträge: 656
Registriert: 10.02.2006 18:34
Wohnort: Schlicktown

Beitrag von dysti »

Das verstehe ich nicht:
oder holst Dir vorher das Workbook-Objekt (nicht die Liste).
Kannst du ein Beispiel geben?
PB5 / Spiderbasic / WB14 / Win7 / Win8.1 / Win10 / Debian 9
schic
Beiträge: 68
Registriert: 25.12.2004 19:04

Beitrag von schic »

Beispiel zur Unterscheidung von Workbook und Workbooks
mit Deinem Code von oben mit Korrekturen:

Code: Alles auswählen

;was$=InputRequester("Exel","Bitte geben Sie ' L ' für Lesen ein,keine Eingabe: Schreiben","")
;# eine Unterscheidung ist nicht notwendig. Es kann im Wechsel gelesen und geschrieben werden!

If UCase(was$)="L"
  lesen=1
Else
  schreiben=1
EndIf

File$="C:\mappe1.xls"

;ActiveX-Script zum öffnen
;Set pXlApp = CreateObject ("Excel.Application")     
;Set pXlBooks = pXlApp.Workbooks.Open(Ex_Datei)
;set pXlSheets = pXlApp.ActiveWorkBook.WorkSheets("Tabelle1")' Name des 1. Tabellenblattes

;ActiveX-Script zum schreiben
;Set pxlApp = CreateObject("Excel.Application")
;Set pxlBooks = pxlApp.Workbooks.Add     <- pXlBooks von oben wird überschrieben!!!!!!!!!
;Set pxlSheets = pxlBooks.Worksheets.Add <- pXlSheets von oben wird überschrieben!!!!!!!!!
;pxlSheet.Cells(1, 1).Value = "hello"    <- Objekt pxlSheet existiert nicht!!!!!!!!!!

;ActiveX-Script zum schliessen
;pxlSheet.SaveAs "test.xls"
;pxlBook.Close
;pxlApp.Quit

;Exel_Object erzeugen
pXlApp.IDispatch = SetAppObj("Excel.Application") ; create the object Excel -> Set pXlApp = Excel.Application
If pXlApp = 0
  Debug LastMessage
  End
EndIf

;Exel sichtbar machen
Dim varArr.VARIANT(1)
varArr(0)\vt = #VT_I4 ;Variant-Value
varArr(0)\lVal = 1    ;for TRUE (=1)
AutoWrap(#DISPATCH_PROPERTYPUT, pXlApp, "Visible", 1); put the value "TRUE" to the property Visible -> pXlApp.Visible = True
VariantClear_(varArr(0))

;Datei / Workbooks_Object erzeugen
pXlBooks.IDispatch = SetComObj(pXlApp, "Workbooks", 0)

File$ = "C:\mappe1.xls"
;Methode Workbooks.Open ausführen
varArr(0)\vt = #VT_BSTR
varArr(0)\bstrVal = Ansi2Uni(File$)
AutoWrap(#DISPATCH_METHOD, pXlBooks, "Open", 1) 
VariantClear_(varArr(0))

;#####################################
;#Methode Workbooks.Open ausführen <- hier wird mit "Add" ein Neues Workbook erzeugt!!!!!!!
;#das bringt Nichts wenn Du das geöffnete Workbook bearbeiten willst!!!!!!!!
;# pXlBooks.IDispatch
;# pvResult.VARIANT
;# VariantInit_(@pvResult);
;# AutoWrap(#DISPATCH_PROPERTYGET, pXlBooks, "Add", 0)
;# pXlBooks = pvResult\pdispVal <- pXlBooks wurde oben bereits erzeugt. Doppelbelegung!!!!!!!!
;#######################################

;ActiveWorkbook-Eigenschaft, betrifft: Application-Objekt
;Gibt ein Workbook-Objekt zurück, das die Arbeitsmappe im 
;aktiven Fenster (das Fenster im Vordergrund) repräsentiert. 
;Schreibgeschützt. Sind keine Fenster geöffnet oder ist das 
;aktive Fenster das info- oder Zwischenablagefenster, so 
;wird Nothing zurückgegeben.
pXlBooks.IDispatch
pvResult.VARIANT
VariantInit_(@pvResult);
AutoWrap(#DISPATCH_PROPERTYGET, pXlApp, "ActiveWorkbook", 0)
pXlBook = pvResult\pdispVal

;Blatt / Worksheet_Object erzeugen <- nicht Worksheet_Object!!! sond. Worksheets-Eigenschaft betrifft: Application-Objekt und Workbook-Objekt
; Gibt für ein Application-Objekt eine Sheets-Auflistung aller Arbeitsblätter 
; der aktiven Arbeitsmappe zurück. Gibt für ein Workbook-Objekt eine 
; Sheets-Auflistung zurück, die alle Arbeitsblätter in der angegebenen 
; Arbeitsmappe darstellt. Schreibgeschütztes Sheets-Objekt.
;pxlSheets.IDispatch = SetComObj(pXlBook, "Worksheets", 0) ; <- Version 1 über das Workbook-Objekt
pxlSheets.IDispatch = SetComObj(pXlApp, "Worksheets", 0)   ; <- Version 2 über das Application-Objekt

;Methode Blatt hinzufügen
pxlSheets.IDispatch
pvResult.VARIANT
VariantInit_(@pvResult);
AutoWrap(#DISPATCH_PROPERTYGET, pxlSheets, "Add", 0)
pxlNewSheet = pvResult\pdispVal ; <- neues Interface verwenden nicht pxlSheets von oben!!!!!!!!

;Eintrag in einer Zelle
XLPutCellsStrValue(pxlNewSheet, 1, 3, "blabla")

Benutzeravatar
dysti
Beiträge: 656
Registriert: 10.02.2006 18:34
Wohnort: Schlicktown

Beitrag von dysti »

@schic, danke für die Antwort. Das hätte ich alleine nicht heraus gefunden.
PB5 / Spiderbasic / WB14 / Win7 / Win8.1 / Win10 / Debian 9
schic
Beiträge: 68
Registriert: 25.12.2004 19:04

Beitrag von schic »

hier noch ein Code zum Bearbeiten von zwei unterschiedlichen Workbooks
eines das geöffnet wird, und eins das neu erzeugt wird.
Ich nehme an, daß Du so etwas in der Richtung vorhattest!?

Code: Alles auswählen

File$="C:\mappe1.xls"

;Exel_Object erzeugen
pXlApp.IDispatch = SetAppObj("Excel.Application") ; create the object Excel -> Set pXlApp = Excel.Application
If pXlApp = 0
  Debug LastMessage
  End
EndIf

;Exel sichtbar machen
Dim varArr.VARIANT(1)
varArr(0)\vt = #VT_I4 ;Variant-Value
varArr(0)\lVal = 1    ;for TRUE (=1)
AutoWrap(#DISPATCH_PROPERTYPUT, pXlApp, "Visible", 1); put the value "TRUE" to the property Visible -> pXlApp.Visible = True
VariantClear_(varArr(0))

;Datei / Workbooks_Object erzeugen
pXlBooks.IDispatch = SetComObj(pXlApp, "Workbooks", 0)

File$ = "C:\mappe1.xls"
;Methode Workbooks.Open ausführen
varArr(0)\vt = #VT_BSTR
varArr(0)\bstrVal = Ansi2Uni(File$)
AutoWrap(#DISPATCH_METHOD, pXlBooks, "Open", 1) 
VariantClear_(varArr(0))

;ActiveWorkbook-Eigenschaft, betrifft: Application-Objekt
;Gibt ein Workbook-Objekt zurück, das die Arbeitsmappe im 
;aktiven Fenster (das Fenster im Vordergrund) repräsentiert. 
;Schreibgeschützt. Sind keine Fenster geöffnet oder ist das 
;aktive Fenster das info- oder Zwischenablagefenster, so 
;wird Nothing zurückgegeben.
pXlBookThatWasOpened.IDispatch
pvResult.VARIANT
VariantInit_(@pvResult);
AutoWrap(#DISPATCH_PROPERTYGET, pXlApp, "ActiveWorkbook", 0)
pXlBookThatWasOpened = pvResult\pdispVal

;#####################################
; Workbooks.Add
; Achtung muß nach ActiveWorkbook ausgeführt werden, 
; sonst gibt´s mit ActiveWorkbook dieses neu hinzugefügte WB!
 pXlBooks.IDispatch
 pvResult.VARIANT
 VariantInit_(@pvResult);
 AutoWrap(#DISPATCH_PROPERTYGET, pXlBooks, "Add", 0)
 pXlBookNeu = pvResult\pdispVal 
;#######################################

;Blatt / Worksheet_Object erzeugen <- nicht Worksheet_Object!!! sond. Worksheets-Eigenschaft betrifft: Application-Objekt und Workbook-Objekt
; Gibt für ein Application-Objekt eine Sheets-Auflistung aller Arbeitsblätter 
; der aktiven Arbeitsmappe zurück. Gibt für ein Workbook-Objekt eine 
; Sheets-Auflistung zurück, die alle Arbeitsblätter in der angegebenen 
; Arbeitsmappe darstellt. Schreibgeschütztes Sheets-Objekt.
pxlSheets.IDispatch = SetComObj(pXlBookThatWasOpened, "Worksheets", 0) ; <- Version 1 über das Workbook-Objekt

;Methode Blatt hinzufügen
pxlNewSheetInBook1.IDispatch
pvResult.VARIANT
VariantInit_(@pvResult);
AutoWrap(#DISPATCH_PROPERTYGET, pxlSheets, "Add", 0)
pxlNewSheetInBook1 = pvResult\pdispVal ; <- neues Interface verwenden nicht pxlSheets von oben!!!!!!!!

;Eintrag in einer Zelle im neuen Sheet in geöffneten Workbook
XLPutCellsStrValue(pxlNewSheetInBook1, 1, 3, "blabla")

;Objektzeiger auf "Tabelle1" des neuen Workbooks holen
varArr(0)\vt = #VT_BSTR
varArr(0)\bstrVal = Ansi2Uni("Tabelle1")
pXlSheetInBook2.IDispatch = SetComObj(pXlBookNeu, "Worksheets", 1)
VariantClear_(varArr(0))

XLPutCellsStrValue(pXlSheetInBook2, 1, 1, "Eintrag in Mappe1 Tabelle1")

cleaningUp:
ReleaseAllObjects()
CoUninitialize_()
Benutzeravatar
dysti
Beiträge: 656
Registriert: 10.02.2006 18:34
Wohnort: Schlicktown

Beitrag von dysti »

Hallo @schic,
tut mir leid, aber es läuft leider nicht und bekomme es auch nicht heraus.
Zum beiden Beispielen bricht das Prg mit ein "Invalid memory access" ab und bleibt in dieser Zeile stehen:

Code: Alles auswählen

hr = *pDisp\GetIDsOfNames(IID_NULL, @ptUniName, 1, #LOCALE_USER_DEFAULT, @dispID)
Der Debugger gibt folgendes aus:

Beispiel1:
  • exception\scode:-2146827284
    Worksheets NOT o.k.
    Add
    getting IDs of Add
Exel ist gestartet. Keine Mappe offen.

Im zweiten Beispiel das gleiche mit dieser Meldung:
  • Worksheets
    getting IDs of Worksheets
Exel ist gestartet, eine Mappe geöffnet.

Was möchte ich?
Eine Exeldatei öffnen, Eine bestimmtes Tabellenblatt, z.B. "Dystiblatt2", aktivieren und eine Zelle aus "Dystiblatt2" auslesen.

Mit deiner Vermutung liegst du richtig.
PB5 / Spiderbasic / WB14 / Win7 / Win8.1 / Win10 / Debian 9
schic
Beiträge: 68
Registriert: 25.12.2004 19:04

Beitrag von schic »

schau mal über dem Abschnitt:

Code: Alles auswählen

;Methode Workbooks.Open ausführen
da habe ich vergessen

Code: Alles auswählen

File$ = "C:\mappe1.xls"
zu löschen. So wird die Variable überschrieben und die Datei gibt´s
bei Dir nicht. Ich denke darin liegt der Grund für den Fehler bei Dir?

Außerdem habe ich im 1ten Bsp. noch einige Fehler übersehen, die bei mir aber keine Meldung verursachen:

Code: Alles auswählen

...
;Methode Blatt hinzufügen
pxlSheets.IDispatch 
muß sein

Code: Alles auswählen

pxlNewSheet.IDispatch 
und

Code: Alles auswählen

...
;aktive Fenster das info- oder Zwischenablagefenster, so
;wird Nothing zurückgegeben.
pXlBooks.IDispatch
muß sein

Code: Alles auswählen

pXlBook.IDispatch
Tja, war ich wohl zu schnell und unkonzentriert :oops:
Benutzeravatar
dysti
Beiträge: 656
Registriert: 10.02.2006 18:34
Wohnort: Schlicktown

Beitrag von dysti »

@schic, bin beim 2. Beispiel und genau diese Zeile hakelt.:

Code: Alles auswählen

pxlSheets.IDispatch = SetComObj(pXlBookThatWasOpened, "Worksheets", 0)
Habe extra die Datei "Mappe1.xls" im C:\-Verzeichnis erstellt, damit ich den Code nicht ändern muß.
PB5 / Spiderbasic / WB14 / Win7 / Win8.1 / Win10 / Debian 9
schic
Beiträge: 68
Registriert: 25.12.2004 19:04

Beitrag von schic »

zuerst mal
Was möchte ich?
Eine Exeldatei öffnen, Eine bestimmtes Tabellenblatt, z.B. "Dystiblatt2", aktivieren und eine Zelle aus "Dystiblatt2" auslesen.

Code: Alles auswählen

Procedure.l XLGetCellsValue(*sheet.IDispatch, Row, Column)
  Shared tmpText$, qtmp.d
  
  Dim varArr.VARIANT(2)
  varArr(0)\vt = #VT_I4
  varArr(0)\lVal = Column
  varArr(1)\vt = #VT_I4
  varArr(1)\lVal = Row
  pXlCells_x_y.IDispatch
  pvResult.VARIANT
  VariantInit_(@pvResult);
  AutoWrap(#DISPATCH_PROPERTYGET, *sheet, "Cells", 2)
  pXlCells_x_y = pvResult\pdispVal
  
  VariantInit_(pvResult.VARIANT)
  AutoWrap(#DISPATCH_PROPERTYGET,  pXlCells_x_y, "Value", 0)
  ;Debug "pvResult\vt: " + Str(pvResult\vt)
  Select pvResult\vt
    Case #VT_BSTR
      tmpText$ = Uni2Ansi(pvResult\bstrVal)
      result = @tmpText$
      
    Case #VT_R8
      qtmp = pvResult\dblVal
      result = @qtmp
      
  EndSelect
  
  VariantClear_(varArr(0))
  VariantClear_(varArr(1))
  VariantClear_(pvResult)
  
  SetObjNothing(pXlCells_x_y)
  
  ProcedureReturn result
EndProcedure

File$="C:\mappe1.xls"

;Exel_Object erzeugen
pXlApp.IDispatch = SetAppObj("Excel.Application") ; create the object Excel -> Set pXlApp = Excel.Application
If pXlApp = 0
  Debug LastMessage
  End
EndIf

;Exel sichtbar machen
Dim varArr.VARIANT(1)
varArr(0)\vt = #VT_I4 ;Variant-Value
varArr(0)\lVal = 1    ;for TRUE (=1)
AutoWrap(#DISPATCH_PROPERTYPUT, pXlApp, "Visible", 1); put the value "TRUE" to the property Visible -> pXlApp.Visible = True
VariantClear_(varArr(0))

;Datei / Workbooks_Object erzeugen
pXlBooks.IDispatch = SetComObj(pXlApp, "Workbooks", 0)

;Methode Workbooks.Open ausführen
varArr(0)\vt = #VT_BSTR
varArr(0)\bstrVal = Ansi2Uni(File$)
AutoWrap(#DISPATCH_METHOD, pXlBooks, "Open", 1)
VariantClear_(varArr(0))

varArr(0)\vt = #VT_BSTR
varArr(0)\bstrVal = Ansi2Uni("Dystiblatt2") ; <- Blatt muß vorhanden sein!
pXlSheetDystiblatt2.IDispatch = SetComObj(pXlApp, "Worksheets", 1)
VariantClear_(varArr(0))

AutoWrap(#DISPATCH_METHOD, pXlSheetDystiblatt2, "Activate", 0)

; für das Auslesen eines Textes
*tmp = XLGetCellsValue(pXlSheetDystiblatt2, 2, 1) ; <- Row + Column anpassen!
If *tmp
  Debug " "
  Debug "###############################"
  Debug "# Ausgelesen: " + PeekS(*tmp)
  Debug "###############################"
  Debug " "
EndIf  

;für das Auslesen einer Zahl
*tmp = XLGetCellsValue(pXlSheetDystiblatt2, 3, 1) ; <- Row + Column anpassen!
If *tmp
  Debug " "
  Debug "###############################"
  Debug "# Ausgelesen: " + StrD(PeekD(*tmp))
  Debug "###############################"
  Debug " "
  EndIf  

cleaningUp:
ReleaseAllObjects()
CoUninitialize_()
und:
war der falsche Dateiname im 1ten Beispiel der Fehler?
Benutzeravatar
dysti
Beiträge: 656
Registriert: 10.02.2006 18:34
Wohnort: Schlicktown

Beitrag von dysti »

Habe das jetzt auf einem anderen System unter WINXP probiert.
Gleiches Verhalten. Hat also nichts mit WIN2000 zu tun.
Auch hier vorher die Datei "Mappe1.xls unter "C:\" generiert.
Es ist zum verrückt werden.
PB5 / Spiderbasic / WB14 / Win7 / Win8.1 / Win10 / Debian 9
Antworten