none
Wie mit VB.NET auf eine laufende Instanz von MS Access zugreifen ?

    Frage

  • Hallo,

    ich hoffe das ich im richtigen Forum gelandet bin ... ;o)

    Ich habe das Problem, das ich mit VB.NET (VB2010 Pro) auf die Access-eigene Funktion DoCmd.TransferSpredsheet zugreifen möchte, damit ich den Import von Excel Daten in die Datenbank mit der recht schnellen Funktion von Access automatisieren kann. Der Umweg über ein Dataset in VB dauert bei der Menge der Daten einfach zu lange.

    Erschwerend kommt hinzu, das die Access DB mit einer eigenen System MDW abgesichert ist.

    Jetzt probiere ich schon seit Tagen mit dem Access.Applikation Objekt herum, komme aber zu keiner funktionierenden Lösung. Egal was ich mache, jeder Zugriff endet in zwei Access Objekten: Die Shell Anweisung (s.u.) öffnet zwar korrekt die DB, aber die GetObject-Anweisung instanziiert trotzdem immer noch eine neue, zusätzliche Instanz. Dann kommt logischerweise die Fehlermeldung, da in der neuen Instanz natürlich kein Inhalt ist. Durch "acc.visible = true" kann man dann auch sehen, das Access zweimal geöffnet wird.

    Es gelingt mir einfach nicht für das Application-Objekt ein Connect zu der von der Shell geöffneten DB. Obwohl es lt. diesem Artikel doch so gehen müsste: http://support.microsoft.com/kb/238610/en-us (ist zwar für Excel geschrieben, sollte aber auch für Access funktionieren).

    Hier ist mein Code:

            Shell("C:\Program Files\Microsoft Office\Office12\MSACCESS.EXE C:\Users\berger\Documents\WIData.mdb /WRKGRP C:\Users\berger\Documents\WIData.mdw /USER berger /PWD berge01", vbMinimizedFocus)
            Me.Focus()
            Dim acc As Access.Application
            acc = GetObject(, "Access.Application")
            acc.Visible = True
            acc.DoCmd.TransferSpreadsheet(Access.AcDataTransferType.acImport, Access.AcSpreadSheetType.acSpreadsheetTypeExcel9, "Sheet1", "C:\DataSource.xls", True)
            acc.CloseCurrentDatabase()
    

    Ich habe schon sehr viel "gegoogelt", es gibt auch viel für "normale" MDBs, aber eben so gut wie nichts für die Verbindung mit einer MDW.

    Vielleicht kann mir hier jemand helfen ? Vielleicht gibt es auch ganz andere Wege ?

    Ich wäre für jede Hilfe dankbar ! :o)

    Gruß

    Uli

    Dienstag, 17. Januar 2012 13:50

Antworten

Alle Antworten

  • Hallo!

    Wenn du die Access-Anwendung per Shell-Funktion startest, müsste die Shell-Funktion die Prozess-ID zurückgeben. Vielleicht kannst du mit der die passende COM-Instanz aus der ROT (Running Object Table) holen.
    Möglicherweise ist aber die Anwendung noch nicht vollständig geladen, wenn die Shell-Funktion fertig ist.

    Ich hole mir z. B. über die ROT die Access-Instanz zu einer VBE-Instanz, die ich in einem VBE-COM-Add-In (AccUnit) erhalte (siehe Klasse "ComTools" (ist allerdings in C#)).

    Wenn du die ROT durchläufst und mit der von der Shell-Funktion erhaltenen Task-ID vergleichst, solltest du eigentlich die passende Instanz finden können.
    Wie das in VB.Net läuft, weiß ich allerdings auch nicht auswendig. ;-)

    Übrigens: Sobald die Datei geöffnet ist, sollte auch der Zugriff über acc = GetObject(FullFileName) funktionieren.

    Ansonsten:
    Wenn du Excel-Tablelen importieren willst, könntest du versuchen, diese nur über die DB-Methoden durchzuführen.

    Prinzip (Jet-SQL):
    insert into Tabelle (Feld1, Feld2, ...)
    Select Feld1, Feld2, ... from [excel 8.0;;imex=2;DATABASE=D:\ein\Exceldatei.xls].[Sheet1$]

    .. oder du nutzt überhaupt ADO.net. ;-)

    mfg
    Josef

     

     


    Code-Bibliothek für Access-Entwickler
    AccUnit - Testen von Access-Anwendungen
    Dienstag, 17. Januar 2012 20:49
  • Hallo,

    den Umweg über Shell solltest Du Dir sparen und das "Ansonsten" von Josef verwenden
    (ausgenommen Du möchtest etwas über COM lernen ;-)

    Eine gesicherte Datenbank kannst Du über den Jet OleDb Provider öffnen wie beschrieben in:
    How to open a secured Access database in ADO through OLE DB (letzter Abschnitt).

    und kannst dafür den OleDbConnectionStringBuilder verwenden.

    TransferSpreadsheet ist nur eine hübsche Verpackung für

    INSERT INTO Tabelle (Spalte1, Spalte2)
    SELECT Spalte1, Spalte2
    FROM [Sheet$] IN '' [Excel 8.0;HDR=Yes;DATABASE=C:\DataSource.xls];
    
    

    Einige weitere Hinweise gibt: How To Use ADO with Excel Data from Visual Basic or VBA

    Sollte die Tabelle noch nicht existieren kannst Du sie mit CREATE TABLE anlegen (spart zusätzliches ADOX Gefummel)
    siehe Fundamental Microsoft Jet SQL for Access 2000  (bzw. ein Blick in JetSql40.chm bis Office 2003)

    Gruß Elmar

    Mittwoch, 18. Januar 2012 09:00
  • Hallo Josef, Elmar,

    vielen Dank für die Antworten (habe den Thread nach Lösung des Problems leider vergessen, daher erst jetzt die Antwort. Besser spät als nie.).

    Hab es mit dem Vorschlag "acc = GetObject(FullFileName) " und dann "insert into Tabelle (Feld1, Feld2, ...)
    Select Feld1, Feld2, ... from [excel 8.0;;imex=2;DATABASE=D:\ein\Exceldatei.xls].[Sheet1$]" tatsächlich hinbekommen.

    Vielen Dank (nachträglich) ;-)

    Gruß

    uli

    Mittwoch, 7. Januar 2015 10:58