[VBA EXCEL] besoin d'aide pour une macro

Bonjour,

voila je suis super débutant en VBA et j'essaie de programmer une fonction complémentaire.
Mon but est de prendre comme argument une plage de cellules (plusieurs cellules sur une meme ligne ou sur une meme colone), de déterminer le nombre de cellules. A partir de là, je construis un vecteur colonne en prenant les données de la plage de cellules et une matrice.
On termine ensuite par un ou 2 petits calculs.

Je vous mets ce que j'ai écrit pour me dire ce qui ne va pas ...

Function Note(E)
' E correspond à une plage de cellules

Dim n As Integer
Dim an
Dim A, Am
Dim i As Integer, j As Integer
Dim lg As Integer, cl As Integer

Set P = Range("E")
lg = P.Rows.Count
cl = P.Columns.Count
'mes données sont sur une meme ligne ou sur une meme colonne
' et je souhaite le déterminer
If cl = 1 Then
n = lg
ElseIf lg = 1 Then
n = cl
End If

an = 2 * Pi / n

'définition de ma matrice et de mon vecteur
Dim M(n - 1, n - 1)
Dim X(n - 1, 0)

If cl = 1 Then
For i = 0 To n - 1
X(i - 1, 0) = R(i - 1, 0)
Next i
ElseIf lg = 1 Then
For i = 0 To n - 1
X(i - 1, 0) = R(0, i - 1)
Next i
End If

For i = 0 To n - 1
For j = 0 To n - 1
M(i, j) = 0
Next j
Next i

M(n - 1, 0) = 1
For i = 0 To n - 2
M(i, i + 1) = 1
Next i

'quelques petits calculs
A = 1 / 2 * Sin(an) * Transpose(X) * M * X
Am = 1 / 2 * Sin(an) * 100 ^ 2 * n
Note = A / Am

End Function

merci bp
Configuration: Windows XP
Internet Explorer 6.0

26 réponses

Résumé de la discussion

La problématique porte sur une fonction VBA Note qui prend une plage de cellules en argument et construit un vecteur colonne et une matrice avant d’effectuer quelques calculs. Des corrections essentielles consistent à remplacer les accès et boucles avec des index 0-based par des références directes, et à utiliser des tableaux dynamiques avec Redim pour les dimensions variables. La meilleure réponse recommande d’alimenter X via ActiveSheet.Cells(lg, Rng(i)) et de passer Rng() en Variant, puis d’adapter la signature en Function fNote(lg As Integer, Rng() As Variant) As Double. En complément, il faut noter que la gestion des dimensions dynamiques et des valeurs non numériques nécessite des vérifications et des conversions appropriées pour éviter des erreurs d’exécution et des résultats incorrects.

Bobot (l’IA à votre service)
  1. "variable ou procédure attendue et non un module"
    ça ne voudrait pas dire que tu aurais nommé un module Note dans ton application ? auquel cas, tu n'as pas le droit d'appeler une fonction Note aussi
    2
    1. viiiiiiiiiii !!!!!!!!!!!!!
      0
      1. cool
        0
    2. j'ai rajouté un test que j'ai inséré en début de la fonction "note" pour pallier à ce pb :

      Dim tst
      tst = 0
      For i = 0 To UBound(X)
      If Not IsNumeric(X(i, 0)) Then
      tst = tst + 1
      End If
      Next

      If tst > 0 Then
      Note = "-"
      Else

      endif
      0
      1. et ça marche ??
        0
    3. existe-t-il un test pour savoir si un élément n'est pas un nombre ??

      car en fait, le contenu de ma cellule peut etre :
      - un nombre
      - un caractète "-"
      - un texte "SO"
      - vide
      - #valeur
      0
      1. par contre il m'est encore apparu un autre problème alors que je testais ce petit prog sur une plus grande échelle et davantage de données.
        En fait je travaille sur des données chiffrées mais il peut arriver que certaines cellules contiennent "-", ce qui signifie qu'il ny' a pas de résultat. El là çà coince dans le programme au niveau de la multiplication des matrices

        la ligne :
        C(i, j) = C(i, j) + A(i, k) * B(k, j)
        est surlignée et le message d'erreur est:
        "erreur d'exécution 13 : incompatibilité de type"

        what can I do ??
        0
        1. tester la valeur et si c'est égale à "-" mettre 0
          0
      2. j'ai trouvé le pb en fait il faut considere à aprt les cas n=1 ou n=2 car mon échantillon test est de petite taille
        0
        1. çà compile !!!

          mais je crois que le résultat est faux :-(
          il doit y avoir un bug quelque part ....
          0
          1. Met des points d'arrêts (F9) et fais le tourner ligne par ligne en appuyant sur F8.

            Dans la fenetre "Variables locales" tu verras le résultat de chacune de tes variables.
            0
        2. ouais en fait j'avais appelé un module Note, d'où la confusion ..
          0
          1. Bonjour,

            Essaye ceci :

            Function Note(lg As Integer, Dim Rng() As Variant) As Long
            0
            1. non il ne veut pas du dim çà me donne

              "erreur de compilation : attendu : identificateur"
              0
            2. pfff ... naouak (chui fatigué moi)
              Function Note(lg As Integer, Rng() As Variant) As Long
              0
            3. @ShaBoodsl mais c'est pas mieux on est reparti sur l'erreur "variable ou procédure attendue et non un module"
              0
            4. @Nyck0lassur quelle ligne l'erreur ???
              0
            5. @ShaBootoujours pareil sur la première occurence de "note" est dans la procédure "notation"
              0
          2. j'ai fait quelques modifs dans le programme et voici le résultat :

            Sub Notation()

            Dim min As Integer, max As Integer
            Dim PE(1), EE(0), SE(1)
            Dim PA(0), EA(1), SA(1)
            Dim i As Integer

            Worksheets("Feuil1").Activate

            min = 2
            max = 9

            EE(0) = "B"
            PE(0) = "C"
            PE(1) = "d"
            SE(0) = "E"

            SA(0) = "f"
            EA(0) = "g"
            PA(0) = "h"
            EA(1) = "i"

            SE(1) = "j"
            SA(1) = "j"

            For i = min To max
            If Cells(i, "a") = "Eau" Then
            Cells(i, "k").Value = Note(i, PE())
            Cells(i, "l").Value = Note(i, EE())
            Cells(i, "m").Value = Note(i, SE())
            ElseIf Cells(i, "a") = "Ass" Then
            Cells(i, "k").Value = Note(i, PA())
            Cells(i, "l").Value = Note(i, EA())
            Cells(i, "m").Value = Note(i, SA())
            Next

            End Sub
            ______________________________________________________

            Function Note(lg As Integer, ParamArray Rng() As Variant) As Long

            Dim i As Integer, j As Integer, n As Integer
            Dim alpha, pi
            Dim A, Am

            'calcul du nombre de cellules
            n = UBound(Rng) + 1

            'calcul de l'angle
            pi = 4 * Atn(1)
            alpha = 2 * pi / n

            Debug.Print n

            'définition de ma matrice M
            Dim M()
            ReDim M(n - 1, n - 1)

            For i = 0 To n - 1
            For j = 0 To n - 1
            M(i, j) = 0
            Next
            Next

            M(n - 1, 0) = 1

            For i = 0 To n - 2
            M(i, i + 1) = 1
            Next

            'definition du vecteur X
            Dim X()
            ReDim X(n - 1, 0)

            For i = 0 To n - 1
            X(i, 0) = ActiveSheet.Cells(lg, Rng(i).Value)
            Next

            'création de la tranposé de X
            Dim TX()
            Call Tvect(X, TX)

            'quelques petits calculs
            Dim p1(), p2()

            Call PMAT(M(), X(), p1())
            Call PMAT(TX(), p1(), p2())

            A = 1 / 2 * Sin(alpha) * p2(0, 0)
            Am = 1 / 2 * Sin(alpha) * 100 ^ 2 * n

            Note = A / Am

            End Function
            __________________________________________________
            Sub PMAT(A(), B(), C())

            Dim i As Integer, j As Integer, k As Integer
            Dim n As Integer, M As Integer, p As Integer

            n = UBound(A, 2)
            M = UBound(A, 1)
            p = UBound(B, 2)

            ReDim C(M, p)

            For i = 0 To M
            For j = 0 To p
            For k = 0 To n
            C(i, j) = C(i, j) + A(i, k) * B(k, j)
            Next
            Next
            Next

            End Sub
            __________________________________
            Sub Tvect(X(), TX())

            Dim i As Integer, n As Integer

            n = UBound(X, 1)

            ReDim TX(0, n)

            For i = 0 To n
            TX(0, i) = X(i, 0)
            Next

            End Sub

            Quand je le lance, le message d'erreur est le suivant :
            "variable ou précédure attendue et non un module"
            et la première occurence de "note" est surlignée dans la procédure notation

            perso je ne vois pas trop où çà coince ....
            0
            1. par contre j'ai un autre problème et oui ....

              cette fois par rapport à du calcul matriciel.

              J'ai défini
              le vecteur X(n-1) et la matrice M(n-1,n-1)
              et je voudrais calculer tX*M*X avec tX représentant "transposé de X".
              J'ai marqué :
              Transpose(X) * M * X
              mais çà ne marche pas

              çà indique
              "erreur de compilation : sub ou function non définie" en surlignant la fonction "transpose" dans le code
              0
              1. j'ai peut-etre trouvé une solution à mon pb avec :

                Public Function Test(ParamArray Rng() As Variant) As Long
                Dim I As Integer, CellCount As Integer

                For I = 0 To UBound(Rng)
                CellCount = CellCount + Rng(I).Cells.Count
                Next

                Test = CellCount
                End Function

                ce qui permet d'avoir un ensemble de plages en argument.
                0
                1. ok c'est cool
                  mais comment je peux faire si je veux un nombre n de range, avec n non défini ?????????
                  that is the question ...
                  0
                  1. Ok ...

                    Ceci devrait te ravir :

                    Private Sub CommandButton1_Click()
                    
                    Debug.Print flNomDeTaFonction(Union(ActiveSheet.Range("B2:C3"), ActiveSheet.Range("E5:F5")))
                    
                    End Sub


                    Function flNomDeTaFonction(oPlg As Range) As Long
                    
                    Dim lRes As Long
                    
                    Debug.Print oPlg.Areas(1).AddressLocal
                    Debug.Print oPlg.Areas(2).AddressLocal
                    
                    'ici tu mets ta petite bidouille de calcul avec oPlg.Areas(1) et oPlg.Areas(2)  (noublie pas : ce sont des ranges)
                    'avec lRes qui stocke le resultat
                    
                    
                    flNomDeTaFonction = lRes
                    End Function
                    
                    0
                2. Tu met un bouton sur ta feuille, tu double-click dessus et tu arrives sur l'editeur vba.

                  Private Sub CommandButton1_Click()
                  
                  Debug.Print flNomDeTaFonction(ActiveSheet.Range("B2:C2"),ActiveSheet.Range("E5:C5")
                    
                  End Sub


                  Dans un module tu mets ceci :

                  Function flNomDeTaFonction(Dim oPlg1 As Range, Dim oPlg2 As Range) As Long
                  
                  Dim lRes As Long
                  
                  'ici tu mets ta petite bidouille de calcul avec oPlg1 et oPlg2 (noublie pas : ce sont des ranges)
                  'avec lRes qui stocke le resultat
                  
                  
                  fNomDeTaFonction = lRes
                  End Function
                  0
                  1. je ne vois pas du tout comment faire pour avoir en argument d'une fonction un ensemble de plage.

                    Dans la fonction SOMME par ex, je peux mettre en argument tout un ensemble de cellules contigues ou non et çà marche. Je voudrais faire la même chose ...
                    0
                    1. il faudrait une liste de range en argument dont la taille n'est pas définie
                      0
                      1. La "taille" d'un Range n'est définie que par ce que tu veux bien lui mettre dedans.
                        0
                      2. @ShaBoomais encore ....?????...????

                        moi ce que je voudrais c'est que lorsque j'indique
                        B2:C3;E5:F5
                        il comprenne
                        B2:C3 + E5:F5
                        et non
                        B2:F5
                        et ce qu'il y ait 2 plages ou plus
                        0
                      3. @Nyck0lasIl faudrait voir les fonctions Union ou bien Intersect pour voir ce cela peut resoudre ton pb.

                        Sinon tu fais 2 objets Range ...
                        0
                    2. j'ai fait quelques tests de rows et columns.count
                      et je me rends compte que lorsque je prends un ensemble de plage, il considère la plage qui recouvre tout.
                      En gros si je choisis
                      Range("B2:C3", "E5:F5")
                      il comprend
                      Range("B2:F5")
                      0
                      1. hiihaaaaaaaaaaaaaa

                        enfin quelque chose qui marche !!!!!!!!!!!

                        il m'affiche bien 1 comme résultat donc tu as raison un ensemble de plage = 1 plage
                        0
                        1. lol
                          0
                        2. Tu aurais pu voir l'affichage de :

                          Debug.Print z.Rows.Count


                          Dans la fenetre "Execution" (si elle est affichée bien sur ;p) de ton editeur vba ...
                          0
                        3. @ShaBooj'ai pas trouvé ...
                          0
                        4. @Nyck0laslol ...

                          quand tu es dans l'editeur vba, tu fais "CTRL+G"
                          0
                        5. @ShaBooçà marche !!
                          0
                      2. Remplace :

                        Debug.Print z.Rows.Count

                        Par :

                        MsgBox z.Rows.Count
                        0
                        • 1
                        • 2