Extraire par programme le code de macro (VBA) à partir de documents Word 2007
-
09-06-2019 - |
Question
Est-il possible d'extraire tout le code VBA d'un document « docm » Word 2007 à l'aide de l'API ?
J'ai trouvé comment insérer du code VBA au moment de l'exécution et comment supprimer tout le code VBA, sans extraire le code réel dans un flux ou une chaîne que je peux stocker (et insérer dans d'autres documents à l'avenir).
Tous les conseils ou ressources seraient appréciés.
Modifier:Merci à tout le monde, AardvarkLa réponse de était exactement ce que je cherchais.J'ai converti son code en C# et j'ai pu l'appeler à partir d'une bibliothèque de classes à l'aide de Visual Studio 2008.
using Microsoft.Office.Interop.Word;
using Microsoft.Vbe.Interop;
...
public List<string> GetMacrosFromDoc()
{
Document doc = GetWordDoc(@"C:\Temp\test.docm");
List<string> macros = new List<string>();
VBProject prj;
CodeModule code;
string composedFile;
prj = doc.VBProject;
foreach (VBComponent comp in prj.VBComponents)
{
code = comp.CodeModule;
// Put the name of the code module at the top
composedFile = comp.Name + Environment.NewLine;
// Loop through the (1-indexed) lines
for (int i = 0; i < code.CountOfLines; i++)
{
composedFile += code.get_Lines(i + 1, 1) + Environment.NewLine;
}
// Add the macro to the list
macros.Add(composedFile);
}
CloseDoc(doc);
return macros;
}
La solution
Vous devrez ajouter une référence à Microsoft Visual Basic pour Applications Extensibility 5.3 (ou quelle que soit la version dont vous disposez).J'ai le SDK VBA et autres sur ma boîte - donc ce n'est peut-être pas exactement ce qu'Office est livré.
Vous devez également activer spécifiquement l'accès au modèle objet VBA - voir le "Centre de confiance" dans les options de Word.Ceci s’ajoute à tous les autres paramètres de sécurité des macros fournis par Office.
Cet exemple extraira le code du document actuel dans lequel il réside - il s'agit lui-même d'une macro VBA (et s'affichera ainsi que tout autre code).Il existe également une collection Application.vbe.VBProjects pour accéder à d'autres documents.Bien que je ne l'ai jamais fait, je suppose qu'une application externe pourrait également ouvrir des fichiers à l'aide de cette collection VBProjects.La sécurité est amusante avec ce genre de choses, donc cela peut être délicat.
Je me demande aussi quel est le format de fichier docm maintenant - XML comme le docx ?Serait-ce une meilleure approche ?
Sub GetCode()
Dim prj As VBProject
Dim comp As VBComponent
Dim code As CodeModule
Dim composedFile As String
Dim i As Integer
Set prj = ThisDocument.VBProject
For Each comp In prj.VBComponents
Set code = comp.CodeModule
composedFile = comp.Name & vbNewLine
For i = 1 To code.CountOfLines
composedFile = composedFile & code.Lines(i, 1) & vbNewLine
Next
MsgBox composedFile
Next
End Sub
Autres conseils
Vous pouvez exporter le code vers des fichiers, puis le relire.
J'utilise le code ci-dessous pour m'aider à conserver certaines macros Excel sous contrôle de code source (en utilisant Subversion et TortoiseSVN).En gros, il exporte tout le code vers des fichiers texte chaque fois que j'enregistre avec l'éditeur VBA ouvert.J'ai mis les fichiers texte dans Subversion pour pouvoir faire des différences.Vous devriez pouvoir en adapter/voler une partie pour fonctionner dans Word.
La vérification du registre dans CanAccessVBOM() correspond à « Accès approuvé au projet Visual Basic » dans le paramètre de sécurité.
Sub ExportCode()
If Not CanAccessVBOM Then Exit Sub ' Exit if access to VB object model is not allowed
If (ThisWorkbook.VBProject.VBE.ActiveWindow Is Nothing) Then
Exit Sub ' Exit if VBA window is not open
End If
Dim comp As VBComponent
Dim codeFolder As String
codeFolder = CombinePaths(GetWorkbookPath, "Code")
On Error Resume Next
MkDir codeFolder
On Error GoTo 0
Dim FileName As String
For Each comp In ThisWorkbook.VBProject.VBComponents
Select Case comp.Type
Case vbext_ct_ClassModule
FileName = CombinePaths(codeFolder, comp.Name & ".cls")
DeleteFile FileName
comp.Export FileName
Case vbext_ct_StdModule
FileName = CombinePaths(codeFolder, comp.Name & ".bas")
DeleteFile FileName
comp.Export FileName
Case vbext_ct_MSForm
FileName = CombinePaths(codeFolder, comp.Name & ".frm")
DeleteFile FileName
comp.Export FileName
Case vbext_ct_Document
FileName = CombinePaths(codeFolder, comp.Name & ".cls")
DeleteFile FileName
comp.Export FileName
End Select
Next
End Sub
Function CanAccessVBOM() As Boolean
' Check resgistry to see if we can access the VB object model
Dim wsh As Object
Dim str1 As String
Dim AccessVBOM As Long
Set wsh = CreateObject("WScript.Shell")
str1 = "HKEY_CURRENT_USER\Software\Microsoft\Office\" & _
Application.Version & "\Excel\Security\AccessVBOM"
On Error Resume Next
AccessVBOM = wsh.RegRead(str1)
Set wsh = Nothing
CanAccessVBOM = (AccessVBOM = 1)
End Function
Sub DeleteFile(FileName As String)
On Error Resume Next
Kill FileName
End Sub
Function GetWorkbookPath() As String
Dim fullName As String
Dim wrkbookName As String
Dim pos As Long
wrkbookName = ThisWorkbook.Name
fullName = ThisWorkbook.fullName
pos = InStr(1, fullName, wrkbookName, vbTextCompare)
GetWorkbookPath = Left$(fullName, pos - 1)
End Function
Function CombinePaths(ByVal Path1 As String, ByVal Path2 As String) As String
If Not EndsWith(Path1, "\") Then
Path1 = Path1 & "\"
End If
CombinePaths = Path1 & Path2
End Function
Function EndsWith(ByVal InString As String, ByVal TestString As String) As Boolean
EndsWith = (Right$(InString, Len(TestString)) = TestString)
End Function