Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Membre expert
    Transfert de certaines colonnes de tableau structuré vers variable tableau
    Bonjour,

    Je dispose d'un tableau structuré (T_Visiteurs) de 27 colonnes.
    Je souhaite ne transférer, dans une variable tableau, qu'une douzaine de ces colonnes.

    Quel serait, selon vous, la meilleure méthode?

    Merci
    Cordialement,
    Franck

  2. #2
    Responsable
    Office & Excel

    Salut Franck,

    Je vois trois solutions:
    1. Copie intégrale du tableau structuré dans un nouveau tableau structuré, suppression des colonnes puis transfert vers l'array (suppose une structure Excel pour accueillir le tableau temporaire );
    2. Transfert vers un array temporaire avec toutes les colonnes, puis transfert par boucle sur un array final en ne prenant que les colonnes qui t'intéressent dans l'array temporaire;
    3. Bouclage sur les lignes du tableau structuré source et alimentation de l'array en boucles en ne reprenant que les colonnes qui t'intéressent (Lourd si gros tableau structuré).


    Pour généraliser l'approche et permettre un temps de traitement raisonnable sur un gros tableau structuré, je privilégierais l'approche 2.

    Avec le tableau structuré suivant, voici un code qui devrait te donner satisfaction, utilisant une fonction générique qui reçoit le tableau structuré et un array (de base 0) qui contient la liste des colonnes à garder.



    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Function getPartialArray(ls As ListObject, Columns)
      Dim temp
      Dim r As Long, c As Long
     
      temp = ls.DataBodyRange.Value
      ReDim t(1 To UBound(temp), 1 To UBound(Columns) + 1)
      For r = 1 To UBound(temp)
        For c = 0 To UBound(Columns)
          t(r, c + 1) = temp(r, ls.ListColumns(Columns(c)).Index)
        Next c
      Next r
      getPartialArray = t
    End Function
     
    Sub Test()
      Dim t
     
      t = getPartialArray(Range("t_Contacts").ListObject, VBA.Array("Prénom", "Service"))
    End Sub
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Une fois pour toutes, je donne mon avis. Je ne vais pas le répéter à chaque message...
    Si je propose une solution générique sur votre solution spécifique, c'est parce que, fainéant de nature, je privilégie le réutilisable...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

  3. #3
    Rédacteur

    Bonjour,
    Je suppose qu'évidemment les colonnes à charger en variable tableau ne se suivent pas.
    Personnellement, je ferais cela en deux temps
    1. Utilisation du filtre avancé d'excel (AdvancedFilter) sans critère et avec une zone d'exportation contenant les étiquettes de colonnes à exporter
    2. Chargement de la zone exportée dans la variable tableau


    ou bien peut-être le Power Query
    Philippe Tulliez
    Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément. (Nicolas Boileau)
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter
    Mes tutoriels : Utilisation de l'assistant « Insertion de fonction », Les filtres avancés ou élaborés dans Excel
    Quelques contributions : USERFORM - Créer, Consulter, Modifier et Supprimer des enregistrements à l'aide d'un formulaire - Géolocalisation d'une adresse avec Excel et Google sans VBA

  4. #4
    Membre expert
    Philippe, Pierre,

    Merci de vos réponses.
    Je vais tester ça, mais, à priori, serais plus "orienté" vers la solution 1 de Pierre ou celle de Philippe (finalement sensiblement identiques).

    Pour tout vous dire, j'étais parti sur une idée plus "Range classique" (un peu dans l'idée 2 de Pierre), comme suit :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Const COL_ENTETE As String = "1;2;3;4;5;6;7;11;12;14;17;20"
    Dim TblDatas, entetes
        TblDatas = LObj.DataBodyRange.Value
        For i = 0 To UBound(entetes)
            For j = LBound(TblDatas, 1) To UBound(TblDatas, 1)
                Debug.Print TblDatas(j, entetes(i)) 'Avec dans l'idée de stocker ça dans une variable tableau
            Next
        Next

    Mais, ce qui me dérange dans cette méthode, c'est l'abandon de l'utilité des tableau structurés, à savoir les noms de colonne...
    Avec ma solution, on ne peux pas insérer ni supprimer de colonnes. Ça reste figé.
    Donc, je vais voir vos solutions.

    Pas besoin de retour, je pense que ce sujet est résolu.
    Cordialement,
    Franck

  5. #5
    Membre expert
    Finalement, je suis parti sur l'idée de Pierre, avec sa fonction getPartialArray.
    J'y ai juste ajouté un paramètre pour pouvoir séparer la ligne d'entêtes du DataBodyRange, etc...
    Comme suit :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Function getPartialArray(ls As ListObject, temp, Columns)
    'https://www.developpez.net/forums/d2091033/logiciels/microsoft-office/excel/transfert-certaines-colonnes-tableau-structure-vers-variable-tableau/#post11618243
    Dim r As Long, c As Long
        ReDim t(1 To UBound(temp), 1 To UBound(Columns) + 1)
        For r = 1 To UBound(temp)
            For c = 0 To UBound(Columns)
                t(r, c + 1) = temp(r, ls.ListColumns(Columns(c)).index)
            Next c
        Next r
        getPartialArray = t
    End Function

    Code d'appel :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Const COL_ENTETE As String = "ID;Date début;Date fin;Nom;Prénom"
    Dim TblEntete, TblDatas, t
        t = Split(COL_ENTETE, ";")
        TblEntete = getPartialArray(LObj, Range(LObj.Name & "[#headers]").Value, t)
        TblDatas = getPartialArray(LObj, LObj.DataBodyRange.Value, t)


    ça m'épargne une feuille de stockage des entêtes pour la solution de Philippe.
    Note : j'y viendrais peut-être un jour car cela permet de s'affranchir d'éventuelles modifications du code "en dur"...

    Merci encore à tous deux.
    Cordialement,
    Franck

  6. #6
    Expert confirmé
    Bonjour le Fil,

    Le fait de nommer Columns le dernier argument de la fonction ne risque-t'il pas de créer une ambigüité avec le Columns de la feuille active ?
    Cordialement,
    Patrice
    Personne ne peut détenir tout le savoir, c'est pour ça qu'on le partage.

    Pour dire merci, cliquer sur et quand la discussion est finie, penser à cliquer sur

  7. #7
    Responsable
    Office & Excel

    Salut Patrice

    Citation Envoyé par Patrice740 Voir le message
    Bonjour le Fil,

    Le fait de nommer Columns le dernier argument de la fonction ne risque-t'il pas de créer une ambigüité avec le Columns de la feuille active ?
    Non, la variable locale est prioritaire. Le VBA va "au plus près" pour trouver de quoi on parle. Lorsque cette variable n'existe pas dans le projet VBA (procédure puis module de la procédure puis autre module public), le VBA cherche dans les bibliothèques si quelque chose du même nom existe et s'arrête sur la première occurrence trouvée, je pense dans l'ordre d'inclusion des bibliothèques. Or, les bibliothèques pour le VBA d'Excel sont d'abord la bibliothèque VBA (c'est normal) puis la bibliothèque Excel. VBA n'exposant pas de propriété Columns dans son modèle objet, le VBA va fouiller dans le modèle Objet Excel qui est écrit de façon à ce que sans préfixe, Columns pointe vers la feuille de travail active (si la feuille active est une feuille de travail!).



    Heureusement d'ailleurs, car il serait impossible de devoir tenir compte de tout ce qui est nommé dans les librairies d'un projet avant de nommer nos propres variables. La bonne pratique ( mais je ne la suis pas, en tout cas pas toujours), serait de préfixer systématiquement les propriétés des objets auxquelles elles se rattachent, et donc d'utiliser ActiveSheet.Columns, et normalement en ayant vérifié que la feuille active est bien une worksheet. D'ailleurs, en l'absence d'une variable Columns dans la hiérarchie des portées de variables, on pourrait avoir un bug avec Columns.Count si la feuille active n'est pas une feuille de travail, mais une feuille de graphique





    Comme dit plus haut, sans préfixe, le code va au plus près, c'est-à-dire d'abord dans la procédure, puis dans le module, puis dans un autre module standard (si une seule variable Columns a été déclarée Public, sinon une erreur de compilation est levée)

    Au plus près => dans la procédure


    Au plus près => dans le module contenant la procédure


    Au plus près => dans un autre module standard



    D'ailleurs, on pourrait avoir une variable Columns As Public dans plusieurs modules standard, comme d'ailleurs plusieurs procédures nommées de façon identique dans différents modules standard. Ca ne pose pas de problème, il suffit de les préfixer du nom du module. C'est une technique que j'utilise souvent dans mes développements, en tout cas pour les procédures et fonctions (pas pour les variables publiques).




    Il faut savoir qu'un module standard n'est jamais qu'un module de classe statique (non instanciable, on ne sait pas faire pointer un objet vers lui) et que, normalement, on devrait préfixer les variables du nom du module [de classe] qui les contient...

    Si, dans un projet, on a plusieurs variables du même nom dans des modules différents, une procédure ne possédant pas de variable de ce nom et se trouvant dans un module qui lui non plus ne possède pas de variable de ce nom ne peut pas utiliser la variable sans la préfixer du module dont elle dépend.



    Enfin, même si l'on conçoit que ce soit déconseillé, on pourrait avoir dans une procédure une variable Columns dans un module qui possède une variable Columns. Cedernier cas est évidemment un cas d'école.

    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Une fois pour toutes, je donne mon avis. Je ne vais pas le répéter à chaque message...
    Si je propose une solution générique sur votre solution spécifique, c'est parce que, fainéant de nature, je privilégie le réutilisable...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

###raw>template_hook.ano_emploi###