Problème référence manquante, envoi document sans template

Fermé
Zawarudio Messages postés 14 Date d'inscription mardi 25 août 2015 Statut Membre Dernière intervention 2 octobre 2015 - Modifié par Zawarudio le 18/09/2015 à 15:18
PlacageGranby Messages postés 393 Date d'inscription mercredi 26 mars 2014 Statut Membre Derniè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:

1 réponse

PlacageGranby Messages postés 393 Date d'inscription mercredi 26 mars 2014 Statut Membre Dernière intervention 7 mars 2019 26
18 sept. 2015 à 15:35
Bonjour,

J'ai tappé dans google :
"vba ajouter référence dynamiquement"

Et j'ai trouvé ce lien
https://www.developpez.net/forums/d17755/logiciels/microsoft-office/access/vba-access/vba-ajouter-dynamiquement-reference/

Dans les réponse on trouve cette ligne de code
References.AddFromFile("C:\Program Files\Common Files\System\ado\msado21.tlb ")


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
0
Zawarudio Messages postés 14 Date d'inscription mardi 25 août 2015 Statut Membre Dernière intervention 2 octobre 2015 1
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
0
PlacageGranby Messages postés 393 Date d'inscription mercredi 26 mars 2014 Statut Membre Dernière intervention 7 mars 2019 26
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.

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

' 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


A tout hasard.
0