Fonction dynamique

Résolu/Fermé
britjessblush - 11 juin 2010 à 19:23
 Britjessblush - 25 juin 2010 à 11:10
Bonjour,

j'ai fait une fonction:

Function Duration2(a As Range) As Double

Dim an As Range
Set an = ThisWorkbook.Sheets("FI").Range("A1:A5")
With Application.WorksheetFunction
Duration2 = .SumProduct(an, a) / .SumProduct(a)
End With
End Function


Qui marche parfaitement et me renvoie normalement une valeur quand je l'utilise , mais il faut a chaque fois que je definisse a .

J'aimerais faire une macro ou fonction peu importe, dynamique ie qui dans ma feuille nommée Fo par ex , du meme workbook, remplace chaque fois, successivement le "a" par toutes les colonnes de la feuille ie par ex quand j'appelle la macro, prend automatiquement la colonne A, fait le calcul et me renvoi le resultat sous la colonne A7; ensuite la colonne B...et me renvoi le resultat sous B7,...... et ainsi de suite pour toutes les colonnes de la feuille.

ofet pr ceux que ne conaisse pas, multiplie chaque cellule et les aditionnes ie ( A1*B1+ A2*B2+.....+A5*B5), donc ne renvoie qu'une seule valeur, le total.
Bien sur, toutes mes colonnes de la feuille Fo sont de meme taille ie s'rretent a la ligne 5.

Merci d' avance

Je suis desperée et Hyper Nulle en VBA SVP :(





A voir également:

2 réponses

eriiic Messages postés 24570 Date d'inscription mardi 11 septembre 2007 Statut Contributeur Dernière intervention 23 avril 2024 7 213
Modifié par eriiic le 12/06/2010 à 12:16
Bonjour,

Ca sera obligatoirement une macro, une fonction ne retournant une valeur que dans sa cellule d'appel.

Macro qui traite la feuille active :
Sub calcule()  
    Dim col As Long  
    For col = 1 To [IV1].End(xlToLeft).Column  
        Cells(7, col) = Duration2(Cells(1, col).Resize(5, 1))  
    Next col  
End Sub


Mais je ne suis pas sûr d'avoir bien compris ton besoin. On s'y perd un peu dans ton explication...
Pour chaque colonne de la feuille active ayant qcq chose en ligne 1 j'appelle ta fonction.

Si ce n'est pas ça dépose un fichier exemple sur cijoint.fr et colle ici le lien fourni.

Si il faut le faire pour toutes les feuilles du classeur (sauf 'FI') ou sur une liste précise d'onglets on peut le rajouter

eric

PS: tu peux remplacer .SumProduct(a) par .Sum(a)

PS2: à la reflexion tu peux tout simplement mettre en A7 de ton autre feuille =Duration2(A1:A5) et tirer la formule vers la droite...
0
britjessblush
12 juin 2010 à 13:32
bonjour eric et merci pour ta réponse rapide.

en fait, dans mon workbook j'ai 2 feuilles: la première nommée FI et la seconde nommée FO.
Dans la Feuille 2 ie FI, j'ai 5 valeurs dans la colonne A ie de A1:A5
Dans la Feuille 1 ie FO, j'ai 5 valeurs par colonnes mais un nombre indéterminée de colonnes
je voudrais que quand j'appelle la macro, me fasse automatiquement le calcul pour toutes les colonnes de la feuille FO, en remplaçant chaque fois la valeur de 'a' par la colonne suivante et mette le résultat sur la ligne 7 donc pour toutes les colonnes calcules, le résultat se trouvera sur la ligne 7 de ces colonnes.

Je sais pas si je suis plus clair.
c'est vrai que pour .SumProduct(a) qu'on peu remplacer par .Sum(a) , j'avais pas fais gaffe, Merci :)

C'est aussi vrai que je peux juste tirer le resultat, mais j'ai beaucoup de fichier a traiter, je souhaitais faire une macro qui le fasse directement si possible :(

au fait, dans ton
For col = 1 To [IV1].End(xlToLeft).Column
Cells(7, col) = Duration2(Cells(1, col).Resize(5, 1))

c'est quoi ton 'IV1'?
et pourquoi le Cells(1, col).Resize(5, 1) en paramètre? je comprend le cells mais pas le Resize.

Encore merciiii de m'aider
0
britjessblush
12 juin 2010 à 13:33
Oups, je me suis contredite au départ, la feuil1 c'est FO et feuil2 FI :)
0
eriiic Messages postés 24570 Date d'inscription mardi 11 septembre 2007 Statut Contributeur Dernière intervention 23 avril 2024 7 213
Modifié par eriiic le 12/06/2010 à 15:39
Au vu de ton complément la macro proposée est bonne.
Elle fonctionne sur la feuille active de n'importe quel classeur ouvert même si elle est absente de ce classeur.

c'est quoi ton 'IV1'
c'est la dernière cellule de la ligne 1 sur excel 2003.
Complété par .end(xltoleft) te place sur sur la dernière saisie de la ligne (équivalent à ctrl+fleche gauche), et .column fourni le n° de la dernière colonne utilisée de la ligne.
Si tu veux te baser sur la ligne 2 (parce que tu as d'autres données sur la ligne 1 au delà de la plage qui t'interesse remplace par IV2

Cells(1, col).Resize(5, 1) en paramètre? je comprend le cells mais pas le Resize.
Partant de la sélection de la 1ère cellule de la colonne, .resize étend la sélection à 5 lignes, 1 colonne

Puisque tu appliques toujours sur la même feuille et que tu signales avoir plusieurs classeurs à traiter tu peux utiliser cette version qui traitera la feuille FO de tous les fichiers ouverts.
Reste à voir s'il faut modifier ta fonction selon si chaque classeur a sa feuille FI avec ses propres valeurs ou non, ou bien même l'abandonner et mettre le calcul dans la macro.
Actuellement c'est FI du classeur actif qui est utilisé pour tous les autres...

Sub calcule() 
    Dim col As Long, wb As Workbook, i As String 
    For Each wb In Workbooks 
        On Error GoTo fin 
        With wb.Worksheets("FO") 
            On Error GoTo 0 
            For col = 1 To .[IV1].End(xlToLeft).Column 
                .Cells(7, col) = Duration2(.Cells(1, col).Resize(5, 1)) 
            Next col 
        End With 
fin: 
    Next wb 
End Sub 


eric
0
britjessblush
12 juin 2010 à 21:13
ah ok, merci beaucoup, ça m'as l'air parfait :).. Dommage j'ai voyage et j'ai n'ai pas mon ordi sur moi :( je testerais mardi pour te dire si ça marche.
Par contre pour ce qui est de ta derniere macro pour tous les workbooks:
-Normalement c'est le meme FI dans tous les classeurs donc peux importe si je n'utilise que celui du classeur ouvert
-Par contre quelques questions au niveau de :
For Each wb In Workbooks
On Error GoTo fin
With wb.Worksheets("FO")
On Error GoTo 0
* que fait les On Error GoTo fin et On Error GoTo 0 ?
*tous les autres workbooks que j'ai a traite sont dans un meme fichier donc faudrait t-il que je les ouvre tous avant de lancer la macro?


et J'aurais une derniere question qui n'as rien avoir avec celle pose precedement, mais comme tu as l'air de bien t'y connaitre en VBA, je profite un peu si ca ne t'embete pas :)

En fait j'ai plusieurs fichiers au depart que je ne peux modifier et il ou il y'a plusieurs donnees . Mais dans ces fichiers, les seuls seuls trucs qui m'interessent sont a partir de la ligne 33 et de la 2e colonne. sur cette ligne 33, sont marques les noms de chacune de mes cellules en caractères, certaines cellules ont pour nom 0(0). les cellules sont remplis par des valeurs par contre toutes les cellules ayant pour nom 0(0) sont vides et certaines cellules ayant un nom aussi sont vides.
je voudrais pouvoir ne copier que les cellules ayant un nom excepete celles nommees 0(0) et qui ne sont pas vides

un exemple comme je n'ai pas excel pr t'envoyer un fichier

colone e B colone C colone D colone E colone F colone G ............
ligne 33 jhuu hhhdg hekhfef jkff 0(0) 0(0)
ligne 34 1 45 67
ligne 36 56 455 445


je voudrais ne copier que les colonnes ayant des noms differents de 0(0) et qui ne sont pas vides
ie que la par exemple, ca ne copiera que les colonnes B, C et E, et de la ligne 33 a la ligne 36

dans ma question, le 33 est toujours fixe, mais apres la taille longueur des cellules est variables ie que toutes les colonnes n'ont pas forcement la même taille.


Encore une fois, milles merciiii :)
0
eriiic Messages postés 24570 Date d'inscription mardi 11 septembre 2007 Statut Contributeur Dernière intervention 23 avril 2024 7 213
12 juin 2010 à 23:45
-Normalement c'est le meme FI dans tous les classeurs donc peux importe si je n'utilise que celui du classeur ouvert
Ta fonction utilisant thisworkbook ça sera donc toujours la feuille FI de ce classeur qui sera utilisée.

On Error GoTo fin
With wb.Worksheets("FO")
On Error GoTo 0

C'est pour gérer le cas d'un classeur ouvert n'ayant pas de feuille FO,
On error goto fin permet de passer à la fin du traitement sans rien faire, d'éviter le message d'erreur et de continuer sur le classeur suivant.
On Error GoTo 0 rétablit le traitement d'erreur

*tous les autres workbooks que j'ai a traite sont dans un meme fichier donc faudrait t-il que je les ouvre tous avant de lancer la macro?
Là je crois qu'il y a un problème de vocabulaire...
Un workbook est un classeur, et est donc un fichier.
Dans un classeur (fichier) tu as plusieurs feuilles (onglets) : les worksheets
Pour moi il n'y avait qu'une seule feuille FO par fichier, et plusieurs fichiers.
La macro traite tous les fichiers ouverts, à toi de voir si tu en ouvres 5 ou 20, par paquets plus ou moins gros.

je voudrais pouvoir ne copier que les cellules ayant un nom excepte celles nommees 0(0) et qui ne sont pas vides
On va attendre un fichier exemple car ça manque terriblement de précision... ;-)
- Déjà nommer une cellule c'est autre chose, là elle contient la valeur 0(0) qui est le nom du champ ?
- est-ce qu'il y a d'autres données non concernées en dessous ?
- et surtout copier où ???
Dans un autre classeur ?
Chaque résultat dans une feuille différente ou rassemblés sur une même feuille ?
Faut-il rappeler le classeur d'origine dans une colonne dédiée ? sur une ligne qui sépare les données ? etc
Donc fait 3 classeurs exemple, 2 de données et un pour le résultat attendu.

eric
0
eriiic Messages postés 24570 Date d'inscription mardi 11 septembre 2007 Statut Contributeur Dernière intervention 23 avril 2024 7 213
Modifié par eriiic le 15/06/2010 à 22:17
Teste pour voir ce que ça donne.
J'ai intégré le code de la fonction dans la macro
Comme demandé ton fichier résultat s'enregistre sous le nom cestpasgrave.xls
FI.xls
eric
0
britjessblush
16 juin 2010 à 01:01
slt,
Desolee, je croyais te donner plus de precision mais je me rend compte que je t'ai totalement embrouille!! encore Merci pour tout, je l'essaie demain et j te tiens au courant! :)


Merciiii :)
0
Britjessblush
16 juin 2010 à 19:50
C'est pas grave, j'ai trouve une autre maniere de coller et d'effacer les cellules non vides.

Par contre ma macro calDuration ne marche pas, si tu peu jeter un petit coup d'oeil stp, je ne comprend pas pourquoi :(

Function Duration(Entite As Range) As Double
Dim Annee As Range
Dim tauxPays As Range
'Dim Change As Range
' Workbooks("noooos.xls").Activate
Set Annee = Workbooks("noooos.xls").Sheets("Taux").Range("A2:A83")
Set tauxPays = Workbooks("noooos.xls").Sheets("Taux").Range("B2:B83")
' ThisWorkbook.Activate
With Application.WorksheetFunction
Duration = .SumProduct(Annee, tauxPays, Entite) / .SumProduct(tauxPays, Entite)
End With
End Function

Sub calDuration()
Dim col As Long
For col = 2 To [IV1].End(xlToLeft).Column
Cells(85, col) = Duration(Cells(2, col).Resize(83, 2))
Next col
End Sub
0
eriiic Messages postés 24570 Date d'inscription mardi 11 septembre 2007 Statut Contributeur Dernière intervention 23 avril 2024 7 213
16 juin 2010 à 19:58
Heuuuu, tu as testé la macro que je t'ai fournie et ça ne va pas ?
Bien entendu tu effaces la dernière ligne et tu fais enregistrer sous...

Pour ta fonction tu l'appelles en lui passant une matrice de 2 colonnes, je ne crois pas que c'était ce qui était prévu.

eric
0
britjessblush
16 juin 2010 à 21:22
Heuuuu, tu as testé la macro que je t'ai fournie et ça ne va pas ?
nn,ca ne marche pas. ca ne fait rien

1)Deja tu avait oublie de dire de coller la copie dans la feuille wbresult tu n'as mis que workbook tout seul.
2) le Range("B33").CurrentRegion ne marche pas nom plus. Ca d'ailleurs je ne comprends pas pourquoi, je l'avais teste mm avant toi mais ca marche pas :(
du coup j'ai mis un range moi mm pr ppouvoir continuer et voir si ca marchait...
3)Apres le paste ne marche pas car avec mes valeurs il me fallait un collage special
j'ai essaye un PasteSpecial Xl....... ca ne marchait pas non plus, mais finalement je suis passe autrement
4) le delete aussi car j'avais certains "-" dans mes cases vides, mais ca c'est de ema faute, j'aurais due te le dire avant, sof k j ne le savais pas non plus :). Mais j'ai adapte avec ce k tu a fait ....

J'ai fait inclure la partie calcul d'abord. Bon la finalement avec klkes changements ca marche, sauf que ce qui m'enbette c'est au niveau du CurrentRegion ie de devoir rentrer le range moi mm.

Bref, Apres pr la Fonction c'est vrai ke c'est pa cel ki etai prévu au depart, mais comme je t'ai explike depuis, ce que j'ai a faire est beaucoup plus complique que ce que je t'ai demande, c'est pour ca que quand tu me pose des questions des fois, je m'embrouille dans mes explications. Je ne veux pas non plus qu'on mache tout pour moi, c'est juste histoire de me faire une idee pour pouvoir adapter apres.
mm la fonction que je t'ai envoye est normalement encore plus complexe,
je dois faire un
= (.SumProduct(Annee, tauxPays, Entite) / .SumProduct(tauxPays, Entite) )*int
mais com deja
= (.SumProduct(Annee, tauxPays, Entite) / .SumProduct(tauxPays, Entite) ne marche pas, je ne vais pas te rajouter d'autres parametres lol :)

Tu arrives a voir s'il y'a un pb dans la fonction de deux parametres alors Stp?
Je pense que normalement ca ne devais pas poser de probleme si on ajoute d'autres arguments non? etant donne que c'est une somme prod et qu'ils on tous la meme longueur.

Ofet, ton lignemax c'est koi? tu ne l'as defini nulle part. du coup ca fait rien je crois....


Merciiiii :) et desole pour le francais et les accents mais mon clavier n'ai pas francais.
0
eriiic Messages postés 24570 Date d'inscription mardi 11 septembre 2007 Statut Contributeur Dernière intervention 23 avril 2024 7 213
Modifié par eriiic le 16/06/2010 à 22:35
nn,ca ne marche pas. ca ne fait rien
Chez moi ça marche bien...
Clic sur le bouton 'traiter un fichier', le choisir, valider.
Le fichier de données est refermé et tu as un nouveau fichier 'cestpasgrave.xls'
1) non, il n'y a qu'à choisir le fichier dans la boite de dialogue, c'est tout
2) pas soucis chez moi
3) idem
4) c'est normal...

Voilà le fichier obtenu à partir de l'exemple 2 : resultat2.xls

la fonction :
Cells(85, col) = Duration(Cells(2, col).Resize(83, 2))
tu envoies 2 colonnes
0