[Catégorie encore et encore modifiée .Net --> VBA] amelioration du code

Signaler
Messages postés
151
Date d'inscription
mardi 20 avril 2010
Statut
Membre
Dernière intervention
15 juin 2014
-
Messages postés
151
Date d'inscription
mardi 20 avril 2010
Statut
Membre
Dernière intervention
15 juin 2014
-
bonjour tout le monde
j'ai une erreur dans mon code jusque là j'ai pas pu la rectifier depuis hier .
elle se trouve à cette ligne mon erreur :
T(j + 5) =  (g(i) * Worksheets("Forwards").Cells(x2(i) + 11, 7).Value + 12 * (j - 1) + (30 - g(i)) * (Worksheets("Forwards").Cells(x1(i) + 11, 7).Value + 12 * (j - 1))) / 30

lorsque j'essai l'execution j'ai une incompatibilité de type !(ereur 13)

aussi j'ai des doutes quant à ma fonction ReDim en fait je veux dimensionner mes tableaux de 6 à la derniere ligne non vide de la colonne A...
si quelqu'un veut bien me donner un coup de main.
Sub Prixspot()

Stop
    Dim k As Long
    Dim x() As Double, T() As Double, p() As Double, g() As Double
    Dim i As Integer, j As Integer, x1() As Integer, x2() As Integer, v() As Integer
    Dim somme() As Single
    ReDim x(6 To Cells(Rows.Count, 1).End(xlUp).Row), T(6 To Cells(Rows.Count, 1).End(xlUp).Row), p(6 To Cells(Rows.Count, 1).End(xlUp).Row), g(6 To Cells(Rows.Count, 1).End(xlUp).Row), v(6 To Cells(Rows.Count, 1).End(xlUp).Row), x1(6 To Cells(Rows.Count, 1).End(xlUp).Row), x2(6 To Cells(Rows.Count, 1).End(xlUp).Row), somme(6 To Cells(Rows.Count, 1).End(xlUp).Row)
    k  = Cells(Rows.Count, 1).End(xlUp).Row
    For i = 6 To k
        somme(i) = 0
    
        '   NombreDeJour(i) = Cells(i, 12).Value - Cells(2, 1).Value 'definir le nombre de jours entre aujourd'hui et la date de fin
        'NbreAnnées(i) = (Cells(i, 8).Value - Cells(2, 1).Value) / 360
        x(i) = Cells(i, 15).Value / 30 'conversion du nombre de jours en mois a la ligne i
        x1(i) = Int(x(i)) 'partie entiere de x(i)
        x2(i) = x1(i) + 1
        v(i) = Cells(i, 14).Value ' nombre d'année de la ligne i
        g(i) = (x(i) - x1(i)) * 30
        While v(i) > 0
                For j = 1 To v(i)
                     p(j + 5) = x(i) / 12 + (j - 1)
                        T(j + 5) = (g(i) * Worksheets("Forwards").Cells(x2(i) + 11, 7).Value + 12 * (j - 1) + (30 - g(i)) * (Worksheets("Forwards").Cells(x1(i) + 11, 7).Value + 12 * (j - 1))) / 30
                        somme(i) = Cells(i, 13).Value / (1 + T(j + 5)) ^ p(j + 5) + 100 / (1 + T(v(i)) ^ p(v(i)))
                Next j
        Wend
        somme(i) = somme(i)
        Cells(i, 11).Value = somme(i)
    Next i
    


End Sub


merci d'avance

11 réponses

Messages postés
1207
Date d'inscription
dimanche 20 avril 2003
Statut
Membre
Dernière intervention
4 juin 2016
10
Bonjour,

Essaie comme ceci

ReDim x(6, Cells(Rows.Count, 1).End(xlUp).Row) en remplaçant le "To" par une virgules sur tous tes redim


Calade
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
74
Ouh là non, ça ne veut absolument pas dire la même chose.
Dim x(x To y) désigne un tableau à une seule dimension
Dim x(x, y) désigne un tableau à 2 dimensions

Avant toute chose, éclaircis ce code qui est imbitable :
- Sépare tes Dim ou Redim : Inutile d'en mettre 4 ou 5 par ligne alors que ces lignes sont déjà complexes
- Pense à utiliser le symbole _ pour faire des coupures de ligne, exemple
maVar = (g(i) * Worksheets("Forwards").Cells(x2(i) + 11, 7).Value _
         + 12 * (j - 1) + (30 - g(i)) * _
        (Worksheets("Forwards").Cells(x1(i) + 11, 7).Value _
         + 12 * (j - 1))) / 30

Revient nous voir quand tu auras fait cette remise en forme (pas le courage)

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
Messages postés
1207
Date d'inscription
dimanche 20 avril 2003
Statut
Membre
Dernière intervention
4 juin 2016
10
Salut Jack,

Oui désolé, je ne suis pas réveillé ce matin. Je cours à la cafetière.


Calade
Messages postés
151
Date d'inscription
mardi 20 avril 2010
Statut
Membre
Dernière intervention
15 juin 2014

bonjour Calade ,bonjour Jack
voila ci-dessous comment j'ai réecrit mes Dim et ReDim
Dim k As Long
Dim x() As Double, T() As Double
    Dim p() As Double, g() As Double
    Dim i As Integer, j As Integer
    Dim x1() As Integer, x2() As Integer
    Dim v() As Integer
    Dim somme() As Single
    ReDim x(6 To Cells(Rows.Count, 1).End(xlUp).Row), T(6 To Cells(Rows.Count, 1).End(xlUp).Row)
    ReDim p(6 To Cells(Rows.Count, 1).End(xlUp).Row), g(6 To Cells(Rows.Count, 1).End(xlUp).Row)
    ReDim v(6 To Cells(Rows.Count, 1).End(xlUp).Row)
    ReDim x1(6 To Cells(Rows.Count, 1).End(xlUp).Row), x2(6 To Cells(Rows.Count, 1).End(xlUp).Row)
    ReDim somme(6 To Cells(Rows.Count, 1).End(xlUp).Row)



et j'ai utilisé votre methode pour faire la coupure de ligne

mais j'ai toujours comme erreur : incompatibilité de type ici:

T(j + 5) = (g(i) * (Worksheets("Forwards").Cells(x2(i) + 11, 7).Value _
         + 12 * (j - 1)) + (30 - g(i)) * _
        (Worksheets("Forwards").Cells(x1(i) + 11, 7).Value _
         + 12 * (j - 1))) / 30


merci bien de votre aide
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
74
Bah il te suffit de visualiser cette ligne lorsque l'erreur survient et de survoler avec la souris chacune des variables pour en connaitre le contenu.
Il doit y en avoir la dedans qui ne contiennent rien ou contiennent des lettres (surement une cellule)
Pour piéger ce type de problème, décompose ta formule en sous-variables.

Pense aussi que le mélange de types de variables dans un calcul n'est jamais bon.
Calculer un Double * par un Integer peut donner des résultats bizarres.
Voir CDbl

Une solution : Convertir chaque chiffre en Double (avec CDbl) + Transformer chaque valeur susceptible de contenir des lettres en chiffre (avec Val), mais au risque d'utiliser la valeur 0 si ce sont des lettres ...

L'abus de _ n'est pas nuisible, surtout s'il permet d'éclaircir la lecture :
Même fonction que toi, mais découpée :
T(j + 5) = ( _
               g(i) * ( _
                        Worksheets("Forwards").Cells(X2(i) + 11, 7).Value _
                        + 12 * (j - 1) _
                      ) _
             + (30 - g(i)) * ( _
                               Worksheets("Forwards").Cells(X1(i) + 11, 7).Value _
                               + 12 * (j - 1) _
                             ) _
           ) / 30
Plus facile à relire et à comprendre, non ?

Attention aussi aux mélanges de + et de * : Les * sont exécutés avant les +, mais gare aux surprises : Mieux vaut ajouter des parenthèses

Dernière chose : Si tu fais des calculs liés aux dates, pense à regarder les fonctions du langage comme DateAdd et DateDiff = très pratique.

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
Messages postés
151
Date d'inscription
mardi 20 avril 2010
Statut
Membre
Dernière intervention
15 juin 2014

MERCI BIEN DE VOTRE AIDE
j'ai pu resoudre le probleme lié a la formule :
T(j + 5) =  ( _
               g(i) * ( _
                        Worksheets("Forwards").Cells(X2(i) + 11, 7).Value _
                        + 12 * (j - 1) _
                      ) _
             + (30 - g(i)) * ( _
                               Worksheets("Forwards").Cells(X1(i) + 11, 7).Value _
                               + 12 * (j - 1) _
                             ) _
           ) / 30

Jack a eu raison en disant de bien regarder ce que contient la formule
effectivement je recuperais dans ma feuille forward des données(des formules)liées au dates en fait je n'avait pas encore executé cette macro (forwards) c'est fait maintenant et il n'y a plus d'erreur d'incompatibilité
par contre ci dessous j'ai une erreur :
" l'indice n'appartient pas a la selection "
somme(i) = Cells(i, 13).Value / (1 + T(j + 5)) ^ p(j + 5) + 100 / (1 + T(v(i)) ^ p(v(i)))

je vous remets mon code en entier ci-dessous:

Sub Prixspot()

Stop
    Dim k As Long
    Dim x() As Double, T() As Double
    Dim p() As Double, g() As Double
    Dim i As Integer, j As Integer
    Dim x1() As Integer, x2() As Integer
    Dim v() As Integer
    Dim somme() As Single
    Dim forwards_x2_11x7 As Double
    Dim forwards_x1_11x7 As Double
    k = Cells(Rows.Count, 1).End(xlUp).Row
    ReDim x(6 To k), T(6 To k)
    ReDim p(6 To k), g(6 To k)
    ReDim v(6 To k)
    ReDim x1(6 To k), x2(6 To k)
    ReDim somme(6 To k)
    
    For i = 6 To k
        somme(i) = 0
        x(i) = Cells(i, 15).Value / 30 'conversion du nombre de jours en mois a la ligne i
        x1(i) = Int(x(i)) 'partie entiere de x(i)
        x2(i) = x1(i) + 1
        v(i) = Cells(i, 14).Value ' nombre d'année de la ligne i
        g(i) = (x(i) - x1(i)) * 30
        forwards_x2_11x7 = Worksheets("Forwards").Cells(x2(i) + 11, 7).Value
        forwards_x1_11x7 = Worksheets("Forwards").Cells(x1(i) + 11, 7).Value
        If v(i) > 0 Then
                For j = 1 To v(i)
                     p(j + 5) = x(i) / 12 + (j - 1)
                     T(j + 5) = (g(i) * (forwards_x2_11x7 + 12 * (j - 1)) + (30 - g(i)) * (forwards_x1_11x7 + 12 * (j - 1))) / 30
                     somme(i) = Cells(i, 13).Value / (1 + T(j + 5)) ^ p(j + 5) + 100 / (1 + T(v(i)) ^ p(v(i)))
                Next j
        End If
             
        
        somme(i) = somme(i)
        Cells(i, 11).Value = somme(i)
    Next i
    


End Sub



merci de votre aide
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
74
somme(i) = Cells(i, 13).Value ...
Surement parce que Cells ne fait pas référence à la feuille
Sinon, à toi de vérifier que chacune des variables indexées comporte bien autant de données que souhaitées
... / (1 + T(j + 5)) ^ p(j + 5) + 100 / (1 + T(v(i)) ^ p(v(i)))

T(j + 5)
Que vaut 'j' et que vaut UBound(T) ?

p(j + 5)
Que vaut 'j' et que vaut UBound(p) ?

T(v(i))
Que vaut v(i) et que vaut UBound(T) ?

p(v(i))
Que vaut v(i) et que vaut UBound(p) ?

Il n'y a que toi qui puisse le savoir, c'est à toi de deboguer !
Messages postés
151
Date d'inscription
mardi 20 avril 2010
Statut
Membre
Dernière intervention
15 juin 2014

je crois que T est un tableau a k-6 elements a mon avis UBound(T)=(k+1)-6 dans mon exemple je fais une boucle de 6 a k=195
le code ci-dessous ne donne aucune erreur
... / (1 + T(j + 5)) ^ p(j + 5) + 100 / (1 + T(v(i)+5) ^ p(v(i)+5)) 


a mon avis parce que mes indices commence a 6.

v()=[5,2,0,6,...,3]Donc
v(6)=5;v(7)=2;...,v(195)=3
x()=[10.33,11,233,8,...14,13] donc
x(6)=10.33,......,x(195)=13
pour calculer
p() supposons pour j=1 en fixant i=6
p(j+5)=p(6)=x(6)/12+(1-1)
vous voyez donc que comme v(i=6)=5 je dois faire une boucle :
for j=1 to 5
p(j+5)=...
et T(j+5)=...
ma question est la suivante elle est reliée a mon exemple
je vais calculer p(6),p(7),jusqua p(11)
mon tableau p() etant defini avec ReDim(6 to k)
aurai -je des zeros apres p(11)? selon le schema ci-dessous:
p()=[p(6),p(7),..., p(11),0,0,0....,0]?
en d'autres terme est ce que les tableaux sont initialisés a zero lorsqu'on les definis.

puis calculer aussi T(j+5)=T(6)

j'espere vous avoir mieux eclairer sur ce que j'essai de faire

merci de votre aide
Messages postés
151
Date d'inscription
mardi 20 avril 2010
Statut
Membre
Dernière intervention
15 juin 2014

voila je vais expliquer ici le resultat attendu
j'ai des colonne dans ma feuille excel
colonne N a partir de la ligne 6 jusqu'a la ligne 195 :
v()=[5,1,6,4,....,3] donc 
v(6)=5,v(7)=1,.....,v(195)=3

raison pour laquelle j'ai defini le tableau v()
en colonne O de la ligne 6 a la ligne 195
x()=[10.33,11.55,8,...,12.33,12] x(6)=10.33,
x(7)=11.55 ,..,x(195)=12 

raison pour laquelle j'ai defini le tableau x()

mon objectif c'est de remplir le tableau
somme()=[................] 
qui est ma colonne K toujours de la ligne 6 a la ligne 195
pour ce faire j'ai creer d'autres tableaux qui me sont utiles :
x1()=Int(x)=[10,11,8,...,12,12] (int=partie entiere de x) donc x1(6)=10,x1(7)=11...
x2()=x1()+1=[11,12,9,...,13,13] x2(6)=11,...
g()=(x()-Int(x()))*30=[0.33*30,0.55*30,0,...,0.33*30,0] 
donc g(6)=0.33*30,...

pour faire ma somme je dois parcourir chaque element du tableau d'ou ma boucle i ,une fois i est fixé je fais
for j=1 à v(i) prenons un exemple:
fixons i=6 j'aurai :
x(6)=10.33;x1(6)=10;x2(6)=11;v(6)=5;
g(6)=0.33*30 
donc je calcule selon la boucle ci dessous:
For j = 1 To v(i)
                        p(j + 5) = x(i) / 12 + (j - 1)
                        T(j + 5) = (g(i) * (forwards_x2_11x7 + 12 * (j - 1)) + (30 - g(i)) * (forwards_x1_11x7 + 12 * (j - 1))) / 30
                        somme(i) = Cells(i, 13).Value / (1 + T(j + 5)) ^ p(j + 5) + 100 / (1 + T(v(i) + 5) ^ p(v(i) + 5))
                    Next j

alors j'aurai
 p(6)=x(6)/12;p(7)=x(6)/12+1;p(8)=x(6)/12+2;p(9)=x(6)/12+3;p(10)=x(6)/12+4 puis je calcule 
T(6)=(g(6) * (forwards_x2_11x7 ) + (30 - g(6)) * (forwards_x1_11x7 )) / 30
T(7)=(g(6) * (forwards_x2_11x7 + 12 ) + (30 - g(6)) * (forwards_x1_11x7 + 12 )) / 30
T(8)=(g(6) * (forwards_x2_11x7 + 12 * 2) + (30 - g(6)) * (forwards_x1_11x7 + 12 * 2)) / 30
T(9)=(g(6) * (forwards_x2_11x7 + 12 * 3) + (30 - g(6)) * (forwards_x1_11x7 + 12 * 3)) / 30
T(10)=(g(6) * (forwards_x2_11x7 + 12 * 4) + (30 - g(6)) * (forwards_x1_11x7 + 12 * 4)) / 30

ouf enfin je fais ma somme(6)
somme(6)=cells(6,13).value*(1/(1+T(6))^p(6)+1/(1+T(7))^p(7)+1/(1+T(8))^p(8)+1/(1+T(9))^p(9)+1/(1+T(10))^p(10))+100/(1+T(10))^p(10)

puis je met
somme(6) dans cells(6,11)

voila j'espere avoir mieux eclairci le probleme
dont voici le code:
Sub Prixspot()


    Dim k As Long
    Dim x() As Double
    Dim T() As Double
    Dim p() As Double, g() As Double
    Dim i As Integer, j As Integer
    Dim x1() As Integer, x2() As Integer
    Dim v() As Integer
    Dim somme() As Single
    Dim forwards_x2_11x7 As Double
    Dim forwards_x1_11x7 As Double
    k = Cells(Rows.Count, 1).End(xlUp).Row
    ReDim x(6 To k), T(6 To k)
    ReDim p(6 To k), g(6 To k)
    ReDim v(6 To k)
    ReDim x1(6 To k), x2(6 To k)
    ReDim somme(6 To k)
    
    For i = 6 To k
        If Cells(i, 15).Value <> "" Then
            somme(i) = 0
            x(i) = Cells(i, 15).Value  'conversion du nombre de jours en mois a la ligne i
            x1(i) = Int(x(i)) 'partie entiere de x(i)
            x2(i) = x1(i) + 1
            v(i) = Cells(i, 14).Value ' nombre d'année de la ligne i
            g(i) = (x(i) - x1(i)) * 30
            forwards_x2_11x7 = Worksheets("Forwards").Cells(x2(i) + 11, 7).Value
            forwards_x1_11x7 = Worksheets("Forwards").Cells(x1(i) + 11, 7).Value
            If v(i) > 0 Then
                 
                    For j = 1 To v(i)
                        p(j + 5) = x(i) / 12 + (j - 1)
                        T(j + 5) = (g(i) * (forwards_x2_11x7 + 12 * (j - 1)) + (30 - g(i)) * (forwards_x1_11x7 + 12 * (j - 1))) / 30
                        somme(i) = Cells(i, 13).Value / (1 + T(j + 5)) ^ p(j + 5) + 100 / (1 + T(v(i) + 5) ^ p(v(i) + 5))
                    Next j
            End If
             
        
        somme(i) = somme(i)
        Cells(i, 11).Value = somme(i)
        End If
    Next i

End sub

le code tourne deja mais ma somme est fausse selon ce que j'ai ecrit dans ma boucle

merci de votre aide
si quelqu'un veut bien m'aider
merci d'avance
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
74
Désolé, pas le courage de servir de coach applicatif.
Le principal est que ton code ne bugue plus.
Si le résultat, n'est pas bon, il va te falloir faire du pas-à-pas avec F9 et F8 pour vérifier chaque calcul, vérifier qu'il ne manque pas un niveau de parenthèse pour être sûr que les opérations se déroulent dans le bon sens ...

Bilan : Tu charges en mémoire des valeurs qui sont à ta disposition dans les feuilles.
Pourquoi ne fais-tu pas tes calculs avec des boucles parmi les cellules ?
Selon que le volume de données est important, tu risques un jour de planter sur des problèmes de gestion de mémoire, des ralentissements épouvantables de la machine ...
+ voir à gérer les calculs des dates avec les fonctions optimisées offertes par le langage
Messages postés
151
Date d'inscription
mardi 20 avril 2010
Statut
Membre
Dernière intervention
15 juin 2014

voila j'ai rectifié l'erreur
mais quelqu'un vient de me dire que ma
somme(i) s'écrase a chaque fois
a votre avis est ce que le calcul de ma somme est correct? car moi je ne vois pas sl'erreur
If v(i) > 0 Then
                 
                            For j = 1 To v(i)
                                 p(j + 5) = x(i) / 12 + (j - 1)
                                    T(j + 5) = (g(i) * (forwards_x2_11x7 + 12 * (j - 1)) + (30 - g(i)) * (forwards_x1_11x7 + 12 * (j - 1))) / 3000
                                    somme(i) = somme(i) + Cells(i, 13).Value / (1 + T(j + 5)) ^ p(j + 5)
                    Next j
                    somme(i) = somme(i) + 100 / (1 + T(v(i) + 5) ^ p(v(i) + 5))
                    Cells(i, 11).Value = somme(i)