VBA - Propriété Type en fonction d'une variable string

Résolu/Fermé
Utilisateur anonyme - 12 janv. 2017 à 16:52
gbinforme Messages postés 14946 Date d'inscription lundi 18 octobre 2004 Statut Contributeur Dernière intervention 24 juin 2020 - 13 janv. 2017 à 17:54
Bonjour à tous,

Je travaille sous Excel 2010 en VBA.

J'aimerai savoir quelle serait la rédaction / méthode pour appeler une propriété d'une variable d'un type personnalisé en fonction d'une variable type string.


Dans le code exemple ci-dessous,

Avec la fonction "Fonction_test()" je rempli (par la procédure "Load_Data") un array avec les données de 2 salariés (Bruce Wayne et Harry Potter) pour les index respectif 0 et 1. Ces données se déclinent en 4 propriétés : Nom, Prénom, Age et Sexe.

Puis je j'appelle une autre procédure paramétrée ("Afficher_information") pour afficher le résultat "Wayne" (c'est là que j'ai besoin de vous pour la rédaction de cette dernière).

Exemple :

'Définition de la variable type
Type Salarie_Type
Nom
Prenom
Age
Sexe
End Type

'création d'un array : liste_salaries()
Dim Liste_salaries() as Salarie_Type

'_______________________________________________________
Private Sub Load_Data()

'remplissage de l'array liste_salaries()
Liste_Salaries(1)

with liste_salaries(0)
.Nom = Wayne
.Prenom = Bruce
.Age = 35
.Sexe = H
end with

with liste_salaries(1)
.Nom = Potter
.Prenom = Harry
.Age = 17
.Sexe = H
end with

End Sub

'_________________________________________________________________
Private Sub afficher_information(pIndex as Long, pPropriete as String)

'doit afficher la valeur paramétrée
msgbox liste_salaries(pIndex).pPropriete

end sub

'__________________________________________________________________
Sub fonction_test()

load_data

'doit m'afficher une msgbox avec écrit "Wayne"
afficher_information 0, "Nom"

end sub


J'anticipe, car je vois venir ceux qui vont me demander l'utilité. J'ai dans mon programme une multitude d'array de Type personnalisés différents et contenant une multitudes de valeurs et j'utilise une fonction sensée fonctionner pour tout mes arrays. Dans cette fonction je définis en arguments : le nom de l'array, une propriété, un index ligne, un index colonne. (pour l'instant évidement ça ne marche pas...). Si j'ai besoin de faire comme ça c'est parce que les types sont différents, donc en appelant la propriété par son nom sous forme de string, ça me simplifie les choses.

(j'espère que j'ai été clair...)

Est ce que c'est seulement possible ? Si oui comment ?

D'avance je vous remercie,

Cordialement

HardEcho

3 réponses

gbinforme Messages postés 14946 Date d'inscription lundi 18 octobre 2004 Statut Contributeur Dernière intervention 24 juin 2020 4 684
12 janv. 2017 à 18:27
Bonjour,

Ton code fonctionnel :
Option Explicit
'Définition de la variable type
Type Salarie_Type
Nom As String
Prenom As String
Age As Integer
Sexe As String
End Type

'création d'un array : liste_salaries()
Public Liste_salaries(1) As Salarie_Type

'_______________________________________________________
Private Sub Load_Data()

'remplissage de l'array liste_salaries()

With Liste_salaries(0)
.Nom = "Wayne"
.Prenom = "Bruce"
.Age = 35
.Sexe = "H"
End With

With Liste_salaries(1)
.Nom = "Potter"
.Prenom = "Harry"
.Age = 17
.Sexe = "H"
End With

End Sub

'_________________________________________________________________
Private Sub afficher_information(pIndex As Long, pPropriete As String)
Dim mes As String
'doit afficher la valeur paramétrée
Select Case pPropriete
    Case "Nom": mes = Liste_salaries(pIndex).Nom
    Case "Prenom": mes = Liste_salaries(pIndex).Prenom
    Case "Age": mes = Liste_salaries(pIndex).Age
    Case "Sexe": mes = Liste_salaries(pIndex).Sexe

End Select
MsgBox mes

End Sub

'__________________________________________________________________
Sub fonction_test()

Load_Data

'doit m'afficher une msgbox avec écrit "Wayne"
afficher_information 0, "Nom"

End Sub


@Patrice33740 :Bonne année 2017 à toi et tes proches.
D'accord avec toi mais j'ai essayé de rendre le code fonctionnel pour HardEcho
2
Utilisateur anonyme
13 janv. 2017 à 14:03
Bonjor gbinforme,

Merci pour votre réponse. Malheureusement, pour les raisons citées au dessous en réponse à patrice, même si ça fonctionne, ça sera un peu limité...

Toutefois, j'apprécie beaucoup votre proposition car elle a le mérite d'être simple et élégante, et j'y trouverai bien une utilité !

Merci pour votre aide !

Cordialement
0
Patrice33740 Messages postés 8556 Date d'inscription dimanche 13 juin 2010 Statut Membre Dernière intervention 2 mars 2023 1 776
12 janv. 2017 à 18:14
Bonjour,

En quoi écrire :
afficher_information 0, "Nom"

présente-t-il un quelconque intérêt par rapport à écrire :
msgbox liste_salaries(0).Nom

Dans les deux cas, il faut préciser 0 et Nom !!!!
0
Patrice33740 Messages postés 8556 Date d'inscription dimanche 13 juin 2010 Statut Membre Dernière intervention 2 mars 2023 1 776
12 janv. 2017 à 18:18
PS : tu devrais lire et appliquer les conseil suivants :
https://silkyroad.developpez.com/VBA/LesVariables/
0
Utilisateur anonyme > Patrice33740 Messages postés 8556 Date d'inscription dimanche 13 juin 2010 Statut Membre Dernière intervention 2 mars 2023
13 janv. 2017 à 14:00
Bonjour Patrice,

Je m'attendais à cette réponse.

En fait je développe un logiciel pour une structure, et ce sous VBA. Au lancement je masque l'application excel et n'affiche que les userform qui vont me permettre de travailler.

Pour l'instant, toutes mes données sont enregistrées par tableau de données, dans chaque onglet, sous forme de base de données (oui je sais excel c'est pas fait pour, Access aurait été mieux, mais c'était plus simple pour la structure, bref). Et j'utilise ces arrays à chaque instant pour mes données.

Du coup j'ai des tableaux correspondants à des entités.
Par exemple ma liste de Bénévoles dans un onglet, avec A: Matricule B: Nom C:Téléphone etc...
Un onglet avec une liste d'horaires de présences avec Colonne A : Référence de l'horaire, B : Matricule du bénévole concerné, C : Horaire de début, D : Horaire de fin etc...
et j'ai comme ça différentes listes de données diverses avec des Matricules pour différencier chaque ligne.

Jusqu'à présent j'utilise des arrays à 2 dimensions pour charger ces données. Au lancement je génère un array "liste_bénévoles()", je le dimensionne au nombre de données et je le remplis.

J'ai donc liste_bénévoles(i,0) <= matricules, liste_bénévoles(i,1) <= Nom etc...
et j'ai de la même façon une liste par type de données, avec à chaque fois le nombre de "colonnes" correspondant.

L'utilité de travailler ainsi c'est de ne pas travailler avec les feuilles excel qui prennent bien plus de temps en terme de calculs.

Lors de l'utilisation des données de ces différentes listes, je vais utiliser des procédures qui vont fonctionner quelle que soit la liste, sous peu que les arguments soient bien saisis.

Par exemple j'ai une fonction de Tri AZ et une Tri ZA (méthode bubble), qui ont chacune pour arguments : nom_array_a_trier, index_maximum, nombre_de_colonnes, colonne_à_trier

Ainsi, peu importe la liste, peu importe sa taille (nombre d'index ou de "colonnes") je peux la trier, avec une seule procédure.

Seulement voilà, j'aimerai remplacer cette méthode avec des arrays n'ayant plus qu'une "colonne" et donc à une seule dimension, et au lieu d'avoir une information (nom, prénom, âge ...) par colonne au sein de la même ligne pour une entité (Bénévole), de tout avoir au sein d'une variable d'un type personnalisé.

Imaginons une liste de 4 bénévoles :
Pierre - 35 ans - Homme - Président
Michelle - 48 ans - Femme - Trésorière
Simone - 58 ans - Femme - Secrétaire
Henry - 23 ans - Homme - Service Civique

J'aimerai remplacer ça :


dim liste_bénévoles()

redim mon_array(3,3) 'rappel 0 = le premier index

liste_bénévoles(0,0) = "Pierre"
liste_bénévoles(0,1) = 35
liste_bénévoles(0,2) = "Homme"
liste_bénévoles(0,3) = "Président"

liste_bénévoles(1,0) = "Michelle" 'et cetera vous avez compris le principe (ici je simplifie, c'est évidemment alimenté par des boucles for next.


Par ça :


Type Bénévole_Type
Prénom as string
Age as long
Sexe as string
Statut as string
End Type

dim liste_bénévoles() as bénévole_type

redim liste_bénévoles(3)

liste_bénévoles(0).prénom = "Pierre"
liste_bénévoles(0).age = 35
liste_bénévoles(0).sexe = "Homme"
liste_bénévoles(0).statut = "Président"

liste_bénévoles(1).prénom = "Michelle" 'et cetera encore une fois vous avez compris le principe.


Alors pourquoi modifier ainsi ?

2 raisons.

1) Pour une question de visibilité. En effet, quand je manipule les données dans le code, à l'heure actuelle j'ai des numéros d'index, et je dois sans cesse me rappeler que mon_array(i,4) (donc la 5ème "colonne" de mon array) est la date de machin, ou le lieu de truc... Avec des noms de propriétés ça serait limpide. : "mon_array(4).cotisation"

2) Et c'est la raison principale, pendant l'utilisation de mon programme, il arrive évidemment qu'il faille ajouter des données, c'est tout le principe. Sauf que l'ajout d'une donnée dans un array de plusieurs dimensions n'est pas possible car on ne peut pas utiliser Redim Preserve, ce qui me force actuellement à recharger toutes les données à chaque fois que j'en ajoute une, vous comprendrez qu'en terme d'efficacité on a connu mieux. Avec la méthode que je cherche à utiliser, je pourrais utiliser Redim Preserve car il n'y aurait plus qu'une dimension dans chacun de mes arrays.

Cela fonctionne super bien pour presque toutes mes procédures lorsque celles-ci sont spécifiques et situationnelle. Par exemple lorsque je sais que je dois utiliser telle propriété pour telle liste (array). Mais dès que je veux appeler une procédure générique j'ai besoin de ce que je vous ai demandé à l'origine, parce que les arrays sont différents, avec des variables Types personnalisés différents, et donc les propriétés (.Propriété) appelées sont différentes.

En effet avant,, quelle que soit ma liste je pouvais utiliser l'index pour un test par exemple. "Si ma_liste(i,4) =3 alors truc" mais là du coup, ça va donner "Si ma_liste(i).ancienneté=3 alors truc".

Dans ce cas exemple ça marche, parce que c'est spécifique à cette liste et cette propriété, mais dans le cas où je veux que la procédure fonctionne quelle que soit la liste, mais en variant sur les arguments, ba il me faut ce que je vous ait demandé. Vous comprenez ?

Voilà, c'est un peu long désolé. Je suis conscient que mon approche peut être déroutante.

J'apprends en même temps de développer, et je crois que la chose la plus importante ce n’est pas de savoir-faire, mais de savoir que ça existe/que c’est possible et donc savoir où chercher. Ce pourquoi je souhaitais savoir si une méthode existait. Voilà.

Ah et j'ai pensé à l'utilisation de modules de classes, mais pour l'instant c'est un peu trop complexe à mon goût...

En tout cas merci pour votre intérêt.

Cordialement

HardEcho
0
gbinforme Messages postés 14946 Date d'inscription lundi 18 octobre 2004 Statut Contributeur Dernière intervention 24 juin 2020 4 684
13 janv. 2017 à 17:54
Bonjour HardEcho,

j'ai pensé à l'utilisation de modules de classes, mais pour l'instant c'est un peu trop complexe à mon goût...
Bien sûr c'est comme tout, il faut commencer et intégrer le concept mais ce n'est pas très compliqué lorsque l'on a un peu utilisé et cela rentre tout à fait dans ta conception de style objet banalisé.
Je pense quand même que l'utilisation des types est assez contraignante (comme tu as vu) lorsque l'on veux banaliser l'utilisation.

J'ai une application dans ton type de base avec une douzaine de feuilles différentes plus ou moins imbriquées et j'ai préféré utiliser les modules de classes avec des tables affichées dans une listbox paramétrable. Toutes les rubriques sont automatiquement enregistrées dans une feuille paramètre : il suffit de mettre à jour leurs propriétés (lors de l'ajout d'une rubrique par exemple) pour que tout le traitement suive.

Il me semble que c'est cette banalisation que tu recherches si j'ai compris ta démarche.
Bon courage pour ton développement.
0