tri de variables en VBA

S

sylsyl

Guest
Bonjour a tous,

comment trier 4 variables (var1, ..., var4) dans l'ordre croissant de leur valeur pour les mettre ensuite dans un array (en VBA).
Exple: si var1<var3<var4<var2
alors Array(1)=var1
Array(2)=var3
etc.

la methode bourrin de comparaison me donne une vingtaine d'IF, alors je colle mes variables dans une feuille pour ensuite faire un tri avec Range(...).Sort pour enfin les recuperer dans l'ordre.
Il doit y avoir beaucoup plus simple !!

Merci beaucoup, Sylsyl.
 
L

LaurentTBT

Guest
Salut Sylsyl,

J'avais pensé utiliser la fonction PetiteValeur, via worksheetfunction, mais elle ne s'applique qu'à un objet range.
Donc il faut mettre tes variables dans des cellules pour que ça marche.
Par exemple:
si elles sont dans A1 à A4, cela donnerait:

for i=1 to 4
array(i)=application.worksheetfunction.small(Range("A1:A4",i)
next i

Mais bon, ce n'est pas encore satisfaisant, à moins que tes variables ne soient déjà initialement dans des cellules.

Bonne journée.
Laurent.
 
S

sylsyl

Guest
Salut Laurent,

en fait mes 4 variables sont issues de textboxs. J'aurais aime les trier pour les remettre dans ces memes textboxs mais dans l'ordre croissant.

Merci de ton aide mais si on est oblige de passer par une feuille, ma methode marche tres bien. Je pensais qu'on pouvez directement "trier" un array.

Merci beaucoup, Sylsyl.
 
T

Ti

Guest
Si, on peut passer par WorksheetFunction sans utiliser de plage. Voici une petite procédure qui fera le tri d'un tableau de valeurs :

Option Explicit
'Ti 11/11/03

Function TriSimple(Tableau)
Dim Bcle As Long, TableauTri, Index As Long
TableauTri = Tableau
For Bcle = LBound(Tableau) To UBound(Tableau)
Index = Index + 1
TableauTri(Bcle) = WorksheetFunction.Small(Tableau, Index)
Next Bcle
TriSimple = TableauTri
End Function

Sub TestTri()
Dim Var1, Var2, Var3, Var4, Var5, Var6, Var7, Var8
Dim ArrayVarTri, Plage As Range
Var1 = 5
Var2 = 3
Var3 = 7
Var4 = 1
Var5 = 22
Var6 = 3
Var7 = 15
Var8 = 18
'Arrayvartri contiendra la liste triée
ArrayVarTri = TriSimple(Array(Var1, Var2, Var3, Var4, Var5, Var6, Var7, Var8))
End Sub
 
S

sylsyl

Guest
Salut Ti, re laurent,

j'ai compris comment ca devait marcher mais ca marche pas...

Cette partie de mon program permet de gerer les 4 semaines de conges annuels dans l'emploi du temps annuel.
Les numeros de ces semaines sont inscrites dans les textbox: W1box, W2box, W3box, W4box dans l'USF "ConfigForm"
"Holiday" est l'array utilise pour traiter ces semaines dans le reste du prog.

j'ai l'erreur: "Unable to get the small property of the WorksheetFunction class"

Voici mon code (allege, light et sans sucre):

Global Holiday(1 To 4) As Integer

Private Sub Wvalid_Click()
Dim IzConf As Boolean
Dim Pouf As Range

Pouf = TriSimple(Array(ConfigForm.W1box.Value, ConfigForm.W2box.Value, ConfigForm.W3box.Value, ConfigForm.W4box.Value))

For i = 1 To 4
Holiday(i) = Pouf(i)
ConfigForm.Controls("W" & i & "box") = Holiday(i)
Next i

End Sub

----------------------------------------------

Function TriSimple(Tableau)
Dim Bcle As Long, TableauTri, Index As Long
TableauTri = Tableau
For Bcle = LBound(Tableau) To UBound(Tableau)
Index = Index + 1
TableauTri(Bcle) = WorksheetFunction.Small(Tableau, Index) 'ligne surlignee en jaune
Next Bcle
TriSimple = TableauTri
End Function

Merci beaucoup et si vous ne trouvez pas, vous prenez pas la tete...

A++, Sylsyl.
 
T

Ti

Guest
essaie de remplacer WorksheetFunction par : Application.WorksheetFunction

D'autre part, "Global" est peut-être utilisé en VB6, mais tu dois lui préférer "Public" en VBA.

Enfin, je ne vois pas pourquoi tu attribues le tableau trié à une variable Range (Pouf) que tu n'initialises même pas avec une adresse.
Laisse donc à cette variable le type Variant/Tableau et si tu veux mettre ces variables dans ta feuille Excel, alors déclare une plage dédiée et donne-leur les valeurs de ton tableau trié, par l'intermédiaire d'une boucle
 
S

sylsyl

Guest
J'ai mis Pouf as Range parce que tu as mis ArrayVarTri as Range dans ton test (TestTri), d'ailleurs a quoi sert le "Plage" ?

A quoi doivent correspondre les 2 argument de Small ? je n'ai pas le fichier d'aide relatif a cette methode (juste pour info).

Est-il normal de mettre TableauTri as Long puis TableauTri = Tableau alors que Tableau est un array ? en fait je m'etonne que ces egalites fonctionnent car je pensais qu'il fallait mettre Dim TableauTri() As Long pour le declarer en "dynamic array".

Finalement j'ai mis ce code et ca marche:

For i = 1 To 4
Holiday(i) = ConfigForm.Controls("W" & i & "box")
Next i
Pouf = TriSimple(Holiday)
For i = 1 To 4
Holiday(i) = Pouf(i)
Cells(i + 2, 9) = Holiday(i)
ConfigForm.Controls("W" & i & "box") = Holiday(i)
Next i

et j'ai rien change Function TriSimple.

Dernieres questions: pourquoi me conseilles-tu d'utiliser Public plutot que Global ?
Quand on ne precise pas si une fonction (ou procedure) est Public ou Private (comme tu as fait), c'est quoi par defaut ?

Mreci pour tout, c'est beaucoup plus propre que ce que je faisais avant.

A++, Sylsyl.
 
T

Ti

Guest
euh, non, ArrayTri est destiné à être un Array, donc je ne l'ai pas déclaré en tant que Range, mais en tant que Variant, idem pour TableauTri qui sera un tableau de Variant, donc je le déclare en tant que Variant et certainement pas en tant que Long.
Regarde à nouveau mes définitions dans le programme que j'ai joint, je pense que tu l'as fait un peu trop vite... ce qui a pu te tromper, c'est que les déclarations ont été faites sur la même ligne, mais VBA implique que chaque variable déclarée se voit déclarer son type, ainsi :

Dim A as Long, B
est différent de :
Dim A as Long, B as Long

Dans la première version, B est un Variant(type par défaut), mais dans la deuxième, c'est un Long, puisqu'on l'a déclaré ainsi. Peu importe quel est le type de la variable A, B doit être toujours déclaré explicitement. Eh oui, les outils Microsoft n'ont pas l'ergonomie des outils Borland...

Au fait, la variable Plage est un reliquat devenu inutile, tu peux le supprimer.

Pour Small, il s'agit de la dénomination anglaise de PETITE.VALEUR, puisque VBA ne connaît que l'anglais...

Je ne connais pas VB6, que je ne pratique pas, donc je ne sais pas trop dans quel contexte on utilise GLOBAL, ce que je sais c'est que c'est inutile en VBA, une variable est soit Public, soit Private et ça suffit bien.

Pour les déclarations, une variable qui n'est pas déclarée Public est Private par défaut, cependant pour les procédures et fonctions c'est le contraire, une procédure qui n'est pas déclarée Private est Public par défaut, allez savoir pourquoi...
 
L

LaurentTBT

Guest
Re-bonjour à tous.

Ti, je n'ai pas l'habitude de travailler avec des tableaux aussi, j'ai eu du mal à comprendre ton code, et notamment pourquoi tu passes par deux tableaux.

Voici ce que j'ai mis:

Sub Trier()
Dim i As Byte
Dim Tableau(4) As Byte

For i = 1 To 4
Tableau(i) = Controls("W" & i & "box")
Next i
For i = 1 To 4
Controls("W" & i & "box") = Application.WorksheetFunction.Small(Tableau, i + 1)
Next i
End Sub

Et pour moi, cela suffit. Mais comme je viens de dire, j'ai beaucoup de mal avec les tableaux, alors j'ai du louper quelque chose.

Dis-moi ce que tu en penses, et ce que ta fonction apporte.

@+. Laurent.
 
S

sylsyl

Guest
Merci beaucoup pour tes precisions.

En fait j'ai confondu "Dim A, B As Long" et "Dim A As Long, B" Desole.

Et pour VB6, il ne reconnait pas la declaration des variables Public en debut de module, il faut mettre Global...

Encore merci d'avoir pris le temps de m'avoir tout explique (et tres clairement en plus !!)

A++, Sylsyl.
 
T

Ti

Guest
Laurent, ton exemple est tout à fait acceptable également, sauf que ton tableau est mal déclaré, tu aurais pu écrire :

Sub Trier()
Dim i As Byte
Dim Tableau(1 To 4) As Byte

For i = 1 To 4
Tableau(i) = Controls("W" & i & "box")
Next i
For i = 1 To 4
Controls("W" & i & "box") = Application.WorksheetFunction.Small(Tableau, i)
Next i
End Sub

Tableau(1 To 4) parce que par défaut un tableau est de base 0 et que là je le déclare de base 1. Ensuite dans Small, je passe l'argument 1, 2 etc alors que toi, tu passes l'argument 2, 3 etc.

En ce qui me concerne, j'ai juste écrit la fonction TriSimple comme pouvant être d'utilisation générale, fonctionnant avec tout type de variable, c'est un tic de programmeur qui pense toujours à réutiliser le plus simplement possible les choses qu'il écrit quelquefois dans la douleur !
D'autre part, si je dois réutiliser plusieurs fois ce code dans un même programme, eh bien justement il n'y aura qu'une seule routine écrite, ce qui nous fait gagner en clarté, en rapidité, en facilité de maintenance etc.
 
L

LaurentTBT

Guest
OK, merci, Ti.

Il ne me reste plus qu'à prendre une bonne habitude de plus!

J'ai enfin compris pourquoi j'avais du mettre i+1 en argument de Small.

Bon, difficile de ne pas se mélanger les pédales avec ce qui commence à 1 et ce qui commence à 0. Je me plante toujours aussi avec les boucles sur les combobox, avec list(i) ou selected(i), je ne sais jamais s'il faut commencer de 1 à listcount, ou de 0 à listcount-1! ça deviendra peut-être automatique pour moi un jour...

Merci pour les explications et bonne soirée.

Laurent.
 

Discussions similaires

Membres actuellement en ligne

Statistiques des forums

Discussions
312 489
Messages
2 088 855
Membres
103 977
dernier inscrit
Hermet