Je veux pouvoir exécuter le processus "compact et réparation" à partir d'un module VBA dans la base de données.
J'ai un processus par lots que j'exécute occasionnellement, il supprime quelques vieilles tables, les réimporte à partir d'autres bases de données, renomme quelques champs, fait quelques mises à jour et apporte quelques autres modifications mineures. Le processus n'est pas sorcier, mais il y a plusieurs étapes, il doit donc être automatisé.
Le problème est que quelques étapes (les MISES À JOUR) augmentent temporairement la taille de la base de données, ce qui peut entraîner des problèmes avec les importations ultérieures.
Si je fais le processus manuellement (y compris le compactage), alors tout fonctionne bien et je me retrouve avec une base de données de 800 Mo. Si j'utilise mon script VBA automatisé (sans compactage), il se bloque à mi-chemin lorsque la base de données dépasse la limite de 2 Go.
J'ai trouvé plusieurs sujets sur ce sujet, mais ils ont tous trois ou quatre ans (ou plus) et les méthodes qu'ils décrivent ne semblent plus fonctionner.
Existe-t-il des solutions qui fonctionnent avec Office 365 (version 1720)?
Le "compactage automatique" entraîne le compactage de la base de données à la fermeture, il ne permet PAS l'ajout du compactage de la base de données entre les étapes.
J'ai essayé ça:
Public Sub CompactDb2()
Dim control As Office.CommandBarControl
Set control = CommandBars.FindControl(Id:=2071)
control.accDoDefaultAction
End Sub
Et ça:
Public Sub CompactDb1()
CommandBars("Menu Bar").Controls("Tools").Controls("Database utilities"). _
Controls("Compact and repair database...").accDoDefaultAction
End Sub
Et ça....
Public Sub CompactDb3()
Application.SetOption "Auto compact", True
End Sub
Parmi d'autres
Ce n'est tout simplement pas possible. Le compactage et la réparation d'une base de données nécessitent sa fermeture. En tant que tel, vous ne pouvez pas compacter et réparer une base de données entre les étapes d'un sous ou d'une procédure, car la base de données est ouverte lors de l'exécution de la procédure.
Vous remarquerez peut-être que le bouton Compacter et réparer sur le ruban nécessite un verrou exclusif, ferme la base de données, puis compacte et répare, puis la rouvre.
Mon conseil: exécutez le processus à partir d'une base de données externe, d'un fichier VBScript ou de PowerShell. Exécutez la première partie de votre lot, fermez le fichier, compactez et réparez, rouvrez, exécutez la deuxième partie
Exemple de code
Dim fileLocation As String
DBEngine.CompactDatabase fileLocation, fileLocation & "_1"
Kill fileLocation
Name fileLocation & "_1" As fileLocation
Vous pouvez également remarquer que le bouton Access compact et réparation fait quelque chose de similaire. Si vous exécutez Compact & Repair, il déplace les données vers une base de données appelée Database.accdb dans votre dossier actuel (le nom peut varier en fonction des noms existants/type de base de données), puis supprime votre base de données actuelle, puis renomme le nouveau.
Eh bien, mais rien n'est impossible, non?
Eh bien, certaines choses le sont, mais ce n'est pas l'une d'entre elles, si vous êtes prêt à faire des tromperies étranges. Comme je viens de le dire, le principal problème est que la base de données actuelle doit être fermée. Ainsi, la solution de contournement effectue les opérations suivantes:
Heureusement, j'ai eu du temps à perdre, j'ai donc trouvé la solution suivante:
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
Cela effectue toutes les étapes décrites ci-dessus et reprend le lot en appelant la fonction ResumeBatch
sur la base de données qui a appelé cette fonction (sans aucun paramètre). Notez que des choses comme la protection click-to-run et les antivirus/politiques n'aimant pas les fichiers vbscript peuvent ruiner cette approche.
Voici le code VBA, j'ai essayé et travaillé, exécuté à partir d'Excel;
Sub CompactAndRepairAccessDB()
Dim Acc As Object
Set Acc = CreateObject("access.application")
Dim dbPath As String, dbPathX As String
dbPath = Application.ThisWorkbook.Path & "\" & "YourDatabaseNameHere.accdb"
dbPathX = Application.ThisWorkbook.Path & "\" & "tmp.accdb"
Acc.DBEngine.CompactDatabase dbPath, dbPathX
Acc.Quit
Set Acc = Nothing
Kill dbPath
Name dbPathX As dbPath
End Sub
Trouvé la solution dans ce lien et modifié un peu.
http://www.vbaexpress.com/forum/showthread.php?9262-Solved-VBA-Compact-and-Repair