Taille de police :

×

Lecture de la page :

Lire Test2

La fonction LET et un outil de débogage lié

0
(0)

Je n'avais pas encore fait d'article sur la fonction LET et si vous êtes un lecteur de mes articles vous avez du constaté que je l'utilise souvent. J'en profite pour vous proposer une fonction personnalisée et une procédure aidant à analyser les résultats générés dans les fonctions LET.

Présentation de la fonction

Objet de la fonction

Au lieu d'utiliser plusieurs cellules/colonnes/lignes d'Excel pour réaliser des calculs intermédiaires, on va pouvoir les générer directement dans la fonction et réutiliser ces résultats "intermédiaires" pour faire un calcul final.

Tout comme en programmation, on va déclarer des variables et leurs valeurs remplaçant ces cellules/colonnes/lignes intermédiaires puis les utiliser pour un calcul final.

Syntaxe

Officielle
= LET(Nom1 ; Nom_valeur1 ; Calcul_ou_nom2 ; [Nom_valeur2 ; Calcul_ou_nom3...])

Personnelle
= LET(NomVariable1 ; ValeurVariable1 [ ; NomVariable2 ; ValeurVariable2]...[ ; NomVariable126 ; ValeurVariable126] ; Calcul_Final)

Arguments :

  • NomVariable1 à 126 ; ValeurVariable126 : 126 paires de valeurs, seule la 1ère paire est obligatoire.
    • NomVariable : Nom de la variable.
      • Il doit être unique parmi les Noms définis.
      • Ne doit pas commencer par un chiffre.
      • Les caractères suivants sont interdits : espace & " ' ( - ) = ~ # { [ | ` ^ @ ] } % * , ; : ! . / +
      • Ne doit pas correspondre à une référence de cellules : "Cas" >OK, "Cas1" > KO (2073eme colonne, ligne 1).
    • ValeurVariable : Valeur, expression, formule.
      • Ne peut utiliser une variable que si celle-ci est définie précédemment (attention à l’ordre de déclaration).
  • Calcul_Final : Formule dont la valeur sera renvoyée par la fonction LET.

Remarque :

  • En cas de conflit (même nom) entre le nom d'une variable déclaré dans la fonction LET et un nom déclaré (via le gestionnaire de noms par exemple), c'est celui déclaré dans la fonction LET qui sera utilisé par la fonction LET (il en est de même avec un nom de fonction en conflit).

Exemples d'utilisation

Exemple 1

Objectif : Récupérer dans une liste unique les personnes entre 50 et 90 ans présent dans 2 listes distinctes.

Version classique
= ASSEMB.V({"Nom"."Age"};
          FILTRE(Liste1;(Liste1[Age]>50)*(Liste1[Age]<90));
          FILTRE(Liste2;(Liste2[Age]>50)*(Liste2[Age]<90)))

Version LET
= LET(AgeMini;50;AgeMaxi;90;
     Liste1;FILTRE(Liste1;(Liste1[Age]>AgeMini)*(Liste1[Age]<AgeMaxi));
     Liste2;FILTRE(Liste2;(Liste2[Age]>AgeMini)*(Liste2[Age]<AgeMaxi));
     Resultat;ASSEMB.V({"Nom"."Age"};Liste1;Liste2);
     Resultat)

La version LET offre plusieurs avantages :

  • Plus lisible.
  • Centralisation des valeurs de seuil (50 et 90) permettant une mise à jour facile et rapide de la formule en cas de changement (2 changements au lieu de 4)
    • Pour faciliter cette mise à jour, j'ai pris l'habitude de centraliser sur la 1ère ligne les valeurs "utilisateurs" (valeur, références cellules/plages).
  • Pour faciliter le contrôle des valeurs intermédiaires calculées via les variables, je place souvent le résultat final dans une variable (ici "Resultat"). Il suffira de remplacer la dernière ligne par "Liste1" ou "Liste2" pour visualiser ces valeurs intermédiaires.

Exemple 2

Objectif : Calculer le montant d'une prime en fonction des ventes (moins de 1 000 € alors pas de prime, entre 1 000 et 2 000 € 5% du montant, plus de 2 000 € 7%).

Version classique
= SI(SOMME(TabVentes[MtVentes])<1000;
     "Pas de prime";
     SI(SOMME(TabVentes[MtVentes])<2000;
        "Prime de " & TEXTE(SOMME(TabVentes[MtVentes])*5%;"# ##0,00 €");
        "Prime de " & TEXTE(SOMME(TabVentes[MtVentes])*7%;"# ##0,00 €")))

Version optimisée
= SI(SOMME(TabVentes[MtVentes])<1000;
     "Pas de prime";
     "Prime de " & TEXTE(SI(SOMME(TabVentes[MtVentes])<2000;
                            SOMME(TabVentes[MtVentes])*5%;
                            SOMME(TabVentes[MtVentes])*7%);
                         "# ##0,00 €"))
Version LET
= LET(Total;SOMME(TabVentes[MtVentes]);
      SI(Total<1000;
         "Pas de prime";
         "Prime de " & TEXTE(SI(Total<2000;Total*5%;Total*7%);"# ##0,00 €")))

La fonction TEXTE est là pour obtenir un formatage en Euros (le formatage classique est inutilisable ici vu que le résultat final est du texte et non une valeur numérique).

La version LET dans ce cas permet d'éviter de calculer plusieurs fois la même formule SOMME(TabVentes[MtVentes]) et ainsi d'obtenir une formule plus courte, plus rapide à calculer et un fichier plus petit.

Autres exemples

Exemple à éviter : Rendre illisible une formule 😁

Basé sur de l'exemple 1.

=LET(x;50;u;90;c;FILTRE;z;Liste1[Age];e;Liste2;o;Liste1;b;Liste2[Age];k;ASSEMB.V;r;c(o;(z>x)*(z<u));g;c(e;(b>x)*(b<u));n;k({"Nom"."Age"};r;g);n)

  • Utilisation de nom pour les "Nom de variable" non expressif.
  • Ordre de déclaration des variables illogique.
  • Utilisation de la fonction cachée des variables permettant même de remplacer les noms des fonctions.
    • ici c remplace le nom de fonction FILTRE : c(o;(z>x)*(z<u)) correspond donc à FILTRE(o;(z>x)*(z<u)).
    • Pourrait quand même être utile dans certain cas notamment avec la fonction LIREDONNEESTABCROISDYNAMIQUE (nom un peu long😁).

Formule certes plus courte mais difficilement maintenable (modifiable par la suite).

Outils de débogage

Je vous propose :

  • Une Fonction à appeler dans une cellule et générant une matrice en résultat.
    ➕ Facile à utiliser, mise à jour automatique.
    ➖ Ne fonctionnant qu'à partir d'une cellule contenant une formule.
  • Une Procédure à exécuter manuellement et générant une nouvelle feuille en résultat.
    ➕ Fonctionne aussi à partir d'une cellule contenant le texte d'une formule.
    ➖ Mise à jour manuelle en réexécutant la procédure.

Pour utiliser ces outils plus facilement vous pourriez :

  • Placer la fonction dans un classeur Complément (.xlam) chargé au démarrage d'Excel.
  • Placer la procédure dans le classeur de macros personnelles.

La fonction

Nécessite la présence des fonctions utilitaires présentées plus bas.

Utilisation

Fonction de test en B4 :

=LET(
cstNum;5,2;
cstTxt;"1forme ; "".fr";
cstTxt2;"1fo[r[m'e.#@fr";
cstMat1;{"ee";"m[;@{'}'[mm"};
cstMat2;{5;6};
cstMat3;{1.3,5.7;2.4.-6};
cellule1;A1;
cellule2;'Fe;u''il2'!B2;
cellule3;'Fe''''u,il4'!B2;
cellule4;'Feu"il5'!B2;
nom;UnNom;
refStruct1;Tableau1[A;''{g"e];
refStruct2;Tableau1[Vi''l'[le];
refStruct3;Tableau1[[A;''{g"e]:[Vi''l'[le]];
plage;A1:B3;
form1;4/0;
form2;5+cstNum+NBCAR(cstTxt);
form3;LET(v_1;SOMME(NBCAR(cstMat1));v_2;INDEX(cstMat3;1;2);v_1+v_2);
form4;cellule1+SOMME(plage);
formMat;INDEX(plage;2;0);
form2+form3)

Formule dans la cellule de destination :

=EvalLET(B4)

Résultat :

Matrice résultat de l'utilisation de la fonction EvalLET

(La mise en forme a été ajoutée manuellement)

Code

Public Function EvalLET(cellRef As Range, Optional Separator) As Variant
    ' Objectif    : Générer une matrice des paramètres (Nom, définition et valeur) de la fonction LET sélectionnée
    ' Utilisation : Comme une fonction classique d'Excel. Commencer à saisir "=EvalLET(" dans la cellule de destination.
    '                   > cellRef : La cellule contenant la fonction LET
    '                   > Separator : Facultatif, le séparateur utilisé (par défaut, celui configuré dans Excel)
    ' Retour      : Matrice de 3 colonnes (Nom, définition et valeur).
    ' Auteur      : Arnaud (www.1forme.fr).
    ' Licence     : CC-BY-NC-SA (Vous pouvez diffuser/partager/modifier cette macro dans les
    '               même conditions, seulement à titre personnel et citant l'auteur/site d'origine.
    Dim strF        As String, strFL            As String   ' Texte de la formule version US (nécessaire pour eval)/FR (Locale)
    Dim intPosPar   As Integer                              ' Position de la parenthèse ouvrante de =LET(
    Dim strInsideF  As String, strInsideFL      As String   ' Texte entre les parenthèses de la formule version US/FR (Locale)
    Dim strPartsF() As String, strPartsFL()     As String   ' Texte des arguments version US/FR (Locale)
    Dim dicVars     As Object                               ' Dico des variables pour les substituer dans les définitions
    Dim out()       As Variant                              ' Tableau résultats
    Dim i           As Long, lgNbVar            As Long
    Dim strVarName  As String                               ' Nom de la variable
    Dim strDefF     As String, strDefFL         As String   ' Définition de la variable version US/FR (Locale)
    Dim strDefF2    As String                               ' Définition de la variable version US avec remplacement des variables
    Dim varValV     As Variant                              ' Valeur de la variable
    Dim strDerDef   As String
    
    If IsMissing(Separator) Then Separator = Application.International(xlListSeparator)
    strF = cellRef.Formula2
    strFL = cellRef.Formula2Local
    intPosPar = InStr(1, strF, "(") + 1
    If Replace(Left$(strF, intPosPar - 1), " ", "") <> "=LET(" Then EvalLET = "#NOT_LET_FUNCTION!": Exit Function
    ' Contenu interne du LET() anglais et français
    strInsideF = Mid$(strF, intPosPar, Len(strF) - intPosPar)
    strInsideFL = Mid$(strFL, intPosPar, Len(strFL) - intPosPar)
    ' Découpage intelligent top-level
    strPartsF = SplitTopLevel(strInsideF, ",")
    strPartsFL = SplitTopLevel(strInsideFL, Separator)
    
    lgNbVar = (UBound(strPartsF) + 1) \ 2 + 1 ' Nombre total éléments LET
    ReDim out(0 To lgNbVar, 0 To 2)
    ' Entêtes
    out(0, 0) = "Paramètre"
    out(0, 1) = "Définition"
    out(0, 2) = "Valeur"
    Set dicVars = CreateObject("Scripting.Dictionary")

    ' Évaluer chaque variable
    For i = 0 To lgNbVar - 2
        strVarName = strPartsF(2 * i)
        strDefF = strPartsF(2 * i + 1)
        strDefFL = "=" & strPartsFL(2 * i + 1)
        strDefF2 = ReplaceLETVariables(strDefF, dicVars) ' On remplace les variables déjà définies
        varValV = Evaluate2(strDefF2)
        
        If TypeName(varValV) <> "Error" Then
            If TypeName(varValV) = "String" And Left(varValV, 1) <> "{" Then ' Chaîne mais pas matrice, doublement des "
                varValV = """" & Replace(varValV, """", """""") & """"
            End If
        End If
        dicVars.Add strVarName, varValV ' Ajout au dico

        ' Tableau final
        out(i + 1, 0) = strVarName
        out(i + 1, 1) = strDefFL
        out(i + 1, 2) = varValV
    Next i

    ' Résultat final LET
    strDerDef = strPartsF(UBound(strPartsF))
    strDerDef = ReplaceLETVariables(strDerDef, dicVars) ' On remplace les variables déjà définies

    out(lgNbVar, 0) = "Formule finale"
    out(lgNbVar, 1) = "=" & strPartsFL(UBound(strPartsFL))
    out(lgNbVar, 2) = Evaluate2(strDerDef)
    EvalLET = out
End Function

La procédure

Nécessite la présence des fonctions utilitaires présentées plus bas.

Utilisation

On sélectionne la fonction de test en B4 dans la feuille "dev" puis on exécute la macro/procédure "AnalyseLET".

Résultat :

Tableau résultat de l'utilisation de la procédure AnalyseLET

Ici on pourrait sélectionner la cellule B19 (contient du texte et non une formule) pour relancer la macro mais elle échouera du fait de la non-définition des variables "cstMat1" et "cstMat3" (extérieures à cette fonction LET). Dans ce cas, la feuille de réponse ayant déjà été créée Excel vous demandera si vous voulez la supprimer.

Code

Public Sub AnalyseLET()
    ' Objectif    : Génère la liste des paramètres (Nom, définition et valeur) de la fonction LET sélectionnée dans une nouvelle feuille
    ' Utilisation : Sélectionner la cellule contenant la formule ou le texte représentant la fonction LET à analyser puis lancer la macro.
    ' Retour      : Tableau de 3 colonnes (Nom, définition et valeur) dans une nouvelle feuille ayant comme suffixe l'adresse de la cellule.
    ' Auteur      : Arnaud (www.1forme.fr).
    ' Licence     : CC-BY-NC-SA (Vous pouvez diffuser/partager/modifier cette macro dans les
    '               même conditions, seulement à titre personnel et citant l'auteur/site d'origine.
    Dim strF         As String, strFL            As String   ' Texte de la formule version US (nécessaire pour eval)/FR (Locale)
    Dim intPosPar    As Integer                              ' Position de la parenthèse ouvrante de =LET(
    Dim strInsideF   As String, strInsideFL      As String   ' Texte entre les parenthèses de la formule version US/FR (Locale)
    Dim strPartsF()  As String, strPartsFL()     As String   ' Texte des arguments version US/FR (Locale)
    Dim dicVars      As Object                               ' Dico des variables pour les substituer dans les définitions
    Dim i            As Long, lgNbVar            As Long
    Dim strVarName   As String                               ' Nom de la variable
    Dim strDefF      As String, strDefFL         As String   ' Définition de la variable version US/FR (Locale)
    Dim strDefF2     As String                               ' Définition de la variable version US avec remplacement des variables
    Dim varValV      As Variant                              ' Valeur de la variable
    Dim strDerDef    As String
    Dim objWs        As Worksheet
    Dim objActivWs   As Worksheet
    Dim strWsName    As String
    Dim strSeparator As String
    
    If ActiveCell.HasFormula Then
        strF = ActiveCell.Formula2
        strFL = ActiveCell.Formula2Local
    Else
        strF = ActiveCell.Value2 ' Dans ce cas c'est en réalité la version local (FL) !
    End If
    intPosPar = InStr(1, strF, "(") + 1
    If Replace(Left$(strF, intPosPar - 1), " ", "") <> "=LET(" Then MsgBox "Pas LET": Exit Sub
    
    strSeparator = Application.International(xlListSeparator)
    Set objActivWs = ActiveSheet
    strWsName = "Let_" & objActivWs.Name & "_" & ActiveCell.Address(False, False)
    On Error Resume Next
    Set objWs = ActiveWorkbook.Sheets(strWsName)
    On Error GoTo erreur
    If objWs Is Nothing Then ' La feuille n'existe pas, on la crée
        Set objWs = ActiveWorkbook.Sheets.Add
        objWs.Name = strWsName
    Else
        objWs.Cells.Clear ' La feuille existe, on efface son contenu
    End If
    objActivWs.Activate
    If strFL = "" Then ' Génération d'un nom pour récupérer la version US
        objWs.Range("A2").Formula2Local = strF
        strFL = strF
        strF = objWs.Range("A2").Formula
        objWs.Range("A2").ClearContents
    End If
    
    ' Contenu interne du LET() anglais et français
    strInsideF = Mid$(strF, intPosPar, Len(strF) - intPosPar)
    strInsideFL = Mid$(strFL, intPosPar, Len(strFL) - intPosPar)
    ' Découpage intelligent top-level
    strPartsF = SplitTopLevel(strInsideF, ",")
    strPartsFL = SplitTopLevel(strInsideFL, strSeparator)

    lgNbVar = (UBound(strPartsF) + 1) \ 2 + 1 ' Nombre total éléments LET
    ' Entêtes
    objWs.Range("A1").Value = "Paramètre"
    objWs.Range("B1").Value = "Définition"
    objWs.Range("C1").Value = "Valeur"
    Set dicVars = CreateObject("Scripting.Dictionary")

    ' Évaluer chaque variable
    For i = 0 To lgNbVar - 2
        strVarName = strPartsF(2 * i)
        strDefF = strPartsF(2 * i + 1)
        strDefFL = "'=" & strPartsFL(2 * i + 1)
        strDefF2 = ReplaceLETVariables(strDefF, dicVars) ' On remplace les variables déjà définies
        varValV = Evaluate2(strDefF2)

        If TypeName(varValV) <> "Error" Then
            If TypeName(varValV) = "String" And Left(varValV, 1) <> "{" Then ' Chaîne mais pas matrice, doublement des "
                varValV = """" & Replace(varValV, """", """""") & """"
            End If
        End If
        dicVars.Add strVarName, varValV ' Ajout au dico

        ' Tableau final
        objWs.Range("A" & i + 2).Value = strVarName
        objWs.Range("B" & i + 2).Value = strDefFL
        objWs.Range("C" & i + 2).Value = varValV
    Next i

    ' Résultat final LET
    strDerDef = strPartsF(UBound(strPartsF))
    strDerDef = ReplaceLETVariables(strDerDef, dicVars) ' On remplace les variables déjà définies
    objWs.Range("A" & lgNbVar + 1).Value = "Formule finale"
    objWs.Range("B" & lgNbVar + 1).Value = "'=" & strPartsFL(UBound(strPartsFL))
    objWs.Range("C" & lgNbVar + 1).Value = Evaluate2(strDerDef)
    objWs.Columns("A:B").EntireColumn.AutoFit ' 3eme colonne non ajusté volontairement
fin:
    Set objWs = Nothing
    Set objActivWs = Nothing
    Exit Sub
erreur:
    If Not objWs Is Nothing Then objWs.Delete
    GoTo fin
End Sub

Fonctions utilitaires

Ces fonctions sont nécessaires pour les 2 solutions Procédure et Fonction.

Private Function ReplaceLETVariables(ByVal strDef As String, ByVal dicVars As Object) As String
    ' Remplace les variables dans les définitions
    ' Appellée par : EvalLET / AnalyseLET
    Dim i           As Long, n          As Long
    Dim strChar     As String, strIdent As String
    Dim boInString  As Boolean
    Dim strResult   As String

    i = 1
    n = Len(strDef)
    While i <= n
        strChar = Mid$(strDef, i, 1)
        ' Gestion des chaînes
        If strChar = """" Then
            boInString = Not boInString
            strResult = strResult & strChar
            i = i + 1
            GoTo NextChar
        End If

        If boInString Then
            strResult = strResult & strChar
            i = i + 1
            GoTo NextChar
        End If
        ' Détection identifiant
        If strChar Like "[A-Za-z_ÀÂÄÉÈËÊÎÏÔÖÙÛÜàâäéèëêîïôöùûü]" Then '
            strIdent = strChar
            i = i + 1
            While i <= n And (Mid$(strDef, i, 1) Like "[A-Za-z0-9_.ÀÂÄÉÈËÊÎÏÔÖÙÛÜàâäéèëêîïôöùûü]")
                strIdent = strIdent & Mid$(strDef, i, 1)
                i = i + 1
            Wend
            If dicVars.Exists(strIdent) Then
                If IsNumeric(dicVars(strIdent)) Then
                    strResult = strResult & Replace(dicVars(strIdent), ",", ".")
                Else
                    strResult = strResult & dicVars(strIdent)
                End If
            Else
                strResult = strResult & strIdent
            End If
            GoTo NextChar
        End If
        ' Sinon caractère normal
        strResult = strResult & strChar
        i = i + 1
NextChar:
    Wend
    ReplaceLETVariables = strResult
End Function

Private Function SplitTopLevel(strInside As String, strSep) As Variant
    ' Tokenise en découpant les arguments de la fonction LET en se basant sur les ";" mais
    '   en ignorant les ";" qui sont dans des parenthèses (arguments
    '   de sous fonctions) ou dans des guillemets (ponctuation)
    ' Caractères problématiques :
    ' []{}";' ne sont pas acceptés dans les noms définis
    ' []      ne sont pas acceptés dans les noms des feuilles
    ' Pas de limite pour le nom des colonnes des tableaux structurés
    '   Carac d'échappement ' pour []'#@
    ' []{}";' ne sont pas acceptés dans les noms des tableaux structurés
    
    ' Appellée par : EvalLET / AnalyseLET
    Dim strParts()  As String                       ' Tableau résultat
    Dim strBuf      As String, strCh    As String   ' Buffer, caractère
    Dim lgLevel     As Long
    Dim boInString  As Boolean, boInSheetName As Boolean, boInStructRef As Boolean
    ' Pour les cas ou un ; est dans une chaîne, dans le nom d'une feuille,
    ' dans une référence structurée (; dans nom des colonnes, non accepté par Excel pour le nom du tableau)
    Dim intNbAppSh  As Integer
    Dim intNbCrocO  As Integer
    Dim boCarEchap  As Boolean ' C'est un caratère d'echapement
    Dim boCarSuiteEchp As Boolean ' C'est le caratère d'echapé
    Dim intNbCarIns As Integer
    Dim i           As Long

    ReDim strParts(0 To 0)
    strBuf = ""
    intNbCarIns = Len(strInside)
    For i = 1 To intNbCarIns
        strCh = Mid$(strInside, i, 1)
        If i < intNbCarIns Then _
            boCarEchap = (strCh = "'") And (InStr("[]'#@", Mid$(strInside, i + 1, 1)) > 0)
        Select Case strCh
            Case """"       ' Chaîne : Bascule In/Out
                If Not boInSheetName And (intNbCrocO = 0) Then boInString = Not boInString
                strBuf = strBuf & strCh
            Case "'"        ' feuille : Bascule In/Out
                If Not boCarEchap And Not boInString And Not boCarSuiteEchp Then boInSheetName = Not boInSheetName
                strBuf = strBuf & strCh
            Case "["        ' Bascule In/Out ("[", "]" non autorisés dans le nom des feuilles)
                If Not boInString And Not boCarSuiteEchp Then intNbCrocO = intNbCrocO + 1
                strBuf = strBuf & strCh
            Case "]"        ' Bascule In/Out ("[", "]" non autorisés dans le nom des feuilles)
                If Not boInString And Not boCarSuiteEchp Then intNbCrocO = intNbCrocO - 1
                strBuf = strBuf & strCh
            Case "(", "{"
                If Not boInString And Not boInSheetName And (intNbCrocO = 0) Then lgLevel = lgLevel + 1
                strBuf = strBuf & strCh
            Case ")", "}"
                If Not boInString And Not boInSheetName And (intNbCrocO = 0) Then lgLevel = lgLevel - 1
                strBuf = strBuf & strCh
            Case strSep
                'Debug.Assert strBuf <> "refStruct2"
                If lgLevel = 0 And Not boInString And Not boInSheetName And (intNbCrocO = 0) Then ' Chgt d'arguments de 1er niveau
                    strParts(UBound(strParts)) = Trim$(strBuf)
                    ReDim Preserve strParts(0 To UBound(strParts) + 1)
                    strBuf = ""
                Else
                    strBuf = strBuf & strCh
                End If
            Case Else
                ' Traitement des retours à la lignes (Alt+Entrer) servant à la présentation
                If Asc(strCh) <> 10 Then strBuf = strBuf & strCh
        End Select
        boCarSuiteEchp = boCarEchap
    Next i
    strParts(UBound(strParts)) = Trim$(strBuf)
    SplitTopLevel = strParts
End Function

Private Function Evaluate2(strDef As String)
    ' Version de "Evaluate" qui transforme les résultats tableau 2D (ex: range) en une chaîne du type "{1,2;3,4}"
    ' Appellée par : EvalLET
    Dim vaValDef    As Variant
    Dim r           As Long, c      As Long
    Dim strValMat   As String
    Dim strRes      As String
    Dim lgRmin      As Long, lgRmax As Long
    Dim lgCmin      As Long, lgCmax As Long
    
    vaValDef = Evaluate(strDef)
    If Not IsArray(vaValDef) Then Evaluate2 = vaValDef: Exit Function
    
    If Not IsArrayDim2(vaValDef) Then
        lgRmin = 1: lgRmax = 1
        lgCmin = LBound(vaValDef): lgCmax = UBound(vaValDef)
    Else
        lgRmin = LBound(vaValDef, 1): lgRmax = UBound(vaValDef, 1)
        lgCmin = LBound(vaValDef, 2): lgCmax = UBound(vaValDef, 2)
    End If
    For r = lgRmin To lgRmax
        For c = lgCmin To lgCmax
            If IsArrayDim2(vaValDef) Then
                strValMat = FormatCellValue(vaValDef(r, c))
            Else
                strValMat = FormatCellValue(vaValDef(c))
            End If
            strRes = strRes & strValMat
            If c < lgCmax Then strRes = strRes & ","
        Next c
        If r < lgRmax Then strRes = strRes & ";"
    Next r
    Evaluate2 = "{" & strRes & "}"
End Function

Private Function IsArrayDim2(varTab As Variant) As Boolean
    ' Teste si varTab à 2 dimensions
    ' Appelée par : Evaluate2
    Dim lgTmp As Long

    On Error Resume Next
    lgTmp = LBound(varTab, 2)
    IsArrayDim2 = (Err.Number = 0)
    Err.Clear
End Function

Private Function FormatCellValue(vaVal As Variant) As String
    ' Formatage des données du tableau
    ' Appelée par : Evaluate2
    Dim strValMat As String

    If IsNumeric(vaVal) Then
        strValMat = vaVal
    Else
        strValMat = """" & vaVal & """"
    End If
    If strValMat = "" Then strValMat = "0"
    strValMat = Replace(strValMat, ",", ".") ' format US
    FormatCellValue = strValMat
End Function

Merci pour votre attention bienveillante.

Article intéressant ?

Cliquez sur une étoile pour noter cet article !

Note moyenne 0 / 5. Nombre de votes : 0

Aucun vote pour l'instant ! Soyez le premier à noter ce post.

Nous sommes désolés que cet article ne vous ait pas été utile !

Améliorons cet article !

Dites nous comment nous pouvons améliorer cet article ?

Publications similaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *