@remrem , I took the liberty of starting from your macro to make it a little more " universal " (don't blame me).
The changes are mainly focused on double reading
" Revision " versus " Revision ".
I also used the " Perplexity " AI to add text comments (AIs are still only good at this but it's still very practical).
In theory, compatibility with the Solidworks > 2022 version is also increased. (but I can't test!).
Tip:
For those who own the " Mycad " Suite, this version is supposed to be compatible with its use in Smartproperties (and therefore automatable when closing the Smartproperties Window (in the event that your revisions are generated with this utility).
This should greatly reduce the risk of bad revision between 3D and Drawings...
Example:

Option Explicit
' =====================================================
' DÉCLARATIONS GLOBALES
' =====================================================
' Ces variables globales stockent les chemins des fichiers pièce (.sldprt) et assemblage (.sldasm)
' détectés automatiquement à partir du chemin de la mise en plan (.slddrw).
' Pourquoi globales ? Pour qu'elles soient accessibles par toutes les fonctions de la macro.
Dim PrtPath As String ' Chemin complet vers la pièce référencée
Dim AsmPath As String ' Chemin complet vers l'assemblage référencé
' =====================================================
' PROCÉDURE PRINCIPALE : main()
' =====================================================
' BUT : Synchroniser la propriété "Révision/Revision" de la mise en plan vers son modèle référencé
' (pièce ou assemblage). Fonctionne avec SolidWorks 2022 et ses spécificités API.
Sub main()
On Error GoTo GestionErreur ' Gestion centralisée des erreurs
' =====================================================
' DÉCLARATION DES OBJETS SOLIDWORKS
' =====================================================
' swApp : Instance principale de SolidWorks (toujours accessible via Application.SldWorks)
Dim swApp As SldWorks.SldWorks
' swDrawModel : Document actif (la mise en plan)
Dim swDrawModel As SldWorks.ModelDoc2
' Extensions et gestionnaires de propriétés personnalisées
Dim swDrawModelDocExt As ModelDocExtension
Dim swDrawCustProp As CustomPropertyManager
' Modèle référencé (pièce ou assemblage à synchroniser)
Dim swRefModel As SldWorks.ModelDoc2
Dim swRefModelDocExt As ModelDocExtension
Dim swRefCustProp As CustomPropertyManager
Dim RefDocType As swDocumentTypes_e ' Type du document référencé
' =====================================================
' VARIABLES UTILITAIRES
' =====================================================
Dim DrawRevision As String ' Valeur de révision dans la mise en plan
Dim RefRevision As String ' Valeur de révision dans le modèle
Dim PropName As String ' Nom exact de la propriété (ex: "Revision" ou "Révision")
Dim FileError As Long ' Code d'erreur ouverture fichier
Dim FileWarning As Long ' Code d'avertissement ouverture fichier
Dim Msg As String ' Message informatif
Dim addRes As Long ' Résultat de l'ajout de propriété
' =====================================================
' ÉTAPE 1 : CONNEXION À SOLIDWORKS ET VÉRIFICATIONS
' =====================================================
Set swApp = Application.SldWorks ' Récupère l'instance SolidWorks courante
Set swDrawModel = swApp.ActiveDoc ' Document actif = mise en plan
' Vérification : un document doit être actif
If swDrawModel Is Nothing Then
swApp.SendMsgToUser2 "Aucun document actif. Ouvrez une mise en plan.", swMbWarning, swMbOk
Exit Sub
End If
' Vérification : le document actif DOIT être une mise en plan (.slddrw)
If swDrawModel.GetType <> swDocDRAWING Then
swApp.SendMsgToUser2 "Le document actif n'est pas une mise en plan.", swMbWarning, swMbOk
Exit Sub
End If
' =====================================================
' ÉTAPE 2 : DÉTECTION DU MODÈLE RÉFÉRENCÉ
' =====================================================
' Recherche automatique du fichier .sldprt ou .sldasm correspondant au .slddrw
RefDocType = RefDocTypeSearch(swDrawModel.GetPathName)
If RefDocType = 0 Then
swApp.SendMsgToUser2 "Aucun modèle référencé trouvé (.sldprt ou .sldasm).", swMbWarning, swMbOk
Exit Sub
End If
' =====================================================
' ÉTAPE 3 : OUVERTURE SILENCIEUSE DU MODÈLE
' =====================================================
' Ouverture sans interface utilisateur (swOpenDocOptions_Silent)
Select Case RefDocType
Case swDocPART ' Pièce
Set swRefModel = swApp.OpenDoc6(PrtPath, swDocPART, swOpenDocOptions_Silent, "", FileError, FileWarning)
Case swDocASSEMBLY ' Assemblage
Set swRefModel = swApp.OpenDoc6(AsmPath, swDocASSEMBLY, swOpenDocOptions_Silent, "", FileError, FileWarning)
End Select
' Vérification ouverture réussie
If swRefModel Is Nothing Or FileError <> 0 Then
swApp.SendMsgToUser2 "Échec ouverture modèle.", swMbStop, swMbOk
Exit Sub
End If
' =====================================================
' ÉTAPE 4 : LECTURE PROPRIÉTÉS M ISE EN PLAN
' =====================================================
Set swDrawModelDocExt = swDrawModel.Extension
Set swDrawCustProp = swDrawModelDocExt.CustomPropertyManager("") ' Propriétés document ("" = niveau document)
' DÉTECTION INTELLIGENTE du nom exact de la propriété révision
PropName = DetectRevisionPropertyFixed(swDrawCustProp)
Debug.Print "=== PROPNAME FINAL : '" & PropName & "' ===" ' Debug pour développeur
If PropName = "" Then
swApp.SendMsgToUser2 "Aucune propriété Révision/Revision trouvée.", swMbStop, swMbOk
GoTo NettoyageSimple
End If
' Lecture de la valeur (avec fallback si vide)
If Not GetCustomPropValue(swDrawCustProp, PropName, DrawRevision) Then
DrawRevision = "NON_RENSEIGNÉ" ' Valeur par défaut
Debug.Print "Valeur mise en plan vide ? fallback"
End If
Debug.Print "Valeur À SYNCHRONISER : '" & DrawRevision & "'"
' =====================================================
' ÉTAPE 5 : ACCÈS PROPRIÉTÉS MODÈLE RÉFÉRENCÉ
' =====================================================
Set swRefModelDocExt = swRefModel.Extension
Set swRefCustProp = swRefModelDocExt.CustomPropertyManager("") ' Propriétés du modèle
' =====================================================
' ÉTAPE 6 : SYNCHRONISATION (CRU DE LA MACRO)
' =====================================================
Debug.Print "--- DÉBUT SYNCHRO ---"
' ? IMPORTANT SolidWorks 2022 : Force la reconstruction pour rafraîchir les propriétés
swRefModel.ForceRebuild3 False ' False = ne pas afficher les messages
' Test 1 : La propriété existe-t-elle déjà dans le modèle ?
If GetCustomPropValue(swRefCustProp, PropName, RefRevision) Then
Debug.Print " ? Propriété existe : '" & RefRevision & "'"
If RefRevision <> DrawRevision Then
Debug.Print " ? MISE À JOUR nécessaire"
' Mise à jour de la valeur existante
Dim setRes As Long
setRes = swRefCustProp.Set2(PropName, DrawRevision) ' Set2 = mise à jour
Debug.Print " ? Set2 retour : " & setRes
If setRes = 0 Then
Msg = "? " & PropName & " mise à jour : " & DrawRevision
Else
Msg = "? Échec mise à jour " & PropName
End If
Else
Msg = "? Déjà OK : " & PropName & " = " & DrawRevision
End If
Else
Debug.Print " ? CRÉATION propriété manquante"
' Création avec Add2 (stable sur SolidWorks 2022)
addRes = swRefCustProp.Add2(PropName, swCustomInfoText, DrawRevision)
Debug.Print " ? Add2 retour : " & addRes
If addRes = 0 Or addRes = 2 Then ' 0=OK, 2=existe déjà
Msg = "? " & PropName & " créée : " & DrawRevision
Else
' Fallback Add3 si Add2 échoue
addRes = swRefCustProp.Add3(PropName, swCustomInfoText, DrawRevision, 0)
Debug.Print " ? Add3 fallback retour : " & addRes
If addRes = 0 Or addRes = 2 Then
Msg = "? " & PropName & " créée (Add3) : " & DrawRevision
Else
Msg = "? ÉCHEC création " & PropName & " (Add2=" & addRes & ", Add3=" & addRes & ")"
End If
End If
End If
' Debug.Print "--- SYNCHRO TERMINÉE : " & Msg & " ---"
' swApp.SendMsgToUser2 Msg, swMbInformation, swMbOk ' Décommentez pour voir le résultat
' =====================================================
' NETTOYAGE : FERMETURE MODÈLE
' =====================================================
NettoyageSimple:
If Not swRefModel Is Nothing Then
On Error Resume Next ' Ignore erreurs de fermeture
swApp.CloseDoc swRefModel.GetPathName ' Ferme sans sauvegarde
On Error GoTo 0 ' Restaure gestion erreurs normale
End If
Exit Sub
' =====================================================
' GESTION D'ERREUR CENTRALE
' =====================================================
GestionErreur:
swApp.SendMsgToUser2 "Erreur : " & Err.Description, swMbStop, swMbOk
Debug.Print "ERREUR # " & Err.Number & " : " & Err.Description
Resume NettoyageSimple ' Nettoyage avant sortie
End Sub
' =====================================================
' FONCTION : DetectRevisionPropertyFixed()
' =====================================================
' BUT : Détecte intelligemment le nom exact de la propriété révision
' Teste d'abord "Revision" ? "Révision" ? scan complet des propriétés
Function DetectRevisionPropertyFixed(CustMgr As CustomPropertyManager) As String
Dim propNames As Variant
Dim i As Long
Dim PropName As String
Dim propVal As String
Debug.Print "=== SCAN COMPLET ==="
' 1?? PRIORITÉ 1 : Test direct "Revision" (standard anglais)
If CustMgr.Get4("Revision", False, "", propVal) Then
DetectRevisionPropertyFixed = "Revision"
Debug.Print "? DIRECT : Revision"
Exit Function
End If
' 2?? PRIORITÉ 2 : Test "Révision" (standard français)
If CustMgr.Get4("Révision", False, "", propVal) Then
DetectRevisionPropertyFixed = "Révision"
Debug.Print "? DIRECT : Révision"
Exit Function
End If
' 3?? PRIORITÉ 3 : Scan complet de TOUTES les propriétés
propNames = CustMgr.GetNames ' Tableau des noms de propriétés
Debug.Print "Nb props: " & IIf(IsEmpty(propNames), 0, UBound(propNames) + 1)
If Not IsEmpty(propNames) Then
For i = 0 To UBound(propNames)
PropName = CStr(propNames(i))
Debug.Print "Prop " & i & ": '" & PropName & "'"
' Recherche insensible à la casse contenant "revision"
If InStr(LCase(PropName), "revision") > 0 Then
DetectRevisionPropertyFixed = PropName
Debug.Print "? TROUVÉ : '" & PropName & "'"
Exit Function
End If
Next i
End If
Debug.Print "? RIEN TROUVÉ"
DetectRevisionPropertyFixed = "" ' Aucune propriété trouvée
End Function
' =====================================================
' FONCTION : GetCustomPropValue()
' =====================================================
' BUT : Lit une propriété personnalisée avec gestion des valeurs vides
' RETOUR : True si propriété existe, False sinon
Function GetCustomPropValue(CustMgr As CustomPropertyManager, PropName As String, ByRef PropValue As String) As Boolean
Dim res As Boolean
Dim valOut As String, valEval As String ' valEval = valeur évaluée (résolue)
On Error Resume Next ' Ignore erreurs Get4
res = CustMgr.Get4(PropName, False, valOut, valEval) ' Lecture propriété
On Error GoTo 0 ' Restaure gestion erreurs
Debug.Print " Get4('" & PropName & "') ? res=" & res & " | val='" & valEval & "'"
If res Then
PropValue = IIf(valEval = "", "VIDE", valEval) ' Gère les valeurs vides
GetCustomPropValue = True
Else
PropValue = ""
GetCustomPropValue = False
End If
End Function
' =====================================================
' FONCTION : RefDocTypeSearch()
' =====================================================
' BUT : Détecte si le chemin .slddrw pointe vers .sldprt OU .sldasm
' Remplit les variables globales PrtPath/AsmPath
Function RefDocTypeSearch(DrawPath As String) As swDocumentTypes_e
Dim DrawPathLow As String
DrawPathLow = LCase(DrawPath) ' Minuscules pour comparaison
' Conversion automatique des noms de fichiers
PrtPath = Replace(DrawPathLow, "slddrw", "sldprt") ' Mise en plan ? Pièce
AsmPath = Replace(DrawPathLow, "slddrw", "sldasm") ' Mise en plan ? Assemblage
Debug.Print "Test pièce : " & PrtPath & " ? " & IIf(IsFileExist(PrtPath), "OK", "KO")
Debug.Print "Test assem : " & AsmPath & " ? " & IIf(IsFileExist(AsmPath), "OK", "KO")
If IsFileExist(PrtPath) Then
RefDocTypeSearch = swDocPART
Exit Function
End If
If IsFileExist(AsmPath) Then
RefDocTypeSearch = swDocASSEMBLY
End If ' Retourne 0 si aucun fichier trouvé
End Function
' =====================================================
' FONCTION UTILITAIRE : IsFileExist()
' =====================================================
' BUT : Teste l'existence d'un fichier sur disque
Function IsFileExist(FullName As String) As Boolean
IsFileExist = (Dir(FullName) <> "") ' VBA standard : Dir retourne "" si fichier inexistant
End Function