Как сжать базу данных MS Access, когда база данных открыта, используя vba - PullRequest
5 голосов
/ 14 мая 2010

Я использую несколько модулей кода VBA. В середине работы происходит сбой кода, когда Access достигает максимального размера 2 ГБ; но, если я сожму базу данных в тот момент, это только 200 МБ.

Можно ли сжимать базу данных через равные промежутки времени во время выполнения кода?

Ответы [ 6 ]

2 голосов
/ 16 декабря 2017

Я недавно наткнулся на этот вопрос, и некоторые вещи, с которыми я сталкиваюсь в ответах, просто неверны:

  1. Вы НЕ МОЖЕТЕ компактировать и восстанавливать базу данных доступа через VBA, пока она открыта! Не имеет значения, все ли таблицы закрыты, есть ли у вас эксклюзивная блокировка и т. Д.
  2. Однако вы можете сжать серверную часть из связанной базы данных, если все подключения к ней закрыты. Вот почему Тони Тьюс мог успешно уплотнять и ремонтировать.

Это прискорбно, и самый простой обходной путь - создать связанную базу данных. Но если это нежелательно, есть одна альтернативная вещь, которую вы можете сделать, если вы готовы сделать какой-то странный обман.

Проблема в том, что основная база данных должна быть закрыта, пока происходит сжатие и восстановление. Чтобы обойти это, мы можем сделать следующее:

  1. Программно создать файл VBScript
  2. Добавьте код в этот файл, чтобы мы могли сжимать и восстанавливать нашу базу данных, не открывая ее
  3. Открыть и запустить этот файл асинхронно
  4. Закройте нашу базу данных, прежде чем произойдет сжатие и восстановление
  5. Сжатие и восстановление базы данных (создание копии), удаление старой, переименование копии
  6. Повторно открыть нашу базу данных, продолжить пакет
  7. Удалить только что созданный файл
Public Sub CompactRepairViaExternalScript()
    Dim vbscrPath As String
    vbscrPath = CurrentProject.Path & "\CRHelper.vbs"
    If Dir(CurrentProject.Path & "\CRHelper.vbs") <> "" Then
        Kill CurrentProject.Path & "\CRHelper.vbs"
    End If
    Dim vbStr As String
    vbStr = "dbName = """ & CurrentProject.FullName & """" & vbCrLf & _
    "resumeFunction = ""ResumeBatch""" & vbCrLf & _
    "Set app = CreateObject(""Access.Application"")" & vbCrLf & _
    "Set dbe = app.DBEngine" & vbCrLf & _
    "Set objFSO = CreateObject(""Scripting.FileSystemObject"")" & vbCrLf & _
    "On Error Resume Next" & vbCrLf & _
    "Do" & vbCrLf & _
    "If Err.Number <> 0 Then Err.Clear" & vbCrLf & _
    "WScript.Sleep 500" & vbCrLf & _
    "dbe.CompactDatabase dbName, dbName & ""_1""" & vbCrLf & _
    "errCount = errCount + 1" & vbCrLf & _
    "Loop While err.Number <> 0 And errCount < 100" & vbCrLf & _
    "If errCount < 100 Then" & vbCrLf & _
    "objFSO.DeleteFile dbName" & vbCrLf & _
    "objFSO.MoveFile dbName & ""_1"", dbName" & vbCrLf & _
    "app.OpenCurrentDatabase dbName" & vbCrLf & _
    "app.UserControl = True" & vbCrLf & _
    "app.Run resumeFunction" & vbCrLf & _
    "End If" & vbCrLf & _
    "objFSO.DeleteFile Wscript.ScriptFullName" & vbCrLf
    Dim fileHandle As Long
    fileHandle = FreeFile
    Open vbscrPath For Output As #fileHandle
    Print #fileHandle, vbStr
    Close #fileHandle
    Dim wsh As Object
    Set wsh = CreateObject("WScript.Shell")
    wsh.Run """" & vbscrPath & """"
    Set wsh = Nothing
    Application.Quit
End Sub

Это делает все шаги, описанные выше, и возобновляет пакет, вызывая функцию ResumeBatch в базе данных, которая вызывала эту функцию (без каких-либо параметров).

Обратите внимание, что такие вещи, как защита "нажми и работай" и антивирус / политика, которой не нравятся файлы VBScript, могут разрушить этот подход.

2 голосов
/ 14 мая 2010

Да, вы можете. Однако вы должны закрыть все переменные набора записей и базы данных, формы и отчеты, которые используют файл базы данных. Вы можете проверить это самостоятельно, запустив свой код и увидев, что файл LDB больше не существует. Также, конечно, все пользователи, кроме вас, должны быть вне файла базы данных.

Вы можете перебрать коллекцию форм (которая на самом деле является открытыми формами) и коллекцию отчетов, чтобы закрыть их все. Конечно, как только вы закончите обработку, вам нужно будет снова открыть любые формы автозапуска и т. Д. И т. Д.

1 голос
/ 20 декабря 2017

Это работало в предыдущих версиях MS-Access, но не работает, так как мы запускаем Access 2010.

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

Конечно, MDB будет закрыт, сжат и повторно открыт. Начиная с Access 2010, операция сжатия должна быть адаптирована Microsoft.

Надеюсь, это поможет.

0 голосов
/ 20 февраля 2012

Согласно Microsoft вы можете сжать открытую базу данных Access, если файл открыт исключительно.

См. http://support.microsoft.com/kb/288631 Ограничения сжатия.

0 голосов
/ 28 октября 2010

Я не уверен насчет vb, но я всегда делал это из командной строки, вызывая ключ командной строки "/ compact". Я думаю, вы можете вызывать БД через ключи командной строки так же, как вы легко открываете любой файл в vb.

за MS

Сжатие и исправление базы данных Access или сжатие проекта Access, указанного в параметре / compact, а затем закрытие Access. Если вы опустите имя целевого файла после параметра / compact, файл будет сжат до исходного имени и папки. Чтобы сжать с другим именем, укажите целевой файл. Если вы не включите путь в целевую базу данных или целевой проект Access, целевой файл будет создан в папке «Мои документы» по умолчанию. В проекте Access этот параметр сжимает файл проекта Access (.adp), но не базу данных SQL Server.

0 голосов
/ 14 мая 2010

Вы можете сжать только базу данных, которая не открыта (или сжать ее в файл с другим именем).

См. здесь для шагов.

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