xlsxNative - XLSX/XLSM-Dateien ohne Excel einlesen und erzeugen

  • Ich musste letztens xlsx-Dateien einlesen und mochte die Variante über Excel.au3 nicht wirklich, da diese durch Excel selbst ziemlichen Overhead hat und außerdem ist man darauf angewiesen dass Excel auch installiert ist. Also hab ich mir mal so eine xlsx-Datei näher angesehen und daraufhin eine kleine Funktion geschrieben, welche mir direkt mit Bordmitteln ein Worksheet aus der Datei in ein Array einliest.

    Das ganze ist jetzt nicht wahnsinnig auf alle Spezialfälle hin ausgebaut sondern deckt bislang die Fälle ab, welche bei mir bisher aufgetreten sind. Es gibt wohl auch schon andere UDFs die das gleiche machen aber selbst machen, macht mehr Spaß!

    Da die xlsx-Dateien entpackt werden müssen empfehle ich eine >>7za.exe<< mit zum Skript dazuzupacken, sonst wird auf die Shell.Application-Methode ausgewichen und die ist laaaaaaangsam...

    Große Erklärung ist nicht notwendig:

    >>Download und Quellcode auf GitHub<<

    Changelog:

    2023/03/25 _xlsx_2Array(): Array-Range-Exceed falls Zellkoordinaten verwendet werden und ganze Zeilen frei bleiben.
    2023/03/13 _xlsx_2Array() - Fix: leere Zellen, welche dennoch Attribute haben, wurden nicht korrekt erkannt.
    _xlsx_2Array() - Fix: geteilte Strings, welche Attribute in ihrer <t>-Definition haben, wurden ignoriert.
    2023/02/27 XML-Parsing komplett neu gestaltet - insbesondere bei großen Dateien teils massive Performancesteigerung hierdurch
    2023/01/26 _xlsx_2Array(): Parameter zur Einschränkung auf bestimmte Spalten hinzugefügt.

    Komplette Überarbeitung der Funktion __getSubFiles() - die UDF sollte nun mit mehr XLSX-Typen klarkommen
    2023/01/22 _xlsx_getWorkSheets() hinzugefügt: Mit dieser erhält man eine Liste mit id und Namen der in der xlsx-Datei enthaltenen Worksheets.
    2021/07/16 _xlsx_WriteFromArray: Bugfix - XML-Sonderzeichen in Werten werden nun escaped
    2021/05/26 _xlsx_2Array: Bugfix - @error = 5 bei mehr als 9 Worksheets
    2021/04/01 _xlsx_2Array: Ermittlung der internen Dateien nun robuster
    2021/03/29 _xlsx_WriteFromArray: Neue Funktion zur Erzeugung von xlsx-Dateien aus AutoIt-Arrays
    2020/08/07 __xlsxExcel2Date: Stringausgabe (lokal formatiert) der Datums/Zeit-Werte implementiert
    2020/07/31

    Fix: Zellen mit hybriden Zellinhalten wurden ignoriert

    Leere aber gestylte Zellen werden nicht mehr prozessiert (Leerzeilen werden vermieden und etwas schneller)

    2020/07/30 Verbesserung der Namespace-Behandlung
    2020/07/29 Parameter um auf bestimmte Zeilen einzugrenzen hinzugefügt

    22 Mal editiert, zuletzt von AspirinJunkie (4. Mai 2023 um 08:57)

  • Hallo AspirinJunkie

    vielen Dank fürs Teilen. Es klappt eigentlich wunderbar. Aber zufällig hatte ich eine Testdatei, bei der das Skript abraucht.

    Hier in der xlsxNative.au3 vllt. einen kurzen Check einbauen.

    Grüße autoiter

  • Neue Version hab ich hochgestellt.

    Deine xlsx hat Zellen die keinen Inhalt haben aber einen Style besitzen.

    Für die Ausgabe als Array sollten die also ignoriert werden.
    Nun ist es jedoch so, dass die UDF zwei Wege hat die Ausmaße des Arrays zu bestimmen.

    Zum einen schaut sie ob ein dimension tag existiert, denn dort trägt Excel ein bis wohin die beschriebenen Zellen gehen.

    Problem hierbei: Gestylte, aber leere Zellen werden hier mit reingezählt.

    Wenn kein solches Tag existiert geht die UDF einfach alle Zellen durch und schaut wo das jeweilige Maximum liegt.
    In deinem Fall wäre diese Vorgehensweise aber meiner Meinung nach besser da du sonst am Ende noch einige leere Zeilen hast.

    Vielleicht sollte ich daher prinzipiell auf die Auswertung des dimension-tag verzichten?

    Vielleicht auch und statt oder? ;)

    Ja hab es natürlich mit ergänzt.

    Edit: Ach hab es jetzt einfach komplett auf die empirische Bestimmung der Dimension umgestellt.
    Der dimension-tag ist nun draußen.

    In Verbindung mit den neuen Zeilenauswahlparametern kann man übrigens Headerzeilen und sowas ignorieren.

    Bei deiner Testdatei z.B könnte daher folgendes die Weiterverarbeitung wohl vereinfachen: _xlsx_2Array("text.xlsx", 1, 5)

    Edit 2: Ach und weil ich gerade sehe, dass du Datumswerte mit drin hast - die kannst du im Nachhinein mit der bereits enthaltenen aber etwas versteckten Funktion __xlsxExcel2Date() in ein normales Datum umrechnen.

    2 Mal editiert, zuletzt von AspirinJunkie (31. Juli 2020 um 08:43)

  • Auch von mir ein großes Dankeschön für dieses Funktionspaket :thumbup:.

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Eine neue Version steht bereit und bringt eine Funktion zum Schreiben von AutoIt-Arrays direkt in XLSX-Dateien mit.

    Die erzeugten xlsx-Dateien sind arg minimal aufgebaut.
    Das hat (noch) den witzigen Nebeneffekt, dass so erzeugte Dateien nicht wieder mit der _xlsx_2Array eingelesen werden können.
    Das baue ich aber noch irgendwann mal in Ruhe ein.

    Edit: Nun können auch die erzeugten Dateien wieder eingelesen werden

    Einmal editiert, zuletzt von AspirinJunkie (1. April 2021 um 10:24)

  • AspirinJunkie 1. April 2021 um 10:20

    Hat den Titel des Themas von „xlsxNative - XLSX/XLSM-Dateien ohne Excel öffnen“ zu „xlsxNative - XLSX/XLSM-Dateien ohne Excel einlesen und erzeugen“ geändert.
  • Hallo

    leider gelingt es mir nicht aus einer Excel-Datei das 3. Arbeitsblatt auszulesen (egal ob xlsm oder xlsx). Das erste Arbeitsblatt funktioniert (Excel 2016).

    $aSheet = _xlsx_2Array(@ScriptDir & "\Kabelplan.xlsm", 3) leider nicht (es gibt 10 Arbeitsblätter in dieser Datei ..).

    Grüsse

    GL

  • Error: 5

    extended: 0

    egal ob: $aSheet = _xlsx_2Array(@ScriptDir & "\Kabelplan.xlsm", 3)

    oder: $aSheet = _xlsx_2Array(@ScriptDir & "\Kabelplan.xlsm", "3")

    dabei wäre das genau DAS was mir aus der Patsche (hier beschrieben: "Excel - Exceldatei schließen ohne speichern ... geht nicht") helfen würde.

    LG

  • Guten Morgen

    Danke für das Angebot. Im Zuge der Bereinigung des Excel-Sheets um Firmenangaben bin ich möglicherweise auf den Kern des Problems gestoßen: mein Workbook umfaßt 10 Arbeitsblätter. Wenn ich ein Arbeitsblatt lösche (egal welches) funktioniert dein UDF. Sowie es >9 Arbeitsblätter hat, kommt der oben erwähnte Fehler. Eventuell ist das ein 1-9 = einstellig, >9 = zweistellig-Problem in der UDF?

    Grüsse

    LG

  • Kann ich nicht wirklich sagen ohne Beispieldatei.
    Im Grunde sollte die Anzahl der Worksheets keinen Einfluss haben.
    Nutzt du die Variante mit der 7za.exe im Skriptverzeichnis? - die Filterung dort habe ich könnte eine Ursache sein

    ... aber ach - ohne Beispiel kann ich weiterhin nur vermuten.

  • Ja, habe die Variante mit 7za benutzt, das Ergebnis ist ohne 7za dasselbe bzw. der gleiche Fehler. Gibt es eine Möglichkeit dir die Datei über das Forum zukommen zu lassen, ohne sie ins Forum zu stellen?

    Wenn ich relevante Daten herauslösche, ist wieder nicht gewähleistet das der Fehler bei dir auftaucht.

    LG

  • Ja klar es gibt ja die privaten Konversationen hier im Forum (über das Profil des jeweiligen Nutzers erreichbar) - hab dir auch gerade eine Testnachricht geschickt.

    Wenn ich relevante Daten herauslösche, ist wieder nicht gewähleistet das der Fehler bei dir auftaucht.

    Taucht der Fehler dann noch bei dir auf wenn du kritische Daten löschst?
    Wenn ja dann passt es doch.
    Das Problem hier scheint ja auch weniger an den Daten als am internen Aufbau der xlsx-Datei zu liegen.

  • Es scheint so. Ich hab die Tabelle bereinigt und kann sie hier heraufstellen (war eh gut, da über > 6 MB ;)). Mit dieser Datei

    ist genau das auch nicht möglich (getestet, Programm liegt bei):

    $aSheet = _xlsx_2Array(@ScriptDir & "\Kabelplan.xlsm", 3)

    Lösche ich auch nur ein einziges Tabellenblatt (somit unter 10 Tabellenblätter, egal welches nach dem 3. Blatt - das will ich ja auslesen) funktioniert xlsxNativ einwandfrei.

    Danke für deine Mühe

    LG

  • Neue Version habe ich hochgeladen.
    Problem war: Die Sheet-Namen sind durcheinander und müssen noch sortiert werden damit die Reihenfolge wieder stimmt.
    Ein normales _ArraySort verhaut da die Sortierung sobald Zahlen mit drin stecken.
    Daher habe ich einfach ein eigenes natural sort implementiert.

    Jetzt klappt es auch mit der Datei.
    Lass aber die Finger vom 4. Worksheet oder bearbeite es vorher - das funktioniert zwar, dauert aber ewig.
    Grund: Alleine dieses Worksheet ist 82 mb groß obwohl im Grunde gar nichts drin steht.

    Ab der 25. Zeile kommt inhaltlich nichts mehr aber die Zellen sind trotzdem in der Datei definiert.
    Wenn man alle Zeilen ab der 26. ordentlich löscht dann ist die ganze Datei auf einmal nur noch 700kb groß.
    Ähnlich ist es beim 2. Sheet mit den vielen überflüssigen Nullen.

  • DANKE! DANKE!

    Das erspart mir eine Menge Arbeit (und vor allem immer wiederkehrend) ...

    LG

    überhaupt ein großes Dankeschön an alle die immer wieder Schnipsel beisteuern oder korrigieren :thumbup::thumbup: