Wie verwenden Sie die Versionskontrolle bei der Access-Entwicklung?

163

Ich bin an der Aktualisierung einer Access-Lösung beteiligt. Es verfügt über eine gute Anzahl an VBA, eine Reihe von Abfragen, eine kleine Anzahl von Tabellen und einige Formulare für die Dateneingabe und Berichterstellung. Es ist ein idealer Kandidat für Access.

Ich möchte Änderungen am Tabellendesign, am VBA, an den Abfragen und an den Formularen vornehmen. Wie kann ich meine Änderungen mit der Versionskontrolle verfolgen? (Wir verwenden Subversion, aber das gilt für jede Variante.) Ich kann die gesamte MDB in Subversion stecken, aber das speichert eine Binärdatei, und ich kann nicht sagen, dass ich nur eine Zeile VBA-Code geändert habe.

Ich dachte darüber nach, den VBA-Code in separate Dateien zu kopieren und diese zu speichern, aber ich konnte sehen, dass diese schnell nicht mehr mit dem Inhalt der Datenbank synchronisiert sind.

Nathan DeWitt
quelle
1
Crossposting dieser Lösung auf die verwandte Frage des Exportierens des Access-Datenbankschemas.
Eric G
1
Access unterstützt die SCC-Schnittstelle, sodass jede mit dieser Schnittstelle kompatible Versionskontrolle für Access bereit ist. Haftungsausschluss: Ich arbeite für plasticscm.com und wir haben mehrere Kunden, die es mit Access verwenden.
Pablo
8
Versuchen Sie dieses vba-Modul github.com/timabell/msaccess-vcs-integration
Tim Abell

Antworten:

180

Wir haben unser eigenes Skript in VBScript geschrieben, das die undokumentierte Application.SaveAsText () in Access verwendet, um alle Code-, Formular-, Makro- und Berichtsmodule zu exportieren. Hier ist es, es sollte Ihnen einige Hinweise geben. (Achtung: Einige der Nachrichten sind auf Deutsch, aber Sie können das leicht ändern.)

EDIT: Um verschiedene Kommentare unten zusammenzufassen: Unser Projekt geht von einer ADP-Datei aus. Um diese Arbeit mit .mdb / .accdb zu erhalten, müssen Sie OpenAccessProject () in OpenCurrentDatabase () ändern.. (Aktualisiert, um zu verwenden, OpenAccessProject()wenn eine ADP-Erweiterung angezeigt wird, andernfalls verwenden OpenCurrentDatabase().)

decompose.vbs:

' Usage:
'  CScript decompose.vbs <input file> <path>

' Converts all modules, classes, forms and macros from an Access Project file (.adp) <input file> to
' text and saves the results in separate files to <path>.  Requires Microsoft Access.
'

Option Explicit

const acForm = 2
const acModule = 5
const acMacro = 4
const acReport = 3

' BEGIN CODE
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")

dim sADPFilename
If (WScript.Arguments.Count = 0) then
    MsgBox "Bitte den Dateinamen angeben!", vbExclamation, "Error"
    Wscript.Quit()
End if
sADPFilename = fso.GetAbsolutePathName(WScript.Arguments(0))

Dim sExportpath
If (WScript.Arguments.Count = 1) then
    sExportpath = ""
else
    sExportpath = WScript.Arguments(1)
End If


exportModulesTxt sADPFilename, sExportpath

If (Err <> 0) and (Err.Description <> NULL) Then
    MsgBox Err.Description, vbExclamation, "Error"
    Err.Clear
End If

Function exportModulesTxt(sADPFilename, sExportpath)
    Dim myComponent
    Dim sModuleType
    Dim sTempname
    Dim sOutstring

    dim myType, myName, myPath, sStubADPFilename
    myType = fso.GetExtensionName(sADPFilename)
    myName = fso.GetBaseName(sADPFilename)
    myPath = fso.GetParentFolderName(sADPFilename)

    If (sExportpath = "") then
        sExportpath = myPath & "\Source\"
    End If
    sStubADPFilename = sExportpath & myName & "_stub." & myType

    WScript.Echo "copy stub to " & sStubADPFilename & "..."
    On Error Resume Next
        fso.CreateFolder(sExportpath)
    On Error Goto 0
    fso.CopyFile sADPFilename, sStubADPFilename

    WScript.Echo "starting Access..."
    Dim oApplication
    Set oApplication = CreateObject("Access.Application")
    WScript.Echo "opening " & sStubADPFilename & " ..."
    If (Right(sStubADPFilename,4) = ".adp") Then
        oApplication.OpenAccessProject sStubADPFilename
    Else
        oApplication.OpenCurrentDatabase sStubADPFilename
    End If

    oApplication.Visible = false

    dim dctDelete
    Set dctDelete = CreateObject("Scripting.Dictionary")
    WScript.Echo "exporting..."
    Dim myObj
    For Each myObj In oApplication.CurrentProject.AllForms
        WScript.Echo "  " & myObj.fullname
        oApplication.SaveAsText acForm, myObj.fullname, sExportpath & "\" & myObj.fullname & ".form"
        oApplication.DoCmd.Close acForm, myObj.fullname
        dctDelete.Add "FO" & myObj.fullname, acForm
    Next
    For Each myObj In oApplication.CurrentProject.AllModules
        WScript.Echo "  " & myObj.fullname
        oApplication.SaveAsText acModule, myObj.fullname, sExportpath & "\" & myObj.fullname & ".bas"
        dctDelete.Add "MO" & myObj.fullname, acModule
    Next
    For Each myObj In oApplication.CurrentProject.AllMacros
        WScript.Echo "  " & myObj.fullname
        oApplication.SaveAsText acMacro, myObj.fullname, sExportpath & "\" & myObj.fullname & ".mac"
        dctDelete.Add "MA" & myObj.fullname, acMacro
    Next
    For Each myObj In oApplication.CurrentProject.AllReports
        WScript.Echo "  " & myObj.fullname
        oApplication.SaveAsText acReport, myObj.fullname, sExportpath & "\" & myObj.fullname & ".report"
        dctDelete.Add "RE" & myObj.fullname, acReport
    Next

    WScript.Echo "deleting..."
    dim sObjectname
    For Each sObjectname In dctDelete
        WScript.Echo "  " & Mid(sObjectname, 3)
        oApplication.DoCmd.DeleteObject dctDelete(sObjectname), Mid(sObjectname, 3)
    Next

    oApplication.CloseCurrentDatabase
    oApplication.CompactRepair sStubADPFilename, sStubADPFilename & "_"
    oApplication.Quit

    fso.CopyFile sStubADPFilename & "_", sStubADPFilename
    fso.DeleteFile sStubADPFilename & "_"


End Function

Public Function getErr()
    Dim strError
    strError = vbCrLf & "----------------------------------------------------------------------------------------------------------------------------------------" & vbCrLf & _
               "From " & Err.source & ":" & vbCrLf & _
               "    Description: " & Err.Description & vbCrLf & _
               "    Code: " & Err.Number & vbCrLf
    getErr = strError
End Function

Wenn Sie einen anklickbaren Befehl benötigen, erstellen Sie anstelle der Befehlszeile eine Datei mit dem Namen "decompose.cmd" mit

cscript decompose.vbs youraccessapplication.adp

Standardmäßig werden alle exportierten Dateien in einen Unterordner "Scripts" Ihrer Access-Anwendung verschoben. Die ADP / MDB-Datei wird ebenfalls an diesen Speicherort kopiert (mit dem Suffix "Stub") und von allen exportierten Modulen befreit, wodurch sie sehr klein wird.

Sie MÜSSEN diesen Stub mit den Quelldateien einchecken, da die meisten Zugriffseinstellungen und benutzerdefinierten Menüleisten nicht auf andere Weise exportiert werden können. Stellen Sie nur sicher, dass Sie Änderungen nur an dieser Datei vornehmen, wenn Sie wirklich eine Einstellung oder ein Menü geändert haben.

Hinweis: Wenn in Ihrer Anwendung Autoexec-Makros definiert sind, müssen Sie möglicherweise die Umschalttaste gedrückt halten, wenn Sie die Zerlegung aufrufen, um zu verhindern, dass sie ausgeführt wird und den Export stört!

Natürlich gibt es auch das umgekehrte Skript, um die Anwendung aus dem "Source" -Verzeichnis zu erstellen:

compose.vbs:

' Usage:
'  WScript compose.vbs <file> <path>

' Converts all modules, classes, forms and macros in a directory created by "decompose.vbs"
' and composes then into an Access Project file (.adp). This overwrites any existing Modules with the
' same names without warning!!!
' Requires Microsoft Access.

Option Explicit

const acForm = 2
const acModule = 5
const acMacro = 4
const acReport = 3

Const acCmdCompileAndSaveAllModules = &H7E

' BEGIN CODE
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")

dim sADPFilename
If (WScript.Arguments.Count = 0) then
    MsgBox "Please enter the file name!", vbExclamation, "Error"
    Wscript.Quit()
End if
sADPFilename = fso.GetAbsolutePathName(WScript.Arguments(0))

Dim sPath
If (WScript.Arguments.Count = 1) then
    sPath = ""
else
    sPath = WScript.Arguments(1)
End If


importModulesTxt sADPFilename, sPath

If (Err <> 0) and (Err.Description <> NULL) Then
    MsgBox Err.Description, vbExclamation, "Error"
    Err.Clear
End If

Function importModulesTxt(sADPFilename, sImportpath)
    Dim myComponent
    Dim sModuleType
    Dim sTempname
    Dim sOutstring

    ' Build file and pathnames
    dim myType, myName, myPath, sStubADPFilename
    myType = fso.GetExtensionName(sADPFilename)
    myName = fso.GetBaseName(sADPFilename)
    myPath = fso.GetParentFolderName(sADPFilename)

    ' if no path was given as argument, use a relative directory
    If (sImportpath = "") then
        sImportpath = myPath & "\Source\"
    End If
    sStubADPFilename = sImportpath & myName & "_stub." & myType

    ' check for existing file and ask to overwrite with the stub
    if (fso.FileExists(sADPFilename)) Then
        WScript.StdOut.Write sADPFilename & " exists. Overwrite? (y/n) "
        dim sInput
        sInput = WScript.StdIn.Read(1)
        if (sInput <> "y") Then
            WScript.Quit
        end if

        fso.CopyFile sADPFilename, sADPFilename & ".bak"
    end if

    fso.CopyFile sStubADPFilename, sADPFilename

    ' launch MSAccess
    WScript.Echo "starting Access..."
    Dim oApplication
    Set oApplication = CreateObject("Access.Application")
    WScript.Echo "opening " & sADPFilename & " ..."
    If (Right(sStubADPFilename,4) = ".adp") Then
        oApplication.OpenAccessProject sADPFilename
    Else
        oApplication.OpenCurrentDatabase sADPFilename
    End If
    oApplication.Visible = false

    Dim folder
    Set folder = fso.GetFolder(sImportpath)

    ' load each file from the import path into the stub
    Dim myFile, objectname, objecttype
    for each myFile in folder.Files
        objecttype = fso.GetExtensionName(myFile.Name)
        objectname = fso.GetBaseName(myFile.Name)
        WScript.Echo "  " & objectname & " (" & objecttype & ")"

        if (objecttype = "form") then
            oApplication.LoadFromText acForm, objectname, myFile.Path
        elseif (objecttype = "bas") then
            oApplication.LoadFromText acModule, objectname, myFile.Path
        elseif (objecttype = "mac") then
            oApplication.LoadFromText acMacro, objectname, myFile.Path
        elseif (objecttype = "report") then
            oApplication.LoadFromText acReport, objectname, myFile.Path
        end if

    next

    oApplication.RunCommand acCmdCompileAndSaveAllModules
    oApplication.Quit
End Function

Public Function getErr()
    Dim strError
    strError = vbCrLf & "----------------------------------------------------------------------------------------------------------------------------------------" & vbCrLf & _
               "From " & Err.source & ":" & vbCrLf & _
               "    Description: " & Err.Description & vbCrLf & _
               "    Code: " & Err.Number & vbCrLf
    getErr = strError
End Function

Dies geht wiederum mit einem Begleiter "compose.cmd" einher, der Folgendes enthält:

cscript compose.vbs youraccessapplication.adp

Sie werden aufgefordert, das Überschreiben Ihrer aktuellen Anwendung zu bestätigen, und erstellen in diesem Fall zunächst ein Backup. Es sammelt dann alle Quelldateien im Quellverzeichnis und fügt sie erneut in den Stub ein.

Habe Spaß!

Oliver
quelle
1
Ich liebe diesen Code. Ich habe festgestellt, dass oApplication.OpenAccessProject für eine .accdb-Datei nicht funktioniert (oder möglicherweise für Access 2007), und ich musste stattdessen oApplication.OpenCurrentDatabase verwenden.
Hughdbrown
1
Ich mache etwas Ähnliches (SaveAsText, aber in VBA und mit einer MDB-Datei anstelle von ADP), aber ich habe noch ein großes Problem: Nach jedem Export erkennt Subversion ungefähr 100 Dateien als geändert (selbst wenn ich nur eine oder zwei geändert habe ). Wenn ich mir die Änderungen ansehe, sehe ich, dass einige Variablennamen oder Kontrollnamen ihre Groß- / Kleinschreibung geändert haben. Beispiel: Jede Datei, die einst "OrderNumber" enthielt, enthält jetzt "Ordernumber" im Export und wird daher als "geändert" markiert (zumindest von SVN, hat noch kein anderes SCM ausprobiert). Irgendeine Idee, wie ich das vermeiden kann? Vielen Dank!
Christian Specht
3
Ja, das ist auch in unserem Projekt ein ständiger Ärger. Soweit wir festgestellt haben, besteht das Problem darin, dass Variablen in Ihrem Projekt dieselben Namen wie Steuerelemente haben, nur in unterschiedlichen Fällen (hoch / niedrig). Abhängig von der Reihenfolge der zusammengesetzten Module scheint Access nun eine Schreibweise zu verwenden und alle anderen zu "korrespondieren", da bei VBA die Groß- und Kleinschreibung nicht berücksichtigt werden soll. Access tut dies, obwohl sich die Steuerelemente in verschiedenen Formen befinden! Das Problem wird größer, wenn Sie sogar mehrere Steuerelemente mit demselben Namen in unterschiedlichen Fällen in unterschiedlichen Formularen haben.
Oliver
3
Die einzige Lösung besteht darin, jede Variable / jeden Kontrollnamen aufzuspüren und die Schreibweise in eine gemeinsame Form zu ändern. Nach einem Export und dem Festschreiben der Änderungen sollten die Namen stabil sein. Durch das Präfixieren der Steuerelementnamen mit ihren Typen wird durch die Namenskonvention sichergestellt, dass die Namen nicht mit Variablen kollidieren. (zB txtTitle für ein Textfeld mit dem Titelfeld oder cmbUsers für eine Combobox usw.)
Oliver
Ich habe vergessen hinzuzufügen, dass ich OpenAccessProject in OpenCurrentDatabase ändern musste, um diese Arbeit mit MDBs zu bekommen .
DaveParillo
19

Es scheint etwas zu sein, das in Access verfügbar ist:

Dieser Link von msdn erklärt, wie Sie ein Versionsverwaltungs-Add-In für Microsoft Access installieren. Dies wird als kostenloser Download als Teil der Access Developer Extensions für Access 2007 und als separates kostenloses Add-In für Access 2003 geliefert.

Ich bin froh, dass Sie diese Frage gestellt haben, und ich habe mir die Zeit genommen, sie nachzuschlagen, da mir diese Fähigkeit auch gefallen würde. Der obige Link enthält weitere Informationen dazu und Links zu den Add-Ins.

Update:
Ich habe das Add-In für Access 2003 installiert. Es funktioniert nur mit VSS, aber es ermöglicht mir, Access-Objekte (Formulare, Abfragen, Tabellen, Module usw.) in das Repository zu stellen. Wenn Sie einen Artikel im Repo bearbeiten, werden Sie aufgefordert, ihn auszuchecken, müssen dies aber nicht. Als nächstes werde ich überprüfen, wie es gehandhabt wird, auf einem System ohne das Add-In geöffnet und geändert zu werden. Ich bin kein Fan von VSS, aber ich mag den Gedanken wirklich, Zugriffsobjekte in einem Repo zu speichern.

Update2: Computer
ohne Add-In können keine Änderungen an der Datenbankstruktur vornehmen (Tabellenfelder, Abfrageparameter usw. hinzufügen). Zuerst dachte ich, dass dies ein Problem sein könnte, wenn jemand es tun müsste, da es keine offensichtliche Möglichkeit gab, die Access-Datenbank aus der Quellcodeverwaltung zu entfernen, wenn Access das Add-In nicht geladen hatte.

ID hat festgestellt, dass Sie beim Ausführen der Datenbank "Kompakt und Reparieren" aufgefordert werden, die Datenbank aus der Quellcodeverwaltung zu entfernen. Ich habe mich für Ja entschieden und konnte die Datenbank ohne das Add-In bearbeiten. Der Artikel im obigen Link enthält auch Anweisungen zum Einrichten von Access 2003 und 2007 für die Verwendung von Team System. Wenn Sie einen MSSCCI-Anbieter für SVN finden, besteht eine gute Chance, dass dies funktioniert.

Brettski
quelle
Beachten Sie, dass wir einige Probleme damit hatten, einen ADP von VSS nicht auschecken zu können, wenn mehr als eine Person ihn bearbeitet hatte. Dafür mussten wir ein separates Backup erstellen!
Simon
Ich habe mit diesem Ansatz gespielt (mit Vault, da ich keine kostenlosen MSSCCI-Anbieter für SVN kenne ... TortoiseSVNSCC ist nicht gewartet und hat bei mir nicht funktioniert, und die anderen zwei oder drei Optionen sind kommerziell). Es funktioniert, aber es zwingt Sie, den archaischen Exklusiv-Locking-Ansatz für die Quellcodeverwaltung zu verwenden. Aus diesem Grund plane ich, ihn aufzugeben und die Lösung von @ Oliver zu verwenden.
Todd Owen
14

Die von Oliver veröffentlichte Compose / Decompose-Lösung ist großartig, hat aber einige Probleme:

  • Die Dateien sind als UCS-2 (UTF-16) codiert, was dazu führen kann, dass Versionskontrollsysteme / -tools die Dateien als binär betrachten.
  • Die Dateien enthalten viele Cruft, die sich häufig ändern - Prüfsummen, Druckerinformationen und mehr. Dies ist ein ernstes Problem, wenn Sie saubere Unterschiede wünschen oder bei dem Projekt zusammenarbeiten müssen.

Ich hatte vor, dies selbst zu beheben, stellte jedoch fest, dass bereits eine gute Lösung verfügbar ist: timabell / msaccess-vcs-Integration auf GitHub. Ich habe die msaccess-vcs-Integration getestet und es funktioniert großartig.

Aktualisiert am 3. März 2015 : Das Projekt wurde ursprünglich von bkidwell auf Github gepflegt / besessen, aber es wurde auf timabell übertragen - der obige Link zum Projekt wird entsprechend aktualisiert. Es gibt einige Gabeln aus dem ursprünglichen Projekt von bkidwell, zum Beispiel von ArminBra und von matonb , die AFAICT nicht verwenden sollte.

Der Nachteil der Verwendung von msaccess-vcs-Integration im Vergleich zu Olivers 'Zerlegungslösung:

  • Es ist deutlich langsamer. Ich bin sicher, dass das Geschwindigkeitsproblem behoben werden kann, aber ich muss mein Projekt nicht so oft in Text exportieren ...
  • Es wird kein Stub Access-Projekt erstellt, bei dem das exportierte Material entfernt wird. Dies kann auch behoben werden (indem Code aus dem Zerlegungsskript übernommen wird), aber auch dies ist nicht so wichtig.

Wie auch immer, meine klare Empfehlung ist msaccess-vcs-Integration. Es löste alle Probleme, die ich mit der Verwendung von Git für die exportierten Dateien hatte.

hansfn
quelle
Es sieht so aus, als ob die ArminBra-Gabel jetzt vorne liegt ( siehe Abbildung des Netzwerkdiagramms ). Matonb hat nicht auf die einzige Pull-Anfrage geantwortet, also haben sie sie zumindest vorerst aufgegeben.
Tim Abell
1
Und jetzt gibt es auch meine Gabel github.com/timabell/msaccess-vcs-integration - behebt den Exportfehler der zusammengesetzten Schlüsseltabelle. Die anderen beiden sehen ein bisschen verlassen aus, daher nehme ich gerne Fehlerberichte über Pull-Anfragen usw. auf meine Abzweigung.
Tim Abell
Ich würde höflich vorschlagen, diese Antwort zu bearbeiten, um auf meine Gabelung zu verweisen, da dies jetzt die am aktivsten gewartete Version ist.
Tim Abell
2
@ TimAbell: Ich habe meine Antwort aktualisiert, um die Tatsache widerzuspiegeln, dass das Projekt an Sie übertragen wurde. PS! Ich hoffe, wir können ein paar Stimmen bekommen, da ich denke, dass dies die beste Lösung ist.
Hansfn
2
Schön, das Navigieren in den Gabeln eines Github-Projekts scheint das neueste Problem zu sein, das wir für uns selbst erfunden haben :-)
Tim Abell
14

Olivers antworten auf Steine, aber die CurrentProjectReferenz hat bei mir nicht funktioniert. Am Ende habe ich die Eingeweide aus der Mitte seines Exports herausgerissen und durch diese ersetzt, basierend auf einer ähnlichen Lösung von Arvin Meyer . Hat den Vorteil, Abfragen zu exportieren, wenn Sie eine MDB anstelle einer ADP verwenden.

' Writes database componenets to a series of text files
' @author  Arvin Meyer
' @date    June 02, 1999
Function DocDatabase(oApp)
    Dim dbs 
    Dim cnt 
    Dim doc 
    Dim i
    Dim prefix
    Dim dctDelete
    Dim docName

    Const acQuery = 1

    Set dctDelete = CreateObject("Scripting.Dictionary")

    Set dbs = oApp.CurrentDb() ' use CurrentDb() to refresh Collections
    Set cnt = dbs.Containers("Forms")
    prefix = oApp.CurrentProject.Path & "\"
    For Each doc In cnt.Documents
        oApp.SaveAsText acForm, doc.Name, prefix & doc.Name & ".frm"
        dctDelete.Add "frm_" & doc.Name, acForm
    Next

    Set cnt = dbs.Containers("Reports")
    For Each doc In cnt.Documents
        oApp.SaveAsText acReport, doc.Name, prefix & doc.Name & ".rpt"
        dctDelete.Add "rpt_" & doc.Name, acReport
    Next

    Set cnt = dbs.Containers("Scripts")
    For Each doc In cnt.Documents
        oApp.SaveAsText acMacro, doc.Name, prefix & doc.Name & ".vbs"
        dctDelete.Add "vbs_" & doc.Name, acMacro
    Next

    Set cnt = dbs.Containers("Modules")
    For Each doc In cnt.Documents
        oApp.SaveAsText acModule, doc.Name, prefix & doc.Name & ".bas"
        dctDelete.Add "bas_" & doc.Name, acModule
    Next

    For i = 0 To dbs.QueryDefs.Count - 1
        oApp.SaveAsText acQuery, dbs.QueryDefs(i).Name, prefix & dbs.QueryDefs(i).Name & ".txt"
        dctDelete.Add "qry_" & dbs.QueryDefs(i).Name, acQuery
    Next

    WScript.Echo "deleting " & dctDelete.Count & " objects."
    For Each docName In dctDelete
        WScript.Echo "  " & Mid(docName, 5)
        oApp.DoCmd.DeleteObject dctDelete(docName), Mid(docName, 5)
    Next

    Set doc = Nothing
    Set cnt = Nothing
    Set dbs = Nothing
    Set dctDelete = Nothing

End Function
DaveParillo
quelle
1
+1 für das Einschließen von Abfragen. Jetzt müssen nur noch Tabellenschemata eingefügt werden.
Marc Stober
Die genehmigte Antwort funktioniert nicht für Access 97, aber diese Antwort hat mir geholfen, sie für meine eigenen Zwecke zu ändern. Vielen Dank für die Veröffentlichung!
CTristan
2
Ich empfehle dringend, das Speichern der Abfrage vor das Speichern der Formulare zu stellen, um die Reihenfolge des Löschens später zu ändern. Ich hatte einige Probleme mit DeleteObject in der letzten For Each-Anweisung, als ich versuchte, Abfragen zu löschen, die bereits automatisch gelöscht wurden, wenn die entsprechenden Formulare zuvor gelöscht wurden. Wenn beim Start einige Formulare geöffnet sind und F11 nicht gedrückt halten (oder deaktiviert) werden soll, fügen Sie einfach oApp.DoCmd.Close acForm, "formName" nach dem Ausführen durch cnt.Documents
Anton Kaiser
@Cunso Bitte können Sie Ihren Code veröffentlichen, der mit Access 97 kompatibel ist. Ich muss ihn also nicht neu entwickeln.
Lorenz Meyer
Wie benutze ich das? Rufen Sie es von einem U-Boot?
Kevinvinkuo
11

Wir haben unser eigenes internes Tool entwickelt, mit dem:

  1. Module: werden als txt-Dateien exportiert und dann mit dem "file compare tool" (Freeware) verglichen.
  2. Formulare: werden über den Befehl undocument application.saveAsText exportiert. Es ist dann möglich, die Unterschiede zwischen 2 verschiedenen Versionen zu sehen ("Dateivergleichstool" noch einmal).
  3. Makros: Wir haben kein Makro zum Vergleichen, da wir nur das Makro "autoexec" mit einer Zeile haben, die die Haupt-VBA-Prozedur startet
  4. Abfragen: sind nur in einer Tabelle gespeicherte Textzeichenfolgen: siehe unten
  5. Tabellen: Wir haben unseren eigenen Tabellenvergleich geschrieben, in dem Unterschiede in Datensätzen UND Tabellenstruktur aufgelistet sind.

Das gesamte System ist intelligent genug, um "Laufzeit" -Versionen unserer Access-Anwendung zu erstellen, die automatisch aus txt-Dateien (Module und Formulare, die mit dem Befehl undocument application.loadFromText neu erstellt werden) und mdb-Dateien (Tabellen) generiert werden.

Es mag seltsam klingen, aber es funktioniert.

Philippe Grondier
quelle
8
Würde gerne dieses Tool Open-Source sehen!
Todd Owen
Ist es eine gute Idee, diese exportierten Textdateien auf GitHub hochzuladen?
Santosh
9

Basierend auf den Ideen dieses Beitrags und ähnlichen Einträgen in einigen Blogs habe ich eine Anwendung geschrieben, die mit den Dateiformaten mdb und adp funktioniert. Es importiert / exportiert alle Datenbankobjekte (einschließlich Tabellen, Referenzen, Beziehungen und Datenbankeigenschaften) in Nur-Text-Dateien. Mit diesen Dateien können Sie mit einer beliebigen Quellversionskontrolle arbeiten. In der nächsten Version können die Nur-Text-Dateien wieder in die Datenbank importiert werden. Es wird auch ein Kommandozeilen-Tool geben

Sie können die Anwendung oder den Quellcode von folgender Adresse herunterladen: http://accesssvn.codeplex.com/

Grüße

Mnieto
quelle
Wir verwenden dies seit fast zwei Jahren und es ist großartig. Danke dir!
McFea
5

Einen alten Thread wiederbeleben, aber das ist gut so. Ich habe die beiden Skripte (compose.vbs / decompose.vbs) für mein eigenes Projekt implementiert und bin auf ein Problem mit alten MDB-Dateien gestoßen:

Es bleibt stehen, wenn es zu einem Formular gelangt, das den Code enthält:

NoSaveCTIWhenDisabled =1

Access sagt, es hat ein Problem und das ist das Ende der Geschichte. Ich habe einige Tests durchgeführt und herumgespielt, um dieses Problem zu umgehen, und diesen Thread mit einer Umgehung am Ende gefunden:

Datenbank kann nicht erstellt werden

Grundsätzlich (für den Fall, dass der Thread tot ist) nehmen Sie die .mdb und führen ein "Speichern unter" im neuen .accdb-Format durch. Dann funktioniert die Quelle sicher oder komponieren / zerlegen. Ich musste auch 10 Minuten herumspielen, um die richtige Befehlszeilensyntax für die (De-) Compose-Skripte zu erhalten, damit sie richtig funktionieren. Hier also auch diese Informationen:

So komponieren Sie (sagen Sie, Ihre Inhalte befinden sich in C: \ SControl (erstellen Sie einen Unterordner mit dem Namen Source, um die extrahierten Dateien zu speichern):

'(to extract for importing to source control)
cscript compose.vbs database.accdb     

'(to rebuild from extracted files saved from an earlier date)
cscript decompose.vbs database.accdb C:\SControl\Source\

Das ist es!

Die Versionen von Access, bei denen das oben genannte Problem aufgetreten ist, enthalten Access 2000-2003 ".mdb" -Datenbanken und haben das Problem behoben, indem sie vor dem Ausführen der Skripts zum Erstellen / Zerlegen in den Formaten ".accdb" 2007-2010 gespeichert wurden. Nach der Konvertierung funktionieren die Skripte einwandfrei!

JKK
quelle
Können Sie dies bearbeiten, um Ihre Access-Versionen einzuschließen, bei denen dieses Problem auftritt?
Nathan DeWitt
Kein Problem, machst du immer noch Zugangsentwicklung Nathan? Wenn ja, Erfolg bei der Integration in die Versionskontrolle?
JKK
Ich mache keine Access-Entwicklung mehr. Ich hatte ein Projekt, das ich auf dem Rückweg verwendet habe, als ich die Frage gestellt habe, und musste nie etwas anderes damit machen.
Nathan DeWitt
Cool, ich denke, die meisten Unternehmen verwenden einen dedizierten SQL Server. In der Situation, in der ich mich gerade befinde, gibt es eine Mischung aus MS SQL Server, Oracle und einer Reihe von Access-Datenbanken, die Daten von Servern in lokale Tabellen abrufen und in Excel exportieren. Es ist eine ziemlich komplizierte Mischung. Ich denke, ich werde eine neue Frage zu einigen Vorschlägen für die Einrichtung eines neuen Projekts stellen, an dem ich bald teilnehmen werde. Sehen Sie, was die Leute vorschlagen können, um die Komplexität zu reduzieren
JKK
4

Nur-Text-Datei-Lösung (Abfragen, Tabellen und Beziehungen enthalten)

Ich habe das Skriptpaar von Oliver so geändert, dass es neben Modulen, Klassen, Formularen und Makros auch Beziehungen, Tabellen und Abfragen exportiert / importiert . Alles wird in Klartextdateien gespeichert, sodass keine Datenbankdatei erstellt wird, die mit den Textdateien in der Versionskontrolle gespeichert werden kann.

Export in Textdateien (decompose.vbs)

' Usage:
'  cscript decompose.vbs <input file> <path>

' Converts all modules, classes, forms and macros from an Access Project file (.adp) <input file> to
' text and saves the results in separate files to <path>.  Requires Microsoft Access.
Option Explicit

Const acForm = 2
Const acModule = 5
Const acMacro = 4
Const acReport = 3
Const acQuery = 1
Const acExportTable = 0

' BEGIN CODE
Dim fso, relDoc, ACCDBFilename, sExportpath
Set fso = CreateObject("Scripting.FileSystemObject")
Set relDoc = CreateObject("Microsoft.XMLDOM")

If (Wscript.Arguments.Count = 0) Then
    MsgBox "Please provide the .accdb database file", vbExclamation, "Error"
    Wscript.Quit()
End If
ACCDBFilename = fso.GetAbsolutePathName(Wscript.Arguments(0))

If (Wscript.Arguments.Count = 1) Then
 sExportpath = ""
Else
 sExportpath = Wscript.Arguments(1)
End If


exportModulesTxt ACCDBFilename, sExportpath

If (Err <> 0) And (Err.Description <> Null) Then
    MsgBox Err.Description, vbExclamation, "Error"
    Err.Clear
End If

Function exportModulesTxt(ACCDBFilename, sExportpath)
    Dim myComponent, sModuleType, sTempname, sOutstring
    Dim myType, myName, myPath, hasRelations
    myType = fso.GetExtensionName(ACCDBFilename)
    myName = fso.GetBaseName(ACCDBFilename)
    myPath = fso.GetParentFolderName(ACCDBFilename)

    'if no path was given as argument, use a relative directory
    If (sExportpath = "") Then
        sExportpath = myPath & "\Source"
    End If
    'On Error Resume Next
    fso.DeleteFolder (sExportpath)
    fso.CreateFolder (sExportpath)
    On Error GoTo 0

    Wscript.Echo "starting Access..."
    Dim oApplication
    Set oApplication = CreateObject("Access.Application")
    Wscript.Echo "Opening " & ACCDBFilename & " ..."
    If (Right(ACCDBFilename, 4) = ".adp") Then
     oApplication.OpenAccessProject ACCDBFilename
    Else
     oApplication.OpenCurrentDatabase ACCDBFilename
    End If
    oApplication.Visible = False

    Wscript.Echo "exporting..."
    Dim myObj
    For Each myObj In oApplication.CurrentProject.AllForms
        Wscript.Echo "Exporting FORM " & myObj.FullName
        oApplication.SaveAsText acForm, myObj.FullName, sExportpath & "\" & myObj.FullName & ".form.txt"
        oApplication.DoCmd.Close acForm, myObj.FullName
    Next
    For Each myObj In oApplication.CurrentProject.AllModules
        Wscript.Echo "Exporting MODULE " & myObj.FullName
        oApplication.SaveAsText acModule, myObj.FullName, sExportpath & "\" & myObj.FullName & ".module.txt"
    Next
    For Each myObj In oApplication.CurrentProject.AllMacros
        Wscript.Echo "Exporting MACRO " & myObj.FullName
        oApplication.SaveAsText acMacro, myObj.FullName, sExportpath & "\" & myObj.FullName & ".macro.txt"
    Next
    For Each myObj In oApplication.CurrentProject.AllReports
        Wscript.Echo "Exporting REPORT " & myObj.FullName
        oApplication.SaveAsText acReport, myObj.FullName, sExportpath & "\" & myObj.FullName & ".report.txt"
    Next
    For Each myObj In oApplication.CurrentDb.QueryDefs
        Wscript.Echo "Exporting QUERY " & myObj.Name
        oApplication.SaveAsText acQuery, myObj.Name, sExportpath & "\" & myObj.Name & ".query.txt"
    Next
    For Each myObj In oApplication.CurrentDb.TableDefs
     If Not Left(myObj.Name, 4) = "MSys" Then
      Wscript.Echo "Exporting TABLE " & myObj.Name
      oApplication.ExportXml acExportTable, myObj.Name, , sExportpath & "\" & myObj.Name & ".table.txt"
      'put the file path as a second parameter if you want to export the table data as well, instead of ommiting it and passing it into a third parameter for structure only
     End If
    Next

    hasRelations = False
    relDoc.appendChild relDoc.createElement("Relations")
    For Each myObj In oApplication.CurrentDb.Relations  'loop though all the relations
    If Not Left(myObj.Name, 4) = "MSys" Then
     Dim relName, relAttrib, relTable, relFoTable, fld
     hasRelations = True

     relDoc.ChildNodes(0).appendChild relDoc.createElement("Relation")
     Set relName = relDoc.createElement("Name")
     relName.Text = myObj.Name
     relDoc.ChildNodes(0).LastChild.appendChild relName

     Set relAttrib = relDoc.createElement("Attributes")
     relAttrib.Text = myObj.Attributes
     relDoc.ChildNodes(0).LastChild.appendChild relAttrib

     Set relTable = relDoc.createElement("Table")
     relTable.Text = myObj.Table
     relDoc.ChildNodes(0).LastChild.appendChild relTable

     Set relFoTable = relDoc.createElement("ForeignTable")
     relFoTable.Text = myObj.ForeignTable
     relDoc.ChildNodes(0).LastChild.appendChild relFoTable

     Wscript.Echo "Exporting relation " & myObj.Name & " between tables " & myObj.Table & " -> " & myObj.ForeignTable

     For Each fld In myObj.Fields   'in case the relationship works with more fields
      Dim lf, ff
      relDoc.ChildNodes(0).LastChild.appendChild relDoc.createElement("Field")

      Set lf = relDoc.createElement("Name")
      lf.Text = fld.Name
      relDoc.ChildNodes(0).LastChild.LastChild.appendChild lf

      Set ff = relDoc.createElement("ForeignName")
      ff.Text = fld.ForeignName
      relDoc.ChildNodes(0).LastChild.LastChild.appendChild ff

      Wscript.Echo "  Involving fields " & fld.Name & " -> " & fld.ForeignName
     Next
    End If
    Next
    If hasRelations Then
     relDoc.InsertBefore relDoc.createProcessingInstruction("xml", "version='1.0'"), relDoc.ChildNodes(0)
     relDoc.Save sExportpath & "\relations.rel.txt"
     Wscript.Echo "Relations successfuly saved in file relations.rel.txt"
    End If

    oApplication.CloseCurrentDatabase
    oApplication.Quit

End Function

Sie können dieses Skript durch Aufrufen ausführen cscript decompose.vbs <path to file to decompose> <folder to store text files>. Wenn Sie den zweiten Parameter weglassen, wird der Ordner 'Source' erstellt, in dem sich die Datenbank befindet. Bitte beachten Sie, dass der Zielordner gelöscht wird, wenn er bereits vorhanden ist.

Fügen Sie Daten in die exportierten Tabellen ein

Zeile 93 ersetzen: oApplication.ExportXML acExportTable, myObj.Name, , sExportpath & "\" & myObj.Name & ".table.txt"

mit Linie oApplication.ExportXML acExportTable, myObj.Name, sExportpath & "\" & myObj.Name & ".table.txt"

Importieren in Datenbankdatei erstellen (compose.vbs)

' Usage:
'  cscript compose.vbs <file> <path>

' Reads all modules, classes, forms, macros, queries, tables and their relationships in a directory created by "decompose.vbs"
' and composes then into an Access Database file (.accdb).
' Requires Microsoft Access.
Option Explicit

Const acForm = 2
Const acModule = 5
Const acMacro = 4
Const acReport = 3
Const acQuery = 1
Const acStructureOnly = 0   'change 0 to 1 if you want import StructureAndData instead of StructureOnly
Const acCmdCompileAndSaveAllModules = &H7E

Dim fso, relDoc, ACCDBFilename, sPath
Set fso = CreateObject("Scripting.FileSystemObject")
Set relDoc = CreateObject("Microsoft.XMLDOM")

If (Wscript.Arguments.Count = 0) Then
 MsgBox "Please provide the .accdb database file", vbExclamation, "Error"
 Wscript.Quit()
End If

ACCDBFilename = fso.GetAbsolutePathName(Wscript.Arguments(0))
If (Wscript.Arguments.Count = 1) Then
 sPath = ""
Else
 sPath = Wscript.Arguments(1)
End If


importModulesTxt ACCDBFilename, sPath

If (Err <> 0) And (Err.Description <> Null) Then
    MsgBox Err.Description, vbExclamation, "Error"
    Err.Clear
End If


Function importModulesTxt(ACCDBFilename, sImportpath)
    Dim myComponent, sModuleType, sTempname, sOutstring

    ' Build file and pathnames
    Dim myType, myName, myPath
    myType = fso.GetExtensionName(ACCDBFilename)
    myName = fso.GetBaseName(ACCDBFilename)
    myPath = fso.GetParentFolderName(ACCDBFilename)

    ' if no path was given as argument, use a relative directory
    If (sImportpath = "") Then
        sImportpath = myPath & "\Source\"
    End If

    ' check for existing file and ask to overwrite with the stub
    If fso.FileExists(ACCDBFilename) Then
     Wscript.StdOut.Write ACCDBFilename & " already exists. Overwrite? (y/n) "
     Dim sInput
     sInput = Wscript.StdIn.Read(1)
     If (sInput <> "y") Then
      Wscript.Quit
     Else
      If fso.FileExists(ACCDBFilename & ".bak") Then
       fso.DeleteFile (ACCDBFilename & ".bak")
      End If
      fso.MoveFile ACCDBFilename, ACCDBFilename & ".bak"
     End If
    End If

    Wscript.Echo "starting Access..."
    Dim oApplication
    Set oApplication = CreateObject("Access.Application")
    Wscript.Echo "Opening " & ACCDBFilename
    If (Right(ACCDBFilename, 4) = ".adp") Then
        oApplication.CreateAccessProject ACCDBFilename
    Else
        oApplication.NewCurrentDatabase ACCDBFilename
    End If
    oApplication.Visible = False

    Dim folder
    Set folder = fso.GetFolder(sImportpath)

    'load each file from the import path into the stub
    Dim myFile, objectname, objecttype
    For Each myFile In folder.Files
     objectname = fso.GetBaseName(myFile.Name)  'get rid of .txt extension
     objecttype = fso.GetExtensionName(objectname)
     objectname = fso.GetBaseName(objectname)

     Select Case objecttype
      Case "form"
       Wscript.Echo "Importing FORM from file " & myFile.Name
       oApplication.LoadFromText acForm, objectname, myFile.Path
      Case "module"
       Wscript.Echo "Importing MODULE from file " & myFile.Name
       oApplication.LoadFromText acModule, objectname, myFile.Path
      Case "macro"
       Wscript.Echo "Importing MACRO from file " & myFile.Name
       oApplication.LoadFromText acMacro, objectname, myFile.Path
      Case "report"
       Wscript.Echo "Importing REPORT from file " & myFile.Name
       oApplication.LoadFromText acReport, objectname, myFile.Path
      Case "query"
       Wscript.Echo "Importing QUERY from file " & myFile.Name
       oApplication.LoadFromText acQuery, objectname, myFile.Path
      Case "table"
       Wscript.Echo "Importing TABLE from file " & myFile.Name
       oApplication.ImportXml myFile.Path, acStructureOnly
      Case "rel"
       Wscript.Echo "Found RELATIONSHIPS file " & myFile.Name & " ... opening, it will be processed after everything else has been imported"
       relDoc.Load (myFile.Path)
     End Select
    Next

    If relDoc.readyState Then
     Wscript.Echo "Preparing to build table dependencies..."
     Dim xmlRel, xmlField, accessRel, relTable, relName, relFTable, relAttr, i
     For Each xmlRel In relDoc.SelectNodes("/Relations/Relation")   'loop through every Relation node inside .xml file
      relName = xmlRel.SelectSingleNode("Name").Text
      relTable = xmlRel.SelectSingleNode("Table").Text
      relFTable = xmlRel.SelectSingleNode("ForeignTable").Text
      relAttr = xmlRel.SelectSingleNode("Attributes").Text

      'remove any possible conflicting relations or indexes
      On Error Resume Next
      oApplication.CurrentDb.Relations.Delete (relName)
      oApplication.CurrentDb.TableDefs(relTable).Indexes.Delete (relName)
      oApplication.CurrentDb.TableDefs(relFTable).Indexes.Delete (relName)
      On Error GoTo 0

      Wscript.Echo "Creating relation " & relName & " between tables " & relTable & " -> " & relFTable
      Set accessRel = oApplication.CurrentDb.CreateRelation(relName, relTable, relFTable, relAttr)  'create the relationship object

      For Each xmlField In xmlRel.SelectNodes("Field")  'in case the relationship works with more fields
       accessRel.Fields.Append accessRel.CreateField(xmlField.SelectSingleNode("Name").Text)
       accessRel.Fields(xmlField.SelectSingleNode("Name").Text).ForeignName = xmlField.SelectSingleNode("ForeignName").Text
       Wscript.Echo "  Involving fields " & xmlField.SelectSingleNode("Name").Text & " -> " & xmlField.SelectSingleNode("ForeignName").Text
      Next

      oApplication.CurrentDb.Relations.Append accessRel 'append the newly created relationship to the database
      Wscript.Echo "  Relationship added"
     Next
    End If

    oApplication.RunCommand acCmdCompileAndSaveAllModules
    oApplication.Quit
End Function

Sie können dieses Skript durch Aufrufen ausführen cscript compose.vbs <path to file which should be created> <folder with text files>. Wenn Sie den zweiten Parameter weglassen, wird der Ordner "Quelle" angezeigt, in dem die Datenbank erstellt werden soll.

Daten aus Textdatei importieren

Zeile 14 ersetzen: const acStructureOnly = 0durch const acStructureOnly = 1. Dies funktioniert nur, wenn Sie die Daten in die exportierte Tabelle aufgenommen haben.

Dinge, die nicht abgedeckt sind

  1. Ich habe dies nur mit .accdb-Dateien getestet, daher kann es bei allem anderen zu Fehlern kommen.
  2. Einstellungen werden nicht exportiert. Ich würde empfehlen, ein Makro zu erstellen, das die Einstellung beim Start der Datenbank anwendet.
  3. Einige unbekannte Abfragen werden manchmal exportiert, denen '~' vorangestellt ist. Ich weiß nicht, ob sie notwendig sind.
  4. MSAccess-Objektnamen können Zeichen enthalten, die für Dateinamen ungültig sind. Das Skript schlägt fehl, wenn versucht wird, sie zu schreiben. Sie können alle Dateinamen normalisieren , aber dann nicht zurück importieren.

Eine meiner anderen Ressourcen bei der Arbeit an diesem Skript war diese Antwort , mit deren Hilfe ich herausfinden konnte, wie Beziehungen exportiert werden.

Jakub M.
quelle
Dies scheint zu funktionieren, versteht aber nicht verknüpfte Tabellen
Lord Darth Vader
2

Es gibt ein Problem: VSS 6.0 kann MDBs nur mit dem Add-In unter einer bestimmten Anzahl von Objekten akzeptieren, einschließlich aller lokalen Tabellen, Abfragen, Module und Formulare. Ich kenne die genaue Objektgrenze nicht.

Um unsere 10 Jahre alte Prod Floor App zu erstellen, die riesig ist, müssen wir 3 oder 4 separate MDBs aus SS zu einer MDB kombinieren, was automatisierte Builds so kompliziert macht, dass wir keine Zeit damit verschwenden.

Ich denke, ich werde das obige Skript versuchen, um diesen MDb in SVN zu spucken und Builds für alle zu vereinfachen.

ChuckB
quelle
2

Für Benutzer von Access 2010 ist SaveAsText keine sichtbare Methode in Intellisense, aber es scheint eine gültige Methode zu sein, da das zuvor erwähnte Skript von Arvin Meyer für mich gut funktioniert hat.

Interessanterweise ist SaveAsAXL neu in 2010 und hat dieselbe Signatur wie SaveAsText, obwohl es anscheinend nur mit Webdatenbanken funktioniert, für die SharePoint Server 2010 erforderlich ist.

Cory
quelle
SaveAsText ist auch in A2003 nicht sichtbar, es sei denn, Sie haben Versteckte Mitglieder anzeigen im Objektbrowser aktiviert. Gute Informationen zu SaveAsAXL.
David-W-Fenton
2

Wir hatten vor einiger Zeit das gleiche Problem.

Unser erster Versuch war ein Drittanbieter-Tool, das einen Proxy der SourceSafe-API für Subversion zur Verwendung mit MS Access und VB 6 bietet. Das Tool finden Sie hier .

Da wir mit diesem Tool nicht so zufrieden waren, haben wir auf Visual SourceSafe und das VSS Acces Plugin umgestellt.

Benjamin Brauer
quelle
2

Ich benutze Oasis-Svn http://dev2dev.de/

Ich kann nur sagen, dass es mich mindestens einmal gerettet hat. Meine MDB wuchs über 2 GB und das hat es kaputt gemacht. Ich könnte zu einer alten Version zurückkehren und die Formulare importieren und habe gerade einen Tag Arbeit verloren.

Friedrich
quelle
1

Ich habe dieses Tool auf SourceForge gefunden: http://sourceforge.net/projects/avc/

Ich habe es nicht benutzt, aber es könnte ein Anfang für dich sein. Möglicherweise sind andere Tools von Drittanbietern in VSS oder SVN integriert, die genau das tun, was Sie benötigen.

Persönlich halte ich einfach eine einfache Textdatei bereit, um ein Änderungsprotokoll zu führen. Wenn ich die binäre MDB festschreibe, verwende ich die Einträge im Änderungsprotokoll als meinen Festschreibungskommentar.

Patrick Manschette
quelle
Haben Sie einen Link zum Herunterladen? Bin ich blind Ich kann es nicht finden.
BIBD
sourceforge.net/project/showfiles.php?group_id=115226 Keine Dateipakete definiert. Yay.
Nathan DeWitt
1

Zur Vollständigkeit...

Es gibt immer "Visual Studio [YEAR] Tools für das Microsoft Office System" ( http://msdn.microsoft.com/en-us/vs2005/aa718673.aspx ), aber das scheint VSS zu erfordern. Für mich ist VSS (Auto Corrupting) schlechter als meine 347 Speicherpunkte auf meiner über gesicherten Netzwerkfreigabe.

BIBD
quelle
1

Ich verwende das Access 2003-Add-In: Quellcodeverwaltung . Es funktioniert gut. Ein Problem sind ungültige Zeichen wie ein ":".

Ich checke ein und aus. Intern macht das Add-In dasselbe wie der Code dort oben, jedoch mit mehr Tool-Unterstützung. Ich kann sehen, ob ein Objekt ausgecheckt ist, und die Objekte aktualisieren.

Sommer
quelle
1

Sie können Ihren MS Access auch mit dem Team Foundation Server verbinden. Es gibt auch eine kostenlose Express-Variante für bis zu 5 Entwickler. Funktioniert wirklich gut!

Bearbeiten: fester Link

WolfgangP
quelle
1

Die Antwort von Oliver funktioniert großartig. Unten finden Sie meine erweiterte Version, die Unterstützung für Access-Abfragen bietet.

( Weitere Informationen / Verwendung finden Sie in der Antwort von Oliver. )

decompose.vbs:

' Usage:
'  CScript decompose.vbs <input file> <path>

' Converts all modules, classes, forms and macros from an Access Project file (.adp) <input file> to
' text and saves the results in separate files to <path>.  Requires Microsoft Access.
'
Option Explicit

const acForm = 2
const acModule = 5
const acMacro = 4
const acReport = 3
const acQuery = 1

' BEGIN CODE
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")

dim sADPFilename
If (WScript.Arguments.Count = 0) then
    MsgBox "Bitte den Dateinamen angeben!", vbExclamation, "Error"
    Wscript.Quit()
End if
sADPFilename = fso.GetAbsolutePathName(WScript.Arguments(0))

Dim sExportpath
If (WScript.Arguments.Count = 1) then
    sExportpath = ""
else
    sExportpath = WScript.Arguments(1)
End If


exportModulesTxt sADPFilename, sExportpath

If (Err <> 0) and (Err.Description <> NULL) Then
    MsgBox Err.Description, vbExclamation, "Error"
    Err.Clear
End If

Function exportModulesTxt(sADPFilename, sExportpath)
    Dim myComponent
    Dim sModuleType
    Dim sTempname
    Dim sOutstring

    dim myType, myName, myPath, sStubADPFilename
    myType = fso.GetExtensionName(sADPFilename)
    myName = fso.GetBaseName(sADPFilename)
    myPath = fso.GetParentFolderName(sADPFilename)

    If (sExportpath = "") then
        sExportpath = myPath & "\Source\"
    End If
    sStubADPFilename = sExportpath & myName & "_stub." & myType

    WScript.Echo "copy stub to " & sStubADPFilename & "..."
    On Error Resume Next
        fso.CreateFolder(sExportpath)
    On Error Goto 0
    fso.CopyFile sADPFilename, sStubADPFilename

    WScript.Echo "starting Access..."
    Dim oApplication
    Set oApplication = CreateObject("Access.Application")
    WScript.Echo "opening " & sStubADPFilename & " ..."
    If (Right(sStubADPFilename,4) = ".adp") Then
        oApplication.OpenAccessProject sStubADPFilename
    Else
        oApplication.OpenCurrentDatabase sStubADPFilename
    End If

    oApplication.Visible = false

    dim dctDelete
    Set dctDelete = CreateObject("Scripting.Dictionary")
    WScript.Echo "exporting..."
    Dim myObj

    For Each myObj In oApplication.CurrentProject.AllForms
        WScript.Echo "  " & myObj.fullname
        oApplication.SaveAsText acForm, myObj.fullname, sExportpath & "\" & myObj.fullname & ".form"
        oApplication.DoCmd.Close acForm, myObj.fullname
        dctDelete.Add "FO" & myObj.fullname, acForm
    Next
    For Each myObj In oApplication.CurrentProject.AllModules
        WScript.Echo "  " & myObj.fullname
        oApplication.SaveAsText acModule, myObj.fullname, sExportpath & "\" & myObj.fullname & ".bas"
        dctDelete.Add "MO" & myObj.fullname, acModule
    Next
    For Each myObj In oApplication.CurrentProject.AllMacros
        WScript.Echo "  " & myObj.fullname
        oApplication.SaveAsText acMacro, myObj.fullname, sExportpath & "\" & myObj.fullname & ".mac"
        dctDelete.Add "MA" & myObj.fullname, acMacro
    Next
    For Each myObj In oApplication.CurrentProject.AllReports
        WScript.Echo "  " & myObj.fullname
        oApplication.SaveAsText acReport, myObj.fullname, sExportpath & "\" & myObj.fullname & ".report"
        dctDelete.Add "RE" & myObj.fullname, acReport
    Next
    For Each myObj In oApplication.CurrentDb.QueryDefs
        if not left(myObj.name,3) = "~sq" then 'exclude queries defined by the forms. Already included in the form itself
            WScript.Echo "  " & myObj.name
            oApplication.SaveAsText acQuery, myObj.name, sExportpath & "\" & myObj.name & ".query"
            oApplication.DoCmd.Close acQuery, myObj.name
            dctDelete.Add "FO" & myObj.name, acQuery
        end if
    Next

    WScript.Echo "deleting..."
    dim sObjectname
    For Each sObjectname In dctDelete
        WScript.Echo "  " & Mid(sObjectname, 3)
        oApplication.DoCmd.DeleteObject dctDelete(sObjectname), Mid(sObjectname, 3)
    Next

    oApplication.CloseCurrentDatabase
    oApplication.CompactRepair sStubADPFilename, sStubADPFilename & "_"
    oApplication.Quit

    fso.CopyFile sStubADPFilename & "_", sStubADPFilename
    fso.DeleteFile sStubADPFilename & "_"


End Function

Public Function getErr()
    Dim strError
    strError = vbCrLf & "----------------------------------------------------------------------------------------------------------------------------------------" & vbCrLf & _
               "From " & Err.source & ":" & vbCrLf & _
               "    Description: " & Err.Description & vbCrLf & _
               "    Code: " & Err.Number & vbCrLf
    getErr = strError
End Function

compose.vbs:

' Usage:
'  WScript compose.vbs <file> <path>

' Converts all modules, classes, forms and macros in a directory created by "decompose.vbs"
' and composes then into an Access Project file (.adp). This overwrites any existing Modules with the
' same names without warning!!!
' Requires Microsoft Access.

Option Explicit

const acForm = 2
const acModule = 5
const acMacro = 4
const acReport = 3
const acQuery = 1

Const acCmdCompileAndSaveAllModules = &H7E

' BEGIN CODE
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")

dim sADPFilename
If (WScript.Arguments.Count = 0) then
    MsgBox "Bitte den Dateinamen angeben!", vbExclamation, "Error"
    Wscript.Quit()
End if
sADPFilename = fso.GetAbsolutePathName(WScript.Arguments(0))

Dim sPath
If (WScript.Arguments.Count = 1) then
    sPath = ""
else
    sPath = WScript.Arguments(1)
End If


importModulesTxt sADPFilename, sPath

If (Err <> 0) and (Err.Description <> NULL) Then
    MsgBox Err.Description, vbExclamation, "Error"
    Err.Clear
End If

Function importModulesTxt(sADPFilename, sImportpath)
    Dim myComponent
    Dim sModuleType
    Dim sTempname
    Dim sOutstring

    ' Build file and pathnames
    dim myType, myName, myPath, sStubADPFilename
    myType = fso.GetExtensionName(sADPFilename)
    myName = fso.GetBaseName(sADPFilename)
    myPath = fso.GetParentFolderName(sADPFilename)

    ' if no path was given as argument, use a relative directory
    If (sImportpath = "") then
        sImportpath = myPath & "\Source\"
    End If
    sStubADPFilename = sImportpath & myName & "_stub." & myType

    ' check for existing file and ask to overwrite with the stub
    if (fso.FileExists(sADPFilename)) Then
        WScript.StdOut.Write sADPFilename & " existiert bereits. Überschreiben? (j/n) "
        dim sInput
        sInput = WScript.StdIn.Read(1)
        if (sInput <> "j") Then
            WScript.Quit
        end if

        fso.CopyFile sADPFilename, sADPFilename & ".bak"
    end if

    fso.CopyFile sStubADPFilename, sADPFilename

    ' launch MSAccess
    WScript.Echo "starting Access..."
    Dim oApplication
    Set oApplication = CreateObject("Access.Application")
    WScript.Echo "opening " & sADPFilename & " ..."
    If (Right(sStubADPFilename,4) = ".adp") Then
        oApplication.OpenAccessProject sADPFilename
    Else
        oApplication.OpenCurrentDatabase sADPFilename
    End If
    oApplication.Visible = false

    Dim folder
    Set folder = fso.GetFolder(sImportpath)

    ' load each file from the import path into the stub
    Dim myFile, objectname, objecttype
    for each myFile in folder.Files
        objecttype = fso.GetExtensionName(myFile.Name)
        objectname = fso.GetBaseName(myFile.Name)
        WScript.Echo "  " & objectname & " (" & objecttype & ")"

        if (objecttype = "form") then
            oApplication.LoadFromText acForm, objectname, myFile.Path
        elseif (objecttype = "bas") then
            oApplication.LoadFromText acModule, objectname, myFile.Path
        elseif (objecttype = "mac") then
            oApplication.LoadFromText acMacro, objectname, myFile.Path
        elseif (objecttype = "report") then
            oApplication.LoadFromText acReport, objectname, myFile.Path
        elseif (objecttype = "query") then
           oApplication.LoadFromText acQuery, objectname, myFile.Path
        end if

    next

    oApplication.RunCommand acCmdCompileAndSaveAllModules
    oApplication.Quit
End Function

Public Function getErr()
    Dim strError
    strError = vbCrLf & "----------------------------------------------------------------------------------------------------------------------------------------" & vbCrLf & _
               "From " & Err.source & ":" & vbCrLf & _
               "    Description: " & Err.Description & vbCrLf & _
               "    Code: " & Err.Number & vbCrLf
    getErr = strError
End Function
Daniel Hillebrand
quelle
0

Ich habe versucht, zu seiner Antwort beizutragen, indem ich eine Exportoption für Abfragen in der Zugriffsdatenbank hinzugefügt habe. (Mit reichlich Hilfe von anderen SO- Antworten )

Dim def
Set stream = fso.CreateTextFile(sExportpath & "\" & myName & ".queries.txt")
  For Each def In oApplication.CurrentDb.QueryDefs

    WScript.Echo "  Exporting Queries to Text..."
    stream.WriteLine("Name: " & def.Name)
    stream.WriteLine(def.SQL)
    stream.writeline "--------------------------"
    stream.writeline " "

  Next
stream.Close

Ich kann das nicht wieder in die 'Compose'-Funktion einarbeiten, aber das ist es nicht, was ich jetzt tun muss.

Hinweis: Ich habe außerdem jedem exportierten Dateinamen in decompose.vbs ".txt" hinzugefügt , damit die Quellcodeverwaltung mir sofort die Dateiunterschiede anzeigt.

Hoffentlich hilft das!


JBickford
quelle
0

Dieser Eintrag beschreibt einen völlig anderen Ansatz als die anderen Einträge und ist möglicherweise nicht das, wonach Sie suchen. Ich werde also nicht beleidigt sein, wenn Sie dies ignorieren. Aber zumindest ist es ein Denkanstoß.

In einigen professionellen kommerziellen Softwareentwicklungsumgebungen wird das Konfigurationsmanagement (CM) von Software-Ergebnissen normalerweise nicht innerhalb der Softwareanwendung selbst oder des Softwareprojekts selbst durchgeführt. CM wird den endgültig zu liefernden Produkten auferlegt, indem die Software in einem speziellen CM-Ordner gespeichert wird, in dem sowohl die Datei als auch ihr Ordner mit einer Versionsidentifikation gekennzeichnet sind. Mit Clearcase kann der Datenmanager beispielsweise eine Softwaredatei "einchecken", ihr einen "Zweig" zuweisen, ihr eine "Blase" zuweisen und "Beschriftungen" zuweisen. Wenn Sie eine Datei anzeigen und herunterladen möchten, müssen Sie Ihre "Konfigurationsspezifikation" so konfigurieren, dass sie auf die gewünschte Version verweist, und dann die CD in den Ordner legen und dort ist sie.

Nur eine Idee.

VolleyballAddictSandiego
quelle
0

Für alle, die mit Access 97 nicht weiterkommen, konnte ich die anderen Antworten nicht zum Laufen bringen. Mit einer Kombination aus den hervorragenden Antworten von Oliver und DaveParillo und einigen Änderungen konnte ich die Skripte mit unseren Access 97-Datenbanken zum Laufen bringen. Es ist auch etwas benutzerfreundlicher, da gefragt wird, in welchem ​​Ordner die Dateien abgelegt werden sollen.

AccessExport.vbs:

' Converts all modules, classes, forms and macros from an Access file (.mdb) <input file> to
' text and saves the results in separate files to <path>.  Requires Microsoft Access.
Option Explicit

Const acQuery = 1
Const acForm = 2
Const acModule = 5
Const acMacro = 4
Const acReport = 3
Const acCmdCompactDatabase = 4
Const TemporaryFolder = 2

Dim strMDBFileName : strMDBFileName = SelectDatabaseFile
Dim strExportPath : strExportPath = SelectExportFolder
CreateExportFolders(strExportPath)
Dim objProgressWindow
Dim strOverallProgress
CreateProgressWindow objProgressWindow
Dim strTempMDBFileName
CopyToTempDatabase strMDBFileName, strTempMDBFileName, strOverallProgress
Dim objAccess
Dim objDatabase
OpenAccessDatabase objAccess, objDatabase, strTempMDBFileName, strOverallProgress
ExportQueries objAccess, objDatabase, objProgressWindow, strExportPath, strOverallProgress
ExportForms objAccess, objDatabase, objProgressWindow, strExportPath, strOverallProgress
ExportReports objAccess, objDatabase, objProgressWindow, strExportPath, strOverallProgress
ExportMacros objAccess, objDatabase, objProgressWindow, strExportPath, strOverallProgress
ExportModules objAccess, objDatabase, objProgressWindow, strExportPath, strOverallProgress
objAccess.CloseCurrentDatabase
objAccess.Quit
DeleteTempDatabase strTempMDBFileName, strOverallProgress
objProgressWindow.Quit
MsgBox "Successfully exported database."

Private Function SelectDatabaseFile()
    MsgBox "Please select the Access database to export."
    Dim objFileOpen : Set objFileOpen = CreateObject("SAFRCFileDlg.FileOpen")
    If objFileOpen.OpenFileOpenDlg Then
        SelectDatabaseFile = objFileOpen.FileName
    Else
        WScript.Quit()
    End If
End Function

Private Function SelectExportFolder()
    Dim objShell : Set objShell = CreateObject("Shell.Application")
    SelectExportFolder = objShell.BrowseForFolder(0, "Select folder to export the database to:", 0, "").self.path & "\"
End Function

Private Sub CreateExportFolders(strExportPath)
    Dim objFileSystem : Set objFileSystem = CreateObject("Scripting.FileSystemObject")
    MsgBox "Existing folders from a previous Access export under " & strExportPath & " will be deleted!"
    If objFileSystem.FolderExists(strExportPath & "Queries\") Then
        objFileSystem.DeleteFolder strExportPath & "Queries", true
    End If
    objFileSystem.CreateFolder(strExportPath & "Queries\")
    If objFileSystem.FolderExists(strExportPath & "Forms\") Then
        objFileSystem.DeleteFolder strExportPath & "Forms", true
    End If
    objFileSystem.CreateFolder(strExportPath & "Forms\")
    If objFileSystem.FolderExists(strExportPath & "Reports\") Then
        objFileSystem.DeleteFolder strExportPath & "Reports", true
    End If
    objFileSystem.CreateFolder(strExportPath & "Reports\")
    If objFileSystem.FolderExists(strExportPath & "Macros\") Then
        objFileSystem.DeleteFolder strExportPath & "Macros", true
    End If
    objFileSystem.CreateFolder(strExportPath & "Macros\")
    If objFileSystem.FolderExists(strExportPath & "Modules\") Then
        objFileSystem.DeleteFolder strExportPath & "Modules", true
    End If
    objFileSystem.CreateFolder(strExportPath & "Modules\")
End Sub

Private Sub CreateProgressWindow(objProgressWindow)
    Set objProgressWindow = CreateObject ("InternetExplorer.Application")
    objProgressWindow.Navigate "about:blank"
    objProgressWindow.ToolBar = 0
    objProgressWindow.StatusBar = 0
    objProgressWindow.Width = 320
    objProgressWindow.Height = 240
    objProgressWindow.Visible = 1
    objProgressWindow.Document.Title = "Access export in progress"
End Sub

Private Sub CopyToTempDatabase(strMDBFileName, strTempMDBFileName, strOverallProgress)
    strOverallProgress = strOverallProgress & "Copying to temporary database...<br/>"
    Dim objFileSystem : Set objFileSystem = CreateObject("Scripting.FileSystemObject")
    strTempMDBFileName = objFileSystem.GetSpecialFolder(TemporaryFolder) & "\" & objFileSystem.GetBaseName(strMDBFileName) & "_temp.mdb"
    objFileSystem.CopyFile strMDBFileName, strTempMDBFileName
End Sub

Private Sub OpenAccessDatabase(objAccess, objDatabase, strTempMDBFileName, strOverallProgress)
    strOverallProgress = strOverallProgress & "Compacting temporary database...<br/>"
    Set objAccess = CreateObject("Access.Application")
    objAccess.Visible = false
    CompactAccessDatabase objAccess, strTempMDBFileName
    strOverallProgress = strOverallProgress & "Opening temporary database...<br/>"
    objAccess.OpenCurrentDatabase strTempMDBFileName
    Set objDatabase = objAccess.CurrentDb
End Sub

' Sometimes the Compact Database command errors out, and it's not serious if the database isn't compacted first.
Private Sub CompactAccessDatabase(objAccess, strTempMDBFileName)
    On Error Resume Next
    Dim objFileSystem : Set objFileSystem = CreateObject("Scripting.FileSystemObject")
    objAccess.DbEngine.CompactDatabase strTempMDBFileName, strTempMDBFileName & "_"
    objFileSystem.CopyFile strTempMDBFileName & "_", strTempMDBFileName
    objFileSystem.DeleteFile strTempMDBFileName & "_"
End Sub

Private Sub ExportQueries(objAccess, objDatabase, objProgressWindow, strExportPath, strOverallProgress)
    strOverallProgress = strOverallProgress & "Exporting Queries (Step 1 of 5)...<br/>"
    Dim counter
    For counter = 0 To objDatabase.QueryDefs.Count - 1
        objProgressWindow.Document.Body.InnerHTML = strOverallProgress & counter + 1 & " of " & objDatabase.QueryDefs.Count
        objAccess.SaveAsText acQuery, objDatabase.QueryDefs(counter).Name, strExportPath & "Queries\" & Clean(objDatabase.QueryDefs(counter).Name) & ".sql"
    Next
End Sub

Private Sub ExportForms(objAccess, objDatabase, objProgressWindow, strExportPath, strOverallProgress)
    strOverallProgress = strOverallProgress & "Exporting Forms (Step 2 of 5)...<br/>"
    Dim counter : counter = 1
    Dim objContainer : Set objContainer = objDatabase.Containers("Forms")
    Dim objDocument
    For Each objDocument In objContainer.Documents
        objProgressWindow.Document.Body.InnerHTML = strOverallProgress & counter & " of " & objContainer.Documents.Count
        counter = counter + 1
        objAccess.SaveAsText acForm, objDocument.Name, strExportPath & "Forms\" & Clean(objDocument.Name) & ".form"
        objAccess.DoCmd.Close acForm, objDocument.Name
    Next
End Sub

Private Sub ExportReports(objAccess, objDatabase, objProgressWindow, strExportPath, strOverallProgress)
    strOverallProgress = strOverallProgress & "Exporting Reports (Step 3 of 5)...<br/>"
    Dim counter : counter = 1
    Dim objContainer : Set objContainer = objDatabase.Containers("Reports")
    Dim objDocument
    For Each objDocument In objContainer.Documents
        objProgressWindow.Document.Body.InnerHTML = strOverallProgress & counter & " of " & objContainer.Documents.Count
        counter = counter + 1
        objAccess.SaveAsText acReport, objDocument.Name, strExportPath & "Reports\" & Clean(objDocument.Name) & ".report"
    Next
End Sub

Private Sub ExportMacros(objAccess, objDatabase, objProgressWindow, strExportPath, strOverallProgress)
    strOverallProgress = strOverallProgress & "Exporting Macros (Step 4 of 5)...<br/>"
    Dim counter : counter = 1
    Dim objContainer : Set objContainer = objDatabase.Containers("Scripts")
    Dim objDocument
    For Each objDocument In objContainer.Documents
        objProgressWindow.Document.Body.InnerHTML = strOverallProgress & counter & " of " & objContainer.Documents.Count
        counter = counter + 1
        objAccess.SaveAsText acMacro, objDocument.Name, strExportPath & "Macros\" & Clean(objDocument.Name) & ".macro"
    Next
End Sub

Private Sub ExportModules(objAccess, objDatabase, objProgressWindow, strExportPath, strOverallProgress)
    strOverallProgress = strOverallProgress & "Exporting Modules (Step 5 of 5)...<br/>"
    Dim counter : counter = 1
    Dim objContainer : Set objContainer = objDatabase.Containers("Modules")
    Dim objDocument
    For Each objDocument In objContainer.Documents
        objProgressWindow.Document.Body.InnerHTML = strOverallProgress & counter & " of " & objContainer.Documents.Count
        counter = counter + 1
        objAccess.SaveAsText acModule, objDocument.Name, strExportPath & "Modules\" & Clean(objDocument.Name) & ".module"
    Next
End Sub

Private Sub DeleteTempDatabase(strTempMDBFileName, strOverallProgress)
    On Error Resume Next
    strOverallProgress = strOverallProgress & "Deleting temporary database...<br/>"
    Dim objFileSystem : Set objFileSystem = CreateObject("Scripting.FileSystemObject")
    objFileSystem.DeleteFile strTempMDBFileName, true
End Sub

' Windows doesn't like certain characters, so we have to filter those out of the name when exporting
Private Function Clean(strInput)
    Dim objRegexp : Set objRegexp = New RegExp
    objRegexp.IgnoreCase = True
    objRegexp.Global = True
    objRegexp.Pattern = "[\\/:*?""<>|]"
    Dim strOutput
    If objRegexp.Test(strInput) Then
        strOutput = objRegexp.Replace(strInput, "")
        MsgBox strInput & " is being exported as " & strOutput
    Else
        strOutput = strInput
    End If
    Clean = strOutput
End Function

Wenn Sie zum Importieren von Dateien in die Datenbank die Datenbank von Grund auf neu erstellen müssen oder aus irgendeinem Grund Dateien außerhalb von Access ändern möchten.

AccessImport.vbs:

' Imports all of the queries, forms, reports, macros, and modules from text
' files to an Access file (.mdb).  Requires Microsoft Access.
Option Explicit

const acQuery = 1
const acForm = 2
const acModule = 5
const acMacro = 4
const acReport = 3
const acCmdCompileAndSaveAllModules = &H7E

Dim strMDBFilename : strMDBFilename = SelectDatabaseFile
CreateBackup strMDBFilename
Dim strImportPath : strImportPath = SelectImportFolder
Dim objAccess
Dim objDatabase
OpenAccessDatabase objAccess, objDatabase, strMDBFilename
Dim objProgressWindow
Dim strOverallProgress
CreateProgressWindow objProgressWindow
ImportQueries objAccess, objDatabase, objProgressWindow, strImportPath, strOverallProgress
ImportForms objAccess, objDatabase, objProgressWindow, strImportPath, strOverallProgress
ImportReports objAccess, objDatabase, objProgressWindow, strImportPath, strOverallProgress
ImportMacros objAccess, objDatabase, objProgressWindow, strImportPath, strOverallProgress
ImportModules objAccess, objDatabase, objProgressWindow, strImportPath, strOverallProgress
objAccess.CloseCurrentDatabase
objAccess.Quit
objProgressWindow.Quit
MsgBox "Successfully imported objects into the database."

Private Function SelectDatabaseFile()
    MsgBox "Please select the Access database to import the objects from.  ALL EXISTING OBJECTS WITH THE SAME NAME WILL BE OVERWRITTEN!"
    Dim objFileOpen : Set objFileOpen = CreateObject( "SAFRCFileDlg.FileOpen" )
    If objFileOpen.OpenFileOpenDlg Then
        SelectDatabaseFile = objFileOpen.FileName
    Else
        WScript.Quit()
    End If
End Function

Private Function SelectImportFolder()
    Dim objShell : Set objShell = WScript.CreateObject("Shell.Application")
    SelectImportFolder = objShell.BrowseForFolder(0, "Select folder to import the database objects from:", 0, "").self.path & "\"
End Function

Private Sub CreateBackup(strMDBFilename)
    Dim objFileSystem : Set objFileSystem = CreateObject("Scripting.FileSystemObject")
    objFileSystem.CopyFile strMDBFilename, strMDBFilename & ".bak"
End Sub

Private Sub OpenAccessDatabase(objAccess, objDatabase, strMDBFileName)
    Set objAccess = CreateObject("Access.Application")
    objAccess.OpenCurrentDatabase strMDBFilename
    objAccess.Visible = false
    Set objDatabase = objAccess.CurrentDb
End Sub

Private Sub CreateProgressWindow(ByRef objProgressWindow)
    Set objProgressWindow = CreateObject ("InternetExplorer.Application")
    objProgressWindow.Navigate "about:blank"
    objProgressWindow.ToolBar = 0
    objProgressWindow.StatusBar = 0
    objProgressWindow.Width = 320
    objProgressWindow.Height = 240
    objProgressWindow.Visible = 1
    objProgressWindow.Document.Title = "Access import in progress"
End Sub

Private Sub ImportQueries(objAccess, objDatabase, objProgressWindow, strImportPath, strOverallProgress)
    strOverallProgress = "Importing Queries (Step 1 of 5)...<br/>"
    Dim counter : counter = 0
    Dim folder : Set folder = objFileSystem.GetFolder(strImportPath & "Queries\")
    Dim objFileSystem : Set objFileSystem = CreateObject("Scripting.FileSystemObject")
    Dim file
    Dim strQueryName
    For Each file in folder.Files
        objProgressWindow.Document.Body.InnerHTML = strOverallProgress & counter + 1 & " of " & folder.Files.Count
        strQueryName = objFileSystem.GetBaseName(file.Name)
        objAccess.LoadFromText acQuery, strQueryName, file.Path
        counter = counter + 1
    Next
End Sub

Private Sub ImportForms(objAccess, objDatabase, objProgressWindow, strImportPath, strOverallProgress)
    strOverallProgress = strOverallProgress & "Importing Forms (Step 2 of 5)...<br/>"
    Dim counter : counter = 0
    Dim folder : Set folder = objFileSystem.GetFolder(strImportPath & "Forms\")
    Dim objFileSystem : Set objFileSystem = CreateObject("Scripting.FileSystemObject")
    Dim file
    Dim strFormName
    For Each file in folder.Files
        objProgressWindow.Document.Body.InnerHTML = strOverallProgress & counter + 1 & " of " & folder.Files.Count
        strFormName = objFileSystem.GetBaseName(file.Name)
        objAccess.LoadFromText acForm, strFormName, file.Path
        counter = counter + 1
    Next
End Sub

Private Sub ImportReports(objAccess, objDatabase, objProgressWindow, strImportPath, strOverallProgress)
    strOverallProgress = strOverallProgress & "Importing Reports (Step 3 of 5)...<br/>"
    Dim counter : counter = 0
    Dim folder : Set folder = objFileSystem.GetFolder(strImportPath & "Reports\")
    Dim objFileSystem : Set objFileSystem = CreateObject("Scripting.FileSystemObject")
    Dim file
    Dim strReportName
    For Each file in folder.Files
        objProgressWindow.Document.Body.InnerHTML = strOverallProgress & counter + 1 & " of " & folder.Files.Count
        strReportName = objFileSystem.GetBaseName(file.Name)
        objAccess.LoadFromText acReport, strReportName, file.Path
        counter = counter + 1
    Next
End Sub

Private Sub ImportMacros(objAccess, objDatabase, objProgressWindow, strImportPath, strOverallProgress)
    strOverallProgress = strOverallProgress & "Importing Macros (Step 4 of 5)...<br/>"
    Dim counter : counter = 0
    Dim folder : Set folder = objFileSystem.GetFolder(strImportPath & "Macros\")
    Dim objFileSystem : Set objFileSystem = CreateObject("Scripting.FileSystemObject")
    Dim file
    Dim strMacroName
    For Each file in folder.Files
        objProgressWindow.Document.Body.InnerHTML = strOverallProgress & counter + 1 & " of " & folder.Files.Count
        strMacroName = objFileSystem.GetBaseName(file.Name)
        objAccess.LoadFromText acMacro, strMacroName, file.Path
        counter = counter + 1
    Next
End Sub

Private Sub ImportModules(objAccess, objDatabase, objProgressWindow, strImportPath, strOverallProgress)
    strOverallProgress = strOverallProgress & "Importing Modules (Step 5 of 5)...<br/>"
    Dim counter : counter = 0
    Dim folder : Set folder = objFileSystem.GetFolder(strImportPath & "Modules\")
    Dim objFileSystem : Set objFileSystem = CreateObject("Scripting.FileSystemObject")
    Dim file
    Dim strModuleName
    For Each file in folder.Files
        objProgressWindow.Document.Body.InnerHTML = strOverallProgress & counter + 1 & " of " & folder.Files.Count
        strModuleName = objFileSystem.GetBaseName(file.Name)
        objAccess.LoadFromText acModule, strModuleName, file.Path
        counter = counter + 1
    Next

    ' We need to compile the database whenever any module code changes.
    If Not objAccess.IsCompiled Then
        objAccess.RunCommand acCmdCompileAndSaveAllModules
    End If
End Sub
CTristan
quelle