[VBA EXCEL] besoin d'aide pour une macro

Nyck0las -  
ShaBoo Messages postés 406 Statut Membre -
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

  • 1
  • 2
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.

Généré automatiquement par IA
sur la base des meilleures réponses
  1. le père
     
    "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
  2. le père
     
    Bonjour,

    Dim M(n - 1, n - 1) ne marche pas, les dimensions doivent être constantes. Pour céer un tableau de dimensions variables il faut faire :
    Dim M()
    Redim M(n-1,n-1)

    Quand à savoir si l'argument passé est bien de type range... Il n'y a que toi qui peux le savoir, c'est toi qui sais comment tu appelles ta fonction ! Comment fais-tu pour l'appeler ?

    S'il te plaît quand tu dis "ça ne marche pas", précise : as-tu un message d'erreur,lequel, le résultat est-il faux ?...
    1
    1. Nyck0las
       
      mais si n est correctement défini avant, les dimensions sont constantes.

      Bien sur que je sais comment j'appelle ma fonction, ce que je voulais c'était m'assurer qu'une plage de données est bien un objet de type range et savoir comment l'utiliser après.
      0
      1. ShaBoo Messages postés 406 Statut Membre 50 > Nyck0las
         
        A quel niveau est défini ton n ? Feuille, Module, ... ???
        0
      2. le père > Nyck0las
         
        Bonjour,

        Mais si n est correctement défini avant, les dimensions sont constantes.

        Dans ton exemple initial Dim M(n-1, n-1) n est une variable puisque tu définis n par Dim n as integer.
        Attention, en informatique, une variable dont on ne change jamais la valeur n'est pas la même chose qu'une constante.
        0
    2. ShaBoo Messages postés 406 Statut Membre 50
       
      Bonjour,

      Je viens de tester l'utilisation d'une constante dans la definition de dimension d'un tableau et ça marche (idem pour 2 dimensions)

      Const cN = 10
      
      
      Sub test()
      
      Dim aTab(cN - 1, cN)
      
      Debug.Print UBound(aTab())
      
      End Sub
      


      (Je suis en Excel 2000)
      0
      1. le père > ShaBoo Messages postés 406 Statut Membre
         
        Bonjour,

        ça ne marche même QUE avec des constantes
        0
  3. le père
     
    Bonjour,

    Set P = Range("E") 

    avec ça, tu travailles sur la colonne E et non pas sur la plage E passée en paramètre
    travaille directement avec E si c'est un objet range ou à la rigueur fais set P=E
    0
  4. Nyck0las
     
    j'ai donc supprimé la ligne

    Set P = Range("E")

    et je travaille directement avec E, c'est à dire que j'ai remplacé P par E partout (d'ailleurs je ne rends compte que dans les lignes de code il ne faut pas lire R mais P)

    le message d'erreur est alors le suivant : "constante requise" en me surlignant le second n dans :

    Dim M(n - 1, n - 1)
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. Nyck0las
     
    quand je sélectionne une ou plusieurs plages de cellules en argumant de ma fonction, est-ce qu'elle le comprend ? Mon argument est bien un objet de type Range ? parce que j'ai essayé un truc tout simple :

    Function Test(Z)

    Test = Z.Areas.Count

    End Function

    et çà marche pas ...
    0
    1. ShaBoo Messages postés 406 Statut Membre 50
       
      Bonjour,

      Quel erreur as tu ?
      0
      1. Nyck0las > ShaBoo Messages postés 406 Statut Membre
         
        soit il me renvoie 0 quand il devrait me sortir 1 et #valeur pour 2 ou plus
        0
  7. Nyck0las
     
    je définis n comme constante mais je lui affecte une valeur avant de l'utiliser donc normalement çà ne devrait pas poser de problème ...

    j'ai modifié un peu mon code, voici la nouvelle version. A mon avis je crois qu'il y a un pb avec la plage de données en argument, son traitement ...

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

    Dim n As Integer
    Dim an
    Dim A, Am
    Dim i As Integer, j As Integer
    Dim E As Range

    E = P.Select

    n = 0

    For i = 1 To E.Areas.Count
    n = n + E.Areas(i).Columns.Count
    Next i

    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) = E(i - 1, 0)
    Next i
    ElseIf lg = 1 Then
    For i = 0 To n - 1
    X(i - 1, 0) = E(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
    0
    1. ShaBoo Messages postés 406 Statut Membre 50
       
      Quelques petites réflexions ... ;p

      Function Note(P)
      ' P correspond à une plage de cellules
      
      Dim n As Integer
      Dim an
      Dim A, Am
      Dim i As Integer, j As Integer
      Dim E As Range
      
      E = P.Select 'est ce bien utile ?
      
      n = 0
      
      'je ne vois pas pourquoi tu fais une boucle ici
      ' si P est une plage tu n'auras qu'un Area
      For i = 1 To E.Areas.Count
        n = n + E.Areas(i).Columns.Count
      Next i
      
      an = 2 * Pi / n
      
      'définition de ma matrice et de mon vecteur
      Dim M(n - 1, n - 1)
      Dim X(n - 1, 0) ' tu devrais le définir comme ceci : Dim X(n - 1)
      
      If cl = 1 Then  'comment est initialisé cl ?
        For i = 0 To n - 1
          X(i - 1, 0) = E(i - 1, 0)  
        Next i
      ElseIf lg = 1 Then 'comment est initialisé lg ?
        For i = 0 To n - 1
          X(i - 1, 0) = E(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


      Sinon, quels sont les erreurs que tu as ??
      0
  8. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1
     
    en fait çà peut etre un ensemble de plages du type A1:C1;G1:J1 donc il peut y avoir plusieurs areas

    pour lg et cl, c'est une erreur de ma part, il faut remplacer le paragraphe par

    For i = 0 To n - 1
    X(i - 1, 0) = E(0, i - 1)
    Next i
    0
    1. ShaBoo Messages postés 406 Statut Membre 50
       
      en fait çà peut etre un ensemble de plages du type A1:C1;G1:J1 donc il peut y avoir plusieurs areas

      Peut etre ... mais un ensemble de plage fait une plage.

      Fais un :

      Debug.Print E.Areas.Count


      Pour t'en rendre compte
      0
      1. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1 > ShaBoo Messages postés 406 Statut Membre
         
        j'ai fait cette petite macro

        Sub Try()

        Dim z As Range

        Worksheets("Feuil1").Activate

        Set z = ActiveSheet.Range("B2:C2", "E2")

        Debug.Print z.Rows.Count

        End Sub

        et quand je la lance çà semble fonctionner mais rien ne s'affiche ...
        0
  9. ShaBoo Messages postés 406 Statut Membre 50
     
    Remplace :

    Debug.Print z.Rows.Count

    Par :

    MsgBox z.Rows.Count
    0
  10. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 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. ShaBoo Messages postés 406 Statut Membre 50
       
      lol
      0
    2. ShaBoo Messages postés 406 Statut Membre 50
       
      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
      1. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1 > ShaBoo Messages postés 406 Statut Membre
         
        j'ai pas trouvé ...
        0
      2. ShaBoo Messages postés 406 Statut Membre 50 > Nyck0las Messages postés 43 Date d'inscription   Statut Membre
         
        lol ...

        quand tu es dans l'editeur vba, tu fais "CTRL+G"
        0
      3. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1 > ShaBoo Messages postés 406 Statut Membre
         
        çà marche !!
        0
  11. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1
     
    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
  12. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1
     
    il faudrait une liste de range en argument dont la taille n'est pas définie
    0
    1. ShaBoo Messages postés 406 Statut Membre 50
       
      La "taille" d'un Range n'est définie que par ce que tu veux bien lui mettre dedans.
      0
      1. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1 > ShaBoo Messages postés 406 Statut Membre
         
        mais 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
      2. ShaBoo Messages postés 406 Statut Membre 50 > Nyck0las Messages postés 43 Date d'inscription   Statut Membre
         
        Il faudrait voir les fonctions Union ou bien Intersect pour voir ce cela peut resoudre ton pb.

        Sinon tu fais 2 objets Range ...
        0
  13. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 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
  14. ShaBoo Messages postés 406 Statut Membre 50
     
    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
  15. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 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. ShaBoo Messages postés 406 Statut Membre 50
       
      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
  16. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 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
  17. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 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
  18. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1
     
    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
  19. ShaBoo Messages postés 406 Statut Membre 50
     
    Bonjour,

    Essaye ceci :

    Function Note(lg As Integer, Dim Rng() As Variant) As Long
    0
    1. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1
       
      non il ne veut pas du dim çà me donne

      "erreur de compilation : attendu : identificateur"
      0
    2. ShaBoo Messages postés 406 Statut Membre 50
       
      pfff ... naouak (chui fatigué moi)
      Function Note(lg As Integer, Rng() As Variant) As Long
      0
    3. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1 > ShaBoo Messages postés 406 Statut Membre
       
      dsl mais c'est pas mieux on est reparti sur l'erreur "variable ou procédure attendue et non un module"
      0
    4. ShaBoo Messages postés 406 Statut Membre 50 > Nyck0las Messages postés 43 Date d'inscription   Statut Membre
       
      sur quelle ligne l'erreur ???
      0
    5. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1 > ShaBoo Messages postés 406 Statut Membre
       
      toujours pareil sur la première occurence de "note" est dans la procédure "notation"
      0
  20. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1
     
    ouais en fait j'avais appelé un module Note, d'où la confusion ..
    0
  21. Nyck0las Messages postés 43 Date d'inscription   Statut Membre 1
     
    çà compile !!!

    mais je crois que le résultat est faux :-(
    il doit y avoir un bug quelque part ....
    0
    1. ShaBoo Messages postés 406 Statut Membre 50
       
      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
  • 1
  • 2