Application.WorksheetFunction.Max d'un en-tête de tableau structuré
Bonsoir tout le monde,
J'ai un soucis avec une fonction. J'ai un tableau comme celui ci-dessous qui est structuré. La première ligne est un en-tête, ce sont des températures.
| 50 | 100 | 150 | 200 | 250 | 300 | 350 | 400 |
| 256 | 241 | 223 | 205 | 188 | 173 | 160 | 150 |
| 247 | 232 | 215 | 197 | 181 | 166 | 154 | 145 |
J'ai dans le gestionnaire de nom créé une liste appelée "Liste_Température", qui fait à pour référence =Tableau[#En-têtes].
Dans ma macro cette liste fonctionne nickel, je l'utilise avec des Find pour aller récupérer les valeur du tableau en fonction de la température. Je l'utilise aussi lorsque que j'ai une température intermédiaire exemple "125" avec un WorksheetFunction.Match qui me permet d'aller chercher la valeur avant et la valeur après afin de faire un interpolation linéaire pour déterminer la valeur intermédiaire.
Le soucis que j'ai c'est quand je viens en bout de tableau, d'un côté j'ai une erreur car il peut pas aller chercher la valeur en dessous de 50, de l'autre il ne peut pas aller chercher la valeur au dessus de 400. Je me suis donc dit allons chercher les extrêmes avec Application.WorksheetFunction.Max et Application.WorksheetFunction.Min un de la plage, mais cela me renvoie sans cesse 0. J'ai réaliser des test avec d'autres plages nommées (Colonnes ou lignes, même plages quelconques) et cela fonctionne parfaitement. Est-ce parce que je suis dans un "En-tête"que cela ne fonctionne pas ?
Vous me direz surement que je pourrais fixer manuellement les extrémités en disant créant un by-pass si je suis = à 50 ou à 400. Sauf que ce code test sera dupliqué sur une 30aines d'autres tableaux et que les valeurs de température ne seront jamais les mêmes. D’où l'envie d'automatiser la recherche dès le départ.
Merci à tous pour votre aide.
Bonsoir,
je vous propose une solution avec un test de la valeur cherchée par rapport aux valeurs des entêtes de votre tableau et de leur position :
on test avec la valeur de la première colonne, et de la dernière colonne, le tout étant "variable" car les instructions ne pointent pas un chiffre particulier de colonne sauf pour la première...
Sub LouReeD()
For i = 0 To 80 Step 10
Range("A1") = i
If i <= CDbl(Range("Tableau1[#Headers]").Cells(1).Value) Then ' range("montstructuré[#Headers]").cells(1).value
MsgBox ("première colonne")
ElseIf i >= CDbl(Range("Tableau1[#Headers]").Cells(Range("Tableau1[#Headers]").Columns.Count).Value) Then
MsgBox ("Dernière colonne")
Else
MsgBox ("colonne centrale")
End If
Next i
End SubLe fichier :
@ bientôt
LouReeD
C'est nickel comme contournement je n'y aurait jamais pensé
Une question sur votre code, j'ai du mal à comprendre le For i = 0 To 80 Step 10
Ne devrais-je pas avoir un I = 0 to "Valeur largement plus grande que mon maximum" (400 actuellement) ?
Au passage je ne connaissais pas le CDbl, une commande de plus dans ma poche, bien utile en plus, merci
Les valeurs n'ont d'utilité que le test proposé et 80 est bien supérieur à 70
@ bientôt
LouReeD
bonjour LouReeD,Heelflip,
un essai, mais si cela convient, on peut créer une fonction personnalisée ... (si vous nous donnez un fichier)
Et pour les valeurs >400, il faut aussi extrapoler ou prendre la valeur maximale ?
Sub Heelflip()
Dim aA, aHeader, i, Valeur
aHeader = Evaluate("iferror(--Tabel1[#Headers],""x"")") 'matrice avec les valeurs numériques de l'entête
aA = Range("Tabel1").Value 'databodyrange du tableau
arr = Array(40, 50, 90, 100, 400, 450) 'les valeurs que vous demandez dans un boucle
For i = 0 To UBound(arr) 'boucler ces valeurs
r = Application.Match(arr(i), aHeader, 1) 'recherchez cette valeur dans l'entête
If IsNumeric(r) Then 'trouvé !!!
If aHeader(r) = arr(i) Then 'match exacte = facile
MsgBox "valeur " & arr(i) & " " & aA(1, r)
Else 'match non-exacte (et supposons que vous voulez utiliser les données de la première listrow)
If r = UBound(aHeader) Then r = r - 1 'extrapoler avec l'avant-dernier et le dernier !!!!
MsgBox "valeur " & arr(i) & " " & WorksheetFunction.Forecast_Linear(arr(i), Array(aA(1, r), aA(1, r + 1)), Array(aHeader(r), aHeader(r + 1))) 'extrapoler
End If
Else
MsgBox "trop petit : " & arr(i)
End If
Next
End Suboubien
Sub Heelflip()
arr = Array(40, 50, 90, 100, 400, 450) 'les températures que vous demandez dans un boucle
For i = 0 To UBound(arr) 'boucler ces valeurs
MsgBox arr(i) & " " & LO_Heelflip("Tabel1", arr(i), 1)
Next
End Sub
Function LO_Heelflip(TS As String, Température, Ligne) 'nom du tableau, températue et numéro du listrow
Dim aHeader, aA, r
On Error Resume Next
aHeader = Evaluate("iferror(--" & TS & "[#Headers],""x"")") 'matrice avec les valeurs numériques de l'entête
aA = Range(TS).Value 'databodyrange du tableau
On Error GoTo 0
If VarType(aHeader) = vbError Or VarType(aHeader) = vbEmpty Then LO_Heelflip = "problème1 avec tableau ou entête": Exit Function
If VarType(aA) = vbError Or VarType(aA) = vbEmpty Then LO_Heelflip = "problème2 avec tableau ou entête": Exit Function
If Ligne < 1 Or Ligne > UBound(aA) Then LO_Heelflip = "problème avec nombre de lignes": Exit Function
r = Application.Match(Température, aHeader, 1) 'recherchez cette valeur dans l'entête
If IsNumeric(r) Then 'trouvé !!!
If aHeader(r) = Température Then 'match exacte = facile
LO_Heelflip = aA(Ligne, r)
Else 'match non-exacte (et supposons que vous voulez utiliser les données de la première listrow)
If r = UBound(aHeader) Then r = r - 1 'extrapoler avec l'avant-dernier et le dernier !!!!
LO_Heelflip = WorksheetFunction.Forecast_Linear(Température, Array(aA(1, r), aA(1, r + 1)), Array(aHeader(r), aHeader(r + 1))) 'extrapoler
End If
Else
LO_Heelflip = "trop petit "
End If
End FunctionBonjour Bart,
Pour les valeur > 400 on n'extrapole pas, c'est une valeur maximale également.
Je vais tester les deux codes, je verrai bien celui qui me convient le mieux, merci à toi également.
If aHeader(r) = Température or r=ubound(aheader) Then 'match exacte oubien dernière colonne
....
Bonjour a vous deux,
Finalement j'ai utilisé le code de LouReeD, plus simple, je l'ai simplifié suivant ce que j'avais besoin de récupérer, en y ajoutant des Références et supprimant la boucle, cela fonctionne parfaitement. Voici mon code final.
Sub LouReeD(ByVal i as Integer, ByVal Table as Range)
If i <= CDbl(Table.Cells(1).Value) Then T°Min = Table.cells(1).value
MsgBox T°Min
If i >= CDbl(Table.Cells(Table.Columns.Count).Value) Then T°Max = Table.Cells(Table.Columns.Count).Value
MsgBox T°Max
End SubIl me suffit de récupérer derrière T°Min et T°Max pour dire ce que je veut faire si je suis en dessous ou au dessus.
Merci à tout les deux
Bonsoir,
vous avez bien fait de retirer la boucle, elle ne servait qu'à "démontrer" le bon fonctionnement de la recherche en fonction d'une donnée !
Merci de votre retour et remerciement !
@ bientôt
LouReeD