Problème référence manquante, envoi document sans template
Fermé
Zawarudio
Messages postés14Date d'inscriptionmardi 25 août 2015StatutMembreDernière intervention 2 octobre 2015
-
Modifié par Zawarudio le 18/09/2015 à 15:18
PlacageGranby
Messages postés393Date d'inscriptionmercredi 26 mars 2014StatutMembreDernière intervention 7 mars 2019
-
18 sept. 2015 à 17:19
Bonjour,
Je travaille actuellement sur un Template .dotm, qui possède un certain nombre de macros.
J'ai une macro qui génère un document à partir de ce dotm dans un classeur excel.
Je souhaiterais cependant que certaines macro qui sont disponible sur mon template soient disponible directement sur le document pour que je puisse envoyer un document avec quelques fonctionnalité sans pour autant envoyer/partager le template.
J'ai donc mis toute les macros que je souhaite exporter dans un module, et je copie ce module dans mon document généré à sa création
'Source : http://www.cpearson.com/Excel/vbe.aspx
Function CopyModule(ModuleName As String, FromVBProject As VBIDE.VBProject, ToVBProject As VBIDE.VBProject, OverwriteExisting As Boolean) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' CopyModule
' This function copies a module from one VBProject to
' another. It returns True if successful or False
' if an error occurs.
'
' Parameters:
' --------------------------------
' FromVBProject The VBProject that contains the module
' to be copied.
'
' ToVBProject The VBProject into which the module is
' to be copied.
'
' ModuleName The name of the module to copy.
'
' OverwriteExisting If True, the VBComponent named ModuleName
' in ToVBProject will be removed before
' importing the module. If False and
' a VBComponent named ModuleName exists
' in ToVBProject, the code will return
' False.
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim VBComp As VBIDE.VBComponent
Dim FName As String
Dim CompName As String
Dim S As String
Dim SlashPos As Long
Dim ExtPos As Long
Dim TempVBComp As VBIDE.VBComponent
'''''''''''''''''''''''''''''''''''''''''''''
' Do some housekeeping validation.
'''''''''''''''''''''''''''''''''''''''''''''
If FromVBProject Is Nothing Then
CopyModule = False
Exit Function
End If
If Trim(ModuleName) = vbNullString Then
CopyModule = False
Exit Function
End If
If ToVBProject Is Nothing Then
CopyModule = False
Exit Function
End If
If FromVBProject.Protection = vbext_pp_locked Then
CopyModule = False
Exit Function
End If
If ToVBProject.Protection = vbext_pp_locked Then
CopyModule = False
Exit Function
End If
On Error Resume Next
Set VBComp = FromVBProject.VBComponents(ModuleName)
If Err.Number <> 0 Then
CopyModule = False
Exit Function
End If
''''''''''''''''''''''''''''''''''''''''''''''''''''
' FName is the name of the temporary file to be
' used in the Export/Import code.
''''''''''''''''''''''''''''''''''''''''''''''''''''
FName = Environ("Temp") & "\" & ModuleName & ".bas"
If OverwriteExisting = True Then
''''''''''''''''''''''''''''''''''''''
' If OverwriteExisting is True, Kill
' the existing temp file and remove
' the existing VBComponent from the
' ToVBProject.
''''''''''''''''''''''''''''''''''''''
If Dir(FName, vbNormal + vbHidden + vbSystem) <> vbNullString Then
Err.Clear
Kill FName
If Err.Number <> 0 Then
CopyModule = False
Exit Function
End If
End If
With ToVBProject.VBComponents
.Remove .Item(ModuleName)
End With
Else
'''''''''''''''''''''''''''''''''''''''''
' OverwriteExisting is False. If there is
' already a VBComponent named ModuleName,
' exit with a return code of False.
''''''''''''''''''''''''''''''''''''''''''
Err.Clear
Set VBComp = ToVBProject.VBComponents(ModuleName)
If Err.Number <> 0 Then
If Err.Number = 9 Then
' module doesn't exist. ignore error.
Else
' other error. get out with return value of False
CopyModule = False
Exit Function
End If
End If
End If
''''''''''''''''''''''''''''''''''''''''''''''''''''
' Do the Export and Import operation using FName
' and then Kill FName.
''''''''''''''''''''''''''''''''''''''''''''''''''''
FromVBProject.VBComponents(ModuleName).Export FileName:=FName
'''''''''''''''''''''''''''''''''''''
' Extract the module name from the
' export file name.
'''''''''''''''''''''''''''''''''''''
SlashPos = InStrRev(FName, "\")
ExtPos = InStrRev(FName, ".")
CompName = Mid(FName, SlashPos + 1, ExtPos - SlashPos - 1)
''''''''''''''''''''''''''''''''''''''''''''''
' Document modules (SheetX and ThisWorkbook)
' cannot be removed. So, if we are working with
' a document object, delete all code in that
' component and add the lines of FName
' back in to the module.
''''''''''''''''''''''''''''''''''''''''''''''
Set VBComp = Nothing
Set VBComp = ToVBProject.VBComponents(CompName)
If VBComp Is Nothing Then
ToVBProject.VBComponents.Import FileName:=FName
Else
If VBComp.Type = vbext_ct_Document Then
' VBComp is destination module
Set TempVBComp = ToVBProject.VBComponents.Import(FName)
' TempVBComp is source module
With VBComp.CodeModule
.DeleteLines 1, .CountOfLines
S = TempVBComp.CodeModule.Lines(1, TempVBComp.CodeModule.CountOfLines)
.InsertLines 1, S
End With
On Error GoTo 0
ToVBProject.VBComponents.Remove TempVBComp
End If
End If
Kill FName
CopyModule = True
End Function
'Mon code
Sub ExportVBCode()
Dim result As Boolean
Dim dimfor As Variant
Dim Source As VBIDE.VBProject
Dim Target As VBIDE.VBProject
For Each dimfor In Application.VBE.VBProjects
If (dimfor.Name = "MyTemplate") Then Set Source = dimfor
If (dimfor.Name = "Project") Then Set Target = dimfor
Next dimfor
result = CopyModule("ThisDocument", Source, Target, True)
result = CopyModule("TBT", Source, Target, True)
result = CopyModule("ChangeColor_UserForm", Source, Target, True)
End Sub
Ce code copie donc le contenu des modules "TBT", un UserForm et ThisDocument dans le document créé.
Cependant, j'ai à présent un problème :
'Sub that will create a new CommandBar, to put subs available to everyone in there
Private Sub Document_Open()
CheckReference
Dim CmdBar As CommandBar
Dim CmdButton As CommandBarButton
Set CmdBar = Application.CommandBars.Add(Name:="MyBar", Position:=msoBarTop, Temporary:=True)
'Adding a button to execute the subs
Set CmdButton = CmdBar.Controls.Add(Type:=msoControlButton)
With CmdButton
.Style = msoButtonWrapCaption
.Caption = "Put new alternatives in other tables"
.OnAction = "Update_Tables_With_Alternatives"
End With
Set CmdButton = CmdBar.Controls.Add(Type:=msoControlButton)
With CmdButton
.Style = msoButtonWrapCaption
.Caption = "Select a color"
.OnAction = "OpenChangeColorUserform"
End With
CmdBar.Visible = True
End Sub
'When closing the document, we delete the commandbar
Private Sub Document_Close()
On Error Resume Next
Application.CommandBars("MyBar").Delete
End Sub
Quand je lance le document créé après avoir cassé le lien entre le Template et le document ( renommé le template ), je dispose dans mon document d'une référence cassée vers mon Template, et Word n'aime pas du tout ça (cf image).
Ma solution pour contourner ce problème est actuellement de supprimer la référence manquante du document (qui semble faire bugger le reste)
Sub CheckReference()
Dim vbProj As VBProject
Dim chkRef As Reference
Set vbProj = ActiveDocument.VBProject
'Check through the selected references in the References dialog box.
For Each chkRef In vbProj.References
'If the reference is broken, send the name to the Immediate Window.
If chkRef.IsBroken Then
Application.VBE.ActiveVBProject.References.Remove chkRef
End If
Next
End Sub
Cependant, cette solution ne fait que contourner le problème, car je ne sait plus restaurer le lien entre le template et le document après avoir fait ça...
De plus, je ne peut pas utiliser Document_Open() donc je suis plus ou moins obligé en ce moment d'exécuter cette macro à la main.
Quelqu'un aurait-il un retour d'expérience sur un problème similaire et sa résolution?
Après ce long post, laissez moi résumer en une phrase ce que je souhaiterais faire :
Je souhaiterais désactiver la référence vers le template d'un document lorsque la référence est manquante, et réactiver cette référence lorsque le document est trouvé
Merci!
Cordialement,
A voir également:
Problème référence manquante, envoi document sans template
Et aussi d'autre ligne de code pour vérifié l'existence de référence.
N'ayant pas testé le tout moi même, je vous souhaite une bonne lecture
Zawarudio
Messages postés14Date d'inscriptionmardi 25 août 2015StatutMembreDernière intervention 2 octobre 20151 18 sept. 2015 à 16:58
Bonjour, et merci de votre intérêt.
Si je veut utiliser cette méthode, il faut que je puisse changer la priorité des références par code lors de la génération du document, chose pour laquelle je ne trouve pas (pour le moment tout du moins, je suis toujours entrain de chercher)
En effet, la référence vers mon template se met avant même la référence aux fonctions de Word, empêchant de faire quoi que ce soit par VBA.
Si je veut débugger tout ça, pour l'instant il faut toujours une action humaine, alors que j'aimerais de préférence automatiser le tout
PlacageGranby
Messages postés393Date d'inscriptionmercredi 26 mars 2014StatutMembreDernière intervention 7 mars 201926 18 sept. 2015 à 17:19
Re-Bonjour,
J'avoue que je suis un peu dépassé, votre compréhension de VBA est probablement supérieur à la mienne :)
En cherchant un peu, j'ai peut-être trouvé quelque chose d'utile (ou peut-être pas).
Au sujet des liaison tardive.
En gros, les déclarations sont fait en tant d'objet pour ne pas avoir besoin des références tout de suite, et plus loin dans le code, on fait l'affectation de la variable
' Declare the object as a late-bound object Dim oExcel As Object
Set oExcel = CreateObject("Excel.Application")
' The Visible property is called via IDispatch oExcel.Visible = True
18 sept. 2015 à 16:58
Si je veut utiliser cette méthode, il faut que je puisse changer la priorité des références par code lors de la génération du document, chose pour laquelle je ne trouve pas (pour le moment tout du moins, je suis toujours entrain de chercher)
En effet, la référence vers mon template se met avant même la référence aux fonctions de Word, empêchant de faire quoi que ce soit par VBA.
Si je veut débugger tout ça, pour l'instant il faut toujours une action humaine, alors que j'aimerais de préférence automatiser le tout
18 sept. 2015 à 17:19
J'avoue que je suis un peu dépassé, votre compréhension de VBA est probablement supérieur à la mienne :)
En cherchant un peu, j'ai peut-être trouvé quelque chose d'utile (ou peut-être pas).
Au sujet des liaison tardive.
https://docs.microsoft.com/en-us/previous-versions/office/troubleshoot/office-developer/binding-type-available-to-automation-clients
En gros, les déclarations sont fait en tant d'objet pour ne pas avoir besoin des références tout de suite, et plus loin dans le code, on fait l'affectation de la variable
A tout hasard.