xls ohne Excel

  • Halli hallo Ihr Lieben,

    ich habe ein kleines Problem mit einem Skript:

    Es geht darum zwei Tabellenblätter aus einer schreibgeschützten xls Datei auszulesen.

    Dafür habe ich mich erst mit den Excel Udf und den Excel Rewrite UDFs beschäftigt.

    Das Problem liegt darin, dass das Skript ohne kommerzielle Software (sprich Excel) funktionieren sollte.

    Beim Googlen bin ich einmal auf ACE Oledb (die Office Schnittstelle für Datenbanken) und den Microsoft Excel Viewer gestossen.

    Ich habe leider keine Ahnung wie ich oder ob ich den Viewer über COM Objects ansteuern kann.

    ACE OLEDB kriege ich leider auch nicht richtig zum laufen ....

    Wenn ihr mir mit einem von beiden oder sogar einer ganz neuen Idee weiterhelfen könnt wäre das echt Bombe !!!

    :D

    Einmal editiert, zuletzt von warhwolf (13. August 2013 um 10:25)

  • Excel und Excel Rewrite UDF bauen darauf auf, dass Office installiert ist.
    Falls Du die Datei als xlsx speichern kannst, dann gibt es hier eine UDF, die ohne Office Installation auf die XML Inhalte zugreifen kann.

  • Mittels ActiveX Data Objects(ADO) kannst Du Excel-Arbeitsmappe auslesen:

    [autoit]


    Const $adSchemaTables = 20
    Const $adUseClient = 3

    [/autoit][autoit][/autoit][autoit]

    Dim $cn = ObjCreate('ADODB.Connection')
    $cn.Provider = 'Microsoft.Jet.OLEDB.4.0'
    $cn.ConnectionString = 'Data Source=' & @ScriptDir & '\Test.xls;Extended Properties=Excel 8.0;'
    $cn.CursorLocation = $adUseClient
    $cn.Open()

    [/autoit][autoit][/autoit][autoit]

    Dim $rsTables = $cn.OpenSchema($adSchemaTables)
    ConsoleWrite('Anzahl Tabellenblätter: ' & $rsTables.RecordCount & @CRLF)

    [/autoit][autoit][/autoit][autoit]

    For $t = 1 To $rsTables.RecordCount
    ConsoleWrite(@CRLF)
    Dim $tableName = $rsTables.Fields('TABLE_NAME').Value
    ConsoleWrite('Tabelle: ' & $tableName & @CRLF)
    ConsoleWrite('----------------------' & @CRLF)

    [/autoit][autoit][/autoit][autoit]

    For $f = 0 To $rsTables.Fields.Count - 1
    ConsoleWrite(' ' & $rsTables.Fields($f).Name & ' = ' & $rsTables.Fields($f).Value & @CRLF)
    Next ; f

    [/autoit][autoit][/autoit][autoit]

    Dim $criterias[4]
    $criterias[2] = $tableName
    Dim $rsColumns = $cn.OpenSchema(4, $criterias)
    ConsoleWrite(@CRLF & ' Anzahl Spalten: ' & $rsColumns.RecordCount & @CRLF)
    Dim $rs = $cn.Execute('[' & $tableName & ']')
    For $c = 1 To $rsColumns.RecordCount
    Dim $columnName = $rsColumns.Fields('COLUMN_NAME').Value
    ConsoleWrite(@CRLF & ' Spalte: ' & $columnName & @CRLF)
    ConsoleWrite(' ----------------------' & @CRLF)

    [/autoit][autoit][/autoit][autoit]

    For $f = 0 To $rsTables.Fields.Count - 1
    ConsoleWrite(' ' & $rsColumns.Fields($f).Name & ' = ' & $rsColumns.Fields($f).Value & @CRLF)
    Next ; f

    [/autoit][autoit][/autoit][autoit]

    ConsoleWrite(@CRLF)
    ConsoleWrite(' Ausgabe Zeilen:' & @CRLF)
    $rs.MoveFirst()
    For $r = 0 To $rs.RecordCount - 1
    ConsoleWrite(' ' & $rs.Fields($columnName).Value & @CRLF)
    $rs.MoveNext()
    Next ; r

    [/autoit][autoit][/autoit][autoit]

    $rsColumns.MoveNext()
    Next ; $c

    [/autoit][autoit][/autoit][autoit]

    $rs.Close()
    $rsColumns.Close()
    $rsTables.MoveNext()
    Next ; $t

    [/autoit][autoit][/autoit][autoit]

    $rsTables.Close()
    $cn.Close()

    [/autoit]
  • water schicke idee, aber ich kriege nur die xls als daten gestellt und müsste dann konvertieren

    @mk genau was ich gesucht hab :D

    Kannst du zufälliger Weise posten was die einzelnen COM-Methoden machen, bzw welche es generell für excel gibt? Eine Refrenz zum selbst anlesen wäre genauso gut :) Denn irgendwie hab ichs nicht gefunden (vlt falsche stichworte?...)

    Ich hatte vor zwei verschiedene Blätter in zwei 2D-Arrays zu importieren (die gehen dann in eine sqlite, aber das krieg ich hin ;) )

    P.S. danke für die superschnelle Antwort ! IHR SEID DIE GRÖßTEN

  • @Spider Und ich habs voher nicht hingekriegt ;) Danke dafür

    @mk Tust du mir den Gefallen und kommentierst das nochmal durch? Ich habe noch nie voher was mit ADO am Hut gehabt und komme nicht ganz mit.

    Als Anleitung habe ich Microsoft Support1, xtremevbtalk und Microsoft Support2 benutzt, aber nicht alles verstanden.

    Inzwischen kann ich fast blind den Provider und den Connectionstring eingeben, hab aber keine Ahnung wie ich eine Abfrage abschicke. (ich glaube es hat was mit nem recordset zu tun ... ;( )

    Am meisten verwirren mich die für meinen beschränkten Verstand viel zu verwirrenden Variblennamen (und ja ich benutze Volltextnamen ;) )

    Ich hoffe ich raub euch nicht die Nerven am Freitagabend ... :S

  • @warhwolf.

    Der Artikel Verwendung von ADO mit Excel-Daten ... erklärt sehr ausführlich die Herangehensweise. Hier ist aber dennoch der kommentierte Quelltext.

    Spoiler anzeigen
    [autoit]

    ; SchemaEnum
    Const $adSchemaTables = 20

    [/autoit] [autoit][/autoit] [autoit]

    ; CursorLocationEnum
    Const $adUseClient = 3

    [/autoit] [autoit][/autoit] [autoit]

    ; Instanziirung der Connection-Klasse. Mit diesem Objekt wird eine dauerhafte Verbindung
    ; zu einer Datenquelle hergestellt.
    Dim $cn = ObjCreate('ADODB.Connection')

    [/autoit] [autoit][/autoit] [autoit]

    ; OLEDB-Provider für die Verbindung festlegen.
    $cn.Provider = 'Microsoft.Jet.OLEDB.4.0'

    [/autoit] [autoit][/autoit] [autoit]

    ; Es wird eine Verbindungszeichenfolge(Connection String auch Init String) erwartet. Die Zeichenfolge ist
    ; eine Reihenfolge von Attribut-Wert-Zuweisungen.
    $cn.ConnectionString = 'Data Source=' & @ScriptDir & '\Test.xls;Extended Properties=Excel 8.0;'

    [/autoit] [autoit][/autoit] [autoit]

    ; Speicherort der Cursorbibliothekt setzen.
    $cn.CursorLocation = $adUseClient

    [/autoit] [autoit][/autoit] [autoit]

    ; Eine Verbindung zur Datenquelle öffnen.
    $cn.Open()

    [/autoit] [autoit][/autoit] [autoit]

    ; Die Datenbankschemainformationen ermitteln. Die OpenSchema-Methode gibt selbstbeschreibene
    ; Informationen üder die Datenquelle zurück.
    ; Tabellen zurückgeben
    Dim $rsTables = $cn.OpenSchema($adSchemaTables)
    ConsoleWrite('Anzahl Tabellenblätter: ' & $rsTables.RecordCount & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    ; Iterationen über alle Tabellen
    For $t = 1 To $rsTables.RecordCount
    ConsoleWrite(@CRLF)

    ; Gibt den Tabellennamen zurück
    Dim $tableName = $rsTables.Fields('TABLE_NAME').Value
    ConsoleWrite('Tabelle: ' & $tableName & @CRLF)
    ConsoleWrite('----------------------' & @CRLF)

    ; Ausgabe der Eigenschaften mit deren Werte
    For $f = 0 To $rsTables.Fields.Count - 1
    ConsoleWrite(' ' & $rsTables.Fields($f).Name & ' = ' & $rsTables.Fields($f).Value & @CRLF)
    Next ; f

    ; Array für die Abfragekriterien
    Dim $criterias[4]
    $criterias[2] = $tableName

    ; Gibt die Spalten der Tabelle zurück
    ; adSchemaColumns = 4
    Dim $rsColumns = $cn.OpenSchema(4, $criterias)
    ConsoleWrite(@CRLF & ' Anzahl Spalten: ' & $rsColumns.RecordCount & @CRLF)

    ; SQL Statement ausführen. Wird nur der Tabellenname angegeben, vervollständig ADO automatisch
    ; die SQL-Anweisung. "SELECT * FROM [<tablename>]"
    Dim $rs = $cn.Execute('[' & $tableName & ']')

    ; Iteration über alle Spalten
    For $c = 1 To $rsColumns.RecordCount

    ; Gibt Spaltennamen zurück
    Dim $columnName = $rsColumns.Fields('COLUMN_NAME').Value
    ConsoleWrite(@CRLF & ' Spalte: ' & $columnName & @CRLF)
    ConsoleWrite(' ----------------------' & @CRLF)

    ; Ausgabe der Eigenschaften mit deren Werte
    For $f = 0 To $rsTables.Fields.Count - 1
    ConsoleWrite(' ' & $rsColumns.Fields($f).Name & ' = ' & $rsColumns.Fields($f).Value & @CRLF)
    Next ; f

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite(@CRLF)
    ConsoleWrite(' Ausgabe Zeilen:' & @CRLF)

    ; Springt zum ersten Datensatz
    $rs.MoveFirst()

    ; Iteration über alle Datensätze
    For $r = 0 To $rs.RecordCount - 1

    ; Ausgabe der Werte
    ConsoleWrite(' ' & $rs.Fields($columnName).Value & @CRLF)

    ; zum nächsten Datensatz springen
    $rs.MoveNext()
    Next ; r <-- Daten

    ; zum nächsten Datensatz springen
    $rsColumns.MoveNext()
    Next ; $c <-- Spalten

    ; Geöffnete Verbindungen schliesen
    $rs.Close()
    $rsColumns.Close()

    ; zum nächsten Datensatz springen
    $rsTables.MoveNext()
    Next ; $t <-- Tabellen

    [/autoit] [autoit][/autoit] [autoit]

    ; Geöffnete Verbindungen schliesen
    $rsTables.Close()
    $cn.Close()

    [/autoit]