1

我有一个只有 3 或 4 人会使用的小型 Access 应用程序,但我希望他们能够从不同的位置使用它。一次只有一个人会使用它。他们是一个非营利组织,几乎没有资金。他们没有服务器,目前在所有人之间来回共享 Excel 电子表格。我能想到的最简单的事情是将.accdb文件上传到 Dropbox 帐户并让他们从那里访问它。我知道您可以将其发布到 SharePoint,但他们只有 Office 的本地副本。做 Dropbox 的事情有什么问题吗?或者你们有没有更好的选择?

4

3 回答 3

3

我同意使用 Dropbox 文件夹作为共享位置可能起作用,前提是任何时候只有一个人打开数据库。如果不止一个人同时打开数据库,那么当 Dropbox 去同步文件时,它可能会破坏其他人的更改,或者出现同步冲突,或者可能只是变得非常混乱。

如果我要尝试使用这种方法,我当然不会依赖于告诉用户“在打开数据库之前始终检查其他人是否正在使用数据库”或“始终以独占模式打开数据库”。相反,我会使用如下 VBScript 之类的小启动器脚本来管理对数据库的访问。它使用第二个文件扩展名 (.Available.IN_USE) 来指示数据库文件的状态,制作本地(未同步)副本,在 Access 中打开该副本,然后将更新后的文件复制回 Dropbox 文件夹以便同步。

Option Explicit
Dim WshShell, fso, f, AccessPath, DropboxFolder, WorkingFolder, DatabaseName
Const TemporaryFolder = 2

DropboxFolder = "C:\Users\Gord\Dropbox\dbStorage\"
DatabaseName = "myDatabase.accdb"

Set fso = CreateObject("Scripting.FileSystemObject")
WorkingFolder = fso.GetSpecialFolder(TemporaryFolder) & "\"
If fso.FileExists(DropboxFolder & DatabaseName & ".Available") Then
    Set f = fso.GetFile(DropboxFolder & DatabaseName & ".Available")
    f.Name = DatabaseName & ".IN_USE"
    WScript.Echo "Copying database file to working folder..."
    f.Copy WorkingFolder & DatabaseName
    Set f = Nothing

    Set WshShell = CreateObject("WScript.Shell")
    AccessPath = WshShell.RegRead("HKEY_CLASSES_ROOT\Access.MDBFile\shell\Open\command\")
    AccessPath = Left(AccessPath, InStr(AccessPath, "MSACCESS.EXE") + 12)

    WScript.Echo "Launching Access..."
    WshShell.Run AccessPath & " """ & WorkingFolder & DatabaseName & """", 1, True

    WScript.Echo "Copying database file back to Dropbox folder..."
    fso.CopyFile WorkingFolder & DatabaseName, DropboxFolder & DatabaseName & ".IN_USE"
    Set f = fso.GetFile(DropboxFolder & DatabaseName & ".IN_USE")
    f.Name = DatabaseName & ".Available"
    Set f = Nothing
Else
    If fso.FileExists(DropboxFolder & DatabaseName & ".IN_USE") Then
        MsgBox "The database is currently in use. Try again later."
    Else
        MsgBox "The database could not be found."
    End If
End If
Set fso = Nothing

启动器可以由其目标为的快捷方式调用

CSCRIPT.EXE C:\wherever\launchMyDatabase.vbs
于 2013-10-12T22:16:27.687 回答
2

这是 Gord Thompsons 脚本的增强版本,它试图通知用户帮助他们做“正确的事情”。

它还处理异常行为,例如糟糕的互联网访问(它鼓励用户不要使用它!),它还处理一旦打开访问权限就被用户终止的脚本)

' This uses a second file extension (.Available or .InUse) to indicate the status of the database file,
' makes a local (not synced) copy inthe temp folder and opens that copy in Access.
' The updated file is copied back to the Dropbox folder so it can be synced.
' A backup fodler and file can be created with a date in the filename if the suer chooses to.
'
' The launcher could be invoked by a shortcut whose target is
'
' CSCRIPT.EXE C:\!AA\OpenFMFtoolDatabase.vbs

' Or to debug (it can open in VS if VS has been setup right with an external tool)
' CSCRIPT.EXE /X C:\!AA\OpenFMFtoolDatabase.vbs






' ----------------------------------------------------------------------------------------
' ----------------------------------------------------------------------------------------
' ----------------------------------------------------------------------------------------
' This file is used to open and backup the FMFtool university and Subject database
'
' It can be invoked by a shortcut whose target is  CSCRIPT.EXE C:\!AA\OpenFMFtoolDatabase.vbs
'
' See the tag #DOTHESE below for constants that need to be changed for each specific user


'Option Explicit

' ----------------------------------------------------------------------------------------
' ----------------------------------------------------------------------------------------
' ----------------------------------------------------------------------------------------
' Supporting functions
'
Function LPad(MyString, MakeStringThisLong, PadWithThisChar)

  Dim n: n = 0
  If MakeStringThisLong > Len(MyString) Then n = MakeStringThisLong - Len(MyString)
  LPad = String(n, PadWithThisChar) & MyString

End Function

Function BuildDateForFile()

    Dim TheMonth, TheDay

    TheMonth = LPad(Month(Date), 2, "0")
    TheDay = LPad(Day(Date), 2, "0")

    BuildDateForFile = DatePart("yyyy", Now) & TheMonth & TheDay & "_"

End Function


' ----------------------------------------------------------------------------------------
' ----------------------------------------------------------------------------------------
' ----------------------------------------------------------------------------------------
' Main Procedure
'
Sub OpenDatabase()

    ' -----------------------------------------------------------------
    ' -----------------------------------------------------------------
    ' USER / MACHINE SPECIFIC #DOTHESE

    Const SupportEmail = "mr@harveyfrench.co.uk"
    ' This script may prompt the user to contact support using this email address.

    Const DropboxFolder = "C:\!AA\DropBox\"
    ' A typical value is "C:\Users\Gord\Dropbox\dbStorage\"   Note that it must END WITH a backslash
    ' It is set to the name of the LOCAL folder (ie a folder on the PC running this script) which is synced with dropbox
    ' (or any internet based file sharing system like Dropbox, Onedrive, GDrive, etc)

    Const DatabaseCalled = "University and Subject Database"
    ' The name of the database file without the file extension (ie no .accdb)

    Const DatabaseExtension = ".accdb"
    ' The file extension (eg .accdb)




    ' -----------------------------------------------------------------
    ' -----------------------------------------------------------------
    ' General constants
    Const TemporaryFolder = 2
    Const TAGForINUSE = ".InUse"
    Const TAGForAVAILABLE = ".Available"
    Const TAGForOldLocalFile = ".OldFile"


    Dim WshShell, f, AccessPath, WorkingFolder, DatabaseName
    Dim FileNameWhenInUse, FileNameWhenAvailable
    Dim DropBoxInUse, DropBoxAvailable
    Dim DropboxBackupFolder, DropboxBackupFileName, DropboxDONOTBackupFileName
    Dim LocalFile, OldLocalFile
    Dim blnOpenLocalFile





    ' -----------------------------------------------------------------
    ' Use these lines when delivering the code
    Dim fso
    Set fso = CreateObject("Scripting.FileSystemObject")

    ' -----------------------------------------------------------------
    ' Use may use these lines when writing the code
    'Dim fso As Scripting.FileSystemObject
    'Set fso = New Scripting.FileSystemObject




    ' -----------------------------------------------------------------
    ' About files and folders

    DatabaseName = DatabaseCalled & DatabaseExtension

    FileNameWhenInUse = DatabaseName & TAGForINUSE
    FileNameWhenAvailable = DatabaseName & TAGForAVAILABLE

    DropBoxInUse = DropboxFolder & FileNameWhenInUse
    DropBoxAvailable = DropboxFolder & FileNameWhenAvailable

    DropboxBackupFolder = DropboxFolder & "Backups"

    WorkingFolder = fso.GetSpecialFolder(TemporaryFolder) & "\"

    ' eg often: C:\Users\Harvey\AppData\Local\Temp\

    LocalFile = WorkingFolder & DatabaseName
    OldLocalFile = LocalFile & TAGForOldLocalFile

    blnOpenLocalFile = False

    ' -----------------------------------------------------------------
    ' WARN User
    '
    If vbNo = MsgBox("This will open " & DatabaseName & vbCrLf & _
                     vbCrLf & _
                     "DO YOU HAVE ACCESS TO THE WEB?" & vbCrLf & _
                     vbCrLf & _
                     "Do not click YES unless you are sure you do as the web is needed to prevent other people from opening the above file while you have it open.  " & vbCrLf & _
                     vbCrLf & _
                     "NOTE 1: It is OK to loose web access once the file is opened - but others will not be able to use it again until you have web access (and have closed the file)." & vbCrLf & _
                     vbCrLf & _
                     "NOTE 2: If you click YES and you do not have web accesss, either you or someone else WILL LOOSE ALL changes made to the file!)", vbYesNo) Then
        Exit Sub
    End If


    ' ---------------------------------------------------------------------------------
    ' ---------------------------------------------------------------------------------
    '
    ' Main processing -
    ' The file is only opened if it is available (ie not in use by another person).
    ' It can also be opened if it is determined that the file was not copied back to the dropbox folder
    ' but was "accidentally" left in the temp folder
    ' When it is opened the file is renamed on dropbox to indicate it is unavailable
    '
    If fso.FileExists(DropBoxAvailable) Then

        Set f = fso.GetFile(DropBoxAvailable)

        ' This renames the file on dropbox to be "InUse"
        f.Name = FileNameWhenInUse

        '
        ' Allow dropbox to upload the file ASAP  (if possible, force dropbox to sync here )
        '

        WScript.Echo "Copying database file to temp folder..."
        f.Copy LocalFile
        Set f = Nothing

        blnOpenLocalFile = True

    Else

        If fso.FileExists(DropBoxInUse) Then

           If fso.FileExists(LocalFile) Then

              MsgBox "The database was found locally and will be opened " & vbCrLf & _
              vbCrLf & _
              "(it had already been previoulsy opened by you, but not written back to the dropbox folder (perhaps a process crashed)."

              blnOpenLocalFile = True

           Else

              MsgBox "The database is currently in use by someone else. Try again later."
              blnOpenLocalFile = False

           End If

        Else

            MsgBox "The database could not be found on dropbox " & vbCrLf & _
            vbCrLf & _
            "(Both " & TAGForINUSE & " and " & TAGForAVAILABLE & " versions are missing from dropbox!)."


            If fso.FileExists(LocalFile) Then
               MsgBox "A Copy of the file exists locally on your computer.  " & vbCrLf & _
               vbCrLf & _
               "(The file will be opened and written back to dropbox as usual BUT - " & vbCrLf & _
               "please email " & SupportEmail & " as this situation should not be arising!)."

               blnOpenLocalFile = True

            Else

                If fso.FileExists(OldLocalFile) Then

                   MsgBox "A backup copy of the local file exists (know as the OldLocalFile)" & vbCrLf & _
                   vbCrLf & "Email support on " & SupportEmail & vbCrLf & _
                   "to find out what to do (as this is a really wierd situation)."

                Else

                   MsgBox "A backup copy of the local file DOES NOT EXIST " & vbCrLf & _
                   vbCrLf & "Email support on " & SupportEmail & vbCrLf & _
                   "..but being honest you may be in a really bad pickle, but if you've been taking backups you'll be fine!"

                End If

                blnOpenLocalFile = False

            End If

        End If

    End If


    If blnOpenLocalFile Then


        ' ---------------------------------------------------------------------------------
        ' Take a daily backup
        '

        If Not fso.FolderExists(DropboxBackupFolder) Then
             WScript.Echo "Creating backup folder."
             fso.CreateFolder DropboxBackupFolder
        End If

        DropboxBackupFileName = DropboxBackupFolder & "\" & BuildDateForFile() & DatabaseName
        DropboxDONOTBackupFileName = DropboxBackupFileName & ".NoBackup"
        DropboxBackupFileName = DropboxBackupFileName & ".Backup"

        If Not (fso.FileExists(DropboxBackupFileName)) And Not (fso.FileExists(DropboxDONOTBackupFileName)) Then

            If vbYes = MsgBox("Do you want to take a daily backup? " & vbCrLf & _
                               vbCrLf & "(click YES if a lot of work has been done since the last backup was taken. " & vbCrLf & _
                               " If in doubt click YES)", vbYesNo) Then

                WScript.Echo "Creating daily backup file."
                fso.CopyFile LocalFile, DropboxBackupFileName

            Else
                ' Create an empty text file to flag no backup is wanted that day
                WScript.Echo "No daily backup file will be created."
                fso.CreateTextFile (DropboxDONOTBackupFileName)

            End If

        End If


        ' ---------------------------------------------------------------------------------
        ' Open the file
        '
        Set WshShell = CreateObject("WScript.Shell")
        AccessPath = WshShell.RegRead("HKEY_CLASSES_ROOT\Access.MDBFile\shell\Open\command\")
        AccessPath = Left(AccessPath, InStr(AccessPath, "MSACCESS.EXE") + 12)

        WScript.Echo "Launching Access and Opening temp database file: " & vbCrLf & LocalFile

        WshShell.Run AccessPath & " """ & LocalFile & """", 1, True

        WScript.Echo "Copying temp database file back to Dropbox folder..."
        fso.CopyFile LocalFile, DropBoxInUse

        Set f = fso.GetFile(DropBoxInUse)
        f.Name = FileNameWhenAvailable
        Set f = Nothing

        ' Make another copy of the file that was copied to the dropbox folder, then delete the original file
        ' (This might help stop a bad catastrophe!)


        WScript.Echo "In Temp Folder: Copying temp database file to be .oldfile"
        fso.CopyFile LocalFile, OldLocalFile

        WScript.Echo "In Temp Folder: Deleting temp database file "
        fso.DeleteFile LocalFile

    End If

    Set fso = Nothing

End Sub

' Do the work!
OpenDatabase
于 2015-09-16T23:23:53.573 回答
0

我知道这是一个老问题,我认为不可能安全地做到这一点。问题是 LDB 文件(管理与数据库的连接共享的文件)可能会丢失对打开状态的跟踪。当外部文件通过 JOIN/IN 类型构造连接到主数据库时,就会发生这种情况。发生这种情况时,即使应用程序退出,Jet/ADO 引擎仍会锁定文件,因为在查询完成时,IN 子句中指定的文件已打开但未关闭。然后 DropBox 创建有冲突的文件副本并且数据丢失。

于 2019-05-09T00:41:00.413 回答