web-dev-qa-db-fra.com

Combinez 2 tableaux Excel en un en ajoutant les données?

J'ai 2 tableaux sur 2 feuilles séparées d'un classeur MS Excel 2007, comme ci-dessous:

===========================
no.   f_name     l_name  
===========================
13   Little     Timmy
1   John       Doe
17   Baby       Jessica
---------------------------


===========================
no.   f_name     l_name  
===========================
1   john       Tim
16   kyle       joe
14   Baby       katy
22   qbcd       wsde
---------------------------

Les deux ont les mêmes colonnes, mais ils peuvent avoir des données différentes.

Je souhaite combiner les données des deux tables verticalement, c’est-à-dire un tableau unique contenant toutes les données d’une troisième feuille séparée. Si possible, je souhaite ajouter une autre colonne avec le nom de la feuille d'où provient la ligne.

===================================
SheetName   no.   f_name     l_name  
===================================
Sheet1      13   Little     Timmy
Sheet1      1   John       Doe
Sheet1      17   Baby       Jessica
Sheet2      1   john       Tim
Sheet2      16   kyle       joe
Sheet2      14   Baby       katy
Sheet2      22   qbcd       wsde
-----------------------------------

Peut-on le faire sans utiliser de macros?

9
anuj

Cette réponse traite de Structured Tables tel qu'interprété par Excel. Bien que les méthodes puissent facilement être transcrites en matrices de données brutes sans structure de tableau attribuée, les formules et le codage VBA pour cette solution seront ciblés sur de véritables tableaux structurés.

Préambule

Une troisième table peut conserver les données combinées de deux tables avec certaines formules de feuille de calcul natives, mais le maintien de la taille correcte de la troisième table au fur et à mesure de l'ajout ou de la suppression de lignes dans les tables dépendantes nécessitera soit des opérations de redimensionnement manuel, soit du VBA permettant de suivre ces modifications et de s'y conformer la troisième table pour convenir. J'ai inclus des options pour ajouter le nom de la feuille de calcul de la table source ainsi que du code VBA de maintenance de table à la fin de cette réponse.

Si tout ce que vous voulez, c'est un classeur d'exemple opérationnel sans toutes les explications, passez à la fin de cette réponse pour rechercher un lien vers le classeur utilisé pour créer cette procédure.

Exemples de tableaux de données

Table Collection Sample Data

J'ai utilisé les exemples de données du PO pour construire deux tables nommées (par défaut) Table1 et Table2 sur les feuilles de calcul Sheet1 et Sheet2 respectivement. Je les ai volontairement décalés à différents degrés depuis la cellule A1 de chaque feuille de calcul afin de démontrer la capacité d'un tableau structuré à s'adresser lui-même ou à un autre tableau structuré d'une formule en tant qu'entité distincte, quelle que soit sa position dans la feuille de calcul parent. La troisième table sera construite de la même manière. Ces compensations sont à des fins de démonstration uniquement; ils ne sont pas nécessaires.

Étape 1: Construisez la troisième table

Construisez les en-têtes de la troisième table et sélectionnez cette ligne d'en-tête future et au moins une ligne en dessous de celle-ci pour baser la commande Insérer ► Tables ► Table.

Combining Tables New Table

Votre nouveau troisième tableau vide sur la feuille de calcul Sheet3 devrait ressembler à ce qui suit.

Collecting Table Data Build New Table

Étape 2: remplir la troisième table

Commencez par renseigner la première cellule de la DataBodyRange de la troisième table. Dans cet exemple, il s'agirait de Sheet3! C6. Tapez ou collez la formule suivante dans C6 en gardant à l'esprit qu'elle est basée sur les noms de table par défaut. Si vous avez modifié les noms de vos tables, ajustez-les en conséquence.

=IFERROR(INDEX(Table1, ROW([@[no.]])-ROW(Table3[#Headers]),COLUMN(A:A)), INDEX(Table2, ROW([@[no.]])-ROW(Table3[#Headers])-ROWS(Table1),COLUMN(A:A)))

Le fonction INDEX récupère d’abord chaque ligne disponible dans Table1 . Les numéros de ligne réels sont dérivés avec le fonction ROW en référençant des parties définies du tableau structuré avec un peu de maths. Lorsque Table1 est à court de lignes, la récupération est transmise à une seconde fonction INDEX faisant référence à Table2 par fonction IFERROR et ses lignes séquentielles. sont récupérés avec le ROW et fonctions ROWS en utilisant un peu plus de maths. La fonction COLUMN est utilisée en tant que COLUMN(A:A) qui va extraire la première colonne de la table référencée, où qu'elle se trouve dans la feuille de calcul. Cela passera à la deuxième, troisième, etc. colonne lorsque la formule est remplie à droite.

En parlant de remplir à droite, remplissez la formule à droite en E6. Vous devriez avoir quelque chose qui se rapproche de ce qui suit.

Aggregating table data, third table

Étape 2.5: [facultatif] Ajoutez le nom de la feuille de calcul parent de la table source.

Saisissez la poignée de dimensionnement de Table3 (indiquée par la flèche orange dans l'exemple d'image ci-dessous) dans le coin inférieur droit et faites-la glisser d'une colonne à droite pour ajouter une nouvelle colonne au tableau. Renommez le libellé d'en-tête en un nom plus approprié que celui par défaut. J'ai utilisé Sheet comme libellé de colonne.

Collating table data - source worksheet name

Bien que vous ne puissiez pas extraire directement le nom de la feuille de calcul de la table source, le fonction CELL peut extraire le chemin complet, le nom de fichier et la feuille de calcul de toute cellule d’un classeur enregistré¹, en tant que l’option info_types .

Placez la formule suivante dans la cellule vide de Table3 dans la première ligne de la nouvelle colonne que vous venez de créer.

=TRIM(RIGHT(SUBSTITUTE(CELL("filename", IF((ROW([@[no.]])-ROW(Table3[#Headers]))>ROWS(Table1), Table2, Table1)), CHAR(93), REPT(CHAR(32), 999)), 255))

Compléter le remplissage de la table3

Si vous ne prévoyez pas de terminer ce petit projet avec un VBA pour conserver les dimensions de Table3 lorsque des lignes sont ajoutées ou supprimées de l'une des deux tables source, saisissez simplement la poignée de redimensionnement de Table3 et faites-la glisser jusqu'à ce que vous ayez accumulé toutes les données des deux tables. . Voir le bas de cette réponse pour un exemple d'image des résultats attendus.

Si vous envisagez d’ajouter de la VBA, ignorez toute la population de Table3 et passez à l’étape suivante.

Étape 3: Ajoutez de la VBA pour gérer la troisième table

L'automatisation complète d'un processus déclenché par des modifications des données d'une feuille de calcul est mieux gérée par la macro d'événements de la feuille de calcul Worksheet_Change . Etant donné que trois tables sont impliquées, chacune sur leur propre feuille de calcul, la macro Workbook_SheetChange est une meilleure méthode pour gérer les événements de modification de plusieurs feuilles de calcul.

Ouvrez le VBE avec Alt+F11. Une fois que vous l'avez ouvert, recherchez l'explorateur de projet en haut à gauche. S'il n'est pas visible, appuyez sur Ctrl+R pour l'ouvrir. Localisez ThisWorkbook et cliquez avec le bouton droit de la souris, puis choisissez Afficher le code (ou double-cliquez simplement sur ThisWorkbook).

Collect data from multiple tables

Collez le texte suivant dans le nouveau volet intitulé quelque chose comme Book1 - ThisWorkbook (Code) .

Option Explicit

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    Select Case Sh.Name
        Case Sheet1.Name
            If Not Intersect(Target, Sheet1.ListObjects("Table1").Range.Offset(1, 0)) Is Nothing Then
                On Error GoTo bm_Safe_Exit
                Application.EnableEvents = False
                Call update_Table3
            End If
        Case Sheet2.Name
            If Not Intersect(Target, Sheet2.ListObjects("Table2").Range.Offset(1, 0)) Is Nothing Then
                On Error GoTo bm_Safe_Exit
                Application.EnableEvents = False
                Call update_Table3
            End If
    End Select

bm_Safe_Exit:
    Application.EnableEvents = True
End Sub

Private Sub update_Table3()
    Dim iTBL3rws As Long, rng As Range, rngOLDBDY As Range
    iTBL3rws = Sheet1.ListObjects("Table1").DataBodyRange.Rows.Count
    iTBL3rws = iTBL3rws + Sheet2.ListObjects("Table2").DataBodyRange.Rows.Count
    iTBL3rws = iTBL3rws + Sheet3.ListObjects("Table3").DataBodyRange.Cells(1, 1).Row - _
                          Sheet3.ListObjects("Table3").Range.Cells(1, 1).Row
    With Sheet3.ListObjects("Table3")
        Set rngOLDBDY = .DataBodyRange
        .Resize .Range.Cells(1, 1).Resize(iTBL3rws, .DataBodyRange.Columns.Count)
        If rngOLDBDY.Rows.Count > .DataBodyRange.Rows.Count Then
            For Each rng In rngOLDBDY
                If Intersect(rng, .DataBodyRange) Is Nothing Then
                    rng.Clear
                End If
            Next rng
        End If
    End With
End Sub

Ces deux routines utilisent intensivement la feuille de calcul propriété. CodeName . Une Nom CodeName est Sheet1, Sheet2, Sheet3, etc et ne change pas lorsqu'une feuille de calcul est renommée. . En fait, ils sont rarement modifiés, même par les utilisateurs les plus avancés. Ils ont été utilisés pour que vous puissiez renommer vos feuilles de calcul sans avoir à modifier le code. Cependant, ils devraient maintenant pointer vers les feuilles de calcul correctes. Modifiez le code si vos tables et feuilles de calcul ne sont pas identiques à celles données. Vous pouvez voir les noms de code de chaque feuille de calcul entre parenthèses à côté de leur feuille de calcul propriété. Name dans l'image ci-dessus montrant l'explorateur de projet de VBE.

Robinet Alt+Q pour revenir à vos feuilles de calcul. Tout ce qui reste à faire serait de finir de remplir le tableau 3 en sélectionnant une cellule quelconque dans le tableau 1 ou Table2 et feignant de le modifier en tapant F2 puis Enter↵. Vos résultats devraient ressembler à ce qui suit.

Combine two tables into one automatically

Si vous avez suivi jusqu'ici, vous devriez avoir une table de collection assez complète qui combine activement les données de deux tables 'enfants' sources. Si vous ajoutez également VBA, la maintenance de la troisième table de collecte est pratiquement inexistante.

Renommer les tables

Si vous choisissez de renommer tout ou partie des trois tableaux, les formules de la feuille de calcul refléteront instantanément et automatiquement les modifications. Si vous avez choisi d'inclure la procédure Workbook_SheetChange et l'aide auxiliaire associée, vous devrez revenir à la feuille de code ThisWorkbook et utiliser Rechercher & remplacer pour apporter les modifications appropriées.

Exemple de classeur

J'ai mis à disposition de mon DropBox public un exemple de classeur entièrement opérationnel.

Table_Collection_w_Sheetname.xlsb


¹ Le fonction CELL ne peut extraire que le nom de la feuille de calcul d'un classeur enregistré. Si un classeur n'a pas été enregistré, il ne possède pas de nom de fichier et la fonction CELLU renvoie une chaîne vide lorsque le nom de fichier est demandé.

8
user4039065

Vous pouvez activer le Presse-papiers Office (flèche en bas à droite de la section Presse-papiers dans l'onglet Accueil du ruban). Copiez les deux plages, puis utilisez la commande Coller tout comme indiqué ci-dessous. 

Vous devez toujours remplir le nom de la feuille dans une colonne supplémentaire en premier lieu, ce qui peut être fait en double-cliquant sur la poignée de recopie.

enter image description here

Mettre à jour

Pour obtenir les mêmes résultats avec les formules, essayez de remplir ceci pour le nom de la feuille:

=IF(ROW()<=COUNTA(Sheet1!A:A),"Sheet1",IF(ROW()<COUNTA(Sheet1:Sheet2!A:A),"Sheet2",""))

puis remplissez cette formule pour les valeurs dans les tableaux:

=IF(ROW()<=COUNTA(Sheet1!A:A),Sheet1!A2,IF(ROW()<COUNTA(Sheet1:Sheet2!A:A),INDEX(Sheet2!A:A,ROW()-COUNTA(Sheet1!A:A)+1),""))
3
lori_m

lori_m a fait une très bonne contribution que j'ai construite en utilisant des tableaux Microsoft Excel et des références structurées.

Créez d'abord une colonne dans votre table en sortie appelée RowID, qui contient le numéro de la ligne dans la table, puis utilisez-la pour renseigner les valeurs de données.

=IF( INDIRECT("Table3[RowId]")<=ROWS(Table1)
    ,INDEX(Table1[column1],INDIRECT("Table3[RowId]"))
    ,INDEX(Table2[Column1],INDIRECT("Table3[RowId]")-ROWS(Table1)))

Il y a un explication détaillée de la façon dont cela fonctionne sur mon blog car c'était trop long à inclure ici.

1
James Bayley

J'utilise ce code/formule. fonctionne bien pour mes besoins La seule chose que j'aimerais savoir, c'est comment puis-je créer une meilleure formule de cellule pour pouvoir utiliser 3 tableaux ou plus à titre de référence. actuellement im imbriquant un tas de déclarations iferror au sein de l'iferror 

=IFERROR(INDEX(Table1, ROW([@Date])-ROW(Table3[#Headers]),COLUMN(A:A)),IFERROR( INDEX(Table2, ROW([@Date])-ROW(Table3[#Headers])-ROWS(Table1),COLUMN(A:A)), IFERROR(INDEX(Table4, ROW([@Date])-ROW(Table3[#Headers])-ROWS(Table2)-ROWS(Table1),COLUMN(A:A)),INDEX(Table5, ROW([@Date])-ROW(Table3[#Headers])-ROWS(Table2)-ROWS(Table1)-ROWS(Table4),COLUMN(A:A)))))

J'utilise aussi le 

0
DJRCB

Une légère modification du code de Jeeped.

Si vous utilisez une approche similaire, mais avec plusieurs tables (plus de 10 par exemple), il sera alors fastidieux d’essayer d’ajouter manuellement chaque nom de chaque table. Cela pose également un problème si vous modifiez les noms des tables, car ces noms sont câblés dans VBA. Pour éviter tout travail supplémentaire, considérez ceci:

Donc, supposons ce qui suit:

  • Chaque feuille de calcul contient une ou plusieurs tables, mais leur structure est similaire. 
  • Il n'y a que des tableaux sur les feuilles de calcul - aucun autre membre de la collection ListObjects n'est présent.
  • Chaque fois que nous modifions une table sur une feuille, cela déclenche une mise à jour dans la table principale (table 3).

Ensuite, le Workbook_SheetChange Sub de l'exemple ci-dessus pourrait ressembler à ceci:

     Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
     Dim tbl As ListObject
     For Each tbl In ActiveSheet.ListObjects
        If Not Intersect(Target, tbl.Range.Offset(1, 0)) Is Nothing Then
            On Error GoTo bm_Safe_Exit
            Application.EnableEvents = False
            Call update_Table
        End If
        Next tbl
        bm_Safe_Exit:
        Application.EnableEvents = True
     End Sub

Modifier. La deuxième routine ressemblera alors à:

   Private Sub update_Table()
    Dim iTBL3rws As Long, rng As Range, rngOLDBDY As Range
    Dim tbl As ListObject
    Dim sht As Worksheet
    iTBL3rws = 0

    ' consider all tables, excluding master table
    For Each sht In ThisWorkbook.Worksheets
        For Each tbl In sht.ListObjects
            If tbl.Name <> "Table3" Then
                iTBL3rws = iTBL3rws + tbl.DataBodyRange.Rows.Count
            End If
        Next tbl
    Next sht

    iTBL3rws = iTBL3rws + Sheet3.ListObjects("Table3").DataBodyRange.Cells(1, 1).Row - Sheet3.ListObjects("Table3").Range.Cells(1, 1).Row
        With Sheet3.ListObjects("Table3")

            Set rngOLDBDY = .DataBodyRange

            .Resize .Range.Cells(1, 1).Resize(iTBL3rws, .DataBodyRange.Columns.Count)

            If rngOLDBDY.Rows.Count > .DataBodyRange.Rows.Count Then
                For Each rng In rngOLDBDY
                    If Intersect(rng, .DataBodyRange) Is Nothing Then
                        rng.Clear
                    End If
                Next rng
            End If
        End With

End Sub

Cette routine diffère de la précédente en éliminant les cas préprogrammés. Lorsqu'une modification est enregistrée dans une feuille de calcul active, toute table de cette feuille qui est sur le point d'être modifiée déclenchera update_Table procedure. 

0
Infinito