XL 2013 Ajouter des formules dans un tableau de dimensions variables

Ananas94

XLDnaute Junior
Bonjour,

Après maintes recherches sur le sujet (qui m'ont déjà pas mal aidées), je suis bloquée dans un programme.
En effet, 2 tableaux (construits et nommés) sont présents:
-le premier, nommé "Tab_Données_ORLI" recueille des données brutes recueillies dans un logiciel.
-Le second nommé "Tab_Calculs" effectue des calculs à partir de ces données.
Les dimensions de ces deux tableaux (en terme de nombre de lignes essentiellement) est variable à chaque utilisation.

Je souhaite effectuer les actions les suivantes :
1- Cliquer sur le bouton de la macro "calcul profil de puissance" -> OK
2- Une fois que j'ai cliqué sur le bouton, le second tableau doit se remplir avec des formules (celles de calculs) et s'arrêter à la dernière ligne remplie. -> NOK

Je suis bloquée en effet car :

1-J'ai un message d'erreur qui est le suivant :
1586185235753.png


Mon code est (l'erreur au débogage est en gras) :

VB:
Option Explicit
Sub Calcul_Profil_Puissance()

    Dim Jours_Stretch As Range, JEPP_stretch As Range, Puissance_corr As Range, Profil_theo As Range, Ecart_theo_exp As Range
    Dim LO1 As ListObject, LO2 As ListObject
    Dim ws1 As Worksheet, ws2 As Worksheet
    Dim cell_d
    Dim Formule_1 As String, Formule_2 As String, Formule_3 As String, Formule_4 As String, Formule_5 As String

    Set ws1 = Sheets("Données_ORLI")
    Set ws2 = Sheets("Résultats")

    Set LO1 = ws1.ListObjects("Tab_Données_ORLI")
    Set LO2 = ws1.ListObjects("Tab_Calculs")
    
    Formule_1 = "=" & "B9-$B$9"
    Formule_2 = "=" & "I10+(H10-H9)*J10/100"
    Formule_3 = "=" & "SI(OU(C10 > 101, 5, C10 < 80), J9, C10)"
    Formule_4 = "=" & "100-0,0584*I9-0,0054*I9*I9+3*I9*I9*I9*0,00001"
    Formule_5 = "=" & "K9-J9"

    
With LO2 'Pour la formule 1'
        .ListColumns("Jours de stretch").Range(2, 1).FormulaLocal = Formule_1 'La formule 1 est placée dans la 1ère case de la colonne'
       [B] .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count).Select[/B]
        .ListColumns("Jours de stretch").Range(2, 1).Etirer_formules "H9:H" 'On étire la formule jusqu'à la fin du tableau, qui a des dimensions variables'
    End With
    
    With LO2 'Pour la formule 2'
        .ListColumns("JEPP de stretch").Range(3, 2).FormulaLocal = Formule_2 'La formule 1 est placée dans la 1ère case de la colonne'
        .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count).Select
        .ListColumns("JEPP de stretch").Range(3, 2).Etirer_formules "I10:I" 'On étire la formule jusqu'à la fin du tableau, qui a des dimensions variables'
    End With
    
    With LO2 'Pour la formule 3'
        .ListColumns("Puissance corrigée").Range(3, 3).FormulaLocal = Formule_3 'La formule 1 est placée dans la 1ère case de la colonne'
        .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count).Select
        .ListColumns("Puissance corrigée").Range(3, 3).Etirer_formules "J10:J" 'On étire la formule jusqu'à la fin du tableau, qui a des dimensions variables'
    End With
    
    With LO2 'Pour la formule 4'
        .ListColumns("Profil théorique NACRE").Range(2, 4).FormulaLocal = Formule_4 'La formule 1 est placée dans la 1ère case de la colonne'
        .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count).Select
        .ListColumns("Profil théorique NACRE").Range(2, 4).Etirer_formules "K9:K" 'On étire la formule jusqu'à la fin du tableau, qui a des dimensions variables'
    End With
    
    With LO2 'Pour la formule 5'
        .ListColumns("Ecart puissance théorie-exp").Range(2, 5).FormulaLocal = Formule_5 'La formule 1 est placée dans la 1ère case de la colonne'
        .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count).Select
        .ListColumns("Ecart puissance théorie-exp").Range(2, 5).Etirer_formules "L9:L" 'On étire la formule jusqu'à la fin du tableau, qui a des dimensions variables'
    End With
            
End Sub


Private Sub Etirer_formules(cell_d)
    Dim der_ligne As Long
    der_ligne = LO2.Cells(Rows.Count, 1).End(xlUp).Row 'Pour la colonne "Jours de stretch"
    Range(cell_d & der_ligne).FillDown
End Sub


2-Lorsque j'ai étiré la formule, des nombre négatifs apparaissent alors que les données corrélées sont vides. Le tableau est systématiquement entièrement rempli alors que ce n'est pas le cas.

Vous trouverez ci-joint le fichier.

Auriez-vous une idée pour me dire où est l'erreur s'il vous plaît ?
Je vous remercie vivement par avance,
Excellente journée,

Anna
 

Pièces jointes

  • Profil stretch PMOX.xlsm
    69.1 KB · Affichages: 22
Solution
Bonjour le fil, Anna

Comment est-ce possible?
Toujours la même réponse ;)
L'inattention

Fais ce test sur une feuille vierge, et observe le contenu des formules
VB:
Sub Test()
Cells(2, 3).FormulaR1C1 = "=SI(OU(C10>101,C10<80),J9,C10)"
Cells(3, 3).Formula = "=SI(OU(C10>101,C10<80),J9,C10)"
Cells(4, 3).FormulaLocal = "=SI(OU(C10>101;C10<80);J9;C10)"
Cells(5, 3).Formula = "=IF(OR(C10>101,C10<80),J9,C10)"
Cells(6, 3).FormulaR1C1 = "=IF(OR(R[7]C>101,R[7]C<80),R[6]C[7],R[7]C)"
End Sub

Sinon, étant pour un usage normal d'un tableau structuré, je m’abstiendrai de commentaire sur tout dévoiement illogique de la chose ;)

Staple1600

XLDnaute Barbatruc
Re

Je faisais juste de l'humour à deux balles aussi ;)
Si maintenant vous considérez l'optimum comme le bien être humain sur une planète propre
C'est "antinomique", non?
Le bien-être de la planète, c'est sans l'humain (fusse-t-il propre comme un sou neuf.
;))

Bon, je retire ma casquette nihiliste, et je remets celle d'XLD ;)

>Anna
Je vais voir ta dernière PJ.

EDITION: Si j'étais infirmier, j'aurai plus urgent à faire que d'être assis devant mon PC à titiller Excel, non? ;)
C'était une référence déguisée à HFT. ;)
 

sylvanu

XLDnaute Barbatruc
Supporter XLD
Oups, en PJ, c'est rectifié.
Je n'avais pas de données dans la seconde colonne et me suis fait piégé.

Par contre je n'efface que les valeurs. Je ne touche pas au tableau structuré. C'était l'idée de base, les deux matrices sont immuables et de même taille.
 

Pièces jointes

  • Profil stretch PMOX_V4.xlsm
    61.4 KB · Affichages: 2

mapomme

XLDnaute Barbatruc
Supporter XLD
Bonjour @Ananas94 :), @Staple1600 ;), @sylvanu ;),

Et même pour vos slips, avec quelques euros de plus, il ne prendra pas le bateau pour vous être livré. https://www.leslipfrancais.fr/

On reconnait là, une végétation indigène bien de chez nous :D:D:D:p:p:p:p.
Les publiciste sont formidables. Un paysage pseudo exotique en fond de scène. On y ajoute pour accentuer la touche exotique, un beau jeune homme noir et musclé, une belle jeune femme à la coiffure afro et la supposée française entre les deux. C'est ti pas une belle image d'un bonheur local (à l'autre bout du monde) ?
Pour acheter un peu plus localement, il faudra se départir de quelques clichés. Le pourrons nous ?
 

Pièces jointes

  • Le slip Franchouiilard.gif
    Le slip Franchouiilard.gif
    367.1 KB · Affichages: 33
Dernière édition:

Ananas94

XLDnaute Junior
Bonjour,

Je viens de corriger l'histoire des circulaires. Je pense que Sylvanu n'avait pas remarqué que des formules étaient insérées en ligne 2, mais ce n'est pas grave, l'erreur est désormais corrigée.

Par ailleurs, j'ai une autre idée : je pourrais utiliser la fonction Redim, qui permet de :
* Redéfinir le nombre d'éléments.
* Changer le nombre de dimensions.
* Etablir les limites supérieures et inférieures de chaque dimension.

J'ai fait des essais ce matin (à l'aide du cours ici : https://silkyroad.developpez.com/vba/tableaux/#LIII-A ).
En fait, je souhaite que les deux tableaux [Tab_Données_ORLI] et [Tab_Calculs] soient tout le temps de même dimensions. Ainsi, j'ai codé la ligne suivante, avant la boucle With :

ReDim Tab_Calculs(nb_lignes, 5)

ce qui donne dans le code entier de la macro "calcul_Profil_Puissance" :
VB:
Option Explicit
Sub Calcul_Profil_Puissance()
    Application.ScreenUpdating = False
    'Déclaration des variables'
    Dim plage As Long
    Dim nb_lignes As Integer
    Dim Tab_Calculs() As Variant
    Dim Tab_Données_ORLI() As Variant
    'Comptage du nombre de lignes remplies du tableau "Tab_Données_ORLI"'
    nb_lignes = Application.CountA([Tab_Données_ORLI])
    'Redimensionnement du tableau  Tab_Calculs:'
    ReDim Tab_Calculs(nb_lignes, 5)
    'Insertion des formules et redimensionnement dans le tableau "Tab_Calculs" :
    
    With [Tab_Calculs]
        .ClearContents
        .Cells(1, 5) = "=K9-J9"
        .Cells(1, 4) = "=100-0.0584*I9-0.0054*I9*I9+3*I9*I9*I9*0.00001"
        .Cells(1, 3) = "=C9"
        .Cells(2, 3).FormulaR1C1 = "=SI(OU(C10>101,C10<80),J10,C10)"
        .Cells(2, 2) = "=I10+(H10-H9)*J10/100"
        .Cells(2, 1) = "=B10-$B$9"
    End With
    [Tab_Calculs].Range(Cells(1 + nb_lignes, 1), Cells(900, 5)).ClearContents
End Sub

Un message d'erreur improbable apparaît : "Erreur de compilation: l'objet associé à With doit être de type défini par l'utilisateur, Object ou Variant"

Je ne comprends pas, car j'ai déclaré les 2 tableaux comme des objets de type variant...

Auriez-vous une idée ?
merci
Anna
 

Pièces jointes

  • Profil stretch PMOX_V3.xlsm
    46.1 KB · Affichages: 3

Staple1600

XLDnaute Barbatruc
Bonjour le fil, Anna

Une petite révision sur les tableaux (Array) pour commencer la journée ;)
VB:
Sub Tableaux()
Dim tablo() As Variant, i As Byte
ReDim tablo(1 To 5)
For i = LBound(tablo) To UBound(tablo)
tablo(i) = i ^ 2
Next
MsgBox tablo(1) & Chr(13) & tablo(2) & Chr(13) & tablo(UBound(tablo)), , "tablo"
Dim tabloo
tabloo = Array(1, 2, 3, 4, 5, 6)
MsgBox tabloo(1), , "tabloo"
Dim tablooo
[A1:B5] = "=ROW()*COLUMN()": [A1:B5] = [A1:B5].Value
tablooo = Range("A1:B5").Value
MsgBox tablooo(1, 1) & Chr(13) & tablooo(1, 2), , "tablooo"
MsgBox tablooo(3, 1) & Chr(13) & tablooo(3, 2), , "tablooo"
End Sub
 

mapomme

XLDnaute Barbatruc
Supporter XLD
Bonjour @Ananas94,

Je viens de modifier votre code pour qu'il fonctionne comme je pense qu'il devrait (mais je n'ai pas suivi le fil). J'ai ponctué le code de quelques commentaires.

La référence circulaire n'a pas été corrigée. A vous de le faire.

Edit: bonjour @Staple1600 :)

VB:
Sub Calcul_Profil_Puissance()
    Dim nb_lignes As Long  'Une référence à un N° de ligne doit être déclarée comme Long
                           'car un numero de ligne peut dépasser le n° 32.767
                  
    Application.ScreenUpdating = False

    'Dim Tab_Calculs() As Variant            ' C'est le meilleur moyen de se planter
    'Dim Tab_Données_ORLI() As Variant       ' Càd: rédéfinir des variables avec des noms
                                             ' qui existent déjà quand on ne maitrise pas
                                             ' les portées des variables et des objets Excel
                                             ' (et même quand on maitrise !)
                                             ' C'est de là que provenait l'ereur (entre autres)

    'Comptage du nombre de lignes remplies du tableau "Tab_Données_ORLI"'
    'on compte les éléments de la première colonne seulement
    nb_lignes = Application.CountA(Range("Tab_Données_ORLI").Columns(1))

    ' Redimensionnement du tableau  Tab_Calculs:
    ' NON ! Puisque qu'on ne l'utilise pas!

    ' En revanche, on va créer un range qui est un redimensionnement de la plage
    ' définit par le nom "Tab_Calculs" dans Excel
    Dim xrgCalculs As Range
    Set xrgCalculs = Range("Tab_Calculs").Resize(nb_lignes)


    'Pour ma part je n'utilise pratiquement jamais la notation [....]
    ' Insertion des formules et redimensionnement dans le tableau "Tab_Calculs" :

    With Range("Tab_Calculs")
        .ClearContents
        .Cells(1, 5) = "=K9-J9"
        .Cells(1, 4) = "=100-0.0584*I9-0.0054*I9*I9+3*I9*I9*I9*0.00001"
        .Cells(1, 3) = "=C9"

        .Cells(2, 3).FormulaR1C1 = "=SI(OU(C10>101,C10<80),J10,C10)"
        'ensuite vous avez une formule avec référence circulaire
        'la colonne 2 de Range("Tab_Calculs") est la colonne I
        'or la formule dans la cellule .cells(2,2) correspond à la cellule I10
        'votre formule dans cette formul fait référence à la cellule I10 elle-même d'où référence circulaire
        .Cells(2, 2) = "=I10+(H10-H9)*J10/100"
        .Cells(2, 1) = "=B10-$B$9"
        ' on fait référence au range Range("Tab_Calculs") décalé de nb_lignes vers le bas
        ' (on saute ainsi les lignes avec données) et on efface les autres
        .Offset(nb_lignes, 0).ClearContents
    End With
End Sub
 

Pièces jointes

  • Ananas94- Formules par VBA- v1.xlsm
    50.4 KB · Affichages: 3
Dernière édition:

Ananas94

XLDnaute Junior
Bonjour !

Je vous prie de m'excuser pour le délai de réponse, mais j'avais beaucoup de travail. Je vous remercie vivement mapomme et Staple1600 pour vos réponses, vous n'imaginez pas comme ça m'aide !! :)

*Staple, j'ai lu attentivement ton cours. je le copie et le garde dans mon ordi. Ca peut servir. Encore merci.

*mapomme, merci beaucoup pour ta correction. C'était tout à fait ce que je voulais. Je viens de corriger la référence circulaire, comme j'avais fait précédemment mais j'ai l'impression que ça ne fonctionne pas. En effet, j'ai placé une formule dans la seconde ligne du tableau, et dans la 3ème ligne (et jusqu'à la fin du tableau), une autre formule est placée. Voici le code où j'insère dans la ligne n°2 des colonnes n°2 et 3 des formules différentes :

VB:
 With Range("Tab_Calculs")
        .ClearContents
        .Cells(2, 5) = "=K9-J9"
        .Cells(2, 4) = "=100-0.0584*I9-0.0054*I9*I9+3*I9*I9*I9*0.00001"
        [B].Cells(2, 3) = "=C9"[/B]
        .Cells(3, 3).FormulaR1C1 = "=SI(OU(C10>101,C10<80),J10,C10)" 'La formule ne démarre qu'en 3ème ligne et non en 2ème ligne'
        'ensuite vous avez une formule avec référence circulaire
        'la colonne 2 de Range("Tab_Calculs") est la colonne I
        'or la formule dans la cellule .cells(2,2) corresponf à la cellule I10
        'votre formule fait référence à la cellule I10 d'ou référence circulaire
        [B].Cells(2, 2) = "=0" 'La première cellule de la colonne vaut 0'[/B]
        .Cells(3, 2) = "=I10+(H10-H9)*J10/100"
        .Cells(2, 1) = "=B10-$B$9"
        ' on fait référence au range Range("Tab_Calculs") décalé de nb_lignes vers le bas
        ' (on saute ainsi les lignes avec données) et on efface les autres
        .Offset(nb_lignes, 0).ClearContents
    End With

Mais j'ai l'impression que lorsque je fais ça, la formule de la 3ème ligne est en fait copiée dans toute la colonne, intégralement.
N'est-il pas possible dans un tableau construit (au sens vba) d'avoir différentes formules selon les cellules ? Ceci m'éviterait d'avoir fatalement la référence circulaire.

Je te remercie vivement par avance et reste à ton écoute,
Excellente journée,
Anna
 

Pièces jointes

  • Profil Stretch PMOX_V4.xlsm
    96.7 KB · Affichages: 1

Staple1600

XLDnaute Barbatruc
Bonjour le fil, Anna, mapomme

Anna
Y a un truc que je ne pige pas !
L'avantage des ListObject, c'est que les formules se recopient automatiquement quand on insère une ligne.
Or donc, dans ce cas, pourquoi insérer les formules par VBA ?
Il suffit de supprimer uniquement le contenu des cellules sans formules (en cas d'actualisation des tableaux).
 

Ananas94

XLDnaute Junior
Bonjour Arthur (je me permets des libertés aujourd'hui ! c'est le confinement ! :) )

En fait, je fais cet outil suite à une demande de quelqu'un. Il souhaite que lorsque l'on ouvre l'outil, le tableau soit VIDE, et que pour avoir les données, nous devions CLIQUER sur un bouton. C'est peut-être absurde, mais c'est comme ça... :(
Je trouvais que l'idée de faire "commencer" la formule dans la cellule n°3 du tableau était une bonne idée, mais j'ai l'impression que ça ne fonctionne pas (ou alors je me suis trompée quelque part ...?)

Merci
Anna
 

Staple1600

XLDnaute Barbatruc
Re

Si tu n'effaces que les données, les formules présentes dans le tableau n'ont rien à afficher...
(Donc visuellement, il paraîtra vide)

Jadis, c'était ta hiérarchie, aujourd'hui, c'est quelqu'un
Passe-moi, ce quelqu'un, c'est moi qui vais l’appeler Arthur ! ;)
 

Ananas94

XLDnaute Junior
Bonjour Staple,
Merci pour ta réponse. J'avais déjà fait ça au début, mais le problème est que des valeurs s'affichent ensuite à la fin du tableau. En fait, le tableau n'est pas complètement vide lorsqu'il n'y a pas de valeurs qui y font référence. C'était justement la chose à corriger.
Ainsi, je vais garder cette solution, aussi illogique soit-elle. J'ai trouvé une autre solution : j'écris, hors de la boucle with, la valeur des cellules du début. Ca fonctionne, c'est l'essentiel.

Néanmoins, il y a quelque chose de vraiment inexpliqué !
dans la cellule J10 (dans le second tableau donc), la formule vue de la feuille excel active, est : =SI(OU($J:$J>101;$J:$J<80);'J9';$J:$J) . ce qui est faux, et qui n'est pas du tout ce que j'ai demandé)

Alors que vu de l'onglet développeur (donc du code de la macro), la formule initiale est :
.Cells(2, 3).FormulaR1C1 = "=SI(OU(C10>101,C10<80),J9,C10)" (ce que je voudrais)

Comment est-ce possible ? Pourquoi ? Comment modifier ? j'ai tenté pas mal de manips, mais rien n'y fait, je n'y parviens pas...

Aurais-tu une idée?
Merci
Bon week-end de Pacques :)
Anna
 

Pièces jointes

  • Profil Stretch PMOX_V4.xlsm
    87.3 KB · Affichages: 1

Discussions similaires

Réponses
2
Affichages
394

Statistiques des forums

Discussions
312 111
Messages
2 085 403
Membres
102 883
dernier inscrit
jameseyz