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!
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!
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))
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.
Sur la feuille de A1 à A15, on a mis les nombres de 1 à 15. Idem de B1 à B15
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
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é incrémentés de patcherColA = 1 en colonne A et de patcherColB = 10 en colonne B.
Code : Sélectionner tout - Visualiser dans une fenêtre à part Vecteur1DFromAndToCells
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 :
2. Extraire un vecteur 1D d'un tableau 2D sans For Next
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
On utilise l'instruction LSet pour séparer la première colonne de la seconde d'un tableau 2D sans boucle For Next.
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
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
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.
Code : Sélectionner tout - Visualiser dans une fenêtre à part Array2DFromAndToCells
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.
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
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
Code : Sélectionner tout - Visualiser dans une fenêtre à part PerfForNext_LSetCela dépend du type des éléments du tableau 2D et de ses dimensions.
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
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 :
15 = 15 = 15
Code : Sélectionner tout - Visualiser dans une fenêtre à part ? arr2D(rowDataEnd, colDataFirst) & " = " & arr1D(rowDataEnd) & " = " & vector1D.ArrTab1D(rowDataEnd)
___________
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 vertci-dessous.
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.
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 ?Envoyé par jfontaine
http://silkyroad.developpez.com/vba/tableaux/#LXIV-E
voir ici, sinon : http://didier-gonard.developpez.com/...vba/#LVIII-C-2
cordialement,
Didier
Bonjour à tous
Nous ne connaissons pas le but final de cette "manipulation", mais pour ma part, je ferai tout simplement 2 tableaux distincts .
Eric
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...
Partager