[VBA EXCEL] besoin d'aide pour une macro
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
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.
-
"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 -
viiiiiiiiiii !!!!!!!!!!!!!
-
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 -
IsNumeric(Valeur)
-
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 -
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 ?? -
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
-
çà compile !!!
mais je crois que le résultat est faux :-(
il doit y avoir un bug quelque part .... -
ouais en fait j'avais appelé un module Note, d'où la confusion ..
-
Bonjour,
Essaye ceci :
Function Note(lg As Integer, Dim Rng() As Variant) As Long
-
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 .... -
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 -
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. -
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 ...-
Ok ...
Ceci devrait te ravir :
Private Sub CommandButton1_Click() Debug.Print flNomDeTaFonction(Union(ActiveSheet.Range("B2:C3"), ActiveSheet.Range("E5:F5"))) End SubFunction 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
-
-
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
-
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 ... -
il faudrait une liste de range en argument dont la taille n'est pas définie
-
-
@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 -
@Nyck0lasIl faudrait voir les fonctions Union ou bien Intersect pour voir ce cela peut resoudre ton pb.
Sinon tu fais 2 objets Range ...
-
-
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") -
hiihaaaaaaaaaaaaaa
enfin quelque chose qui marche !!!!!!!!!!!
il m'affiche bien 1 comme résultat donc tu as raison un ensemble de plage = 1 plage -
Remplace :
Debug.Print z.Rows.Count
Par :
MsgBox z.Rows.Count
- 1
- 2