IpxBrowser : discussion sur le code VBA

Je créé ce post pour les geeks qui souhaitent discuter spécifiquement sur le code VBA de l’utilitaire

Je préfère réserver le post Utilitaire IpxBrowser pour IPX800 V5 à la diffusion des versions et aux discussion portant sur les difficultés rencontrées par les utilisateurs.
:gear: Utilitaire IpxBrowser pour IPX800 V5

Pour information, le projet a démarré en décembre 2021 et une première version a été présentée un an plus tard à @fgtoul, @grocrabe, @jweb et bien sur @gce. Avec l’aide de @fgtoul, xpool a été intégré au premier trimestre 2023.

Les premières versions intégraient le composant Tshark (de la suite WireShark) pour récupérer les informations liées aux connecteurs, aux scènes et aux règles. C’était un peu une usine à gaz.

Le projet à ensuite évolué en fonction de ma progression dans la connaissance d’IPX800V5, mais aussi de VBA (modules de classe, collections…).

Début 2024, je me suis lancé dans la « déGeekisation » de l’interface et j’ai ensuite obtenu de @Jeremy_GCE une modification d’IPX800V5 simplifiant l’accès aux informations.

Je remercie toutes les personnes citées pour leur aide et leurs soutien qu’elles m’ont apportées.

Serait-il possible à un administrateur de déplacer la réponse de @cce66 dans ce post ?

Bonne journée

6 « J'aime »

EDIT par FGTOUL : Post déplacé.

Bonjour @Michel94

Beau boulot, je me posais la question récemment sur ce développement :+1: initié il y a un paquet de mois, j’ai la réponse et quelle réponse ! :clap: :clap: :clap:

Un peti bug relevé en cliquant sur IPX

« On Error Resume Next » étant placé avant le code en cause cela empêche la poursuite du programme, néanmoins le problème est que cette instruction ne clear pas l’erreur et va propager cette erreur à d’autre endroit dans le programme !

Je te met 3 exemple de sub qui me permettais de gérer les erreurs dans mes progs VB VBA quand j’étais encore à la barre (VB et VBA vers Autocad et système wmi) !
th-3374040504

La première permet d’avoir une trace dans un fichier log, elle est à ajouter dans un module (je l’ai mise dans Module_erreur)

WriteErrLog

’ *************************************************************************
’ * Ecriture fichier erreur log
’ *************************************************************************
Public Sub WriteErrLog(strMsg As String)

On Error GoTo errSub

Dim lFile As Long, lPtr As Long, strWrite As String, strFileErrProg

strFileErrProg = App.Path & IIf(Right(App.Path, 1) = "", «  », "") & « IpxBroser.log »

’ *** si fichier absent ouvre en ecriture sinon en ajout
lFile = FreeFile
If Dir(strFileErrProg, vbNormal) = «  » Then
Open strFileErrProg For Output As lFile
Else
Open strFileErrProg For Append As lFile
End If

’ *** ecrit le msg de log, ferme et quitte
’ renvoie la longueur du fichier
lPtr = LOF(lFile)

’ si longueur = 0 definit le pointeur a 1
If lPtr = 0 Then lPtr = 1

’ positionne le pointeur du fichier
Seek #lFile, lPtr - 2

’ ecrit dans le fichier
Write #lFile, strMsg

’ ferme le fichier
Close lFile
Exit Sub

errSub:
Err.Clear
Resume Next

End Sub

La 2de permet d’ecrire dans ce fichier log en incluant le message passé en paramètre et horodater l’erreur

GestionErr

’ *************************************************************************
’ * Affiche ou ecrit sur disque gestion err
’ *************************************************************************
Public Sub GestionErr(strMsg As String)

Call WriteErrLog(Format(Now, « dd/mm/yyyy hh:mm:ss ») & " - erreur - " & strMsg)

End Sub

la 3ème est un exemple qui sert via le wmi de tuer un process (nom du process passé en paramètre, l’erreur est gérée par la ligne suivante à mettre dans toutes les procédures critiques

On Error GoTo errSub

qui en cas d’erreur trace l’erreur et la clear puis poursuit le programme de la sub ou fonction

errSub:
Call GestionErr("Erreur Sub KillProcess : " & Err.Number & " " & Err.Description & vbCrLf)
Err.Clear
Resume Next

le code exemple pour l’appel en cas d’erreur

KillProcess

’ *************************************************************************
’ * Kill les process
’ *************************************************************************
Public Sub KillProcess(strProcess)

On Error GoTo errSub

Dim oWmi, oCol, oObj, lRet As Long

Set oWmi = GetObject(« winmgmts:{impersonationLevel=impersonate}!\.\root\cimv2 »)
Set oCol = oWmi.ExecQuery(« Select * From Win32_Process Where Name = ' » & strProcess & « ' »)
For Each oObj In oCol
lRet = oObj.Terminate()
DoEvents
Next
Set oObj = Nothing
Set oCol = Nothing
Set oWmi = Nothing
Exit Sub

errSub:
Call GestionErr("Erreur Sub KillProcess : " & Err.Number & " " & Err.Description & vbCrLf)
Err.Clear
Resume Next

End Sub

Le prog ne s’arrete plus sur l’erreur

cela permet de tracer la sub dans laquelle s’est produit l’erreur et le message d’erreur propre à l’erreur avant qu’elle soit clear et ainsi elle n’est pas propagée

Quelques remarques au passage si je puis me permettre de partager mon expérience:
Dim i As Integer a proscrire Dim ii As Integer à préférer (pour le débogage c’est mieux de chercher une variable ii que i ! :wink:
il vaut mieux typer les noms de variables cela évite dans le code de mélanger les genres (notation hongroise)
boNomVariable pour un boolean
iNomVariable pour un integer
dNomVariable pour un double
strNomVariable pour un string
objNomVariable pour un objet
etc
Tu peux utiliser les constante vbLf à la place de Chr(10) vbCr pour Chr(13) et vbCrLf pour Chr(10) + Chr(13)

utiliser un max de width …end with (même si cela ne joue plus beaucoup sur les perfs actuelles c’est plus pour la clarté)

Beaucoup commenter, car j’ai souvenir d’un collègue qui commentait peu et quand il revenait sur du code quelque mois plus tard c’était la cata et surtout pour d’autres qui devaient reprendre le code !

Il est possible d’optimiser le code avec l’utilisation de iif
If errorSheet.Cells(Rows.Count, 1).End(xlUp).row >= FIRST_WORKING_ROW Then
sheetObject.Visible = xlSheetVisible
Else
sheetObject.Visible = xlSheetHidden
End If

peut être remplacé par l’utilisation de iif par
sheetObject.Visible = IIf(errorSheet.Cells(Rows.Count, 1).End(xlUp).row >= FIRST_WORKING_ROW, xlSheetVisible, xlSheetHidden)

attention au déclaration de variable : strParamFlag As Boolean
Implicitement dans le code cela laisse à penser que c’est un string alors qu’il est déclaré boolean et le code serait plus clair en précisant que la valeur vaut true dans la condition

Sinon pour le reste :+1: :clap:

utilise pour les ouverture de fichier ma méthode avec freefile comme dans mon exemple
par exemple dans un de tes sub (doublon sur startText)
Sub GetRequestsList()
Dim mainFileName As String, filePath As String, fileData As String, startOfText As Integer, endOfText As Integer, apiText As String, apiItem() As String
Dim startText As String, startApiOffset As Integer, apiPath As String, apiPathEnd As Integer, apiList As String, i As Integer, z As String
mainFileName = Dir(ActiveWorkbook.Path & « \Main.ce*.js »)
If mainFileName = «  » Then Exit Sub
filePath = ActiveWorkbook.Path & « " & mainFileName
startText = «  »« GET » », «  »/api/"
startText = «  »« /api/ »
startApiOffset = Len(startText)
Open filePath For Input As #2
Do While Not EOF(2)
Line Input #2, fileData

il vaut mieux utiliser
Dim lFile As Long
lFile = FreeFile
Open filePath For Input As lFile

etc
l’utilisation de freefile évite d’utiliser un numéro de fichier qui pourrait avoir été ouvert ailleurs dans le code

Comme je suis un gros fainéant je prend une sub au hasard du module Module_IpxConfig qui a une variable i et je demande à ChatGPT la requête suivante

requete chatGPT

remplace dans le code suivant la variable i par ii et commente le code : Sub ConnectedsGroupsEndProcessing_groupeConnected(groupObject As cIpx5_Group)
'Détecte si le groupObject contient des variables connectées. Si c’est le cas, le groupe est déclaré connecté
Dim i As Integer, variableKey() As String, variableObject As cIpx5_Variable, pairObject As cIpx5_jsonPair
If groupObject.connected Then Exit Sub
For Each pairObject In groupObject.collecVariables
If Right(pairObject.name, 1) = « . » Then
If Mid(pairObject.name, Len(pairObject.name) - 4, 1) = « _ » Then 'si la variable est partagée (share ou tag)
groupObject.connected = True
Exit Sub
End If
End If
ExtractFromList pairObject.value, variableKey()
For i = 0 To UBound(variableKey)
If Contains(collecVariable, variableKey(i)) Then
Set variableObject = collecVariable(variableKey(i))
If variableObject.connected Then
groupObject.connected = True
Exit Sub
End If
End If
Next i
Next
End Sub

Le résultat

ConnectedsGroupsEndProcessing_groupeConnected chatgpt

Sub ConnectedsGroupsEndProcessing_groupeConnected(groupObject As cIpx5_Group)
’ Cette procédure détecte si le groupObject contient des variables connectées.
’ Si c’est le cas, le groupe est déclaré connecté.

Dim ii As Integer, variableKey() As String, variableObject As cIpx5_Variable, pairObject As cIpx5_jsonPair
' Vérifie si le groupe est déjà connecté, et si oui, quitte la procédure
If groupObject.connected Then Exit Sub

' Parcourt toutes les variables de collection associées au groupe
For Each pairObject In groupObject.collecVariables
    ' Vérifie si le nom de la variable se termine par un point
    If Right(pairObject.name, 1) = "." Then
        ' Vérifie si la variable est partagée (nom contenant un underscore à une position spécifique)
        If Mid(pairObject.name, Len(pairObject.name) - 4, 1) = "_" Then
            ' Si oui, marque le groupe comme connecté et quitte
            groupObject.connected = True
            Exit Sub
        End If
    End If
    
    ' Extrait les clés de la variable et les place dans un tableau variableKey
    ExtractFromList pairObject.value, variableKey()
    
    ' Parcourt les clés extraites
    For ii = 0 To UBound(variableKey)
        ' Vérifie si la clé est présente dans collecVariable
        If Contains(collecVariable, variableKey(ii)) Then
            ' Récupère l'objet variable correspondant
            Set variableObject = collecVariable(variableKey(ii))
            
            ' Si cette variable est connectée, marque le groupe comme connecté et quitte
            If variableObject.connected Then
                groupObject.connected = True
                Exit Sub
            End If
        End If
    Next ii
Next

End Sub

Bluffant faut juste vérifier mais le temps gagné on peut le passer à faire autre chose ! :slight_smile:

J’ai pas encore parcouru tout le code, je vais le faire mais quel boulot de dingue réalisé ! :exploding_head:

Ca troue le cul de savoir que Microsoft ne soit pas capable de sortir des compilateurs sur les 2 pate forme qui soient compatibles ! :thinking:
Sous Mac sinon il reste la solution d’utiliser un émulateur windows pour y faire tourner excel dedans ! :wink:

2 « J'aime »

Bonjour @cce66,

Pourrais-je en savoir un peu plus sur le bug constaté : quelle est la valeur de text ?

La gestion des erreurs, je vais prendre un peu de temps pour analyser.

Les chr() sont des scories héritées des toutes premières versions. Cela indique que cette partie n’a pas été retouchée depuis plusieurs mois.

En principe, lorsque la liste des propriétés est longue (>3), je les utilises. Sinon, je trouve la lecture moins claire ! J’utilise aussi beaucoup set monRange = maSheet.cells(....).

Bonne journée

Private Sub CheckBox_OnOff_Click()

code origine

Private Sub CheckBox_OnOff_Click()
Dim setData As String
If CheckBox_OnOff.value = True Then
Label_OnOff.Caption = « On » ’ ************* code doublon avec la ligne plus loin
setData = « true »
Label_OnOff.backColor = &HF000&
Label_OnOff.ForeColor = 0
Else
Label_OnOff.Caption = « Off » ’ ************* code doublon avec la ligne plus loin
setData = « false »
Label_OnOff.backColor = &H404040
Label_OnOff.ForeColor = &HFFFFFF
End If

If CheckBox_OnOff Then setData = « true » Else setData = « false » ’ ************* code doublon avec les lignes plus haut

If Not setValidFlag Then Exit Sub
setData = "{""on"":" & setData & "}"
JsonSendRequest_PutVariable apiName, localVariableObject.key, setData

End Sub

code modifié à l’ancienne (sans ChatGPT quoi : :slightly_smiling_face:)

>Private Sub CheckBox_OnOff_Click()
>  Dim setData As String
>  With Label_OnOff
>    .Caption = Iif(CheckBox_OnOff.value = True, "On", "Off")
>    .backColor = Iif(CheckBox_OnOff.value = True, &HF000,  &H404040) 
>    .ForeColor = Iif(CheckBox_OnOff.value = True, 0, &HFFFFFF)
>  End With
>  setData = Iif(CheckBox_OnOff.value = True, "true", "false")
>  ' on peut aussi mettre : 
    ' setData =  (CheckBox_OnOff.value = True)
>   
>  If Not setValidFlag Then Exit Sub
> 
>  setData = "{""on"":" & setData & "}"
>  ' on peut aussi mettre (en supprimant la ligne d'affectation plus haut) : 
    setData = "{""on"":" &  (CheckBox_OnOff.value = True) & "}"
> 
>  JsonSendRequest_PutVariable apiName, localVariableObject.key, setData
>
> End Sub

Set Mode fainéant=ON; ChatGPT activation = true : :rofl: ON :exploding_head: OFF

je donne à bouffer cette sub de ta UserForm_Variable en demandant :

remplace dans ce code les conditions if par des conditions iif :
Private Sub TextBox_VariableName_Change()
If Len(TextBox_VariableName.text) > 39 Then
TextBox_VariableName.ForeColor = &HFF& 'rouge
Else
TextBox_VariableName.ForeColor = &H80000012
End If
If Not setValidFlag Then Exit Sub
If Len(TextBox_VariableName.text) > 31 Then
CommandButton_Send.Enabled = False
Else
CommandButton_Send.Enabled = True
End If
End Sub

La réponse rapide et efficace, juste s’assurer que le code est bon ! :wink:

Voici comment remplacer les conditions If par des conditions IIf dans votre code :
Private Sub TextBox_VariableName_Change()
’ Utilisation de IIf pour changer la couleur de texte en fonction de la longueur du texte
TextBox_VariableName.ForeColor = IIf(Len(TextBox_VariableName.Text) > 39, &HFF&, &H80000012)

' Si setValidFlag n'est pas défini, sortir de la procédure
If Not setValidFlag Then Exit Sub

' Utilisation de IIf pour activer ou désactiver le bouton en fonction de la longueur du texte
CommandButton_Send.Enabled = IIf(Len(TextBox_VariableName.Text) > 31, False, True)

End Sub

Explications :

  • IIf est une fonction qui permet d’évaluer une condition sur une seule ligne. Elle renvoie une valeur si la condition est vraie, et une autre si elle est fausse.
  • Dans ce code, nous l’utilisons pour la couleur du texte et pour activer ou désactiver le bouton.

La réponse avec DeepSeek Coder v-2.5 (moins connu mais très efficace, il indique que c’est du VBA alors que c’est le même code en VB6 !)

Pour remplacer les conditions if par des conditions iif dans votre code VBA, vous pouvez utiliser la fonction IIf qui est une fonction ternaire en VBA. Voici comment vous pouvez réécrire votre code :

vba

Copy code

Private Sub TextBox_VariableName_Change() TextBox_VariableName.ForeColor = IIf(Len(TextBox_VariableName.text) > 39, &HFF&, &H80000012) If Not setValidFlag Then Exit Sub CommandButton_Send.Enabled = IIf(Len(TextBox_VariableName.text) > 31, False, True) End Sub

Explication :

  • Première condition :
    • IIf(Len(TextBox_VariableName.text) > 39, &HFF&, &H80000012) : Si la longueur du texte dans TextBox_VariableName est supérieure à 39, la couleur du texte sera rouge (&HFF&), sinon elle sera &H80000012.
  • Deuxième condition :
    • IIf(Len(TextBox_VariableName.text) > 31, False, True) : Si la longueur du texte dans TextBox_VariableName est supérieure à 31, le bouton CommandButton_Send sera désactivé (False), sinon il sera activé (True).

Remarque :

  • La fonction IIf est une fonction ternaire en VBA, similaire à ? : en d’autres langages de programmation. Elle prend trois arguments : la condition, la valeur si la condition est vraie, et la valeur si la condition est fausse.
  • Bien que IIf soit pratique pour des conditions simples, il est important de noter que les deux branches de l’expression sont évaluées, même si seule une est utilisée. Cela peut avoir des implications en termes de performance ou de comportement si les branches contiennent des opérations coûteuses ou des effets de bord.

Dans UserForm_FileSelector

Private Sub CommandButton_Delete_Click()
Dim action As Integer, i As Integer
action = MsgBox(« Delete " & TextBox_FileName.value & vbCrLf & UBound(selectedValue) & " " & fileExtension & " file(s) ? », vbOKCancel, « Delete file(s) »)
If action = 1 Then
For i = 1 To UBound(selectedValue)
Kill SelectedFile(i)
Next i
LoadListBox
End If
End Sub

autre exemple d’optimisation
Private Sub CommandButton_Delete_Click()
Dim action As Integer, i As Integer
if MsgBox(« Delete " & TextBox_FileName.value & vbCrLf & UBound(selectedValue) & " " & fileExtension & " file(s) ? », vbOKCancel, « Delete file(s) ») =vbOk Then
For i = 1 To UBound(selectedValue)
Kill SelectedFile(i)
Next i
LoadListBox
End If
End Sub

On peut supprimer l’utilisation de la variable action en codant directement

Private Sub CommandButton_Delete_Click()
Dim ii As Integer
If MsgBox(« Delete " & TextBox_FileName.value & vbCrLf & UBound(selectedValue) & " " & fileExtension & " file(s) ? », vbOKCancel, « Delete file(s) ») = vbOK Then
For ii = 1 To UBound(selectedValue)
Kill SelectedFile(ii)
Next
Call LoadListBox
End If
End Sub

Attention dans cette partie de code, une erreur survenant sur kill (fichier ouvert) n’est pas gérée
Call LoadListBox plutot que LoadListBox (on sait qu’on à affaire à un appel de procédure ou fonction mais c’est un avis perso)

Private Sub ToggleButton_DownDate_Click()
If stopSortFlag Then Exit Sub
stopSortFlag = True
ToggleButton_DownName = False
ToggleButton_UpName = False
LoadListBox
stopSortFlag = False
End Sub

Private Sub ToggleButton_DownName_Click()
If stopSortFlag Then Exit Sub
stopSortFlag = True
ToggleButton_DownDate = False
ToggleButton_UpName = False
LoadListBox
stopSortFlag = False
End Sub

Private Sub ToggleButton_UpName_Click()
If stopSortFlag Then Exit Sub
stopSortFlag = True
ToggleButton_DownDate = False
ToggleButton_DownName = False
LoadListBox
stopSortFlag = False
End Sub

Les 3 codes étant identiques les passer dans une fonction SetToggleButton

Private Sub SetToggleButton()
If stopSortFlag Then Exit Sub
stopSortFlag = True
ToggleButton_DownDate = False
ToggleButton_DownName = False
LoadListBox
stopSortFlag = False
End Sub

Private Sub ToggleButton_DownDate_Click()
Call SetToggleButton
End Sub

Private Sub ToggleButton_DownName_Click()
Call SetToggleButton
End Sub

Private Sub ToggleButton_UpName_Click()
Call SetToggleButton
End Sub

Un autre bug relevé sur un clic droit à cet endroit


Mais je pense que c’est plus lié au type de donnée de la cellule

Le savoir n’a de valeur que quand il est partagé… :wink:

@fgtoul pour le coup possible de déplacer mon message sur le post dédié (le temps que je l’écrives :writing_hand: le post a été créé :slight_smile: : ) . Merci :pray:

Bonjour @Michel94

la fonction peut être améliorée en ajoutant un checkbox debogage dans les feuilles (c’est surtout pour que l’utilisateur puisses donner un contexte d’erreur)

Oui en lisant le code on voit nettement la différence entre certaines parties du code qui date du début et la progression, mais :+1: car je trouves bien plus ardu le codage vba que vb6 pur car il faut en plus maitriser les objets, propriétés et méthodes de l’appli cible ici Excel (le codage vba sur Autocad était pas mal non plus :laughing:) ! C’est pas toi qui a fait monter l’action Sanofi pour le doliprane en 2021 par hasard ? :thinking: :rofl:

C’est pour cela que je me suis permit de suggérer des voies d’amélioration car il y a une quinzaine d’années l’aide dans ce domaine c’était de la doc papeterie essentiellement aujourdh’ui c’est cool il y a la communauté, google et l’IA maintenant ! :exploding_head:

Bonne journée également

@fgtoul merci pour le déplacement :pray:

Je compte publier une version corrigeant le bug constaté par @tous30.

Avant cela, je voudrais en savoir plus sur le bug « Ipx ». Est-ce un bug constaté ? Si oui pourrais-je connaitre la valeur de la variable string « text » lors du bug ?

Pour info, le On Error Resume Next était destiné, lors du développement, à éviter le plantage lorsque un pavé rule était écrit dans dans une cellule comportant déjà un commentaire.
un .AddComment dans une cellule ayant déjà un commentaire, ça crash !
Maintenant ça ne se produit plus (la position des objets est mieux maitrisée) et, par sécurité, tous les ajouts de commentaires sont de la forme :

    .comment.Delete
    .AddComment

Edit : après test, ici, .comment.Delete plante : je remet le On Error Resume Next
J’ai modifié les chr() :innocent:

c’est dans la sub Sub DisplayCell_Rule

en traçant

MsgBox cellRange.text & " / " & text & " / " & variableObject.name

image

image

j’ai désactivé la gestion d’erreur, au passage je me suis aperçu qu’il manque le « exit sub » sinon le prog rentre dans la gestion d’erreur !

à l’affichage il va jusqu’à

point d’arrêt posé là aussi

D’ailleurs pourquoi ne pas mettre ipx800v5 au lieu d’ipx dans l’etiquette au dessus d’ipx800v4 ?

Pour info il est possible de placer des espions sur les variables. Cela permet de récupérer plus d’informations qu’un simple msgbox.

c’est avec la cellule

image

Peut être parce qu’il y a des cas ou la cellule n’a pas de commentaire à deleter, tu peux ajouter cette condition à la place de .comment.Delete comme cela il delete que si c’est pas vide

If Not .Comment Is Nothing Then .Comment.Delete
.addComment

Les togglesBouton sont des options de tri de la listBox et les trois codes sont différents : le principe est de faire l’équivalent des boutons options avec des togglesButton : chaque bouton On positionne les deux autre à Off.

Mais il est vrai que le code est un peu bourrin :flushed:

J’ai modifié :

Private Sub ToggleButton_DownDate_Click()
    If ToggleButton_DownDate.value Then SortByToggleButton 0
End Sub

Private Sub ToggleButton_DownName_Click()
    If ToggleButton_DownName.value Then SortByToggleButton 1
End Sub

Private Sub ToggleButton_UpName_Click()
    If ToggleButton_UpName.value Then SortByToggleButton 2
End Sub

Private Sub SortByToggleButton(Idx As Integer)
    Dim valueFlag(2) As Boolean
    valueFlag(Idx) = True
    ToggleButton_DownDate = valueFlag(0)
    ToggleButton_DownName = valueFlag(1)
    ToggleButton_UpName = valueFlag(2)
    LoadListBox
End Sub

J’ai mis If Not .Comment Is Nothing Then .Comment.Delete et supprimé On Error Resume Next :wink:

Pour le pb de l’Ipx, il semble être lié à une première action manquante dans la règle 0 actionnant le reboot. L’erreur serait mal interprétée par DisplayCell_Rule.

Pourrais-je avoir en messagerie privé, la copie de la configuration, pour reproduire le défaut ?
Voir 5.7 - Gestion des configurations
Il est possible d’anonymiser le fichier par la commande Create anonymized file
J’ai en peu de mal avec les .rar. Serait-il possible de l’avoir en .zip ?

ipx correspond au nom de l’onglet ipx dans l’éditeur GCE. J’essaie d’être le plus proche possible des dénominations utilisées par GCE.
Les nom utilisés sont, le plus souvent, ceux des API.

Bonjour
Un checkbox debogage me parait une bonne idée

En VBA Excel,
setData = Iif(CheckBox_OnOff.value = True, "true", "false")
est différent de
setData = CheckBox_OnOff.value = True)

Dans le deuxième cas, si la langue paramétrée est le français, on risque se retrouver avec des « VRAI » et des « FAUX ».

j’ai essayé de t’envoyer en mp le fichier mais ca passe pas, il faut que tu actives l’acceptation de fichier privé je pense

effectivement c’est logique

J’ai reçu hier le fichier de @tous30 .
En principe, si le fichier est zippé, ça passe

en cliquant sur mon logo, vous devriez intialiser une communication privée. J’en ai initialisé une de mon côté…

c’est parti, ya plus qu’a

Pour @grocrabe et d’autres il y a possibilité de faire tourner ton prog sous les 2 env

il faut déclarer une variable globale dans un module
Public strOS As String

il faut mettre cette sub dans ce module

Sub DetectOS()

strOS = Application.OperatingSystem
If InStr(strOS, "Windows") > 0 Then
      strOS ="Windows"
  ElseIf InStr(strOS, "Mac") > 0 Then
      strOS= "Mac"
  Else
     strOS="??"
End If

End Sub

ajouter un appel à cette fonction à l’ouverture du fichier dans sheet activate afin d’affecter la variable strOS
Call DetectOS

ensuite partout ou il peut y avoir une erreur sur mac utiliser cette variable pour adapter le code
Par exemple pour les chemins de fichier apparemment c’est codé "" sous windows et « / » sous mac
if strOS =« Windows » then
chemin= path avec ""
elseif strOS =« Mac »
chemin= path avec « / »
else
chemin= path avec ""
end if

il y a
Public Declare PtrSafe Sub Sleep Lib « kernel32 » (ByVal dwMilliseconds As Long)
qui appelle une lib windows qu’il faut supprimer et remplacer par une sub
Sub Pause(Milliseconds As Long)
Dim StartTime As Single
StartTime = Timer
Do While Timer < StartTime + Milliseconds / 1000
DoEvents
Loop
End Sub
il y a plus qu’a remplacer dans le code Sleep par Pause

pour le reste comme @grocrabe a un mac il pourra te dire ou ça plante