MS Access: как сжать текущую базу данных в VBA - PullRequest
18 голосов
/ 22 сентября 2009

Довольно простой вопрос, я знаю.

Ответы [ 13 ]

29 голосов
/ 22 сентября 2009

Если вы хотите сжать / восстановить внешний файл MDB (а не тот, в котором вы сейчас работаете):

Application.compactRepair sourecFile, destinationFile

Если вы хотите сжать базу данных, с которой работаете:

Application.SetOption "Auto compact", True

В этом последнем случае ваше приложение будет сжато при закрытии файла.

Мое мнение: запись нескольких строк кода в дополнительный «компактный» файл MDB, который вы можете вызвать, когда хотите сжать / восстановить файл mdb, очень полезен: в большинстве случаев файл, который нужно сжать, не может быть больше не открывается, поэтому вам нужно вызвать метод из-за пределов файла.

В противном случае для автокомпакта по умолчанию должно быть установлено значение true в каждом главном модуле приложения Access.

В случае аварии создайте новый файл mdb и импортируйте все объекты из файла с ошибками. Обычно вы найдете неисправный объект (форму, модуль и т. Д.), Который вы не сможете импортировать.

2 голосов
/ 21 марта 2018

Для Access 2013 вы можете просто сделать

Sendkeys "%fic"

Это то же самое, что набирать ALT, F, I, C на клавиатуре.

Возможно, это разные последовательности букв для разных версий, но символ «%» означает «ALT», так что сохраните это в коде возможно, вам просто нужно изменить буквы, в зависимости от того, какие буквы появляются при нажатии ALT

Буквы, которые появляются при нажатии ALT в Access 2013

2 голосов
/ 08 октября 2013

Попробуйте добавить этот модуль, довольно просто, просто запустите Access, откройте базу данных, установите для параметра «Сжать при закрытии» значение «True», а затем закройте.

Синтаксис для автоматического сжатия:

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

Для возврата к значению по умолчанию *:

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

* необязательно, но если ваша внутренняя база данных> 1 ГБ, это может быть довольно раздражающим, когда вы входите в нее напрямую, и для выхода требуется 2 минуты!

РЕДАКТИРОВАТЬ: добавлена ​​возможность проходить через все папки, я запускаю этот ночной, чтобы свести базы данных к минимуму.

'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
1 голос
/ 09 июля 2015

Попробуй это. Он работает в той же базе данных, в которой находится код. Просто вызовите функцию CompactDB (), показанную ниже. Убедитесь, что после добавления функции вы нажимаете кнопку «Сохранить» в окне редактора VBA перед первым запуском. Я проверял это только в Access 2010. Ба-да-бинг, ба-да-бум.

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
1 голос
/ 20 июня 2012

Если у вас есть база данных с внешним и внутренним интерфейсом. Вы можете использовать следующий код в главной форме главной навигационной формы внешнего интерфейса:

Dim sDataFile As String, sDataFileTemp As String, sDataFileBackup As String
Dim s1 As Long, s2 As Long

sDataFile = "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 compact
Open sDataFile For Binary As #1
s1 = LOF(1)
Close #1

'backup data file
FileCopy sDataFile, sDataFileBackup

'only proceed if data file exists
If 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 If

Else
        DoCmd.Hourglass False
        MsgBox "ERROR: Unable to backup data file"
End If

DoCmd.Hourglass False
1 голос
/ 22 сентября 2009

Когда пользователь выходит из FE, попытайтесь переименовать базовый MDB, предпочтительно с текущей датой в имени в формате гггг-мм-дд. Перед этим убедитесь, что вы закрыли все связанные формы, включая скрытые формы и отчеты. Если вы получили сообщение об ошибке, ой, он занят, так что не беспокойтесь. Если это успешно, тогда сожмите это назад.

См. Мое Резервное копирование, доверяете ли вы пользователям или системным администраторам? страница советов для получения дополнительной информации.

1 голос
/ 22 сентября 2009

Да, это просто сделать.

Sub CompactRepair()
  Dim control As Office.CommandBarControl
  Set control = CommandBars.FindControl( Id:=2071 )
  control.accDoDefaultAction
End Sub

По сути, он просто находит пункт меню «Компактность и ремонт» и щелкает по нему программно.

0 голосов
/ 29 июня 2015

Если вы не хотите использовать сжатие при закрытии (например, потому что front-end mdb - это программа-робот, которая работает постоянно), и вы не хотите создавать отдельный mdb только для сжатия, рассмотрите возможность использования cmd файл

Я позволил своему robot.mdb проверить свой собственный размер:

FileLen(CurrentDb.Name))

Если его размер превышает 1 ГБ, он создает файл cmd следующим образом ...

Dim f As Integer
Dim Folder As String
Dim Access As String
    'select Access in the correct PF directory (my robot.mdb runs in 32-bit MSAccess, on 32-bit and 64-bit machines)
    If Dir("C:\Program Files (x86)\Microsoft Office\Office\MSACCESS.EXE") > "" Then
        Access = """C:\Program Files (x86)\Microsoft Office\Office\MSACCESS.EXE"""
    Else
        Access = """C:\Program Files\Microsoft Office\Office\MSACCESS.EXE"""
    End If
    Folder = ExtractFileDir(CurrentDb.Name)
    f = FreeFile
    Open Folder & "comrep.cmd" For Output As f
    'wait until robot.mdb closes (ldb file is gone), then compact robot.mdb
    Print #f, ":checkldb1"
    Print #f, "if exist " & Folder & "robot.ldb goto checkldb1"
    Print #f, Access & " " & Folder & "robot.mdb /compact"
    'wait until the robot mdb closes, then start it
    Print #f, ":checkldb2"
    Print #f, "if exist " & Folder & "robot.ldb goto checkldb2"
    Print #f, Access & " " & Folder & "robot.mdb"
    Close f

... запускает файл cmd ...

Shell ExtractFileDir(CurrentDb.Name) & "comrep.cmd"

... и выключается ...

DoCmd.Quit

Затем файл cmd сжимает и перезапускает robot.mdb.

0 голосов
/ 25 февраля 2015

Application.SetOption "Auto compact", False '(упомянуто выше) Используйте это с надписью кнопки: «DB Not Compact On Close»

Введите код для переключения заголовка с помощью «DB Compact On Close» вместе с Application.SetOption "Авто компакт", True

Автокомпакт может быть установлен с помощью кнопки или кода, например: после импорта больших временных таблиц.

Форма запуска может содержать код, который отключает Auto Compact, поэтому он не запускается каждый раз.

Таким образом, вы не пытаетесь бороться с Access.

0 голосов
/ 30 сентября 2009

DBEngine.CompactDatabase source, dest

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...