Làm thế nào để bạn sử dụng kiểm soát phiên bản với phát triển Access?


163

Tôi tham gia cập nhật giải pháp Access. Nó có một lượng VBA tốt, một số truy vấn, một lượng nhỏ các bảng và một vài biểu mẫu để nhập dữ liệu & tạo báo cáo. Đó là một ứng cử viên lý tưởng cho Access.

Tôi muốn thay đổi thiết kế bảng, VBA, truy vấn và biểu mẫu. Làm cách nào tôi có thể theo dõi các thay đổi của mình với kiểm soát phiên bản? (chúng tôi sử dụng Subversion, nhưng điều này phù hợp với bất kỳ hương vị nào) Tôi có thể dính toàn bộ mdb trong lật đổ, nhưng điều đó sẽ lưu trữ một tệp nhị phân và tôi sẽ không thể nói rằng tôi chỉ thay đổi một dòng mã VBA.

Tôi đã nghĩ về việc sao chép mã VBA vào các tệp riêng biệt và lưu chúng, nhưng tôi có thể thấy chúng nhanh chóng không đồng bộ với những gì trong cơ sở dữ liệu.


1
Crossposting giải pháp này cho câu hỏi liên quan về xuất khẩu lược đồ db truy cập.
Eric G

1
Access hỗ trợ giao diện SCC, do đó, mọi phiên bản điều khiển tương thích với giao diện này đều sẵn sàng cho Access. Tuyên bố miễn trừ trách nhiệm: Tôi làm việc cho plasticcm.com và chúng tôi đã có một số khách hàng sử dụng nó với Access.
pablo

Câu trả lời:


180

Chúng tôi đã viết tập lệnh riêng của mình bằng VBScript, sử dụng Application.SaveAsText () trong Access để xuất tất cả các mô-đun mã, biểu mẫu, macro và báo cáo. Đây là nó, nó sẽ cung cấp cho bạn một số gợi ý. (Coi chừng: một số tin nhắn bằng tiếng Đức, nhưng bạn có thể dễ dàng thay đổi điều đó.)

EDIT: Để tóm tắt các ý kiến ​​khác nhau dưới đây: Dự án của chúng tôi giả định một tập tin .adp. Để có được công việc này với .mdb / .accdb, bạn phải thay đổi OpenAccessProject () thành OpenCienDatabase (). (Được cập nhật để sử dụng OpenAccessProject()nếu thấy phần mở rộng .adp, sử dụng khác OpenCurrentDatabase().)

phân hủy.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

Nếu bạn cần một Lệnh có thể nhấp, thay vì sử dụng dòng lệnh, hãy tạo một tệp có tên "decompose.cmd" bằng

cscript decompose.vbs youraccessapplication.adp

Theo mặc định, tất cả các tệp được xuất sẽ đi vào thư mục con "Tập lệnh" của ứng dụng Access của bạn. Tệp .adp / mdb cũng được sao chép vào vị trí này (với hậu tố "còn sơ khai") và tước bỏ tất cả các mô-đun đã xuất, làm cho nó thực sự nhỏ.

Bạn PHẢI kiểm tra sơ khai này với các tệp nguồn, bởi vì hầu hết các cài đặt truy cập và thanh menu tùy chỉnh không thể được xuất theo bất kỳ cách nào khác. Chỉ cần đảm bảo cam kết thay đổi tệp này, nếu bạn thực sự thay đổi một số cài đặt hoặc menu.

Lưu ý: Nếu bạn có bất kỳ Autoexec-Makros nào được xác định trong Ứng dụng của mình, bạn có thể phải giữ phím Shift khi bạn gọi phép phân tách để ngăn không cho nó thực thi và can thiệp vào việc xuất!

Tất nhiên, cũng có kịch bản ngược, để xây dựng Ứng dụng từ "Nguồn" -Directory:

sáng tác.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

Một lần nữa, điều này đi kèm với một "compose.cmd" đồng hành có chứa:

cscript compose.vbs youraccessapplication.adp

Nó yêu cầu bạn xác nhận ghi đè ứng dụng hiện tại của bạn và trước tiên tạo bản sao lưu, nếu bạn làm như vậy. Sau đó, nó thu thập tất cả các tệp nguồn trong Thư mục nguồn và chèn lại chúng vào gốc.

Chúc vui vẻ!


1
Tôi yêu mã này. Tôi thấy rằng oApplication.OpenAccessProject sẽ không hoạt động trên tệp .accdb (hoặc có thể đó là điều Access 2007) và thay vào đó tôi phải sử dụng oApplication.OpenCienDatabase.
hughdbrown

1
Tôi đang làm một cái gì đó tương tự (SaveAsText, nhưng trong VBA và với tệp MDB thay vì ADP), nhưng tôi còn một vấn đề lớn: sau mỗi lần xuất, Subversion nhận ra khoảng 100 tệp được thay đổi (ngay cả khi tôi chỉ thay đổi một hoặc hai ). Khi tôi nhìn vào các thay đổi, tôi thấy rằng một số tên biến hoặc tên điều khiển đã thay đổi chính tả chữ hoa / chữ thường. Ví dụ: mọi tệp đã từng chứa "OrderNumber" hiện chứa "Ordernumber" trong bản xuất và do đó được đánh dấu là "đã thay đổi" (ít nhất là bởi SVN, chưa thử SCM khác). Bất cứ ý tưởng làm thế nào tôi có thể tránh điều này? Cảm ơn rất nhiều!
Christian Specht

3
Vâng, đây là một phiền toái liên tục trong dự án của chúng tôi cũng có. Theo như chúng tôi đã xác định, vấn đề là các biến trong dự án của bạn có cùng tên với các điều khiển, chỉ trong các trường hợp khác nhau (tăng / thấp). Bây giờ, tùy thuộc vào thứ tự của các mô-đun được soạn thảo, Access dường như mất một lỗi chính tả và "sửa lỗi" cho tất cả các mô-đun khác, vì VBA được coi là không phân biệt chữ hoa chữ thường. Access thực hiện điều này, mặc dù các điều khiển nằm trên các hình thức khác nhau! Vấn đề trở nên lớn hơn nếu bạn thậm chí có nhiều điều khiển cùng tên trong các trường hợp khác nhau trên các hình thức khác nhau.
Oliver

3
Giải pháp duy nhất là tìm kiếm từng Biến / Tên điều khiển và thay đổi chính tả thành một dạng phổ biến. Sau khi xuất và cam kết thay đổi, tên sẽ ổn định. Tiền tố các tên điều khiển với các kiểu của chúng khá nhiều đảm bảo thông qua quy ước đặt tên rằng các tên không xung đột với các biến. (ví dụ: txtTitle cho hộp văn bản chứa trường Tiêu đề hoặc cmbUsers cho hộp tổ hợp, v.v.)
Oliver

Quên thêm rằng để có được công việc này với mdb, tôi đã phải thay đổi OpenAccessProject thành OpenCienDatabase .
DaveParillo

19

Nó dường như là một cái gì đó khá khả dụng trong Access:

Liên kết này từ msdn giải thích cách cài đặt bổ trợ kiểm soát nguồn cho Microsoft Access. Điều này được vận chuyển dưới dạng tải xuống miễn phí như một phần của Tiện ích mở rộng dành cho nhà phát triển truy cập cho Access 2007 và dưới dạng bổ trợ miễn phí riêng cho Access 2003.

Tôi rất vui vì bạn đã hỏi câu hỏi này và tôi đã dành thời gian để tìm kiếm nó, vì tôi cũng muốn khả năng này. Liên kết ở trên có thêm thông tin về điều này và liên kết đến các bổ trợ.

Cập nhật:
Tôi đã cài đặt bổ trợ cho Access 2003. Nó sẽ chỉ hoạt động với VSS, nhưng nó cho phép tôi đặt các đối tượng Access (biểu mẫu, truy vấn, bảng, mô-đun, ect) vào kho lưu trữ. Khi bạn đi chỉnh sửa bất kỳ mục nào trong repo, bạn được yêu cầu kiểm tra, nhưng bạn không phải làm thế. Tiếp theo tôi sẽ kiểm tra cách nó xử lý được mở và thay đổi trên một hệ thống mà không cần bổ trợ. Tôi không phải là một fan hâm mộ của VSS, nhưng tôi thực sự thích ý tưởng lưu trữ các đối tượng truy cập trong một repo.

Update2: Các
máy không có bổ trợ không thể thực hiện bất kỳ thay đổi nào đối với cấu trúc cơ sở dữ liệu (thêm trường bảng, tham số truy vấn, v.v.). Lúc đầu, tôi nghĩ đây có thể là một vấn đề nếu ai đó cần, vì không có cách nào rõ ràng để xóa cơ sở dữ liệu Access khỏi kiểm soát nguồn nếu Access không tải bổ trợ.

Id phát hiện ra rằng việc chạy cơ sở dữ liệu "nhỏ gọn và sửa chữa" sẽ nhắc bạn nếu bạn muốn xóa cơ sở dữ liệu khỏi kiểm soát nguồn. Tôi đã chọn có và có thể chỉnh sửa cơ sở dữ liệu mà không cần bổ trợ. Bài viết trong liên kết ở trên cũng đưa ra hướng dẫn trong việc thiết lập Access 2003 và 2007 để sử dụng Hệ thống nhóm. Nếu bạn có thể tìm thấy một nhà cung cấp MSSCCI cho SVN, rất có thể bạn có thể khiến điều đó hoạt động.


Lưu ý rằng chúng tôi có khá nhiều vấn đề với việc không thể kiểm tra ADP từ VSS nếu có nhiều người đã chỉnh sửa nó. Chúng tôi đã kết thúc việc phải có một bản sao lưu riêng cho việc này!
Simon

Tôi đã chơi theo cách tiếp cận này (sử dụng Vault, vì tôi biết không có nhà cung cấp MSSCCI miễn phí nào cho SVN ... TortoiseSVNSCC không rõ ràng và không hoạt động đối với tôi, và hai hoặc ba tùy chọn khác là thương mại). Nó hoạt động, nhưng nó buộc bạn phải sử dụng phương pháp khóa độc quyền cổ xưa để kiểm soát nguồn và vì lý do đó, tôi dự định từ bỏ nó và sử dụng giải pháp của @ Oliver.
Todd Owen

14

Giải pháp soạn thảo / phân hủy được đăng bởi Oliver rất tuyệt, nhưng nó có một số vấn đề:

  • Các tệp được mã hóa dưới dạng UCS-2 (UTF-16) có thể khiến các hệ thống / công cụ kiểm soát phiên bản coi các tệp là nhị phân.
  • Các tập tin chứa rất nhiều hành trình thay đổi thường xuyên - tổng kiểm tra, thông tin máy in và nhiều hơn nữa. Đây là một vấn đề nghiêm trọng nếu bạn muốn làm sạch khác biệt hoặc cần hợp tác trong dự án.

Tôi đã lên kế hoạch tự khắc phục sự cố này, nhưng phát hiện đã có sẵn một giải pháp tốt: tích hợp timabell / msaccess-vcs trên GitHub. Tôi đã thử nghiệm tích hợp msaccess-vcs và nó hoạt động rất tốt.

Cập nhật ngày 3 tháng 3 năm 2015 : Dự án ban đầu được duy trì / sở hữu bởi bkidwell trên Github, nhưng nó đã được chuyển sang timabell - liên kết ở trên để dự án được cập nhật tương ứng. Có một số nhánh từ dự án ban đầu của bkidwell, ví dụ như ArminBramatonb , mà AFAICT không nên được sử dụng.

Nhược điểm của việc sử dụng tích hợp msaccess-vcs so với giải pháp phân hủy của Olivers:

  • Nó chậm hơn đáng kể. Tôi chắc chắn rằng vấn đề tốc độ có thể được khắc phục, nhưng tôi không cần phải xuất dự án của mình sang văn bản thường xuyên ...
  • Nó không tạo ra một dự án Access còn sơ khai với những thứ đã xuất. Điều này cũng có thể được sửa chữa (bằng cách áp dụng mã từ tập lệnh phân tách), nhưng một lần nữa - không quan trọng.

Dù sao, khuyến nghị rõ ràng của tôi là tích hợp msaccess-vcs. Nó đã giải quyết tất cả các vấn đề tôi gặp phải khi sử dụng Git trên các tệp được xuất.


Có vẻ như ngã ba ArminBra đang ở phía trước (hình từ việc nhìn vào biểu đồ mạng ). Matonb đã không trả lời yêu cầu kéo duy nhất nên tôi đoán ít nhất họ đã từ bỏ nó.
Tim Abell

1
Và bây giờ cũng có ngã ba github.com/timabell/msaccess-vcs-integration của tôi - sửa lỗi phá vỡ bảng xuất tổng hợp. Hai cái còn lại trông hơi bị bỏ rơi, vì vậy tôi rất vui khi nhận các yêu cầu báo cáo lỗi, v.v. trên ngã ba của nó.
Tim Abell

Tôi sẽ lịch sự đề nghị chỉnh sửa câu trả lời này để chỉ vào ngã ba của tôi vì bây giờ đó là phiên bản được duy trì tích cực nhất.
Tim Abell

2
@TimAbell: Tôi đã cập nhật câu trả lời của mình để phản ánh thực tế rằng dự án đã được chuyển cho bạn. Tái bút Tôi hy vọng chúng ta có thể nhận được một số phiếu bầu vì tôi nghĩ đây là giải pháp tốt nhất.
hansfn 3/03/2015

2
một điều tuyệt vời, điều hướng các nhánh của một dự án github dường như là vấn đề mới nhất mà chúng tôi tự phát minh ra :-)
Tim Abell

14

Olivers trả lời đá, nhưng CurrentProjecttài liệu tham khảo không làm việc cho tôi. Cuối cùng tôi đã xé ruột ra giữa xuất khẩu của anh ấy và thay thế nó bằng cái này, dựa trên một giải pháp tương tự của Arvin Meyer . Có lợi thế xuất khẩu Truy vấn nếu bạn đang sử dụng mdb thay vì adp.

' 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

1
+1 để bao gồm các truy vấn. Bây giờ chỉ cần bao gồm các lược đồ bảng.
Marc Stober

Câu trả lời được phê duyệt không hoạt động đối với Access 97, nhưng câu trả lời này đã giúp tôi sửa đổi nó cho mục đích sử dụng của riêng tôi. Cảm ơn vì đã đăng tải điều này!
CTristan

2
Tôi đặc biệt khuyến khích đặt lưu truy vấn trước khi lưu biểu mẫu để thay đổi thứ tự xóa sau này. Tôi đã gặp một số rắc rối với DeleteObject trong câu lệnh For Each cuối cùng khi tôi cố xóa các truy vấn đã bị xóa tự động khi các biểu mẫu tương ứng của chúng đã bị xóa trước đó. Ngoài ra, nếu bạn có một số biểu mẫu mở khi khởi động và không muốn giữ F11 (hoặc đã hủy kích hoạt), chỉ cần chèn oApp.DoCmd.C Đóng acForm, "formName" sau khi bạn chạy throug cnt.Document
Anton Kaiser

@Cunso Xin vui lòng bạn có thể đăng mã của mình tương thích với Access 97. Vì vậy, tôi không cần phải phát triển lại.
Lorenz Meyer

Làm thế nào để tôi sử dụng này? Gọi nó từ một phụ?
kevinykuo

11

Chúng tôi đã phát triển công cụ nội bộ của riêng mình, trong đó:

  1. Các mô-đun: được xuất dưới dạng tệp txt và sau đó được so sánh với "công cụ so sánh tệp" (phần mềm miễn phí)
  2. Biểu mẫu: được xuất qua lệnh application.saveAsText. Sau đó có thể thấy sự khác biệt giữa 2 phiên bản khác nhau ("công cụ so sánh tệp" một lần nữa).
  3. Macro: chúng tôi không có bất kỳ macro nào để so sánh, vì chúng tôi chỉ có macro "autoexec" với một dòng khởi chạy thủ tục VBA chính
  4. Truy vấn: chỉ là các chuỗi văn bản được lưu trữ trong một bảng: xem infra
  5. bảng: chúng tôi đã viết so sánh bảng riêng của chúng tôi, liệt kê sự khác biệt trong hồ sơ VÀ cấu trúc bảng.

Toàn bộ hệ thống đủ thông minh để cho phép chúng tôi tạo các phiên bản "thời gian chạy" của ứng dụng Access, được tạo tự động từ các tệp txt (mô-đun và biểu mẫu được tạo lại bằng lệnh application.loadFromText) và tệp mdb (bảng).

Nghe có vẻ lạ nhưng nó hoạt động.


8
Rất thích nhìn thấy công cụ này nguồn mở!
Todd Owen

Sẽ là một ý tưởng tốt để tải lên các tệp văn bản đã xuất này trên GitHub?
Santosh

9

Dựa trên ý tưởng của bài đăng này và các mục tương tự trong một số blog tôi đã viết một ứng dụng hoạt động với định dạng tệp mdb và adp. Nó nhập / xuất tất cả các đối tượng cơ sở dữ liệu (bao gồm bảng, tham chiếu, quan hệ và thuộc tính cơ sở dữ liệu) sang tệp văn bản thuần túy. Với những tệp đó, bạn có thể làm việc với bất kỳ điều khiển phiên bản nguồn nào. Phiên bản tiếp theo sẽ cho phép nhập lại các tệp văn bản đơn giản vào cơ sở dữ liệu. Cũng sẽ có một công cụ dòng lệnh

Bạn có thể tải xuống ứng dụng hoặc mã nguồn từ: http://accesssvn.codeplex.com/

Trân trọng


Chúng tôi đã sử dụng điều này gần hai năm nay và nó thật tuyệt. Cảm ơn bạn!
mcfea

5

Phục hồi một chủ đề cũ nhưng đây là một chủ đề tốt. Tôi đã triển khai hai tập lệnh (compose.vbs / decompose.vbs) cho dự án của riêng tôi và gặp sự cố với các tệp .mdb cũ:

Nó dừng lại khi nó đến một biểu mẫu bao gồm mã:

NoSaveCTIWhenDisabled =1

Access nói rằng nó có một vấn đề và đó là kết thúc của câu chuyện. Tôi đã chạy một số bài kiểm tra và chơi xung quanh để cố gắng khắc phục vấn đề này và tìm thấy chủ đề này với một công việc ở cuối:

Không thể tạo cơ sở dữ liệu

Về cơ bản (trong trường hợp luồng bị chết), bạn lấy .mdb và thực hiện "Lưu dưới dạng" sang định dạng .accdb mới. Sau đó, nguồn an toàn hoặc công cụ soạn thảo / phân hủy sẽ hoạt động. Tôi cũng đã phải chơi khoảng 10 phút để có được cú pháp dòng lệnh đúng để (de) soạn thảo các tập lệnh hoạt động đúng, vì vậy đây cũng là thông tin:

Để soạn thảo (giả sử nội dung của bạn nằm trong C: \ SControl (tạo thư mục con có tên Nguồn để lưu trữ các tệp được giải nén):

'(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\

Đó là nó!

Các phiên bản của Access nơi tôi gặp phải sự cố ở trên bao gồm cơ sở dữ liệu Access 2000-2003 ".mdb" và khắc phục sự cố bằng cách lưu chúng vào các định dạng ".accdb" 2007-2010 trước khi chạy tập lệnh soạn thảo / phân tách. Sau khi chuyển đổi các kịch bản hoạt động tốt!


Bạn có thể chỉnh sửa điều này để bao gồm các phiên bản Access của bạn khi bạn gặp phải vấn đề này không?
Nathan DeWitt

Không có vấn đề gì, bạn vẫn đang tiếp cận phát triển Nathan chứ? Nếu có thành công nào tích hợp nó với kiểm soát phiên bản?
JKK

Tôi không làm tiếp cận phát triển nữa. Tôi đã có một dự án mà tôi đã sử dụng nó trên đường trở lại khi tôi đặt câu hỏi, và không bao giờ phải làm bất cứ điều gì khác với nó.
Nathan DeWitt

Thật tuyệt, tôi nghĩ rằng hầu hết các doanh nghiệp sử dụng một số loại máy chủ SQL chuyên dụng. Tình huống hiện tại tôi có một hỗn hợp gồm MS SQL Server, Oracle và một loạt các cơ sở dữ liệu Access để kéo dữ liệu từ máy chủ xuống các bảng cục bộ và xuất ra excel. Đó là một hỗn hợp khá phức tạp. Tôi nghĩ rằng tôi sẽ bắt đầu một câu hỏi mới về một số gợi ý để thiết lập một dự án mới, tôi sẽ sớm có mặt, xem mọi người có thể đề xuất gì để giảm độ phức tạp
JKK

4

Giải pháp chỉ tập tin văn bản (bao gồm các truy vấn, bảng và mối quan hệ)

Tôi đã thay đổi cặp tập lệnh của Oliver để chúng xuất / nhập các mối quan hệ, bảng và truy vấn bên cạnh các mô-đun, lớp, biểu mẫu và macro. Mọi thứ được lưu vào các tệp văn bản gốc, do đó không có tệp cơ sở dữ liệu nào được tạo để lưu trữ cùng với các tệp văn bản trong kiểm soát phiên bản.

Xuất thành tệp văn bản (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

Bạn có thể thực thi kịch bản này bằng cách gọi cscript decompose.vbs <path to file to decompose> <folder to store text files>. Trong trường hợp bạn bỏ qua tham số thứ hai, nó sẽ tạo thư mục 'Nguồn' nơi đặt cơ sở dữ liệu. Xin lưu ý rằng thư mục đích sẽ bị xóa nếu nó đã tồn tại.

Bao gồm dữ liệu trong các bảng đã xuất

Thay thế dòng 93: oApplication.ExportXML acExportTable, myObj.Name, , sExportpath & "\" & myObj.Name & ".table.txt"

với dòng oApplication.ExportXML acExportTable, myObj.Name, sExportpath & "\" & myObj.Name & ".table.txt"

Nhập vào Tạo tệp cơ sở dữ liệu (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

Bạn có thể thực thi kịch bản này bằng cách gọi cscript compose.vbs <path to file which should be created> <folder with text files>. Trong trường hợp bạn bỏ qua tham số thứ hai, nó sẽ xem xét thư mục 'Nguồn' nơi cơ sở dữ liệu sẽ được tạo.

Nhập dữ liệu từ tệp văn bản

Thay dòng 14: const acStructureOnly = 0bằng const acStructureOnly = 1. Điều này sẽ chỉ hoạt động nếu bạn đã bao gồm dữ liệu trong bảng xuất.

Những thứ không được bảo hiểm

  1. Tôi đã thử nghiệm điều này chỉ với các tệp .accdb, vì vậy với bất kỳ điều gì khác có thể có một số lỗi.
  2. Cài đặt không được xuất, tôi khuyên bạn nên tạo Macro sẽ áp dụng cài đặt khi bắt đầu cơ sở dữ liệu.
  3. Một số truy vấn không xác định đôi khi được xuất mà đi trước '~'. Tôi không biết nếu chúng cần thiết.
  4. Tên đối tượng MSAccess có thể chứa các ký tự không hợp lệ cho tên tệp - tập lệnh sẽ thất bại khi cố gắng viết chúng. Bạn có thể bình thường hóa tất cả tên tệp , nhưng sau đó bạn không thể nhập lại chúng.

Một trong những tài nguyên khác của tôi khi thực hiện kịch bản nàycâu trả lời này , điều này giúp tôi tìm ra cách xuất các mối quan hệ.


Điều này có vẻ hiệu quả, nhưng không hiểu các bảng được liên kết
Lord Darth Vader

2

Có một gotcha - VSS 6.0 chỉ có thể chấp nhận MDB bằng cách sử dụng bổ trợ theo một số đối tượng nhất định, bao gồm tất cả các bảng, truy vấn, mô-đun và biểu mẫu cục bộ. Không biết giới hạn đối tượng chính xác.

Để xây dựng ứng dụng sàn prod 10 năm tuổi của chúng tôi, rất lớn, chúng tôi buộc phải kết hợp 3 hoặc 4 MDB riêng biệt với SS thành một MDB, điều này làm phức tạp các bản dựng tự động đến mức chúng tôi không lãng phí thời gian để thực hiện.

Tôi nghĩ rằng tôi sẽ thử tập lệnh ở trên để đưa MDb này vào SVN và đơn giản hóa các bản dựng cho mọi người.


2

Đối với những người sử dụng Access 2010, SaveAsText không phải là một phương thức có thể nhìn thấy trong Intellisense nhưng nó dường như là một phương thức hợp lệ, vì tập lệnh của Arvin Meyer đã đề cập trước đó hoạt động tốt với tôi.

Thật thú vị, SaveAsAXL là phiên bản mới của năm 2010 và có cùng chữ ký với SaveAsText, mặc dù có vẻ như nó sẽ chỉ hoạt động với cơ sở dữ liệu web, yêu cầu SharePoint Server 2010.


SaveAsText cũng không hiển thị trong A2003, trừ khi bạn đã bật Hiển thị thành viên ẩn trong Trình duyệt đối tượng. Thông tin tốt về SaveAsAXL.
David-W-Fenton

2

Chúng tôi đã có cùng một vấn đề một thời gian trước đây.

Thử nghiệm đầu tiên của chúng tôi là một công cụ của bên thứ ba cung cấp proxy của SourceSafe API cho Subversion được sử dụng với MS Access và VB 6. Công cụ có thể được tìm thấy ở đây .

Vì không hài lòng với công cụ đó, chúng tôi đã chuyển sang Visual SourceSafe và VSS Acces Plugin.


2

Tôi đang sử dụng Oasis-Svn http://dev2dev.de/

Tôi chỉ có thể nói rằng nó đã cứu tôi ít nhất một lần. Mdb của tôi đã tăng lên hơn 2 GB và điều đó đã phá vỡ nó. Tôi có thể quay lại phiên bản cũ và nhập Biểu mẫu và chỉ mất một ngày làm việc.


1

Tôi đã tìm thấy công cụ này trên SourceForge: http://sourceforge.net/projects/avc/

Tôi đã không sử dụng nó, nhưng nó có thể là một khởi đầu cho bạn. Có thể có một số công cụ bên thứ 3 khác tích hợp với VSS hoặc SVN làm những gì bạn cần.

Cá nhân tôi chỉ giữ một tệp văn bản đơn giản để giữ nhật ký thay đổi. Khi tôi cam kết MDB nhị phân, tôi sử dụng các mục trong nhật ký thay đổi làm nhận xét cam kết của mình.


Có một liên kết thực sự tải nó? Tôi có bị mù không? Tôi dường như không thể tìm thấy nó.
BIBD

sourceforge.net/project/showfiles.php?group_id=115226 Không có gói tệp nào được xác định. Yay
Nathan DeWitt

1

Để hoàn thiện ...

Luôn có "Công cụ Visual Studio [NĂM] cho Hệ thống Microsoft Office" ( http://msdn.microsoft.com/en-us/vs2005/aa718673.aspx ) nhưng dường như cần VSS. Đối với tôi VSS (tự động hỏng) tệ hơn so với 347 điểm lưu của tôi trên chia sẻ mạng được sao lưu uber của tôi.


1

Tôi đang sử dụng Bổ trợ Access 2003: Kiểm soát mã nguồn . Nó hoạt động tốt. Một vấn đề là các ký tự không hợp lệ như ":".

Tôi đang kiểm tra trong và ngoài. Trên thực tế, Bổ trợ thực hiện giống như mã trên đó, nhưng có thêm công cụ hỗ trợ. Tôi có thể xem nếu một đối tượng được kiểm tra và làm mới các đối tượng.



1

Câu trả lời từ Oliver hoạt động rất tốt. Vui lòng tìm phiên bản mở rộng của tôi bên dưới để thêm hỗ trợ cho các truy vấn Access.

(vui lòng xem câu trả lời từ Oliver để biết thêm thông tin / cách sử dụng)

phân hủy.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

sáng tác.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

0

Tôi đã cố gắng giúp đóng góp vào câu trả lời của anh ấy bằng cách thêm tùy chọn xuất cho Truy vấn trong cơ sở dữ liệu truy cập. (Với sự giúp đỡ phong phú từ các câu trả lời SO khác )

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

Không thể hoạt động trở lại tính năng 'sáng tác', nhưng đó không phải là điều tôi cần làm ngay bây giờ.

Lưu ý: Tôi cũng đã thêm ".txt" vào mỗi tên tệp được xuất trong decompose.vbs để điều khiển nguồn sẽ ngay lập tức hiển thị cho tôi tệp khác.

Mong rằng sẽ giúp!



0

Mục này mô tả một cách tiếp cận hoàn toàn khác với các mục khác và có thể không phải là những gì bạn đang tìm kiếm. Vì vậy, tôi sẽ không bị xúc phạm nếu bạn bỏ qua điều này. Nhưng ít nhất nó là thức ăn cho suy nghĩ.

Trong một số môi trường phát triển phần mềm thương mại chuyên nghiệp, việc quản lý cấu hình (CM) của các phần mềm phân phối thường không được thực hiện trong chính ứng dụng phần mềm hoặc chính dự án phần mềm. CM được áp dụng cho các sản phẩm có thể phân phối cuối cùng, bằng cách lưu phần mềm vào thư mục CM đặc biệt, trong đó cả tệp và thư mục của nó được đánh dấu bằng nhận dạng phiên bản. Ví dụ: Clearcase cho phép trình quản lý dữ liệu "đăng nhập" tệp phần mềm, gán cho nó một "nhánh", gán cho nó một "bong bóng" và áp dụng "nhãn". Khi bạn muốn xem và tải xuống một tệp, bạn phải định cấu hình "spec spec" của bạn để trỏ đến phiên bản bạn muốn, sau đó cd vào thư mục và nó ở đó.

Chỉ là một ý tưởng.


0

Đối với bất kỳ ai bị mắc kẹt với Access 97, tôi không thể làm cho các câu trả lời khác hoạt động. Sử dụng kết hợp các câu trả lời xuất sắc của OliverDaveParillo và thực hiện một số sửa đổi, tôi có thể khiến các tập lệnh hoạt động với cơ sở dữ liệu Access 97 của chúng tôi. Nó cũng thân thiện hơn một chút vì nó hỏi thư mục nào sẽ đặt các tệp.

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

Và để nhập tệp vào cơ sở dữ liệu, bạn cần phải tạo lại cơ sở dữ liệu từ đầu hoặc bạn muốn sửa đổi các tệp bên ngoài Access vì một số lý do.

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.