IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

Macros et VBA Excel Discussion :

Prendre un vecteur 1D à partir d'un tableau 2D


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 42
    Par défaut Prendre un vecteur 1D à partir d'un tableau 2D
    Bonjour,

    j'ai un tableau 2D de 15x2 dans une variable et je voudrais sélectionner les 15 valeurs de la première colonne sans devoir faire une boucle for. Est-ce possible?

    Ex : vecteur1d=tableau2d(:,1)

    Merci!

  2. #2
    Expert confirmé Avatar de jfontaine
    Homme Profil pro
    Contrôleur de Gestion
    Inscrit en
    Juin 2006
    Messages
    4 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Contrôleur de Gestion

    Informations forums :
    Inscription : Juin 2006
    Messages : 4 756
    Par défaut
    Bonjour,

    Je trouve qu'une boucle for est plus "propre" mais pour répondre à ta question tu peux utiliser une plage de cellule

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Dim vecteur1d() As Variant
     
    'Copie de la variable tableau dans un onglet
    Sheets("Feuil1").Range(Cells(1, 1), Cells(UBound(tableau2d, 1) + 1, UBound(tableau2d, 2) + 1)) = tableau2d
     
    'Copie des données de la première colonne dans la variable à une dimension
    vecteur1d= Sheets("Feuil1").Range(Cells(1, 1), Cells(UBound(tableau2d, 1) + 1, 1))

  3. #3
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 141
    Par défaut Extraire une colonne d'un tableau 2D pour écrire sur la feuille Excel
    A la ligne 5 précédente, comme tableau2d a deux dimensions -- 15 rangées sur 2 colonnes --, l'affectation proposée a de forte chance de modifier à la fois les colonnes A & B. Hors on souhaite extraire la première colonne de tableau2d sans boucle For Next.

    Cela sera montré au chapitre 2 par une façon que d'aucuns trouveront un tout petit peu inhabituel grâce à l'instruction peu connue LSet pour extraire la première colonne du tableau 2D sans boucles apparentes.

    1. Ecrire un vecteur 1D dans une portion de colonne de la feuille

    Au final on aboutira à l'affectation 2D vers 1D demandée, les boucles For Next intermédiaires ne servant qu'à lire le tableau 2D ou modifier ses éléments mais ne sont pas utilisées pour la lecture ou l'écriture sur la feuille. L'utilisation de l'expression "sélectionner les 15 valeurs de la première colonne" a pu faire penser qu'il s'agissait d'une écriture du tableau2d vers la feuille Excel.

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    Option Explicit ' Lecture / écriture d'une portion de colonne via un vecteur
    ' ============================ Description de la feuille
    Public Const rowDataStart = 1               ' Première rangée des données
    Public Const rowDataEnd = rowDataStart + 14 ' Dernière rangée des données
     
    Public Const colDataFirst = 1               ' Première colonne des données
    Public Const colDataLast = colDataFirst + 1 ' Dernière colonne des données
     
    Const patcherColA = 1, patcherColB = 10     ' Modificateur de colonnes A et B
     
    Const colVar = 1 ' Le variant de lecture de la colonne A n'a qu'une colonne
    Type VectorType
        ArrTab1D(rowDataStart To rowDataEnd) As Integer                   ' Vrai vecteur 1D
    End Type
    Type VectorCellType
        ArrTab2D(rowDataStart To rowDataEnd, colVar To colVar) As Integer ' Faux vecteur 1D
    End Type
     
    Type ArrayDoubleColType
        Col1 As VectorCellType  ' Faux vecteur 1D de la première colonne
        CoL2 As VectorCellType  ' Faux vecteur 1D de la seconde colonne
    End Type
    Type Array2ColType          ' Vrai tableau 2D
        ArrCol2D(rowDataStart To rowDataEnd, colDataFirst To colDataLast) As Integer
    End Type
     
    Sub Vecteur1DFromAndToCells()
    Dim vector1D As VectorType, vectorCell As VectorCellType
    Dim indRow As Integer, rngVect As Range, varVector As Variant
     
        Set rngVect = Range(Cells(rowDataStart, colDataFirst), Cells(rowDataEnd, colDataFirst))
        varVector = rngVect.Value     ' Lit en une seule fois la colonne A dans le Variant
     
        For indRow = rowDataStart To rowDataEnd ' Modifie le vecteur en incrémentant chaque élément.
            vectorCell.ArrTab2D(indRow, colVar) = varVector(indRow, colVar) + patcherColA
        Next
        rngVect = vectorCell.ArrTab2D ' Ecrit le vecteur en une seule fois en colonne A
    '    rngVect = varVector          ' est aussi possible si on veut rester avec le Variant
     
        LSet vector1D = vectorCell    ' Copie vecteur 2D vers 1 D
        With vector1D
            For indRow = rowDataStart To rowDataEnd ' Modifie le vecteur 1D
                .ArrTab1D(indRow) = .ArrTab1D(indRow) + patcherColB ' élément par élément.
            Next
        End With
        LSet vectorCell = vector1D    ' Copie vecteur 1D vers 2D
     
        Set rngVect = Range(Cells(rowDataStart, colDataLast), Cells(rowDataEnd, colDataLast))
        rngVect = vectorCell.ArrTab2D ' Ecrit le vecteur "1D" en une seule fois en colonne B
    End Sub
     
    Sub Array2DFromAndToCells()
    Dim rngArr As Range, array2Col As Array2ColType, arrayDouble As ArrayDoubleColType
    Dim indRow As Integer, rngVect As Range, varVector As Variant, vectorCell As VectorCellType
     
        Set rngArr = Range(Cells(rowDataStart, colDataFirst), Cells(rowDataEnd, colDataLast))
        varVector = rngArr.Value     ' Lit en une seule fois les colonnes A & B dans le Variant
     
        With array2Col
            For indRow = rowDataStart To rowDataEnd ' Copie Variant vers tableau 2D
                .ArrCol2D(indRow, colDataFirst) = varVector(indRow, colDataFirst)
                .ArrCol2D(indRow, colDataLast) = varVector(indRow, colDataLast) - patcherColA - patcherColB
            Next
        End With
        LSet arrayDouble = array2Col        ' Copie le tableau 2D
        LSet vectorCell = arrayDouble.CoL2  ' Copie uniquement la seconde colonne
     
        Set rngVect = Range(Cells(rowDataStart, colDataLast), Cells(rowDataEnd, colDataLast))
        rngVect = vectorCell.ArrTab2D       ' Ecrit le vecteur "1D" en une seule fois en colonne B
     
        LSet vectorCell = arrayDouble.Col1  ' Ne copie que la première colonne
        With vectorCell
            For indRow = rowDataStart To rowDataEnd ' Restore la valeur initiale
                .ArrTab2D(indRow, colVar) = vectorCell.ArrTab2D(indRow, colVar) - patcherColA
            Next
            Set rngVect = Range(Cells(rowDataStart, colDataFirst), Cells(rowDataEnd, colDataFirst))
            rngVect = .ArrTab2D             ' Ecrit le vecteur en une seule fois en colonne A
        End With
    End Sub
    Sur la feuille de A1 à A15, on a mis les nombres de 1 à 15. Idem de B1 à B15

    Dans la fenêtre d'Exécution immédiate (Ctrl+G) du VBE d'Excel, copier-coller et valider par ENTER :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Vecteur1DFromAndToCells
    Sur la feuille, les nombres ont été incrémentés de patcherColA = 1 en colonne A et de patcherColB = 10 en colonne B.

    On lit dans un Variant la colonne A. Une fois le variant modifié, l'écriture est réalisée en une seule opération. Plutôt qu'un variant on peut également utiliser un faux vecteur 1D dont la seconde dimension est toujours colVar = 1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        LSet vector1D = vectorCell    ' Copie vecteur 2D vers 1 D
     ' Modifier vector1D dans une boucle For Next
        LSet vectorCell = vector1D    ' Copie vecteur 1D vers 2D
        rngVect = vectorCell.ArrTab2D ' Ecrit le vecteur "1D" en une seule fois en colonne B
    2. Extraire un vecteur 1D d'un tableau 2D sans For Next

    On utilise l'instruction LSet pour séparer la première colonne de la seconde d'un tableau 2D sans boucle For Next.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        LSet arrayDouble = array2Col        ' Copie le tableau 2D 
        LSet vectorCell = arrayDouble.Col1  ' Ne copie que la première colonne
        With vectorCell
            Set rngVect = Range(Cells(rowDataStart, colDataFirst), Cells(rowDataEnd, colDataFirst))
            rngVect = .ArrTab2D             ' Ecrit le vecteur en une seule fois en colonne A
        End With
    Dans la fenêtre d'Exécution immédiate (Ctrl+G) du VBE d'Excel, copier-coller et valider par ENTER :
    Sur la feuille, les nombres ont été restaurés à leurs valeurs initiales 1 à 15 en colonne A et B mais en deux étapes bien distinctes à suivre en pas à pas dans le débogueur pour démontrer l'affectation de chaque vecteur individuellement par colonne.

    3. Performance For Next 2D -> 1D vs. double LSet

    Vérifions la performance du double LSet par rapport à extraire la première colonne du tableau 2D 15 rangées * 2 colonnes par une boucle For Next classique.

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    Sub PerfForNext_LSet()
    Const nbrIterationPerf = 100000000
    Dim tStart As Double, tEnd As Double, indPerf As Long
    Dim arr2D(rowDataStart To rowDataEnd, colDataFirst To colDataLast) As Integer
    Dim arr1D(rowDataStart To rowDataEnd) As Integer, vector1D As VectorType
    Dim array2Col As Array2ColType, arrayDouble As ArrayDoubleColType
    Dim indRow As Integer, rngData As Range, varVector As Variant
     
        Set rngData = Range(Cells(rowDataStart, colDataFirst), Cells(rowDataEnd, colDataLast))
        varVector = rngData.Value     ' Lit en une seule fois les colonnes A & B dans le Variant
     
        With array2Col
            For indRow = rowDataStart To rowDataEnd ' Copie Variant vers tableau 2D
                array2Col.ArrCol2D(indRow, colDataFirst) = varVector(indRow, colDataFirst)
                array2Col.ArrCol2D(indRow, colDataLast) = varVector(indRow, colDataLast)
                arr2D(indRow, colDataFirst) = varVector(indRow, colDataFirst)
                arr2D(indRow, colDataLast) = varVector(indRow, colDataLast)
            Next
        End With
        tStart = Time
        For indPerf = 1 To nbrIterationPerf
            For indRow = rowDataStart To rowDataEnd: arr1D(indRow) = arr2D(indRow, colDataFirst): Next
        Next
        tEnd = Time
        Debug.Print "Copie élément par élément de la 1ere colonne en : " + Format(tEnd - tStart, "HH:MM:SS")
        tStart = Time
        For indPerf = 1 To nbrIterationPerf
            LSet arrayDouble = array2Col        ' Copie le tableau 2D
            LSet vector1D = arrayDouble.Col1    ' Copie uniquement la première colonne
        Next
        tEnd = Time
        Debug.Print "Copie de la 1ere colonne via deux LSet en       : " + Format(tEnd - tStart, "HH:MM:SS")
        Stop
    End Sub
    Dans la fenêtre d'Exécution immédiate (Ctrl+G) du VBE d'Excel, copier-coller et valider par ENTER :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Copie élément par élément de la 1ere colonne en : 00:00:59
    Copie de la 1ere colonne via deux LSet en       : 00:00:07
    Cela dépend du type des éléments du tableau 2D et de ses dimensions.
    Le LSet apporte un gain ! Même s'il faut relativiser ce gain en considérant le nombre d'itérations 100000000 pour faire apparaître une différence de performance.

    Le programme de mesure de la performance s'est arrêté sur le Stop avant End Sub.
    Dans la fenêtre d'Exécution immédiate :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ? arr2D(rowDataEnd, colDataFirst) & " = " & arr1D(rowDataEnd) & " = " & vector1D.ArrTab1D(rowDataEnd)
    15 = 15 = 15
    ___________

    Si la discussion est résolue, vous pouvez cliquer sur le bouton

    En bas de ce message s'il vous a apporté des éléments de réponse pertinents, pensez également à voter en cliquant sur le bouton vert ci-dessous.

  4. #4
    Expert confirmé
    Avatar de Didier Gonard
    Homme Profil pro
    Formateur Office et développeur VBA en freelance
    Inscrit en
    Février 2008
    Messages
    2 805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Formateur Office et développeur VBA en freelance

    Informations forums :
    Inscription : Février 2008
    Messages : 2 805
    Par défaut
    Citation Envoyé par hbc87 Voir le message
    Bonjour,

    j'ai un tableau 2D de 15x2 dans une variable et je voudrais sélectionner les 15 valeurs de la première colonne sans devoir faire une boucle for. Est-ce possible?
    Bonjour,

    la vraie question serait : est-ce raisonnable ?

    Alourdir une appli par une usine à Gaz, est-ce vraiment le but ?

    Surtout si on considère le but final d'un code (hors son bon fonctionnement qui est de rigueur) : légèreté, lisibilité, portabilité, maintenance.

    Citation Envoyé par jfontaine
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    'Copie des données de la première colonne dans la variable à une dimension
    vecteur1d= Sheets("Feuil1").Range(Cells(1, 1), Cells(UBound(tableau2d, 1) + 1, 1))
    as-tu vérifié le nombre de dimensions de ta variable dans le fenêtre Variables locales de l'éditeur VBE ou par ce biais ?
    http://silkyroad.developpez.com/vba/tableaux/#LXIV-E

    voir ici, sinon : http://didier-gonard.developpez.com/...vba/#LVIII-C-2

    cordialement,

    Didier

  5. #5
    Membre émérite
    Homme Profil pro
    retraité
    Inscrit en
    Mai 2006
    Messages
    542
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Mai 2006
    Messages : 542
    Par défaut
    Bonjour à tous

    Nous ne connaissons pas le but final de cette "manipulation", mais pour ma part, je ferai tout simplement 2 tableaux distincts .

    Eric

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 42
    Par défaut
    Bonjour,

    j'aurais due préciser un peu plus, j'ai un tableau 2D de 15x2 dans une variable suite à des calculs faits dans excel. Le but était d'extraire les noms des colonnes du tableau (qui n'ont aucun lien avec les noms des colonnes excel pour ensuite les envoyer dans l'axe X d'un histogramme.

    Dans le langage matlab c'est possible simplement avec la commande variable2=variable1(15, : ).

    Peut-être que VBA n'a pas été conçu de la même manière...

Discussions similaires

  1. Réponses: 5
    Dernier message: 29/09/2014, 23h08
  2. Réponses: 2
    Dernier message: 28/12/2005, 16h53
  3. alimanter une listbox a partir d'un tableau
    Par wikimeta dans le forum Composants VCL
    Réponses: 9
    Dernier message: 31/10/2005, 14h24
  4. [MySQL] Comment ecrire dans une BDD à partir d'un tableau ?
    Par weed dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 16/09/2005, 15h53
  5. courbe à partir d'un tableau
    Par chafcha dans le forum MFC
    Réponses: 3
    Dernier message: 26/02/2004, 08h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo