OVH Cloud OVH Cloud

Vecteurs Excel dans une user defined function

9 réponses
Avatar
Charles
Bonjour,

j'ai une petite question technique: j'entre un vecteur dans une User
defined function, par exemple mafonction(A1:A25)

La fonction est definie du type function mafonction(VV as variant)
Dim V
V=VV
et ensuite je peux travailler sur V(i,j)

Mon probleme est le suivant: lorsque VV est un vecteur d'une seule
ligne, il semble que VBA ne le considere pas comme un vecteur et
n'autorise pas la syntaxe V(i,j). J'obtiens une erreur dans ma
fonction.

Existe-t-il donc un moyen de
- soit verifier que VV est un vecteur de plus d'une ligne, et dans ce
cas je fais un cas particulier dans la fonction,
- ou alors de "forcer" VBA a considerer V comme un vecteur, quitte a ce
que la seule coordonne accessible soit V(1,1) lorsque j'aurai entre
mafonction(A1:A1)?

Je vous remercie d'avance pour votre aide
Charles

9 réponses

Avatar
garnote
Salut Charles,

Peut-être que :
Function mafonction(v As Range)
mafonction = 4 * v(3)
End Function

Ai-je bien compris ta question ?

Serge

"Charles" a écrit dans le message de news:

Bonjour,

j'ai une petite question technique: j'entre un vecteur dans une User
defined function, par exemple mafonction(A1:A25)

La fonction est definie du type function mafonction(VV as variant)
Dim V
V=VV
et ensuite je peux travailler sur V(i,j)

Mon probleme est le suivant: lorsque VV est un vecteur d'une seule
ligne, il semble que VBA ne le considere pas comme un vecteur et
n'autorise pas la syntaxe V(i,j). J'obtiens une erreur dans ma
fonction.

Existe-t-il donc un moyen de
- soit verifier que VV est un vecteur de plus d'une ligne, et dans ce
cas je fais un cas particulier dans la fonction,
- ou alors de "forcer" VBA a considerer V comme un vecteur, quitte a ce
que la seule coordonne accessible soit V(1,1) lorsque j'aurai entre
mafonction(A1:A1)?

Je vous remercie d'avance pour votre aide
Charles



Avatar
garnote
J'ai essayé ceci :

Function mafonction(v As Range)
'=mafonction(C2:E2)
mafonction = 4 * v(1, 1) + 5 * v(1, 2) + 10 * v(1, 3)
End Function

et ça fonctionne.

Serge
Avatar
JB
Bonjour,

Fonction MaSomme() et Masomme2():

Function MaSomme2(champ As Range)
Application.Volatile
For Each c In champ
MaSomme2 = MaSomme2 + c.Value
Next
End Function

Function MaSomme(champ As Range)
Application.Volatile
MaSomme = 0
nbLignes = champ.Rows.Count
nbColonnes = champ.Columns.Count
For col = 1 To nbColonnes
For lig = 1 To nbLignes
MaSomme = MaSomme + champ(lig, col)
Next
Next
End Function

Pour illustrer plusieurs façons d'utiliser les paramètres dans les
Procs et fonctions:

Sub essai(champ As Range)
Dim tableau2
'-- méhode 1 on travaille directement sur le champ
x = champ(1, 1)
nbLignes = champ.Rows.Count
nbColonnes = champ.Columns.Count
'-- méthode 2: on transfère dans un tableau
tableau = champ ' 2 dimensions
xx = tableau(1, 1)
'-- 3e méthode : on transfère dans un tableau avec une boucle
nbLignes = champ.Rows.Count
nbColonnes = champ.Columns.Count
ReDim tableau2(1 To nbLignes, 1 To nbColonnes)
For col = 1 To nbColonnes
For lig = 1 To nbLignes
tableau2(lig, col) = champ(lig, col)
Next lig
Next col
End Sub
Sub essai2()
essai Range("A1:A3") ' tableau à 1 colonne
End Sub

Sub essai3()
essai Range("A1:B3") ' tableau à 2 colonnes
End Sub

Sub essai4()
essai Range("A1:B1") ' tableau à 2 colonnes
End Sub

http://www.excelabo.net/moteurs/compteclic.php?nom=jb-fonctionsperso


Cordialement JB
Avatar
Charles
Ces deux reponses sont tres interessantes et devraient me permettre de
resoudre mon probleme. Merci infiniment.

J'ai cependant une question. La performance n'est pas une preoccupation
aujourd'hui, mais pour info, est ce que l'utilisation de Range en
variable de la fonction implique un acces de VBA a Excel a chaque fois
qu'on utilise un element du vecteur? Cela ralentirait notoirement la
fonction par rapport a une copie du vecteur.

Ou alors peut etre peut on faire une copie au debut et travailler sur
des vecteurs

Charles
Avatar
JB
Si on doit accéder aux valeurs d'un champ plusieurs fois, il est +
performant de transférer dans un tableau

JB
Avatar
Charles
Apres essai, j'obtiens un resultat qui marche mais qui est extremement
lent (deux ou trois secondes pour recalculer la spreadsheet, ce qui a
l'usage est un peu penible, cette fonction etant utilisee environ 300
fois)

J'ai un peu modifie ma fonction et j'ai l'impression qu'il s'en ferait
de peu pour que cela marche. Voici la fonction exacte:

Public Function Portfolio(Rprof As Variant, Rpur As Range, Rseas As
Range)
Application.Volatile
'Purchase and Seasoning must have the same size
'Seasoning must be expressed in months
'Profile must be expressed in 100 of monetary unit
Dim nbyrs As Integer
nbyrs = Rpur.Rows.Count
Dim temp As Double
temp = 0
Dim Vpur
Dim Vprof
Dim Vseas
Vprof = Rprof
ReDim Vpur(1 To nbyrs, nbyrs)
ReDim Vseas(1 To nbyrs, nbyrs)
Vpur = Rpur
Vseas = Rseas
For i = 1 To nbyrs
temp = temp + Vpur(i, 1) * Vprof(nbyrs - i + Vseas(i, 1) + 2, 1) /
Vprof(Vseas(i, 1) + 1, 1)
Next i
Portfolio = temp
End Function


Cette fonction marche sauf pour les vecteurs de taille 1. Est ce que
vous voyez un moyen de la modifier de sorte qu'on continue a travailler
sur des vecteurs VB (limitation des acces a Excel) et que les formules
marchent encore pour un vecteur d'une ligne?

comme on a nbyrs je peux m'en sortir avec un if mais je me demande s'il
n'y aurait pas une solution plus elegante

Charles
Avatar
JB
Je ne comprends pas pourquoi :
-le Redim
-et le nb de colonnes égal au nombre de lignes:

ReDim Vpur(1 To nbyrs, nbyrs)
ReDim Vseas(1 To nbyrs, nbyrs)

JB
Avatar
garnote
Que contient Rprof, Rpur et Rseas au juste ?

Serge

"Charles" a écrit dans le message de news:

Apres essai, j'obtiens un resultat qui marche mais qui est extremement
lent (deux ou trois secondes pour recalculer la spreadsheet, ce qui a
l'usage est un peu penible, cette fonction etant utilisee environ 300
fois)

J'ai un peu modifie ma fonction et j'ai l'impression qu'il s'en ferait
de peu pour que cela marche. Voici la fonction exacte:

Public Function Portfolio(Rprof As Variant, Rpur As Range, Rseas As
Range)
Application.Volatile
'Purchase and Seasoning must have the same size
'Seasoning must be expressed in months
'Profile must be expressed in 100 of monetary unit
Dim nbyrs As Integer
nbyrs = Rpur.Rows.Count
Dim temp As Double
temp = 0
Dim Vpur
Dim Vprof
Dim Vseas
Vprof = Rprof
ReDim Vpur(1 To nbyrs, nbyrs)
ReDim Vseas(1 To nbyrs, nbyrs)
Vpur = Rpur
Vseas = Rseas
For i = 1 To nbyrs
temp = temp + Vpur(i, 1) * Vprof(nbyrs - i + Vseas(i, 1) + 2, 1) /
Vprof(Vseas(i, 1) + 1, 1)
Next i
Portfolio = temp
End Function


Cette fonction marche sauf pour les vecteurs de taille 1. Est ce que
vous voyez un moyen de la modifier de sorte qu'on continue a travailler
sur des vecteurs VB (limitation des acces a Excel) et que les formules
marchent encore pour un vecteur d'une ligne?

comme on a nbyrs je peux m'en sortir avec un if mais je me demande s'il
n'y aurait pas une solution plus elegante

Charles



Avatar
Charles
Pour le redim, c'est une erreur, il faut lire ReDim Vpur(1 To nbyrs, 1)

Le Redim si j'ai bien compris permet de dimensioner la variable variant
en un vecteur de la taille souhaitee.

Rprof, Rpur et Rseas contiennent des nombres a virgule

Charles