| |
|
|
Christof Neuß | Hallo,
hat sich schon mal jemand mit der DLL LibXL befasst? Damit kann man direkt auf Exceldateien (auch xlsx und xlsm) zugreifen und diese bearbeiten.
Dateien öffnen und Texte reinschreiben kann ich schon, aber ich verzweifle momentan an den Funktionen, die eine Zahl in eine Zelle schreiben oder einen Wert auslesen. Das kann doch nicht so schwer sein.
Ist für mich interessant, da einige Anwender von Programmen Excel gar nicht mehr lokal installiert haben und die Bearbeitung über ActiveX nicht mehr funktioniert.
Danke...!!! |
|
|
| |
|
|
|
H.Brill | Wenn ja schon das wesentliche klappt : Was steht denn in der Doku von der DLL ? Wie sind denn die Übergabe - Parameter ?
Sowas scheitert meistens, wenn die Übergabe der Parameter falsch ist. Will heißen, ob sie per Referenz oder per Wert übergeben werden.
Bei den Zahlen weiß ich jetzt nicht genau, ob da Profan auch per Ref. übergibt. Notfalls mal die zu übergebene Zahl in einen Bereich schreiben und diesen dann übergeben. Das gleiche gilt auch beim Lesen. |
|
|
| Benutze XPROFAN X3 + FREEPROFAN Wir sind die XProfaner. Sie werden von uns assimiliert. Widerstand ist zwecklos! Wir werden alle ihre Funktionen und Algorithmen den unseren hinzufügen.
Was die Borg können, können wir schon lange. | 15.03.2016 ▲ |
|
|
|
|
RGH | Hakllo,
das Problem ist hier, dass die Funktion zum Schreiben der numerischen Werte ein Double (64 Bit) als Wert (byVal) erwartet. In 32-Bit-XProfan sind aber alle Parameter bei einem API-Aufruf 32-Bit breit. Mit einer kleinen Zusatz-Prozedur können wir aber ein Double auf zwei LongInts verteilen und diese übergeben. Einer API-Funktion ist es egal ob die 64 Bit als ein Parameter oder als zwei Parameter überegeben werden. Es müssen halt 64 Bit sein, die da kommen:
Declare Handle hLibxl, book, sheet
hLibxl = ImportDLL("libxl.dll", "")
set("CallConv","CDECL")
proc xlSheetWriteNumD
parameters handle s, longint x,y , double d, handle f
declare longint d1, d2, memory md
dim md, 8' Ein Double hat 8 Byte = 64 Bit
md = addr(d)' Das Double wird auf den Bereich gemappt
d1 = long(md,0)' Die ersten vier Bytes kommen nach d1
d2 = long(md,4)' Die zweiten vier Bytes kommen nach d2
xlSheetWriteNumA(s, x, y, d1, d2, f)
endproc
cls
book = xlCreateBookCA()
IF book
sheet = xlBookAddSheetA(book, "sheet1", 0)
IF sheet
xlSheetWriteStrA(sheet, 2, 2, "Hello, World!", 0)
xlSheetWriteNumD(sheet, 3, 1, 1000, 0)
ENDIF
xlBookSaveA(book, "example.xls")
MessageBox("File Written", "", 0)
xlBookReleaseA(book)
ENDIF
WaitInput
END
So funktioniert es! Da beim Auslesen das gleiche Problem auftaucht, sollte man numerische Werte als String auslesen und dann mit VAL umwandeln.
Gruß Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 15.03.2016 ▲ |
|
|
|
|
Christof Neuß | Das ist ja mal wieder genial
Kaum geht man 'ne Std. joggen, um das Hirn wieder etwas zu lüften, schon findet man hier einen Hinweis, der weiterhilft. DANKE Roland. Das hat schon mal gut geklappt.
Leider bin ich im Umgang mit DLLs immer noch Laie und verzweifle weiter...
Schau' mal:
Declare Handle hLibxl, book, sheet
hLibxl = ImportDLL("libxl.dll", "")
set("CallConv","CDECL")
Var Datei$="Test1.xls"
Var Gelesen$=""
proc xlSheetWriteNumD
parameters handle s, LONGint x,y , double d, handle f
declare longint d1, d2, memory md
dim md, 8' Ein Double hat 8 Byte = 64 Bit
md = addr(d)' Das Double wird auf den Bereich gemappt
d1 = long(md,0)' Die ersten vier Bytes kommen nach d1
d2 = long(md,4)' Die zweiten vier Bytes kommen nach d2
xlSheetWriteNumA(s, x, y, d1, d2, f)
endproc
cls
book = xlCreateBookCA()
xlBookLoadA(book, Datei$)
IF book
'sheet = xlBookAddSheetA(book, "sheet1", 0)
sheet = xlBookGetSheetA(book, 0)
IF sheet
xlSheetWriteStrA(sheet, 2, 2, "Hello!", 0)
xlSheetWriteNumD(sheet, 3, 1, 1000, 0)
Gelesen$=xlSheetReadStrA(sheet, 9,0)
Print Gelesen$
ENDIF
xlBookSaveA(book, "Test1.xls")
xlBookReleaseA(book)
ENDIF
Print "FERTIG!"
WaitInput
END
Gelesen$ wird zwar bestückt, aber ich erhalte sowas wie einen Pointer, oder? Wie gehe ich denn damit um? Hab' schon das eine oder andere ausprobiert, aber ich finde es nicht raus.
Und beim Zahlenauslesen als Text - was ich grundsätzlich verstehe - stellt sich die Frage, ob die Funktion xlSheetReadStr() bei einer "Zahlenzelle" überhaupt funktioniert.
Schon mal wieder ein großes DANKE... |
|
|
| |
|
|
|
H.Brill | Soweit ich das sehe, wird da noch ein Format mit zurückgegeben :
Reads a string and its format from cell
Müßtest du mal ausprobieren, ob da ein Bereich nicht besser wäre :
Wenn die DLL-Funktion ein Nullbyte hinter den String setzt, ist es ja einfach, mit String$(Bereich#, 0) an den String zu kommen.
Roland : Könnte er zur Übergabe von Zahlen nicht auch Double(N&) oder QuadInt nehmen ? Die sind doch 64Bit breit.
Ansonsten probier es mal mit Bereich#. Da bekommt man man ja auch mit Float(V, A) einen 64Bit - Wert. |
|
|
| Benutze XPROFAN X3 + FREEPROFAN Wir sind die XProfaner. Sie werden von uns assimiliert. Widerstand ist zwecklos! Wir werden alle ihre Funktionen und Algorithmen den unseren hinzufügen.
Was die Borg können, können wir schon lange. | 15.03.2016 ▲ |
|
|
|
|
Christof Neuß | Hi,
Texte und Formeln auslesen kann ich jetzt schon mal. Das geht relativ einfach mit
Bei Zahlen funktioniert das aber leider nicht. |
|
|
| |
|
|
|
H.Brill | Nimm aber lieber mal Bereiche :
Gelesen& ist ein normaler LongInt. Das klappt zwar oben, weil beides die Variablen-Adresse beinhaltet, ist aber nicht so von Roland beabsichtigt und kann durchaus mal fehlschlagen.
Mach besser :
Was noch geht, ist ein Pointer.
Bei Zahlen kann das auch nicht funktionieren. Hier muß man die Bereichsfunktionen Float(V,A) oder Long(V, A) benutzen. Die String$() - Funktion liest solange, bis entweder ein Nullbyte kommt oder bis ans das Ende des Bereichs. Und Zahlenwerte haben nunmal kein Nullbyte. |
|
|
| Benutze XPROFAN X3 + FREEPROFAN Wir sind die XProfaner. Sie werden von uns assimiliert. Widerstand ist zwecklos! Wir werden alle ihre Funktionen und Algorithmen den unseren hinzufügen.
Was die Borg können, können wir schon lange. | 15.03.2016 ▲ |
|
|
|
|
Christof Neuß | Merci für den Hinweis. Ok, hab' s auf Bereiche umgestellt. Im STR-Bereich alles wie vorher und - leider - auch im Zahlenbereich. Es funktioniert nicht. Egal, was ich auch probiere...
So geht's nicht...
... mit ZahlGelesen&=Long(Gelesen#,0) geht's auch nicht. Ich bekomme nur Fehlermeldungen.
|
|
|
| |
|
|
|
RGH | Zum String-Bereich: Er muss nicht dimensioniert werden, da die API-Funktion dies in diesem Fall erledigt.
Zum Lesen von Zahlen: Hier ist das Problem, dass auch der Rückgabewert einer API-Funktion im 32-Bit-XProfan nur ein 32-Bit-Wert (LongInt, Bereich, Handle oder Double) sein kann, was für die gesamte Windows-API zutrifft. Die Funktion der DLL liefert aber bei numerischen Werten einen Double (64 Bit) zurück, was mit XProfan nun mal nicht geht. AUch das Auislesen als String funktioniert nicht, da die Funktion, wie es auch in der Dokumentation steht, NULL zurückliefert, wenn in der Zelle kein String ist
Gruß Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 15.03.2016 ▲ |
|
|
|
|
Christof Neuß | Hallo Roland,
danke für die Info. Schade. Aber dann brauche ich nicht mehr zu probieren. Momentan brauche ich tats. nur die Lesefunktion für Strings. Das reicht ja dann. Leider kann ich's dann nicht für andere Anwendungen nutzen. |
|
|
| |
|
|
|
RGH | Es gibt eine Lösung, die aber nicht ganz aufwandsarm ist:
In Delphi eine Wrapper-DLL schreiben, die dann mit Single arbeitet und die Double als String zurückliefert, etc. Ich habe für mich mal so eine DLL geschrieben, die zur Zeit nur die Funktionen aus meinem Beispiel enthält. Bei der Gelegenheit habe ich die Aufrufkonvention auch von CDECL nach STDCALL gewandelt. Damit sieht das Beispiel jetzt so aus und funktioniert einwandfrei:
Declare Handle hLibxl, book, sheet, format, memory gelesen
hLibxl = ImportDLL("prlibxl.dll", "")
cls
book = xlCreateBookCA()
IF book
sheet = xlBookAddSheetA(book, "sheet1", 0)
IF sheet
xlSheetWriteStrA(sheet, 2, 2, "Hello, World!", 0)
xlSheetWriteNumA(sheet, 3, 1, single(1000), 0)
gelesen = xlSheetReadStrA(sheet, 2, 2, 0)
Print String$(Gelesen, 0)
gelesen = xlSheetReadNumA(sheet, 3, 1, 0)
Print String$(Gelesen, 0)
ENDIF
xlBookSaveA(book, "example.xls")
MessageBox("File Written", "", 0)
xlBookReleaseA(book)
ENDIF
WaitInput
END
Bei WriteNum wird die Funktion single() verwandt, damit die Zahl 1000 nicht als Integer übergeben wird. Man könnte aber auch 1000.0 schreiben oder direkt eine Variable des Typs SINGLE übergeben.
Es wäre also machbar, eine Wrapper-DLL zu schreiben, die alle Funktionen der Original-DLL enthält. Eine andere Möglichkeit wäre, eine Wrapper-DLL nur für die Funktionen zu schreiben, die Double ls Parameter erhalten und/oder Double zurückliefern. Das wäre etwas weniger aufwendig.
Gruß Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 16.03.2016 ▲ |
|
|
|
|
Christof Neuß | Hallo Roland,
wie Du schon schreibst... "nicht ganz aufwandsarm". Und das gilt nicht nur dafür, die zusätzliche DLL-zu realisieren, sondern auch für meine in die Jahre gekommene Anwendung, die ich ziemlich umbauen müsste. Das Problem ist u.a., dass ich auf native Funktionen für ein paar schnelle Dateifunktionen zurückgreife und hier noch mit XPSE compiliere. Der wiederum ist aber nicht so ganz Freund mit einigen XProfan X3-Funktionen und so führt eins zum anderen... Hätte ich jetzt 100 zahlende Kunden würde es mich auch nicht abhalten, das - relativ kleine - Programm ganz neu zu schreiben. Aber es sind nur eine Handvoll Kunden und es wird wahrscheinlich demnächst ganz eingestellt werden. Ich verzichte jetzt auf eine Plausibilitätsprüfung und dann läuft's auch ohne Excelaufruf durch.
Das Thema "Zugriff auf Exceldateien" beschäftigt mich aber weiter. Vielleicht gehe ich mal auf XLware zu und frage, ob es eine Lösung gibt (z.B. Num-Werte als String zu lesen).
EIN Grund für mich seinerzeit mit XProfan anzufangen war auch, aufgrund der Mächtigkeit der Sprache, nahezu keine weitere DLL einsetzen zu müssen. Wenn das so bleiben soll, muss ich andere Möglichkeiten finden.
Vorerst vielen Dank an alle, die hier mitgedacht und geholfen haben. |
|
|
| |
|
|