Copier un tableau
Bonjour tout le monde,
Je suis en train d'apprendre à utiliser Excel VBA et je bloque sur un petit problème. Je ne pense pas que cela soit compliqué mais je n'ai rien trouvé ni sur Internet, ni sur le didactiel de ce site.
Je cherche à copier coller un tableau sans connaitre à l'avance son nombre de ligne et de colonnes.
A l'heure actuelle, mon code est le suivant :
Sub update()
Dim table(number_of_line, number_of_column)
For j = 0 To number_of_column
For i = 0 To number_of_line
table(i, j) = Sheets("BASE TOTAL").Range("A" & i + 2)
Next
Next
End Sub
number_of_column fait bien sur référence au nombre de colonne de mon tableau
de même pour number_of_line
Mon nouveau tableau que je cherche à remplir s'appelle table et l'ancien tableau que je veux copier coller est situé sur la page "BASE TOTAL".
En l'occurrence (mais sa va changer au cours du temps), il s'agit d'un tableau 16 x 55.
Le problème que je rencontre est qu'à chaque occurrence du j (je parcours les colonnes), je dois "incrémenter la lettre" du range. Par exemple, pour tout i, je dois avoir la lettre A pour j =0, la lettre B, pour j = 1 etc... non ? Comment faire dans ce cas ?
Merci beaucoup pour votre aide, je débute tout juste VBA mais ayant quelques connaissances (vite fait) en java et C, sa ne devrait pas être trop dur.
Bonjour et bienvenu
Si j'ai compris utilises Cells(Ligne,Colonne) à la place de Range
Ce qui pourrait donner
Sub update()
Dim table(number_of_line, number_of_column)
For j = 0 To number_of_column
For i = 0 To number_of_line
table(i, j) = Sheets("BASE TOTAL").Cells(i + 2,[surligner=#FFFF80]j + 1)
Next
Next
End SubBonjour et bienvenue sur le forum
Première remarque.
Il y a plusieurs façons de définir une plage de cellules.
Supposons que tu veuilles définir la plage de cellules qui va de la cellule B3 à la cellule D9.
Tu pourras la désigner au choix de 3 façons différentes :
Range(‘’B3:D9’’)
Range(cells(3, ‘’B ‘’),cells(9,’’D’’))
Range(cells(3,2),cells(9,4))
Dans ton cas, tu veux faire varier les lignes et les colonnes. Avec la méthode que tu as choisi pour parvenir à tes fins, tu n’as pas le choix. Il te faut utiliser la 3° façon.
Deuxième remarque
Tu veux copier un tableau, qui est supposons sur la Feuil1 et le coller ailleurs, supposons sur la Feuil2 au même endroit.
Copier les cellules une après l’autre n’est pas la solution la plus rapide mais elle est correcte.
Mais le nombre de colonnes importe peu. Il est plus important de connaitre les valeurs de la dernière ligne et de la dernière colonne. On suppose que les première ligne et colonne sont connues et fixes. Supposons que le tableau commence en A1.
On définit la dernière ligne avec l’instruction :
Last_Line = Range("A1").End(xlDown).Rowet la dernière colonne avec l’instruction :
Last_Column = Range("A1").End(xlToRight).ColumnMaintenant, tu as tout pour faire ta boucle :
Sub Essai1()
Last_Line = Range("A1").End(xlDown).Row
Last_Column = Range("A1").End(xlToRight).Column
For i = 1 To Last_Line
For j = 1 To Last_Column
Cells(i, j).Copy
Sheets("Feuil2").Cells(i, j).PasteSpecial xlPasteValues
Next j
Next i
End SubTroisième remarque
Il serait plus judicieux et plus rapide pour la macro, dans ton cas, de copier l’ensemble de ton tableau et de le coller en une seule opération, sans boucle :
Sub essai2()
Last_Line = Range("A1").End(xlDown).Row
Last_Column = Range("A1").End(xlToRight).Column
Range(Cells(1, 1), Cells(Last_Line, Last_Column)).Copy
With Sheets("Feuil2")
.Range(.Cells(1, 1), .Cells(Last_Line, Last_Column)).PasteSpecial xlPasteValues
End With
End SubBye !
Bonjour,
Avant toute chose, merci à tous les deux pour vos réponse.
Gmb, je n'ai pas tout saisi concernant tes remarques et j'aurais souhaité revenir sur 3 points.
Tu dis
Tu veux copier un tableau, qui est supposons sur la Feuil1 et le coller ailleurs, supposons sur la Feuil2 au même endroit.
En fait, je vais parcourir ce 1er tableau (Feuil1) plein de fois pour chercher des éléments particuliers et les coller dans un autre tableau qui existe déjà (Feuil3 par ex). Du coup, afin de réduire le temps de calcul, j'avais cru comprendre qu'il valait mieux copier coller ce tableau, mais sans avoir besoin de voir apparaitre sur une feuille particulière (Feuil2 si je suis tes notations) le nouveau tableau copier qui en pratique ne sert que d'intermédiaire pour les 2 autres tableaux existants. Du coup, est-ce quand même la bonne méthode que tu me proposes ?
Par ailleurs, tu dis
. Mais c'est la position de la dernière ligne et de la dernière colonne (ou de facon plus ou moins équivalente, le nombre de ligne et de colonne) qu'il est important de connaitre, non les valeurs de la dernière ligne et dernière colonne non ?Il est plus important de connaitre les valeurs de la dernière ligne et de la dernière colonne
Enfin, concernant ta remarque, tu dis
Il serait plus judicieux et plus rapide pour la macro, dans ton cas, de copier l’ensemble de ton tableau et de le coller en une seule opération, sans boucle :
Je te crois sur parole mais je me demande, par curiosité, pk ce serait plus rapide sans boucle ? Car en pratique, il y a une boucle (voir même 2) mais qui sont faites implicitement avec la fonction Range(Cells(1, 1), Cells(Last_Line, Last_Column)) non ? Ce 3eme point, est le moins primordial en soi.
Merci pour tes réponses gmb
Bonjour
Tu écris dans ton premier message :
Je cherche à copier coller un tableau sans connaitre à l'avance son nombre de ligne et de colonnes.
Moi j’ai traduit cela en : je cherche à copier un tableau qui existe sur une feuille (Feuille que je suppose s’appeler ‘’Feuille 1’)’ et à le coller dans une autre feuille (que je suppose s’appeler Feuille 2)
Dans mon esprit et donc dans ma proposition, il n’y a pas de feuille intermédiaire.
Mais peut-être n’ai-je rien compris à ta demande.
Mais c'est la position de la dernière ligne et de la dernière colonne...qu'il est important de connaitre, non les valeurs de la dernière ligne et dernière colonne non ?
Là, je suis tout à fait d’accord avec toi, c’est ce que j’ai voulu dire en parlant de ‘’Valeur de la dernière ligne et de la dernière colonne. Désolé de m'être mal exprimé.
par curiosité, pk ce serait plus rapide sans boucle ?
La macro ne fait que faire, très vite, ce que tu ferais à la main beaucoup moins vite.
Alors, si tu dois copier un tableau à la main, comment vas-tu faire ? Deux solutions :
1 – Tu sélectionnes le tableau entier, tu le copies et le colles sur une autre feuille
2 – Tu sélectionnes une cellule du tableau, tu la copies et tu vas la coller sur autre feuille et tu recommences pour chacune des cellules du tableau.
A ton avis, quelle solution te permettra de finir le plus vite ?
On est bien d'accord concernant les 2 derniers points. Par contre pour le 1er point, je pense effectivement qu'il y a malentendu (j'ai du mal m'expliquer, excuse-moi). J'ai vu sur ce site (https://www.excel-pratique.com/fr/vba/tableaux_vba.php) qu'on gagnait beaucoup de temps en travaillant sur des tableaux "informels" plutôt que sur des sur tableaux excels.
Le but de mon travail est de créer un système qui actualise automatiquement une base de données. Du coup, je travaille sur 2 pages : une feuille ou il y a la base de données actuelle et une autre feuille ou on copie colle les données à mettre à jour. Je vais donc devoir considérer chaque ligne de ma feuille 2, comparer les chaines de caractères à la base de données et agir en conséquence (modification ou ajout) sur la base de données. En gros, sa fait beaucoup de boucle avec beaucoup de comparaison. C'est pour sa que je préférerais partir sur des tableaux "informels" afin de diminuer nettement le temps de calcul et donc je voudrais copier-coller la base de données (feuille 1) ainsi que les données à mettre à jour (feuille 2) pour améliorer le temps de calcul (mais en pratique, le rendu final est bien un tableau excel, je veux juste éviter de parcourir 5000 ligne d'un tableau excel pour faire 5 modif, autant utiliser directement un tableau informel).
Je ne sais pas si je suis clair, j'espère, sinon dis-moi ce qui manque de précision/clarté
Mais en conséquence, la solution que tu me proposais ne correspond pas...
Par ailleurs, je rencontre un autre problème (dois-je créer un nouveau post pour cela ?).
Il s'agit toujours du même projet. J'ai donc la base de données (tableau excel présent sur la 1ere feuille appelé BASE TOTAL) et un autre tableau excel (données à mettre à jour) sur la seconde feuille. Je crée donc 2 tableaux "informels" pour ces 2 tableaux (appelons les BASE et table).
Je m'intéresse aux colonnes y et z des tableaux table et BASE (respectivement). Je considère une cellule donnée de la colonne y et je compare sa valeur (chaine de caractères) aux valeurs (chaines de caractères) de toute les cellules de mon tableau BASE de la colonne z. Mon but étant de savoir si il y a des éléments égaux ou non pour déterminer s'il s'agit d'une modification ou d'un ajout (car le numéro client de la base de données ne change jamais, mais s'il s'agit d'un nouveau client alors son numéro n'existe pas).
Voila mon code (x : dernière ligne du tableau, ils commencent bien évidemment à 0 car ce sont des tableaux "informels", values représente une ligne donnée) :
Sub procedure(ByVal values As Integer)
Dim cel As Variant
Dim page As String
page = Sheets("Feuil2").cells(values, y).value
Set cel = Worksheets("Feuil1").Range(cells(0, z), cells(x,z)).Find(what:="page", MatchCase:=False)
'Si pas de correspondance, nouveau client
If cel Is Nothing Then newclient
Else
oldclient
End If
End SubMais malheureusement, cela ne marche pas et je ne sais pas pourquoi. Je n'arrive même pas à compiler d'ailleurs !!! Cela me dérange bc, je pense que c'est parce que j'utilise une procédure qui prend un argument en entrée (values) mais c'est la 1ere fois que j'utilise ce genre de procédure...
J'avais pensé à une autre solution en utilisant une boucle for (en j) et where + like, quelque chose dans le genre :
If "Worksheets("Feuil1").cells(j, z).value" Like "Worksheets("Feuil2").cells(values,y).value" Then oldclient
Else
newclient
End Ifmais cela ne marche pas non plus et je crains que ce ne soit beaucoup plus long donc non intéressant.
Si tu peux encore m'aider sur ce problème, ce serait génial ! J'ai beau cherché sur internet, je n'arrive pas à trouver la solution. Merci d'avance pour tout conseil ou remarques
Bonjour
Essaie ce code :
Dim BDD, Table(), DerLn, DerCol, i, j
Sub Essai()
Sheets("Destination").Cells(2, "B").CurrentRegion.Offset(1, 0).ClearContents
With Sheets("BASE TOTAL")
DerLn = .Range("A" & Rows.Count).End(xlUp).Row
DerCol = .Cells(1, Columns.Count).End(xlToLeft).Column
'On charge la variable tableau (Table)
ReDim Table(DerLn - 1, DerCol)
For i = 0 To DerLn - 2
For j = 0 To DerCol
Table(i, j) = .Cells(i + 2, j + 1).Value
Next j
Next i
End With
'On recopie sur la feuille 'Destination' à partir de la variable tableau
With Sheets("Destination")
For i = 0 To UBound(Table, 1)
For j = 0 To UBound(Table, 2)
'ici, on peut poser des conditions sur les cellules
'de la Base, avant de les reporter sur la feuille
'Destination
.Cells(i + 2, j + 1).Value = Table(i, j)
Next j
Next i
End With
End SubBye !
Effectivement sa marche. En fait, ma méthode n'était vraiment pas loin de la tienne. La seul différence est que je calcule DerLn et DerCol dans une autre procédure en les déclarant global car je vais utiliser ces valeurs dans plusieurs procédures différentes.
Mais finalement, à l'aide de ton code et en bidouillant le mien, sa fonctionne finalement. Le pb était uniquement vis à vis de la page active vu que je travaille sur 2 feuilles excel.
Merci bc
Néanmoins, j'ai un petit souci. L'un des tableaux à copier comprend qq chose comme 700 lignes et 55 colonnes remplie de chaines de caractères et 65 000 lignes en plus (environ) qui ne contiennent pas de caractères mais une mise en page particulière (couleur) et donc ces lignes qui ne m'intéressent pas sont aussi copié dans mon tableau. Il faudrait donc modifier le code qui calcule DerLn pour que DerLn soit égal à 700 et non à 65 500. Comme sa, quand je rempli mon tableau, je ne m'intéresse plus aux lignes à partir de 701 !
Je vais voir si je peux trouver qq chose à ce sujet ! Mais si tu as une idée, je suis preneur
Merci bc en tout cas
Finalement, ta solution ne fonctionne pas si bien. C'est très étrange car à certains moment, la compilation marche très bien, je peux meme verifier que c'est bon avec des MsgBox par ex.
Et à d'autres moments (il suffit que je change le nom du tableau dans la procédure, ou que j'efface une ligne puis que je la recopie) sa bug totalement, pour les tableaux et sa me dit :
rreur 9: L'indice n'appartient pas à la selection
en surlignant sa :
ReDim base(number_of_line_in_the_database - 3, number_of_column_in_the_database - 1)Il ne s'agit pas d'un problème de taille du tableau, j'en suis sur j'ai vérifié plusieurs fois les bornes !
Voila mon code à tout hasard :
Dim number_of_column As Integer
Dim number_of_line As Integer
Dim number_of_column_in_the_database As Integer
Dim number_of_line_in_the_database As Integer
'determine le nombre de colonnes et lignes des feuilles BASE TOTAL et Nuevos informaciones
Sub number()
'Number of lines and columns in the database
With Sheets("BASE TOTAL")
number_of_line_in_the_database = .Range("A" & Rows.Count).End(xlUp).Row
number_of_column_in_the_database = .cells(2, Columns.Count).End(xlToLeft).Column
End With
'Number of lines and columns in the sheet Nuevos informaciones
With Sheets("Nuevos informaciones")
number_of_line = .Range("A" & Rows.Count).End(xlUp).Row
number_of_column = .cells(2, Columns.Count).End(xlToLeft).Column
End With
'begin the updating'
creationtable
creationbase
End Sub
'procedure which copies the new sheet Nuevos informaciones in a tab, called table, so as to reduce the time of calcul
Sub creationtable()
Dim table()
ReDim table(number_of_line - 3, number_of_column - 1)
For j = 0 To number_of_column - 1
For i = 0 To number_of_line - 3
table(i, j) = cells(i + 3, j + 1)
Next i
Next j
End Sub
'procedure which copies the sheet BASE TOTAL in a tab, called base, so as to reduce the time of calcul
Sub creationbase()
Dim base()
ReDim base(number_of_line_in_the_database - 3, number_of_column_in_the_database - 1)
For j = 0 To number_of_column_in_the_database - 1
For i = 0 To number_of_line_in_the_database - 3
base(i, j) = cells(i + 3, j + 1)
Next i
Next j
End SubJe ne comprend pas pk j'ai erreur 9 qui apparait de temps en temps sans raison...
Bonjour
Tu écris :
Je ne comprend pas pk j'ai erreur 9 qui apparait de temps en temps sans raison...
Je suis désolé mais sans fichier, je ne peux pas t'aider.
Bye !
Qu'appelle tu fichier ? L'ensemble du code, les données excel ou les 2 ?
Il parle de ton fichier Excel avec données j'en suis convaincue!
Les données étant confidentiel, j'ai recrée de fausses données excel. Mais du coup, j'ai fait des tableaux très petit (2 lignes et 55 colonnes pour la 1ere feuille, 1 ligne et 55 colonnes pour la 2nd feuille).
j'espère que sa ira ! Besoin du code en entier ou pas ?
Prenez plutôt ce fichier là ! Il y a les données et le code en VBA !
edit : fichier supprimé
Bonjour à tous
Bonjour Barthe
bonjour Saniafe
@Barthe
Tu écris :
Qu'appelle tu fichier ? L'ensemble du code, les données excel ou les 2 ?
Un fichier est un classeur ; il comprend les feuilles de calcul et si il y en a, les macros VBA
Les documents joints à ton dernier message ont l'air d'être ce que je souhaite.
Je regarderai cela demain.
A bientôt.
Bonjour gmb,
c'est bien ce que je pensais.
Super ! Merci pour ton aide
Depuis le début du post, en parcourant des forums et avec l'aide d'autres personnes j'ai réussi à améliorer mon code (je te met ici la version finale, ayant fait qq modifs depuis ce matin). Globalement, tout tourne assez bien, notamment le remplissage des tableaux (pb initial) se fait bien.
Le seul souci est que ponctuellement, une erreur 9 "Sub ou fonction non définie" empêche la compilation du programme. Cette erreur surligne toujours en jaune un ReDilm !
J'espère que tu trouveras le pb car coder un code qui ne marche que ponctuellement, c'est pas génial :p
Bon week-end sinon
edit : fichier supprimé
Bonjour
Tu écris :
J'espère que tu trouveras le pb car coder un code qui ne marche que ponctuellement, c'est pas génial :p
Je suis désolé mais je ne trouve pas.
Bye !
Ce n'est pas grave, merci énormément pour ton aide ! Merci aussi aux autres m'ayant aidé par ailleurs
Pour le moment sa compile donc je ne vais pas me plaindre !
Merci à tout le monde pour votre aide