MS Access: how to compact current database in VBA MS Access: how to compact current database in VBA vba vba

MS Access: how to compact current database in VBA


If you want to compact/repair an external mdb file (not the one you are working in just now):

Application.compactRepair sourecFile, destinationFile

If you want to compact the database you are working with:

Application.SetOption "Auto compact", True

In this last case, your app will be compacted when closing the file.

My opinion: writting a few lines of code in an extra MDB "compacter" file that you can call when you want to compact/repair an mdb file is very usefull: in most situations the file that needs to be compacted cannot be opened normally anymore, so you need to call the method from outside the file.

Otherwise, the autocompact shall by default be set to true in each main module of an Access app.

In case of a disaster, create a new mdb file and import all objects from the buggy file. You will usually find a faulty object (form, module, etc) that you will not be able to import.


If you have the database with a front end and a back end. You can use the following code on the main form of your front end main navigation form:

Dim sDataFile As String, sDataFileTemp As String, sDataFileBackup As StringDim s1 As Long, s2 As LongsDataFile = "C:\MyDataFile.mdb"sDataFileTemp = "C:\MyDataFileTemp.mdb"sDataFileBackup = "C:\MyDataFile Backup " & Format(Now, "YYYY-MM-DD HHMMSS") & ".mdb"DoCmd.Hourglass True'get file size before compactOpen sDataFile For Binary As #1s1 = LOF(1)Close #1'backup data fileFileCopy sDataFile, sDataFileBackup'only proceed if data file existsIf Dir(sDataFileBackup vbNormal) <> "" Then        'compact data file to temp file        On Error Resume Next        Kill sDataFileTemp        On Error GoTo 0        DBEngine.CompactDatabase sDataFile, sDataFileTemp        If Dir(sDataFileTemp, vbNormal) <> "" Then            'delete old data file data file            Kill sDataFile            'copy temp file to data file            FileCopy sDataFileTemp, sDataFile            'get file size after compact            Open sDataFile For Binary As #1            s2 = LOF(1)            Close #1            DoCmd.Hourglass False            MsgBox "Compact complete " & vbCrLf & vbCrLf _                & "Size before: " & Round(s1 / 1024 / 1024, 2) & "Mb" & vbCrLf _                & "Size after:    " & Round(s2 / 1024 / 1024, 2) & "Mb", vbInformation        Else            DoCmd.Hourglass False            MsgBox "ERROR: Unable to compact data file"        End IfElse        DoCmd.Hourglass False        MsgBox "ERROR: Unable to backup data file"End IfDoCmd.Hourglass False


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 versionOption ExplicitFunction 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 = FalseDim colFiles As New Collection, vFile As Variant, i As Integer, j As Integer, sFails As String, t As SingleDim SizeBefore As Long, SizeAfter As Longt = TimerRecursiveDir colFiles, strFolder, "*.accdb", True  'comment this out if you only have Access 2003 installedRecursiveDir 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 NextCompactCompactFailed:On Error GoTo 0        j = j + 1   'counts failures        sFails = sFails & vFile & vbLf  'records failureNextCompact:On Error GoTo 0        SizeAfter = SizeAfter + (FileLen(vFile) / 1048576)    Next vFileApplication.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 FunctionFunction 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 pthfnOn Error GoTo CompactFailedDim A As ObjectSet 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    .QuitEnd WithSet A = NothingacCompactRepair = TrueExit FunctionCompactFailed:End Function'source: http://www.ammara.com/access_image_faq/recursive_folder_search.html'tweaked slightly for error handlingPrivate 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 strFolderOn 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 IfEnd FunctionPrivate 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 IfEnd Function