MS Access: how to compact current database in VBA

后端 未结 13 1560
慢半拍i
慢半拍i 2020-11-29 07:34

Pretty simple question, I know.

相关标签:
13条回答
  • 2020-11-29 08:01

    Try this. It works on the same database in which the code resides. Just call the CompactDB() function shown below. Make sure that after you add the function, you click the Save button in the VBA Editor window prior to running for the first time. I only tested it in Access 2010. Ba-da-bing, ba-da-boom.

    Public Function CompactDB()
    
        Dim strWindowTitle As String
    
        On Error GoTo err_Handler
    
        strWindowTitle = Application.Name & " - " & Left(Application.CurrentProject.Name, Len(Application.CurrentProject.Name) - 4)
        strTempDir = Environ("Temp")
        strScriptPath = strTempDir & "\compact.vbs"
        strCmd = "wscript " & """" & strScriptPath & """"
    
        Open strScriptPath For Output As #1
        Print #1, "Set WshShell = WScript.CreateObject(""WScript.Shell"")"
        Print #1, "WScript.Sleep 1000"
        Print #1, "WshShell.AppActivate " & """" & strWindowTitle & """"
        Print #1, "WScript.Sleep 500"
        Print #1, "WshShell.SendKeys ""%yc"""
        Close #1
    
        Shell strCmd, vbHide
        Exit Function
    
        err_Handler:
        MsgBox "Error " & Err.Number & ": " & Err.Description
        Close #1
    
    End Function
    
    0 讨论(0)
  • 2020-11-29 08:05

    There's also Michael Kaplan's SOON ("Shut One, Open New") add-in. You'd have to chain it, but it's one way to do this.

    I can't say I've had much reason to ever want to do this programatically, since I'm programming for end users, and they are never using anything but the front end in the Access user interface, and there's no reason to regularly compact a properly-designed front end.

    0 讨论(0)
  • 2020-11-29 08:09

    For Access 2013, you could just do

    Sendkeys "%fic"
    

    This is the same as typing ALT, F, I, C on your keyboard.

    It's probably a different sequence of letters for different versions, but the "%" symbol means "ALT", so keep that in the code. you may just need to change the letters, depending on what letters appear when you press ALT

    Letters that appear when pressing ALT in Access 2013

    0 讨论(0)
  • 2020-11-29 08:09

    Try adding this module, pretty simple, just launches Access, opens the database, sets the "Compact on Close" option to "True", then quits.

    Syntax to auto-compact:

    acCompactRepair "C:\Folder\Database.accdb", True
    

    To return to default*:

    acCompactRepair "C:\Folder\Database.accdb", False
    

    *not necessary, but if your back end database is >1GB this can be rather annoying when you go into it directly and it takes 2 minutes to quit!

    EDIT: added option to recurse through all folders, I run this nightly to keep databases down to a minimum.

    'accCompactRepair
    'v2.02 2013-11-28 17:25
    
    '===========================================================================
    ' HELP CONTACT
    '===========================================================================
    ' Code is provided without warranty and can be stolen and amended as required.
    '   Tom Parish
    '   TJP@tomparish.me.uk
    '   http://baldywrittencod.blogspot.com/2013/10/vba-modules-access-compact-repair.html
    '   DGF Help Contact: see BPMHelpContact module
    '=========================================================================
    
    'includes code from
    'http://www.ammara.com/access_image_faq/recursive_folder_search.html
    'tweaked slightly for improved error handling
    
    '   v2.02   bugfix preventing Compact when bAutoCompact set to False
    '           bugfix with "OLE waiting for another application" msgbox
    '           added "MB" to start & end sizes of message box at end
    '   v2.01   added size reduction to message box
    '   v2.00   added recurse
    '   v1.00   original version
    
    Option Explicit
    
    Function accSweepForDatabases(ByVal strFolder As String, Optional ByVal bIncludeSubfolders As Boolean = True _
        , Optional bAutoCompact As Boolean = False) As String
    'v2.02 2013-11-28 17:25
    'sweeps path for .accdb and .mdb files, compacts and repairs all that it finds
    'NB: leaves AutoCompact on Close as False unless specified, then leaves as True
    
    'syntax:
    '   accSweepForDatabases "path", [False], [True]
    
    'code for ActiveX CommandButton on sheet module named "admin" with two named ranges "vPath" and "vRecurse":
    '   accSweepForDatabases admin.Range("vPath"), admin.Range("vRecurse") [, admin.Range("vLeaveAutoCompact")]
    
    Application.DisplayAlerts = False
    
    Dim colFiles As New Collection, vFile As Variant, i As Integer, j As Integer, sFails As String, t As Single
    Dim SizeBefore As Long, SizeAfter As Long
    t = Timer
    RecursiveDir colFiles, strFolder, "*.accdb", True  'comment this out if you only have Access 2003 installed
    RecursiveDir colFiles, strFolder, "*.mdb", True
    
        For Each vFile In colFiles
            'Debug.Print vFile
            SizeBefore = SizeBefore + (FileLen(vFile) / 1048576)
    On Error GoTo CompactFailed
        If InStr(vFile, "Geographical Configuration.accdb") > 0 Then MsgBox "yes"
            acCompactRepair vFile, bAutoCompact
            i = i + 1  'counts successes
            GoTo NextCompact
    CompactFailed:
    On Error GoTo 0
            j = j + 1   'counts failures
            sFails = sFails & vFile & vbLf  'records failure
    NextCompact:
    On Error GoTo 0
            SizeAfter = SizeAfter + (FileLen(vFile) / 1048576)
    
        Next vFile
    
    Application.DisplayAlerts = True
    
    'display message box, mark end of process
        accSweepForDatabases = i & " databases compacted successfully, taking " & CInt(Timer - t) & " seconds, and reducing storage overheads by " & Int(SizeBefore - SizeAfter) & "MB" & vbLf & vbLf & "Size Before: " & Int(SizeBefore) & "MB" & vbLf & "Size After: " & Int(SizeAfter) & "MB"
        If j > 0 Then accSweepForDatabases = accSweepForDatabases & vbLf & j & " failures:" & vbLf & vbLf & sFails
        MsgBox accSweepForDatabases, vbInformation, "accSweepForDatabases"
    
    End Function
    
    Function acCompactRepair(ByVal pthfn As String, Optional doEnable As Boolean = True) As Boolean
    'v2.02 2013-11-28 16:22
    'if doEnable = True will compact and repair pthfn
    'if doEnable = False will then disable auto compact on pthfn
    
    On Error GoTo CompactFailed
    
    Dim A As Object
    Set A = CreateObject("Access.Application")
    With A
        .OpenCurrentDatabase pthfn
        .SetOption "Auto compact", True
        .CloseCurrentDatabase
        If doEnable = False Then
            .OpenCurrentDatabase pthfn
            .SetOption "Auto compact", doEnable
        End If
        .Quit
    End With
    Set A = Nothing
    acCompactRepair = True
    Exit Function
    CompactFailed:
    End Function
    
    
    'source: http://www.ammara.com/access_image_faq/recursive_folder_search.html
    'tweaked slightly for error handling
    
    Private Function RecursiveDir(colFiles As Collection, _
                                 strFolder As String, _
                                 strFileSpec As String, _
                                 bIncludeSubfolders As Boolean)
    
        Dim strTemp As String
        Dim colFolders As New Collection
        Dim vFolderName As Variant
    
        'Add files in strFolder matching strFileSpec to colFiles
        strFolder = TrailingSlash(strFolder)
    On Error Resume Next
        strTemp = ""
        strTemp = Dir(strFolder & strFileSpec)
    On Error GoTo 0
        Do While strTemp <> vbNullString
            colFiles.Add strFolder & strTemp
            strTemp = Dir
        Loop
    
        If bIncludeSubfolders Then
            'Fill colFolders with list of subdirectories of strFolder
    On Error Resume Next
            strTemp = ""
            strTemp = Dir(strFolder, vbDirectory)
    On Error GoTo 0
            Do While strTemp <> vbNullString
                If (strTemp <> ".") And (strTemp <> "..") Then
                    If (GetAttr(strFolder & strTemp) And vbDirectory) <> 0 Then
                        colFolders.Add strTemp
                    End If
                End If
                strTemp = Dir
            Loop
    
            'Call RecursiveDir for each subfolder in colFolders
            For Each vFolderName In colFolders
                Call RecursiveDir(colFiles, strFolder & vFolderName, strFileSpec, True)
            Next vFolderName
        End If
    
    End Function
    
    Private Function TrailingSlash(strFolder As String) As String
        If Len(strFolder) > 0 Then
            If Right(strFolder, 1) = "\" Then
                TrailingSlash = strFolder
            Else
                TrailingSlash = strFolder & "\"
            End If
        End If
    End Function
    
    0 讨论(0)
  • 2020-11-29 08:12

    Application.SetOption "Auto compact", False '(mentioned above) Use this with a button caption: "DB Not Compact On Close"

    Write code to toggle the caption with "DB Compact On Close" along with Application.SetOption "Auto compact", True

    AutoCompact can be set by means of the button or by code, ex: after importing large temp tables.

    The start up form can have code that turns off Auto Compact, so that it doesn't run every time.

    This way, you are not trying to fight Access.

    0 讨论(0)
  • 2020-11-29 08:13

    I did this many years back on 2003 or possibly 97, yikes!

    If I recall you need to use one of the subcommands above tied to a timer. You cannot operate on the db with any connections or forms open.

    So you do something about closing all forms, and kick off the timer as the last running method. (which will in turn call the compact operation once everything closes)

    If you haven't figured this out I could dig through my archives and pull it up.

    0 讨论(0)
提交回复
热议问题