Comment utiliser un tableau ?
Bonjour,
J'ai un programme où je dois envoyer mon tableau dans une fonction, puis une fois les valeurs du tableau modifiées, renvoyer ces dernières à ce même tableau.
J'ai l'habitude d'utiliser les pointeurs mais là je bloque, je n'arrive pas à trouver la casse précise qu'il faut utiliser lorsqu'on se sert des tableaux et mon programme m'indique "Impossible d'affecter à un tableau" quand je retourne la fonction.
Voici les lignes principales :
Dim tabPlage(3) As Variant
' ...
tabPlage = plageAAC(fAna2016, tabPlage)
' ...
Function plageAAC(class As Workbook, tableau() As Variant)
Dim classeur As Workbook
Dim feuille As Worksheet
Set classeur = class
Set feuille = classeur.Worksheet(1)
Dim i As Integer, debut As Integer
i = 0
While feuille.Cells(i, 1) <> "AAC"
i = i + 1
Wend
taleau(0) = i
i = i + 1
While feuille.Cells(i, 1) <> "AQU"
i = i + 1
Wend
tableau(1) = i
End Function
Quelqu'un saurait m'indiquer d'où vient le problème ? :/
Merci d'avance !
- Messages
- 2'415
- Excel
- 2019
- Inscrit
- 13/07/2017
- Emploi
- Formateur, animateur,tech.informatique
Bonjour toutes et tous
1/ J'ai un doute avec la même variable ===> i <===
Exemple peut-être: Dim i, j, k As integer
tableau(1) = i & j & k
ou
@ tester car aucune idée
2/ à corriger manque lettre b: ===> taleau(0) = i
tableau(0) = i
je vois aussi tableau(1) ?
crdlt,
André
Bonjour,
il faut affecter le résultat au nom de la fonction personnalisée. Ex :
Dim tabPlage(3) As Variant
' ...
tabPlage(1) = plageAAC(fAna2016)
' ...
Function plageAAC(class As Workbook)
'...
plageAAC = i
End Function
comme en plus tu ne calcules pas tout le tableau d'un coup mais un seul élément, il faut affecter ta fonction à l'indice que tu veux mettre à jour.
Par ailleurs, pourquoi :
Dim classeur As Workbook
alors que tu as class qui a été passé et qui est utilisable ?
et :
Set feuille = classeur.Worksheet(1)
tu cours le risque de retourner n'importe quoi si qq'un bouge les feuilles...
eric
Merci pour les réponses !
André :
Oui, effectivement j'avais mal écrit tableau, et du coup comme j'ai besoin de renvoyer un tableau je peux pas utiliser 3 lettres différentes, je ne pourrais en renvoyer qu'une seule !
Eric :
1) Le soucis est que je veux renvoyer un tableau, mais que je ne sais pas si cela est possible. Si non, y a t-il un moyen de "renvoyer" plusieurs valeurs à la fin de la fonction comme avec des pointeurs ?
2) C'est vrai que y avait pas besoin, j'y ai pas trop réfléchit à ce moment là !
3) Chaque classeur ne possède qu'une seule feuille, donc ça ne devrait pas poser problème même si je sais que c'est pas très optimisé !
Je te donne le code complet au cas où (j'ai essayé de commenté le mieux que j'ai pu) mais avec les fichiers ça risque d'être compliqué vu que c'est confidentiel.. S'il les faut absolument je veux bien essayé de les censurer
Sub calcul()
' ------ DECLARATION ------
' Workbooks
Dim synthese As Workbook, ana2016 As Workbook, ana2017 As Workbook, ana2018 As Workbook, classeur As Workbook
Set synthese = Workbooks("synthese 2015-2018")
Set ana2016 = Workbooks("Balance analytique 2015 2016")
Set ana2017 = Workbooks("Balance analytique 2016 2017")
'Set ana2018 = Workbooks("Balance analytique 2017 2018")
'Worksheets
Dim fSynthese As Worksheet, fAna2016 As Worksheet, fAna2017 As Worksheet, fAna2018 As Worksheet, feuille As Worksheet
Set fSynthese = synthese.Worksheets(1)
Set fAna2016 = ana2016.Worksheets(1)
Set fAna2017 = ana2017.Worksheets(1)
'Set fAna2018 = ana2018.Worksheets(1)
Dim somme As Variant
Dim debut As Integer, taille As Integer, nbFeuilles As Integer, x As Integer
ReDim tabPlage(3) As Variant
' ------ INITIALISATION ------
somme = 0
debut = 0
taille = 0
nbFeuilles = fSynthese.Range("A17")
' ------ CODE ------
For i = 1 To nbFeuilles ' Parcours chaque année
' Attribution plage de la feuille entre AAC et AQU
If i = 1 Then
Set feuille = fAna2016
ElseIf i = 2 Then
Set feuille = fAna2017
End If
tabPlage = plage(feuille, tabPlage)
' AAC puis AQU
For j = 1 To 2
If j = 1 Then
debut = 19
x = 1 ' Indice de début plage AQU
Else
debut = 43
x = 0 ' Indice de début plage AAC
End If
' Préparation plage synthese
For k = debut To debut + 18
somme = 0
taille = Len(CStr(fSynthese.Cells(k, 2)))
If Not (IsEmpty(fSynthese.Cells(k, 2))) Then ' Si dans synthèse il y a un n° de compte
For n = tabPlage(x) To tabPlage(x + 1) ' plage AAC ou AQU
If Left(classeur.Worksheet(1).Cells(n, 1) = fSynthese.Cells(k, 2), taille) Then ' S'il y a correspondance de compte entre les deux classeurs
somme = somme + classeur.Worksheet(1).Cells(n, 15)
End If
Next n
End If
Next k
Next j
Next i
End Sub
Function plage(feuille As Workbook, tableau() As Variant)
Dim i As Integer, debut As Integer
i = 0
While feuille.Cells(i, 1) <> "AAC"
i = i + 1
Wend
tableau(0) = i
i = i + 1
While feuille.Cells(i, 1) <> "AQU"
i = i + 1
Wend
tableau(1) = i
While feuille.Cells(i, 1) <> "Total"
i = i + 1
Wend
tableau(2) = i
plage = tableau
End Function
Pour la fonction il y a en colonne A des numéros de compte comptable de format "7012000" par exemple. Cependant il y a 2 entreprises, AQU et AAC, qui peuvent avoir les même numéros de compte mais nous voulons le détail de chaque entreprise, il faut donc déterminer de où à où va AAC, et de où à où va AQU. Il faut donc chercher entre ces numéros de compte où se situe AAC pour le début de la plage AAC, AQU pour le début de la plage AQU/fin de la plage AAC et total, pour la fin de la plage AQU
Le soucis maintenant c'est que cette ligne :
tabPlage = plage(feuille, tabPlage)
me donne l'erreur 13 "incompatibilité de type" alors que le tableau est en variant.. des idées ?
Merci d'avance !
Bonjour,
Une feuille c'est As Worksheet et non As Workbook.
Encore une fois, tu n'as pas à passer en paramètre la variable sensée recevoir le résultat puisque c'est la fonction elle même qui retourne le résultat lorsque qu'elle affectée à la variable. Tu écris : a=ta_fonction(x) et non a=ta_fonction(x,a)
Il vaut mieux rechercher ta valeur plutôt que de lire toute les cellules une par une, c'est beaucoup plus rapide.
Comme tu fais 3 fois la même chose, autant mettre dans une boucle cette partie de code.
A tester :
Sub test()
Dim a
a = plage(Sheets("Feuil1"))
End Sub
Function plage(feuille As Worksheet)
Dim i As Integer, tabl(), c As Range, cherche
cherche = Array("AAC", "AQU", "Total")
ReDim tabl(0 To UBound(cherche))
For i = 0 To UBound(tabl)
Set c = feuille.Columns(1).Find(cherche(i), , xlValues, xlWhole)
If c Is Nothing Then
' #VALEUR! si non trouvé,tu peux mettre =0 si tu trouves ça plus pratique à tester ensuite
tabl(i) = CVErr(xlErrValue)
Else
tabl(i) = c.Row
End If
Next i
plage = tabl
End Function
tu peux changer le nombre de valeurs recherchées dans l'Array, la fonction s'adaptera en conséquence.
eric
Oui, j'ai voulu changer trop vite et j'ai oublié de rectifier le type, merci ! Et c'est vrai que je n'ai pas besoin d'envoyer le tableau vu que je ne l'utilise pas :c
Wow, à vrai dire ton code dépasse un petit peu mes compétences Excel actuelles (je n'ai pas l'habitude de UBound et le Java m'a un peu traumatiser pour la gestion des erreurs).
Mais c'est vrai que c'est plus pratique pour éviter de boucler à l'infini sur une mauvaise manip.
Par contre je ne comprends pas pourquoi la recherche est supposée plus rapide ? Dans tous les cas on passe par une fonction tier et en terme d'itération et d'exécution on les deux doivent être équivalent vu qu'il faudra toujours comparer les cellules, non ?
Un énorme merci Eric !
F1 sur les fonctions qu'on ne connait pas, on progresse très vite ainsi
Lire une cellule est très lent, et tu le fais à multiple reprises dans une boucle.
Lire toute ta colonne en une fois dans une variable tableau pour rechercher dedans serait déjà considérablement plus rapide.
Faire une recherche est presque instantané, tu peux avoir un gain de l'ordre de x100.
eric
Merci pour l'astuce, je n'avais pas vu qu'avec F1 on pouvait faire une recherche rapide
Cherche est donc plus rapide ? J'ai tendance à oublier le fait que les fonctions des langages haut niveau sont fait pour être optimisées, mais sans la spécification formelle c'est compliqué de se faire une idée :s
Une dernière petite question : "Total" apparaît 2 fois dans ma colonne et je voudrais sélectionner uniquement le 2ème pour prendre son numéro de ligne, il faut que je rajoute quoi à la fonction ? :c
Merci d'avance !
Function plage(feuille As Worksheet)
Dim i As Integer, tabl(), c As Range, c2 As Range
Dim cherche
cherche = Array("AAC", "AQU", "Total")
ReDim tabl(0 To UBound(cherche))
Set c2 = [A1]
For i = 0 To UBound(tabl)
Set c = feuille.Columns(1).Find(cherche(i), c2, xlValues, xlWhole)
If c Is Nothing Then
' #VALEUR! si non trouvé,tu peux mettre =0 si tu trouves ça plus pratique à tester ensuite
tabl(i) = CVErr(xlErrValue)
Else
If cherche(i) = "Total" Then
' chercher le suivant
Set c = feuille.Columns(1).FindNext(c)
If c Is Nothing Then
' #VALEUR! si non trouvé,tu peux mettre =0 si tu trouves ça plus pratique à tester ensuite
tabl(i) = CVErr(xlErrValue)
Else
tabl(i) = c.Row
End If
End If
tabl(i) = c.Row
End If
Next i
plage = tabl
End Function
eric
Edit 17h10 : j'ai modifié un peu le code