Résolu VBA: copier coller grace a des informations en dur .

  • Auteur de la discussion aurelie1985
  • Date de début

aurelie1985

Nouveau membre
Bonjour tout le monde :hello: .
Je débute actuellement en programmation et tout particulièrement avec le VBA , et voici mon problème .

J'ai un tableau sur l' une de mes feuilles avec deux types de colonnes , l'une contenant la position des cellules ( colonnes cells ) , l'autre contenant le texte que je souhaite copier ( la première cellule de cette colonne contenant le nom de la feuille ciblé ).
Il y a plusieurs colonnes et donc plusieurs feuilles ciblés , de plus la colonne Cells est toujours a gauche de la colonne FeuilleCible .

Ici la difficultées est donc de récuperer les infos " en dur " ( la cellule et la feuille cible ) via le code pour obtenir la destination pour copier chaque mot a son emplacement .

(Si c'est trop confu , n'hésitez pas a me le dire )

J'ai donc un bout de code ( attention les yeux , ça pique :ange: )

[cpp]

Option Explicit

Private Sub Test


Dim ws_source As Worksheet
Dim NomFeuilTarget As String
Dim positionCell As String
Dim TabLangue As String
Dim LigneD As Range
Dim Feuil_source As Range
Dim celD_source As Range
Dim column_source As Range
Dim cel_source As Range
Dim cel_target As Range
Dim Target As Range

TabLangue = ComboBoxChxLangue.Text
Set ws_source = Worksheets(TabLangue)
Set LigneD = ws_source.Range(ws_source.Rows(1), ws_source.Rows(1))
Set Feuil_source = ws_source.Range(ws_source.Rows(1), ws_source.Rows(41))


For Each celD_source In LigneD.Rows
If celD_source.Value <> " cell " Then

For Each column_source In Feuil_source.Rows
For Each cel_source In column_source.Cells

NomFeuilTarget = cel_source + Target.Offset(0, 0) ' // premiere cellule de la colonne , elle contient le nom de la feuille cible , je ne sais pas si ça marche .
positionCell = cel_source + Target.Offset(0, -1) ' // cellule a gauche contient la position ciblé
Set cel_target = Worksheets(NomFeuilTarget).Cells(positionCell) '//on applique les informations

cel_target.Value = cel_source.Text

End If

End Sub

[/cpp]

Je suppose que c'est une horreur totale pour n'importe quel programmeur mais je suis completement bloqué :??: .

Si quelqu'un a une idée voir un code a me proposer , je suis toute ouie :)

Aurelie
 

zeb

Modérateur
Salut,

Eh, il y a de bonnes choses la dedans... et du moins bon.

Tu veux m'expliquer ça : ?
Code:
Set LigneD = ws_source.Range(ws_source.Rows(1), ws_source.Rows(1))
:lol:
Où sont les Next correspondants aux For ? :/
Et pourquoi ce code n'est-il pas correctement indenté ? On n'y voit rien ! :o

Si c'est trop confu (sic)
Eh, c'est surtout dans ta tête que c'est confus. :D
Tu parles de colonnes, mais tu utilises des Rows. Faudrait savoir.

Offset(0, 0) ne fait pas grand' chose. Mais je te l'accorde, pour fixer les idées, ça m'arrive de l'écrire.
cel_source + Target.Offset(0, 0) M'enfin, pourquoi une addition ? De cel_source, tu t'intéresses à quoi ? Qu'est-ce que Target ? De Target.Offset(0, 0), tu t'intéresses à quoi

Explique-toi/moi la ligne 30. Mot à mot. Tes incohérences vont te sauter aux yeux. Tu pourras alors corriger de toi-même ou bien me redemander de l'aide.
 

aurelie1985

Nouveau membre
Bonjour Zeb ,
Oui je dois dire que c'est assez confus quand je prog , j'ai tendance a être aproximative , j'ai hésité a mettre mon code d'ailleurs , je me suis dis que j'allais plus embrouiller qu'autre choses :sarcastic: .


Pour le :
[cpp]Set LigneD = ws_source.Range(ws_source.Rows(1), ws_source.Rows(1))[/cpp]

Je dois tout d'abord , lire la première ligne de mon tableau , pour déterminer sur quelle colonne je dois copier les cellules , elle est directement lié à

[cpp]For Each celD_source In LigneD.Rows
If celD_source.Value <> " cell " Then[/cpp]

Mais en fait , ceci serait peut-être plus juste ?
[cpp]Set LigneD = ws_source.Range(ws_source.Rows(1))[/cpp]

Oulà oui , j'ai oublier de mettre mes Next , :pt1cable: .

Oui , pour la colonne , confondu ligne avec colonne , je modifie .
[cpp]For Each column_source In Feuil_source.Columns[/cpp]

Pour la ligne 30 bah , ce que je veut faire , c'est de récuperer la valeur de la premiere cellule de la colonne a lequel apartient cel_source pour renseigner la variable NomFeuilTarget et ainsi indiquer la feuille ciblé .
Je m'etais dit , a tort , que Offset(0, 0) , serait par défaut , la premiere cellule de la colonne .


J'espere que je ne t'embrouille pas trop :/
 

zeb

Modérateur
Si ws est une feuille, alors ws.Rows est la collection de toutes ses lignes, et parmi elles, ws.Rows(1) en est la première. Range(..) est un ensemble de cellules. Donc Range(ws.Rows(1)) est l'ensemble des cellules de la ligne 1, bref, c'est la ligne 1. Pas la peine d'en faire tant :
Code:
Set LigneD = ws_source.Rows(1)
Je voudrais que tu te fasses toi-même ce genre de réflexion.

Code:
For Each celD_source In LigneD.Rows
Pour chacun des éléments de LigneD.Rows...
LigneD est une ligne.
LigneD.Rows est l'ensemble des lignes de la zone LigneD qui par construction n'en contient qu'une.
Donc celD_Source va valoir LigneD.Rows(1) et c'est tout.

Si tu veux parcourir les cellules de la ligne LigneD, il faut écrire :
Code:
For Each celD_source In LigneD.Cells
Je voudrais que tu sois cohérente.

valeur (value) de la premiere cellule (cells(1)) de la colonne(columns) a lequel apartient cel_source

Soit une cellule c, la ligne à laquelle est appartient est c.EntireColumn.
Sa première cellule est c.EntireColumn.Cells(1), et sa valeur est donc c.EntireColumn.Cells(1).Value.

Worksheets() est la collection de toutes les feuilles d'un classeur.
Worksheets("Nom") ou Worksheets(N) est une feuille de cette collection, qui s'appelle "Nom" ou qui est numérotée N.

Donc si c.EntireColumn.Cells(1).Value est un nom de feuille, la feuille est Worksheets(c.EntireColumn.Cells(1).Value).
Je voudrais que tu puisses refaire ce raisonnement.

Réécris donc ton code, à la lumière de ces éléments...
 

aurelie1985

Nouveau membre
C'est vrai qu'une fois qu'on voit a vu ses erreurs , elle paraissent aberantes :ange: .

Cependant j'ai un problème desormais , ma condition de seulement lire les colonnes qui ne commencent pas par "Cell" passe desormais par :
[cpp]NomFeuilTarget = cel_source.EntireColumn.Cells(1).Value
If cel_source.EntireColumn.Cells(1).Value = " Cell " Then
[/cpp]

Je ne sais pas comment coder pour qu'il passe a la colonne suivante sans rien copier si cette condition est respectée ( Si la valeur de la premiere cellule de la colonne est Cell donc ).
Pour l'instant j'ai ceci mais ce code est incomplet ...
[cpp]
Private Sub Test

Dim ws_source As Worksheet
Dim NomFeuilTarget As String
Dim positionCell As String
Dim TabLangue As String
Dim Feuil_source As Range
Dim column_source As Range
Dim cel_source As Range
Dim cel_target As Range

TabLangue = ComboBoxChxLangue.Text
Set ws_source = Worksheets(TabLangue)
Set Feuil_source = ws_source.Range(ws_source.Rows(1), ws_source.Rows(41))

For Each column_source In Feuil_source.Columns
For Each cel_source In column_source.Cells


NomFeuilTarget = cel_source.EntireColumn.Cells(1).Value '//premiere cellule de la colonne , elle contient le nom de la feuille cible
If cel_source.EntireColumn.Cells(1).Value = " Cell " Then '// je ne sais pas si on peut le faire .
Else

positionCell = ActiveCell.Offset(0, -1).cel_source.Value '// cellule a gauche contient la position ciblé
Set cel_target = Worksheets(NomFeuilTarget).Cells(positionCell) '//on applique les informations

cel_target.Value = cel_source.Text
End If
Next
Next

End Sub[/cpp]
 

zeb

Modérateur
Sois gentille, apprends à indenter ton code. C'est TRES important. :o

---------------

M'enfin, tu fais n'importe quoi !

Ligne 16, tu parcours tes colonnes.
Ligne 17, tu parcours les cellules de ces colonnes.
Ligne 21, tu récupères la première cellule de la colonne de la cellule courant.
Eh, t'aurais pas pu le faire entre les lignes 16 et 17 ?????

Ligne 20, tu te casses la nénette à récupérer un mot que tu mets dans une variable.
Ligne 21, au lieu de reprendre ta variable, tu recommences !

Ligne 24, qu'est-ce que ce ActiveCell ?

Médite tout ça. Ensuite seulement, lis la suite...

---------------

Ça y est, t'as bien réfléchi ? Alors tu n'as pas besoin de lire ça :
Code:
For Each column_source In Feuil_source.Columns
    NomFeuilTarget = column_source.Cells(1).Value
    If NomFeuilTarget= "Cell" Then
        MsgBox "Je ne veux pas de la colonne " & column_source.Address
    Else
        For Each cel_source In column_source.Cells
            positionCell = cel_source.Offset(0, -1).Value
            Set cel_target = Worksheets(NomFeuilTarget).Cells(positionCell)
            cel_target.Value = cel_source.Text
        Next
    End If
Next
Sauf que Cells() à la ligne 8, attend des coordonnées (Row,Column), et que je ne pense pas que positionCell puissent convenir.
Quelle est la nature de l'information dans positionCell ?
Au pif-o-mètre, c'est Range() qu'il va falloir utiliser.
 

aurelie1985

Nouveau membre
L'information , dans la colonne Cell , est sous cette forme : 1,17
1,18
2,21
...
En effet positionCell n'a pas l'air de convenir , je cherche mais pour l'instant j'ai pas encore trouvé .
 

zeb

Modérateur
Attention !

Pour Excel, en français, 1,17 est un nombre rationnel qu'on peut écrire 1+1/10+7/100.
En VB, "1,17" est une chaîne de 4 caractères qui ne représente pas un nombre. 1.17 est un nombre.
Ce que nous voulons, c'est deux nombres entiers, 1 et 17, pour mettre comme argument à Cells(row, column).

Il faut donc écrire quelque chose comme ça :
Code:
positionCell = "1,17"
positionCellrow = nombre_à_gauche_de_la_virgule(positionCell)
positionCellcol = nombre_à_droite_de_la_virgule(positionCell)
Set cel_target = Worksheets(NomFeuilTarget).Cells(positionCellrow, positionCellcol)
Sauf que la fonction nombre_à_gauche_de_la_virgule n'existe pas. :o

Il faudrait trouver une fonction pour splitter sur la virgule... [:patch]
 

aurelie1985

Nouveau membre
Et si je crée 2 colonnes , une qui contient la ligne et l'autre la colonne , désigné respectivement positionCellrow et positionCellcol .
Et qu'ensuite je fasse ceci :

[cpp]positionCellrow = cel_source.Offset(0, -2).Value
positionCellcol =cel_source.Offset(0,-1).Value

Set cel_target = Worksheets(NomFeuilTarget).Cells(positionCellrow , positioncellcol)

[/cpp]

Est ce judicieux , a ton avis ?
 

zeb

Modérateur
C'est une solution :o
Mais que c'est moche !

Autre solution, mettre "Q1" pour 1,17 et utiliser Range() plutôt que Cells().
Mais relis mon baratin, une solution pour 1,17 s'y cache. ;)
 

aurelie1985

Nouveau membre
Je pense que je vais essayer avec ta deuxieme solution ^^ .

Par contre il y a un soucis et là je ne comprend pas du tout d'ou ça peut provenir o_O .

Cette ligne est mise en debugage et un message "Propriété ou méthode non gérée par cet objet ?"
(j'ai fait l'aide mais cela ne m'a pas vraiment éclairée ....)

[cpp]NomFeuilTarget = column_source.Cells(1).Values[/cpp]

EDIT : Trouvé , j'avait écrit value avec un " s " a la fin ...
 

aurelie1985

Nouveau membre
Quoi que je fasse , j'ai toujours le problème avec :

[cpp]positionCell = cel_source.Offset(0, -1).Value[/cpp]

Le message affiche : "Erreur définie par l'application ou par l'objet"

Et je pense savoir pourquoi , en effet dans :

[cpp]For Each cel_source In column_source.Cells
positionCell = cel_source.Offset(0, -1).Value[/cpp]

Ma cel_source se balade aussi dans mes colonnes "Cell" (et donc tout est faussé) or je veut qu'elle se cantonne qu'a mes colonnes ou sont mes mots a copier-coller , et qu'elle n'aille dans les colonnes "Cell" seulement via mon :

[cpp]positionCell = cel_source.Offset(0, -1).Value[/cpp]

pour recuperer la position .
Il faudrait donc une condition pour que cel_source aille directement a la colonne suivante si celle-ci a pour premiere cellule " cell " mais ne pas totalement empecher son accès pour le :
[cpp]positionCell = cel_source.Offset(0, -1).Value[/cpp]

Donc , je planche dessus mais si t'as une idée, je suis plus que preneuse :whistle:

 

zeb

Modérateur
Salut,

Je vois que tu as bien travaillé en mon absence. :)
Tu es difficile à suivre... Voudrais-tu republier ton code et réexpliquer calmement ce que tu souhaites.

A te lire.
 

aurelie1985

Nouveau membre


Mouais , j'ai plutôt pataugé ^^ .

Je n'arrive pas a inserer le tableau Excel sur lequel je travaille et qui faciliterais peut-être la comprehension du problème .
Il y a 2 types de colonnes , l'une qui contient les cellules cibles (correspondant au mot a sa droite ), l'autre qui contient les infomations a copier , de plus dans cette colonne , le nom de la feuille cible est la premiere cellule .
En gros c'est ceci :

Cell l NomFeuilCible1
A1 l Name
A2 l Surname

Et ainsi de suite ( il y a 10 colonnes de chaque. )
( désolé , c'est assez pitoyable mais bon ... )


Ce que je veut c'est copier coller ces informations grace a la cellule cible qui est indiqué a gauche du mot et grace au nom de la feuille de la cellule cible dans la premiere cellule .
Tu as compris ?

Mon code actuel , as pas mal changé mais ne m'apporte rien :

[cpp]
Private Sub Test()

'//verification si les champs sont renseignées

If ComboBoxChxLangue = "" Then
MsgBox "Please fill fields "

End If

Dim ws_source As Worksheet
Dim NomFeuilTarget As String
Dim NomFeuilTarget2 As String
Dim positionCell As String
Dim TabLangue As String
Dim Feuil_source As Range
Dim column_source As Range
Dim cel_source As Range
Dim cel_source2 As Range
Dim cel_target As Range
Dim l As Long
Dim c As Long

TabLangue = ComboBoxChxLangue.Text
Set ws_source = Worksheets(TabLangue) '//feuille source
Set Feuil_source = ws_source.Range(ws_source.Columns(1), ws_source.Columns(20)) '// la feuille de la col 1 a 20

For c = 1 To 20
For l = 1 To 36

For Each column_source In ws_source.Columns
For Each cel_source In column_source.Cells
If cel_source.Cells(1, c) Like "Cell" Then '// si colonne Cell alors
cel_source = cel_source.Offset(0, 1) '// je veut passer directement a la colonne suivante or ici je copie la valeur .
Else '// sinon
NomFeuilTarget = cel_source.Cells(1, c).Value '// la premiere cellule de la colonne est le nom de la feuille Cible
positionCell = cel_source.Offset(0, -1).Value '// autre problème , ceci ne marche pas car elle comprend aussi la premiere ligne qui contient l'entete "Cell" , qui est purement indicative .

Set cel_target = Worksheets(NomFeuilTarget).Cells(positionCell) '//on renseigne la position de la feuille et celule cible
cel_target.Value = cel_source.Text '// on copie


End If
Next
Next
Next l
Next c[/cpp]

J'ai commenté un maximum pour que tu comprennes ce que j'ai voulu faire .

 

zeb

Modérateur
Sur la possibilité de faire un lien de ce topic vers ton classeur :
Et ben non. C'est interdit. Comme ça, je n'ai ici que de braves Aurélies, un peu perdues, mais bien gentilles quand même.
Et aucun méchant salaud ne posant de stupides questions que pour faire ouvrir un fichier plein de macro-virus aux couillons qui voudraient rendre service.

Sur la forme :
Ton code est mal indenté, c'est mal. :o
Ligne 25, tu déclares une plage de cellules que tu appelles Feuille_.... Si tu veux te tromper, ou tromper les autres, t'as qu'à donner des noms d'oiseaux à tes variables. En plus, tu ne t'en ressers pas ! :o
Ne mets des commentaires que fonctionnels. Rien de technique ni d'explicatif par rapport au BASIC qui doit se lire dans le texte (au début, c'est dur ;) )

Sur le fond :
Pourquoi y-a-t-il QUATRE niveaux de For .. Next imbriqués ?
Ligne 32, tu utilises Like. M'enfin, pourquoi faire s'il n'y a pas d'astérisque dans ce à quoi tu compares ?

-------------

Je ne comprends pas l'organisation de ton fichier. Et ainsi de suite n'est pas assez clair.
Tu as en fait :
Code:
Cell | NomFeuilCible1 | Cell | NomFeuilCible1 | Cell | NomFeuilCible1 
A15  | Name           | A3   | LastName       | A1   | FirstName           
A2   | Surname        | A12  | Subname        | A24  | Lastname        
.....|................|......|................|......|

C'est ça ?
 

aurelie1985

Nouveau membre
Bonjour Zeb ,

Oui , le Feuil_source n'est pas utile en fait ^^ .

Euh pour les Next , je ne vois pas le problème , j'ai 4 For et je boucle les 4 par un Next ( patapay :sweat: )

Pour le Like , c'est un oubli de ma part , c'est sur que sans asterisque ...

Pour le tableau , alors oui c'est ça , par contre , chaque colonne "NomFeuil" est destiné a une feuille cible differente ( j'ai 10 feuilles en tout ) , donc ça serait ici plutot Cell , NomFeuil1 , Cell ,NomFeuil2 ,Cell , NomFeuil3 ....

Pour les commentaires , je les ai rajoutés pour toi car même si a la base un code doit se suffire pour la comprehension , il y a souvent un fossé entre ce que je veut et ce que j'ai fait :sarcastic: .
 

zeb

Modérateur
Meilleure réponse
Bon je commence à comprendre un peu ce que tu veux.
Par contre, moi, je que je veux, c'est que tu T'expliques pourquoi tu as besoin de QUATRE boucles imbriquées !!!

----------------------

A étudier :
Code:
Dim feuille_source    As Worksheet
Dim donnees_source    As Range
Dim colonne_source    As Range
Dim cellule_l1_source As Range
Dim cellule_source    As Range

Dim feuille_cible     As Worksheet
Dim nom_feuille_cible As String
Dim cellule_cible     As Range

Set feuille_source = Worksheets(1)
Set donnees_source = feuille_source.Range(feuille_source.Rows(2), feuille_source.Rows(20))

'// Parmi toutes les cellules de la ligne 1
For Each cellule_l1_source In feuille_source.Rows(1).Cells
    '// Considérer celles qui contienntt "Cell"
    If cellule_l1_source.Text = "Cell" Then
        '// Considérer la feuille dont le nom est à droite de notre première cellule
        nom_feuille_cible = cellule_l1_source.Offset(0, 1).Text
        Set feuille_cible = Worksheets(nom_feuille_cible)
        
        '// La colonne courante
        Set colonne_source = cellule_l1_source.EntireColumn
        
        '// Dans la colonne ET dans la zone des données
        For Each cellule_source In Intersect(colonne_source, donnees_source)
            If cellule_source.Text <> "" Then
                '// Déperminer la cible
                Set cellule_cible = feuille_cible.Range(cellule_source.Text)
            
                '// Feu!
                cellule_cible.Value = cellule_source.Offset(0, 1).Text
            End If
        Next
    End If
Next
 

aurelie1985

Nouveau membre
Ce code marche parfaitement , je te remercie beaucoup pour l'aide et le temps passé .
J'essaie en ce moment de rajouter la modification du nom de la feuille , des charts et autre text box via le tableau .
Je pense mettre mon code demain pour ceux que ça interesse :)



Aurelie .
 
Vous devez vous inscrire ou vous connecter pour répondre ici.
Derniers messages publiés
Statistiques globales
Discussions
730 134
Messages
6 718 063
Membres
1 586 394
Dernier membre
Manoushk
Partager cette page
Haut