Transfert de données d'un classeur vers un autre classeur Excel VBA

Bonjour Pedro ! J'espère que tu as passé un bon week-end

J'ai utilisé tes raccourcis pour vérifier et comprendre les endroits ou VBA m'indique que j'ai des erreurs et je souhaitais juste confirmer quelques choses avec toi.

Pour cette capture d'écran, j'ai utilisé le raccourci F1 en sélectionnant un objet. Il semble me dire que ma première erreur se trouve dans l'expression du ".Value".

Est-ce qu'utiliser le ".Value" dans ce contexte est faux car mes variables sont déclarées en tant que As Variant, As Workbook et As Long plutôt qu'en As String ?

(c'est ce que je comprends des indications présentent dans la fenêtre "aide").

Bonjour !

A moins d'utiliser un type inadapté à tes données, le type de variable ne génère pas d'erreur. Aussi, cheminfichier est effectivement une chaîne de caractères, et pourrait être déclaré en type String (moins consommateur de mémoire que Variant).

Je suis presque certain que l'origine du problème est liée à des plages de tailles différentes. En effet, la plage copiée démarre à la ligne 2, et se prolonge jusqu'à LigImport. Donc, en résumé, on copie LigImport - 1 lignes. Ce décalage est à prendre en compte dans la plage de destination...

Effectivement, je me doutais que ce serait peut-être un problème de plage de données. Tu me dis que je dois prendre en compte le fait que nous ayons mis LigImport- 1ligne donc peut-être que je devrais utiliser l'une de ces deux solutions (la deuxième me parait la plus jouable).

Première solution

ça :

WBdest.Range("A" & DerLig & ":AE" & DerLig + LigImport).Value = .Range("A:AE" & LigImport).Value

Plutôt que ça :

WBdest.Range("A" & DerLig & ":AE" & DerLig + LigImport).Value = .Range("A2:AE" & LigImport).Value

Deuxième solution:

ça :

LigImport = .Range("A" & .Rows.Count).End(xlUp).Row+1 'Détermine la dernière ligne de l'import
           WBdest.Range("A" & DerLig & ":AE" & DerLig + LigImport).Value = .Range("A2:AE" & LigImport).Value

Plutôt que ça :

LigImport = .Range("A" & .Rows.Count).End(xlUp).Row 'Détermine la dernière ligne de l'import
           WBdest.Range("A" & DerLig & ":AE" & DerLig + LigImport).Value = .Range("A2:AE" & LigImport).Value

Qu'en penses-tu ?

La plage copiée débute à la ligne 2, considérant que la première ligne est une en-tête, et qu'il n'est pas nécessaire de la reporter.

Ta première proposition est fausse, car "A:AE" & LigImport n'est pas une plage valide, puisque tu n'as pas de ligne de départ.

Ta seconde proposition, bien que la syntaxe soit correcte, est inadaptée. En effet, il ne s'agit pas de copier une ligne de plus (LigImport + 1 étant par ailleurs une ligne vide), mais de coller sur une ligne de moins. En clair, le problème n'est pas sur la plage à copier, mais sur la plage où l'on colle les données !

D'accord donc si je comprends bien ce que tu veux dire, la modification que je dois effectuer si je souhaite que le code fonctionne se trouve sur cette partie:

[WBdest.Range("A" & DerLig & ":AE" & DerLig + LigImport).Value/code]

de cette ligne :

[code]WBdest.Range("A" & DerLig & ":AE" & DerLig + LigImport).Value = .Range("A2:AE" & LigImport).Value

car de cette manière, je modifierais la plage de données ou l'on colle les données et pas la plage de données à copier ?

D'accord donc si je comprends bien ce que tu veux dire, la modification que je dois effectuer si je souhaite que le code fonctionne se trouve sur cette partie:

[WBdest.Range("A" & DerLig & ":AE" & DerLig + LigImport).Value/code]

de cette ligne :

[code]WBdest.Range("A" & DerLig & ":AE" & DerLig + LigImport).Value = .Range("A2:AE" & LigImport).Value

car de cette manière, je modifierais la plage de données ou l'on colle les données et pas la plage de données à copier ?

Exact

Bon d'accord alors j'ai essayé ça :

 WBdest.Range("A" & DerLig & ":AE" & DerLig - 1 + LigImport).Value = .Range("A2:AE" & LigImport).Value

Plutôt que ça:

WBdest.Range("A" & DerLig & ":AE" & DerLig + LigImport).Value = .Range("A2:AE" & LigImport).Value

Premièrement ça ne fonctionne pas

et deuxièmement est-ce que ça revient à annuler le + 1 de cette ligne de code ?

DerLig = .Range("A" & .Rows.Count).End(xlUp).Row + 1 

Enfait j'aurais besoin que tu m'expliques cette ligne :

WBdest.Range("A" & DerLig & ":AE" & DerLig + LigImport).Value = .Range("A2:AE" & LigImport).Value

Comme ça je pourrais trouver l'erreur.

Parce que pour moi cette ligne de code signifie :

"Je copie les valeurs des cellules de la colonne A2 à la colonne AE jusqu'à la première ligne vide. Puis, je les colle dans les cellules de la colonne A à partir de la dernière ligne remplie (derlig) jusqu'aux cellules de la colonne AE à partir de la dernière ligne remplie (derlig) dans le classeur actif."

Je n'arrive pas à associer de fonctions à LigImport dans cette ligne.

Enfait j'aurais besoin que tu m'expliques cette ligne :

WBdest.Range("A" & DerLig & ":AE" & DerLig + LigImport).Value = .Range("A2:AE" & LigImport).Value

Comme ça je pourrais trouver l'erreur.

Parce que pour moi cette ligne de code signifie :

"Je copie les valeurs des cellules de la colonne A2 à la colonne AE jusqu'à la première ligne vide. Puis, je les colle dans les cellules de la colonne A à partir de la dernière ligne remplie (derlig) jusqu'aux cellules de la colonne AE à partir de la dernière ligne remplie (derlig) dans le classeur actif."

Je n'arrive pas à associer de fonctions à LigImport dans cette ligne.

Tu n'es pas loin. Je te mets un fichier pour mieux illustrer. Dans mon exemple, chaque onglet correspond à un fichier.

30illu-plages.xlsx (21.26 Ko)

Super bien illustré (merci d'avoir pris le temps de faire ça) !

Donc on voit bien que dans l'onglet "WBsource" (qui est un autre fichier bien sur), il y a 49 lignes à importer (car on ne prend pas en compte les titres des colonnes). On voit que LigImport est enfait la dernière ligne remplie donc la 50ème. C'est ça ?

Et quand dans le premier onglet "WBdest" tu dis que "'64 = DerLig + LigImport - 2" en mettant un -2 car DerLig comporte un +1 (donc -1) et qu'il faut éliminer les champs de l'onglet deux donc -1. Je me trompe pas ?

Super bien illustré (merci d'avoir pris le temps de faire ça) !

Donc on voit bien que dans l'onglet "WBsource" (qui est un autre fichier bien sur), il y a 49 lignes à importer (car on ne prend pas en compte les titres des colonnes). On voit que LigImport est enfait la dernière ligne remplie donc la 50ème. C'est ça ?

Et quand dans le premier onglet "WBdest" tu dis que "'64 = DerLig + LigImport - 2" en mettant un -2 car DerLig comporte un +1 (donc -1) et qu'il faut éliminer les champs de l'onglet deux donc -1. Je me trompe pas ?

Oui. DerLig correspond bien à la première ligne vide, où l'on commence à coller la plage copiée (d'où ce +1 dans son calcul). Cette fois, ça devrait fonctionner !

Autre remarque : le code utilisé pour le calcul des dernières lignes repose uniquement sur la colonne A, et la valeur peut-être erronée si la cellule A de la dernière ligne est vide. Si tu prend le fichier que je t'ai envoyé et que tu supprimes la cellule A50 de l'onglet "WBsource", la macro déterminera LigImport comme égale à 49, bien que le reste de la ligne 50 soit complet...

A toi de voir si le cas risque de se présenter dans tes données ou pas ! Si oui, il faut peut-être choisir une autre colonne dont tu es sûre qu'elle est systématiquement complète ou utiliser une autre méthode dans le code.

je sais que celle-ci sera systématiquement complète malheureusement la ligne ne fonctionne toujours pas...

WBdest.Range("A" & DerLig & ":AE" & DerLig + LigImport - 2).Value = .Range("A2:AE" & LigImport).Value

Nous sommes d'accords ?

Il existe d'autres méthodes ? Si tu en connais, pourrais-tu me les expliquer pour que j'essaie de les coder ?

J'ai modifié le code pour le tester sur le petit fichier exemple :

Sub Import()

Dim cheminfichier As Variant, WBsource As Worksheet, WBdest As Worksheet, DerLig As Long, LigImport As Long

        'On affecte le classeur actif à un nom, pour pouvoir y revenir facilement
        Set WBdest = Sheets(1)
        With WBdest
              DerLig = .Range("A" & .Rows.Count).End(xlUp).Row + 1 'Première ligne vide de la feuille
        End With

        ' Sélection du classeur source à partir d'une fenêtre
        'cheminfichier = Application.GetOpenFilename("Fichiers Excels (*.xlsm), *.xlsm")

        'Ouverture du classeur source, que l'on affecte à un objet classeur
        Set WBsource = Sheets(2)

        'Report des valeurs
        With WBsource
             LigImport = .Range("A" & .Rows.Count).End(xlUp).Row 'Détermine la dernière ligne de l'import
             WBdest.Range("A" & DerLig & ":AK" & DerLig + LigImport - 2).Value = .Range("A2:AK" & LigImport).Value
        End With

End Sub

Il fonctionne sans problèmes.

Edit : je crois avoir trouvé le problème... J'ai oublié de préciser la feuille entre "WBdest" (= le classeur) et Range (= la plage).

Quand tu utilises ce code, tu ne travailles pas sur deux fichiers (classeurs) différents ?

Parce que c'est ça ma problématique initiale : importer des données d'un classeur vers un autre

Quand tu utilises ce code, tu ne travailles pas sur deux fichiers (classeurs) différents ?

Parce que c'est ça ma problématique initiale : importer des données d'un classeur vers un autre

Oui, je l'ai juste modifié pour le tester sur un même fichier. Mais regarde en bas de mon post, je crois avoir trouvé le problème.

Voilà du coup le code à tester :

Sub Import2()

Dim cheminfichier As Single, WBsource As Workbook, WBdest As Workbook, DerLig As Long, LigImport As Long

'On affecte le classeur actif à un nom, pour pouvoir y revenir facilement
Set WBdest = ThisWorkbook
DerLig = Sheets("MaFeuille").Range("A" & Rows.Count).End(xlUp).Row + 1 'Première ligne vide de la feuille

'Sélection du classeur source à partir d'une fenêtre
cheminfichier = Application.GetOpenFilename("Fichiers Excels (*.xlsm), *.xlsm")

'Ouverture du classeur source, que l'on affecte à un objet classeur
Set WBsource = Workbooks.Open(cheminfichier)

'Report des valeurs
With WBsource.Sheets(1)
    LigImport = .Range("A" & .Rows.Count).End(xlUp).Row 'Détermine la dernière ligne de l'import
    WBdest.Sheets("MaFeuille").Range("A" & DerLig & ":AK" & DerLig + LigImport - 2).Value = .Range("A2:AK" & LigImport).Value
End With

End Sub

J'ai modifié le code pour le tester sur le petit fichier exemple :

Sub Import()

Dim cheminfichier As Variant, WBsource As Worksheet, WBdest As Worksheet, DerLig As Long, LigImport As Long

        'On affecte le classeur actif à un nom, pour pouvoir y revenir facilement
        Set WBdest = Sheets(1)
        With WBdest
              DerLig = .Range("A" & .Rows.Count).End(xlUp).Row + 1 'Première ligne vide de la feuille
        End With

        ' Sélection du classeur source à partir d'une fenêtre
        'cheminfichier = Application.GetOpenFilename("Fichiers Excels (*.xlsm), *.xlsm")

        'Ouverture du classeur source, que l'on affecte à un objet classeur
        Set WBsource = Sheets(2)

        'Report des valeurs
        With WBsource
             LigImport = .Range("A" & .Rows.Count).End(xlUp).Row 'Détermine la dernière ligne de l'import
             WBdest.Range("A" & DerLig & ":AK" & DerLig + LigImport - 2).Value = .Range("A2:AK" & LigImport).Value
        End With

End Sub

Il fonctionne sans problèmes.

Edit : je crois avoir trouvé le problème... J'ai oublié de préciser la feuille entre "WBdest" (= le classeur) et Range (= la plage).

Ici tu veux dire :

With WBsource.Sheets("ETAT DE LA LISTE DES FACTURES")
             LigImport = .Range("A" & .Rows.Count).End(xlUp).Row + 1 'Détermine la dernière ligne de l'import
             WBdest.Range("A" & DerLig & ":AK" & DerLig + LigImport - 2).Value = .Range("A2:AK" & LigImport).Value
        End With
WBdest.Range("A" & DerLig & ":AK" & DerLig + LigImport - 2).Value = .Range("A2:AK" & LigImport).Value

Entre WBdest et Range ?

ça y'est ça fonctioooooonne OH MON DIEU MERCI BEAUCOUP PEDRO (si tu t'appelles vraiment pedro) !!!

ça y'est ça fonctioooooonne OH MON DIEU MERCI BEAUCOUP PEDRO (si tu t'appelles vraiment pedro) !!!

Non, mais c'est pas grave. J'espère que tu comprends un peu mieux le code maintenant, ça me parait indispensable pour ne pas produire n'importe quoi...

Bonjour !

Comment tu t'appelles alors ?

J'ai appris grâce au cours VBA dispo sur ce forum à comprendre les sélections de plage de données.

Du coup, je sais que si je rajoute un 6 derrière le A comme ici, ça ne fonctionne pas car DerLig et LigImport exprime les lignes:

WBdest.Sheets("BDDengie").Range("A6" & DerLig & ":AK" & DerLig + LigImport - 2).Value = .Range("A2:AK" & LigImport).Value

Je veux mettre un A6 car je veux que mon export commence à partir de la ligne A6 puisque avant cette ligne j'ai mis un menu.

Est-ce que je peux ouvrir un procédure "WITH" qui concerne les coordonnées de cellules A6, la feuille 1 et le classeur actif.

Comme ceci:

  'Report des valeurs
        With WBsource.Sheets("ETAT DE LA LISTE DES FACTURES")
             LigImport = .Range("A" & .Rows.Count).End(xlUp).Row + 1 'Détermine la dernière ligne de l'import
             With WBdest.Sheets("Feuil1").Range("A6")
             WBdest.Sheets("BDDengie").Range("A" & DerLig & ":AK" & DerLig + LigImport - 2).Value = .Range("A2:AK" & LigImport).Value
             End With
        End With

Bonjour !

Comment tu t'appelles alors ?

J'ai appris grâce au cours VBA dispo sur ce forum à comprendre les sélections de plage de données.

Du coup, je sais que si je rajoute un 6 derrière le A comme ici, ça ne fonctionne pas car DerLig et LigImport exprime les lignes:

WBdest.Sheets("BDDengie").Range("A6" & DerLig & ":AK" & DerLig + LigImport - 2).Value = .Range("A2:AK" & LigImport).Value

Je veux mettre un A6 car je veux que mon export commence à partir de la ligne A6 puisque avant cette ligne j'ai mis un menu.

Est-ce que je peux ouvrir un procédure "WITH" qui concerne les coordonnées de cellules A6, la feuille 1 et le classeur actif.

Comme ceci:

  'Report des valeurs
        With WBsource.Sheets("ETAT DE LA LISTE DES FACTURES")
             LigImport = .Range("A" & .Rows.Count).End(xlUp).Row + 1 'Détermine la dernière ligne de l'import
             With WBdest.Sheets("Feuil1").Range("A6")
             WBdest.Sheets("BDDengie").Range("A" & DerLig & ":AK" & DerLig + LigImport - 2).Value = .Range("A2:AK" & LigImport).Value
             End With
        End With

Bonjour,

Non, ça ne veut strictement rien dire cette instruction With... Si tu veux que ton premier import se colle à partir de la ligne 6, soit tu t'arranges pour avoir une donnée en A5 dans ton fichier et que la procédure détermine donc que DerLig = 6, soit tu rajoutes une structure If qui contrôle la valeur de DerLig et la remplace par 6 si elle est inférieure à cette valeur.

Tu m'excuseras, ce n'est pas spécialement méchant mais voit le plutôt comme un électrochoc... Tu ajoutes régulièrement des instructions qui n'ont ni queue ni tête sans te poser les bonnes questions, à savoir : que fais réellement ce que j'écris (déjà est-ce que ça a un sens ?) et surtout, où et comment écrire ce que je veux faire ?

Je suis inquiet concernant la fiabilité de ton travail quand je te vois attaquer du code VBA de cette manière. PREND LE TEMPS DE LIRE DAVANTAGE DE COURS ET DE T’ENTRAÎNER AVEC DES MANIP' SIMPLES !!!!! On ne peut coder sans comprendre le code...

Rechercher des sujets similaires à "transfert donnees classeur vba"