ExcelFunktionen COMatePlus

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Lord
Beiträge: 312
Registriert: 21.01.2008 19:11

Re: ExcelFunktionen COMatePlus

Beitrag von Lord »

Hallo Peter!

"Invoke" scheint der richtige Weg zu sein, aber...
Debug hat geschrieben:Protect: The operation completed, but was only partially successful. (The 'ActiveSheet' property returned a NULL object!)
Das zustängige Codeteil sieht jetzt so aus:

Code: Alles auswählen

  Protected.COMateObject ActiveSheet
  ActiveSheet = ExcelObject\GetObjectProperty("ActiveSheet")
  Debug "ActiveSheet: "+comate_getlasterrordescription()
  If ActiveSheet
    Debug "Active: "+ActiveSheet
    
    ActiveSheet\Invoke("ActiveSheet\Protect(#Opt, #True, #True, #True)")    
    Debug "Protect: "+comate_getlasterrordescription()

    ActiveSheet\Release()
    Debug "Release: "+comate_getlasterrordescription()
  Else
    Debug "No ActiveSheet"    
  EndIf
Die zugehörigen Fehlermeldungen:
Debug hat geschrieben:ActiveSheet: Okay.
Active: 28789824
Protect: The operation completed, but was only partially successful. (The 'ActiveSheet' property returned a NULL object!)
Release: The operation completed, but was only partially successful. (The 'ActiveSheet' property returned a NULL object!)
Ein Auffüllen der restlichen Parameter mit "#Opt" zeitigt selbige Fehlermeldung.

Code: Alles auswählen

 ActiveSheet\Invoke("ActiveSheet\Protect( #Opt, #True, #True, #True, #Opt, #Opt, #Opt, #Opt, #Opt, #Opt, #Opt, #Opt, #Opt, #Opt, #Opt, #Opt)")    
Das Einfügen eines Passwortes hilft ebenfalls nicht:

Code: Alles auswählen

Protected pw.s="einpasswort"
ActiveSheet\Invoke("ActiveSheet\Protect('"+pw+"', #True, #True, #True)")    
Dieses ergibt ebenfalls wieder obige Fehlermeldungen.

Was kann man da noch machen?
Bild
Benutzeravatar
Kiffi
Beiträge: 10620
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: ExcelFunktionen COMatePlus

Beitrag von Kiffi »

da ist ein ActiveSheet zuviel (hatte ich übersehen):

Code: Alles auswählen

ActiveSheet\Invoke("Protect(#Opt, #True, #True, #True)")
Grüße ... Peter
Hygge
Lord
Beiträge: 312
Registriert: 21.01.2008 19:11

Re: ExcelFunktionen COMatePlus

Beitrag von Lord »

Hallo Peter!
Kiffi hat geschrieben:da ist ein ActiveSheet zuviel (hatte ich übersehen)
...
Das war's! :allright:

Die Erstellung einer Tabelle mit Formatierung, nicht scrollbarer Kopfzeile
und das Sperren der Zellen der Kopfzeile funktioniert jetzt. Mit Excel kann
man sie einlesen, bearbeiten usw. Alles wie es soll. :)

Nur funktioniert jetzt das Einlesen der Tabelle mittels COMate nicht mehr. :shock:
Ich habe mittels Debuganweisungen diese Zeile als Auslöser für einen IMA
isoliert:

Code: Alles auswählen

LastRow=XLSFunc_GetLastRow(NewExcelObject)
Die Zeile davor liefern alle "Okay".
In der COMatePLUS.pbi wird in der Procedure COMateClass_INTERNAL_InvokeiDispatch()
in diesem Teil mit IMA abgebrochen:

Code: Alles auswählen

If excep\bstrSource
  SysFreeString_(excep\bstrSource); <- hier tritt der Fehler auf
EndIf          
Es hat nichts mit dem Passwort zu tun. Wenn ich statt einem PW "#Opt"
einsetze gibt es ebenfalls einen IMA.

Kommentiere ich allerdings den Code für das Sperren der Zellen aus,
erscheint der Fehler nicht mehr.
Es muß also noch etwas falsch sein beim Sperren der Zellen.

Bild
Bild
Benutzeravatar
Falko
Admin
Beiträge: 3531
Registriert: 29.08.2004 11:27
Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.0
Kontaktdaten:

Re: ExcelFunktionen COMatePlus

Beitrag von Falko »

Ich bin mir nicht sicher, aber in COMate wird nach der Zeichenfolge "#opt" und nicht
"#Opt" abgefragt. Darum wird das vermutlich als Fehler angemeckert.

Hier der Auszug aus COMATE...

Code: Alles auswählen

 Case "#empty", "#optional", "#opt" ;Used for optional parameters.
Gruß,
Falko
Bild
Win10 Pro 64-Bit, PB_5.4,GFA-WinDOS, Powerbasic9.05-Windows, NSBasic/CE, NSBasic/Desktop, NSBasic4APP, EmergenceBasic
Lord
Beiträge: 312
Registriert: 21.01.2008 19:11

Re: ExcelFunktionen COMatePlus

Beitrag von Lord »

Hallo Falko!

Danke für Deine Antwort.

Die Schreibweise für "#Opt" ist hier nicht ausschlaggebend.
Egal, ob "#Opt", "#opt", "#Optional" oder "#optional" eingesetzt
wird, tritt der Fehler auf.

Die Erzeugung der Tabelle funktioniert ja auch dahingehend, daß
sie mit Excel les-, bearbeit- und speicherbar ist.

Der Speicherfehler tritt ja erst beim Einlesen der erzeugten Tabelle
mittels COMate auf. Dieser Programmteil hatte bisher keine Probleme
bereitet. Ich kann damit fremde Excel-Tabellen und die selber er-
zeugten Tabellen einlesen. Nur wenn ich jetzt die Kopfzeilenzellen
sperre, bricht der Lesevorgang mit IMA ab.

Nachtrag:
Ich habe gerade festgestellt, daß der Fehler auch auftritt, wenn ich
ein solches geschütztes Tabellenblatt mit Excel erstelle und dann
versuche mit COMate einzulesen.
Die Erstellung einer Tabelle, welche geschütze Zellen enthält ist dem-
nach nicht das Problem. Vielmehr scheint COMate Probleme zu haben,
ein solche geschütztes Tabellenblatt einzulesen.
Kann das jemand so bestätigen?
Bild
Lord
Beiträge: 312
Registriert: 21.01.2008 19:11

Re: ExcelFunktionen COMatePlus

Beitrag von Lord »

Anderer Ansatz:
Wie läßt sich folgendes in COMate umsetzen:
letztezeile = ActiveSheet.Cells(65536, 1).End(xlUp).Row
Ich versuche damit XLS_GetLastRow() aus der ExcelFunktion.pbi
zu ersetzen, da mir da immer der IMA dazwischenfunkt.
Läßt sich dafür

Code: Alles auswählen

ExcelObject\GetIntegerProperty()
nutzen? Wenn ja, wie?
Bild
Benutzeravatar
Kiffi
Beiträge: 10620
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: ExcelFunktionen COMatePlus

Beitrag von Kiffi »

Lord hat geschrieben:Vielmehr scheint COMate Probleme zu haben,
ein solche geschütztes Tabellenblatt einzulesen.
Bastel doch mal bitte einen kleinen Code zusammen, der ein Tabellenblatt schützt, abspeichert und wieder einliest.

Ich versuche dann, mich durch den COMate-Code zu wuseln und die Stelle zu finden, die für den IMA verantwortlich ist.

Grüße ... Peter
Hygge
Lord
Beiträge: 312
Registriert: 21.01.2008 19:11

Re: ExcelFunktionen COMatePlus

Beitrag von Lord »

Hallo Peter!

Danke für Dein Hilfsangebot.
Hier die beiden Prozeduren zum Erzeugen und Einlesen einer (geschützten) Tabelle:

Code: Alles auswählen

XIncludeFile "...\COMmate\ExcelFunctions.pbi" ; hier aktuellen Pfad setzen
EnableExplicit

Procedure MakeEmptyXLS()
  Debug "Enter MakeEmptyXLS()"
  Protected.COMateObject ExcelObject, WorkBook, ActiveSheet
  Protected XLSPath.s, Datei.s, Range.s, pw.s
  Datei.s=GetPathPart(ProgramFilename())+"Neu.xls"
  Debug Datei
  Datei.s=SaveFileRequester("Leere Excel-Datei erstellen...", Datei, "Excel-Datei (*.xls)|*.xls", 0)
  If Datei<>""
    If FileSize(Datei)>-1
      If MessageRequester("Achtung!",
                          "Die Datei '"+GetFilePart(Datei)+"' existiert bereits."+#CRLF$+#CRLF$+"Soll sie überschrieben werden?",
                          #PB_MessageRequester_YesNo|#MB_ICONQUESTION)=#PB_MessageRequester_No
        ProcedureReturn
      EndIf
    EndIf
    
    
    XLSPath=GetPathPart(Datei)
    ExcelObject = COMate_CreateObject("Excel.Application")
    If ExcelObject
      ExcelObject\SetProperty("Visible = #false")                   ; Excel im Hintergrund. Kann man nur im Taskmanager sehen
      WorkBook = ExcelObject\GetObjectProperty("Workbooks\Add")     ; fügt eine Tabelle hinzu
      ExcelObject\SetProperty("WorkSheets(1)\Name = 'Tabelle 1'")   ; Tabelle1 mit Namen verzeichnen
      ExcelObject\SetProperty("WorkSheets(2)\Name = 'Tabelle 2'")   ; Tabelle1 mit Namen verzeichnen
      ExcelObject\SetProperty("WorkSheets(3)\Name = 'Tabelle 3'")   ; Tabelle1 mit Namen verzeichnen
      XLSFunc_DeleteWorksheet(ExcelObject.COMateObject,"Tabelle 2") ; Tabellenblatt 2 löschen
      XLSFunc_DeleteWorksheet(ExcelObject.COMateObject,"Tabelle 3") ; Tabellenblatt 3 löschen
      Debug "Delete Sheets 2 and 3: "+comate_getlasterrordescription()
      
      XLSFunc_SetCellFormat(ExcelObject, "A:H", "@")                ; Spalten "Kopf 1" bis "Kopf 5" als Text formatieren   
      XLSFunc_SetCellFormat(ExcelObject, "F:F", "000000000")        ; Spalte "Kopf 6" als Zahl mit neun Stellen und führender Null
      XLSFunc_SetCellFormat(ExcelObject, "1:1", "@")                ; Kopfzeile als Text formatieren 
      Debug "Set Format: "+comate_getlasterrordescription()
      
      XLSFunc_SetFontAlignment(ExcelObject, "E:G",#xlHAlignCenter)  ; Spalte "Kopf 5" zentrieren
      XLSFunc_SetFontAlignment(ExcelObject, "1:1",#xlHAlignCenter)  ; Spalte "Kopf 6" zentrieren
      Debug "Align : "+comate_getlasterrordescription()
      
      
      ExcelObject\SetProperty("Cells(1,1) = 'Kopf 1'")              ; Header "Kopf 1"
      ExcelObject\SetProperty("Cells(1,2) = 'Kopf 2'")              ; Header "Kopf 2"
      ExcelObject\SetProperty("Cells(1,3) = 'Kopf 3'")              ; Header "Kopf 3"
      ExcelObject\SetProperty("Cells(1,4) = 'Kopf 4'")              ; Header "Kopf 4"
      ExcelObject\SetProperty("Cells(1,5) = 'Kopf 5'")              ; Header "Kopf 5"
      ExcelObject\SetProperty("Cells(1,6) = 'Kopf 6'")              ; Header "Kopf 6"
      ExcelObject\SetProperty("Cells(1,7) = 'Kopf 7'")              ; Header "Kopf 7"
      ExcelObject\SetProperty("Cells(1,8) = 'Kopf 8'")              ; Header "Kopf 8"
      Debug "Set title text: "+comate_getlasterrordescription()
      
      
      XLSFunc_LockFirstLine(ExcelObject, "A2")                      ; Kopfzeile soll nicht scrollen
      Debug "Lock: "+comate_getlasterrordescription()
      
      
      ;   Sub Makro1()
      ; '
      ; ' Makro1 Makro
      ; ' Makro am 02.12.2015 aufgezeichnet
      ; '
      ; ' Tastenkombination: Strg+s
      ; '
      ;     Columns("A:H").Select
      ;     Selection.Locked = False
      ;     Selection.FormulaHidden = False
      ;     Range("A1:H1").Select
      ;     Selection.Locked = True
      ;     Selection.FormulaHidden = False
      ;     Range("A2").Select
      ;     ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
      ; End Sub
      
      Range= "A:IV"                                                    ; Gesamtes Blatt entsperren
      ExcelObject\Invoke("Range('" +Range+ "')\Select" )
      Debug "Set Range A:H: "+comate_getlasterrordescription()
      
      ExcelObject\setproperty("Selection\Locked = #False")
      Debug "Set Locked = #False: "+comate_getlasterrordescription()
      
      ;   ExcelObject\setproperty("Selection\FormulaHidden = #False")   ; nicht benötigt
      ;   Debug "Set FormulaHidden = #False: "+comate_getlasterrordescription()
      ;   
      Range= "A1:H1"                                                   ; Zellen der Kopfeinträge auswählen...
      ExcelObject\Invoke("Range('" +Range+ "')\Select" )
      Debug "Set Range A1:H1: "+comate_getlasterrordescription()
      
      ExcelObject\setproperty("Selection\Locked = #True")              ; und sperren
      Debug "Set Locked = #True: "+comate_getlasterrordescription()
      
      ;   ExcelObject\setproperty("Selection\FormulaHidden = #False")   ; nicht benötigt
      ;   Debug "Set FormulaHidden =#False: "+comate_getlasterrordescription()
      
      Range= "A1"                                                      ; Kosmetik: A1 ist aktuelle Zelle
      ExcelObject\Invoke("Range('" +Range+ "')\Select" )
      Debug "Set Range A1: "+comate_getlasterrordescription()
      
      ActiveSheet = ExcelObject\GetObjectProperty("ActiveSheet")       ; Tabellenblatt zum Sperren der Zellen auswählen
      Debug "ActiveSheet: "+comate_getlasterrordescription()
      
      If ActiveSheet
        
        pw="Passwort"                                                   ; Passwort zum Entsperren setzen
        ActiveSheet\Invoke("Protect('"+pw+"', #True, #True, #True)")    ; gewählte Zellen sperren
                                                                        ;     ActiveSheet\Invoke("Protect(#opt, #True, #True, #True)")
        Debug "Protect: "+comate_getlasterrordescription()
        
        ActiveSheet\Release()                                           ; Tabellenblatt wieder freigeben 
        Debug "Release: "+comate_getlasterrordescription()
      Else
        Debug "No ActiveSheet"    
      EndIf
      
      
      ExcelObject\SetProperty("Application\DisplayAlerts = #False") ; Excel-Alerts vor dem Speichern und Beenden ausschalten
      Debug "Set DisplayAlerts = #False: "+comate_getlasterrordescription()
      ExcelObject\Invoke("ActiveWorkbook\SaveAs('"+Datei+"')")      ; Dateiname
      Debug "SaveAs: "+comate_getlasterrordescription()
      ExcelObject\Invoke("ActiveWorkbook\Close")                    ; Schließe aktive Tabelle
      Debug "Close ActiveWorkbook: "+comate_getlasterrordescription()
      ExcelObject\Invoke("Workbooks\Close")                         ; Schließe Excelmappe
      Debug "Close Workbooks: "+comate_getlasterrordescription()
      ExcelObject\Invoke("Quit()")                                  ; Excel beenden
      Debug "Quit: "+comate_getlasterrordescription()
      ExcelObject\SetProperty("Application\DisplayAlerts = #True")  ; Excel-Alerts wieder aktivieren
      Debug "Set DisplayAlerts = #True: "+comate_getlasterrordescription()
      ExcelObject\Release()                                         ; Objekt freigeben
      Debug "Release: "+comate_getlasterrordescription()
    Else
      MessageRequester("Achtung!", "Excel-Datei konnte nicht erstellt werden.")
    EndIf  
  EndIf  
EndProcedure
Procedure ReadXLS()
  Debug "Enter ReadXLS()"
  Protected.COMateObject NewExcelObject
  Protected Row.i, LastRow.i=1
  Protected XLSFile.s, Zeile.s
  XLSFile=GetPathPart(ProgramFilename())+"Neu.xls"
  
  
  NewExcelObject=XLSFunc_OpenExcelFile(XLSFile)
  Debug "NewExcelObject: "+comate_getlasterrordescription()
  
  If NewExcelObject:Debug "NewExcelObject"
    XLSFunc_ExcelVisible(NewExcelObject,#False)
    Debug "Visible set to: #False: "+comate_getlasterrordescription()
    If XLSFunc_GetSheetName(NewExcelObject, 1)="Tabelle 1"
      Debug "GetSheetName: "+comate_getlasterrordescription()
      XLSFunc_ChangeToWorksheet(NewExcelObject, "Tabelle 1")
      Debug "ChangeToWorksheet: "+comate_getlasterrordescription()
      
      LastRow=XLSFunc_GetLastRow(NewExcelObject)
      Debug XLSFunc_GetLastCellFillFirst(NewExcelObject)
      
      ; Workaround für GetLastRow(): 
      ;       While XLSFunc_ReadCellS(NewExcelObject, LastRow, 6)
      ;         Debug "LastRow: "+comate_getlasterrordescription()
      ;         LastRow+1
      ;       Wend
      ;       LastRow-1
      
      Row=1
      
      Zeile+XLSFunc_ReadCellS(NewExcelObject, Row, 1)+Chr(9)+
            XLSFunc_ReadCellS(NewExcelObject, Row, 2)+Chr(9)+
            XLSFunc_ReadCellS(NewExcelObject, Row, 3)+Chr(9)+
            XLSFunc_ReadCellS(NewExcelObject, Row, 4)+Chr(9)+
            XLSFunc_ReadCellS(NewExcelObject, Row, 5)+Chr(9)+
            XLSFunc_ReadCellS(NewExcelObject, Row, 6)+Chr(9)+
            XLSFunc_ReadCellS(NewExcelObject, Row, 7)+Chr(9)+
            XLSFunc_ReadCellS(NewExcelObject, Row, 8)
      Debug "ReadCell (all): "+comate_getlasterrordescription()
      Debug Zeile
      
    Else
      Debug "Konnte 'Tabelle 1 nicht finden."
    EndIf
    
    XLSFunc_CloseWorkbook(NewExcelObject)
    XLSFunc_CloseExcelAll(NewExcelObject)
  EndIf
EndProcedure
MakeEmptyXLS()
ReadXLS()
Zeilen 159 bis 163 enthalten übrigens ein workaround für das
Ermitteln der letzten Tabellenzeile. Dieses ist aber nur für
meinen speziellen Fall gültig, da ich weiß, daß Spalte 6 ("Kopf 6")
immer in der letzten Zeile gefüllt ist.

Viel Spaß beim "wuseln".
Bild
Benutzeravatar
Kiffi
Beiträge: 10620
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: ExcelFunktionen COMatePlus

Beitrag von Kiffi »

Lord hat geschrieben:Viel Spaß beim "wuseln".
oh, ich musste gar nicht wuseln. Dein Code läuft bei mir (Excel 2003) problemlos durch. Kein IMA bei XLSFunc_GetLastRow().
PB-Debugger hat geschrieben:Enter MakeEmptyXLS()
C:\Users\tuebben\AppData\Local\Temp\Neu.xls
Delete Sheets 2 and 3: Okay.
Set Format: Okay.
Align : Okay.
Set title text: Okay.
Lock: Okay.
Set Range A:H: Okay.
Set Locked = #False: Okay.
Set Range A1:H1: Okay.
Set Locked = #True: Okay.
Set Range A1: Okay.
ActiveSheet: Okay.
Protect: Okay.
Release: Okay.
Set DisplayAlerts = #False: Okay.
SaveAs: Okay.
Close ActiveWorkbook: Okay.
Close Workbooks: Okay.
Quit: Okay.
Set DisplayAlerts = #True: Okay.
Release: Okay.
Enter ReadXLS()
NewExcelObject: Okay.
NewExcelObject
Visible set to: #False: Okay.
GetSheetName: Okay.
ChangeToWorksheet: Okay.
0
ReadCell (all): Okay.
Kopf 1 Kopf 2 Kopf 3 Kopf 4 Kopf 5 Kopf 6 Kopf 7 Kopf 8
Grüße ... Peter
Hygge
Benutzeravatar
Falko
Admin
Beiträge: 3531
Registriert: 29.08.2004 11:27
Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.0
Kontaktdaten:

Re: ExcelFunktionen COMatePlus

Beitrag von Falko »

Ich habs bei meinem Excel 2015 Business auch mal durchlaufen lassen (64bitPB)
Enter MakeEmptyXLS()
C:\Users\Falko\AppData\Local\Temp\Neu.xls
Delete Sheets 2 and 3: Okay.
Set Format: Okay.
Align : Okay.
Set title text: Okay.
Lock: Okay.
Set Range A:H: Okay.
Set Locked = #False: Okay.
Set Range A1:H1: Okay.
Set Locked = #True: Okay.
Set Range A1: Okay.
ActiveSheet: Okay.
Protect: Okay.
Release: Okay.
Set DisplayAlerts = #False: Okay.
SaveAs: Okay.
Close ActiveWorkbook: Okay.
Close Workbooks: Okay.
Quit: Okay.
Set DisplayAlerts = #True: Okay.
Release: Okay.
Enter ReadXLS()
NewExcelObject: Okay.
NewExcelObject
Visible set to: #False: Okay.
GetSheetName: Okay.
ChangeToWorksheet: Okay.
0
ReadCell (all): Okay.
Kopf 1 Kopf 2 Kopf 3 Kopf 4 Kopf 5 Kopf 6 Kopf 7 Kopf 8
Ebenfalls kein IMA

Gruß,
Falko
Bild
Win10 Pro 64-Bit, PB_5.4,GFA-WinDOS, Powerbasic9.05-Windows, NSBasic/CE, NSBasic/Desktop, NSBasic4APP, EmergenceBasic
Antworten