web-dev-qa-db-fra.com

Comment fusionner deux tableaux dans Excel avec des colonnes identiques?

Dans Excel, j'ai une feuille de calcul qui extrait les données d'une base de données SQL dans une table, puis génère un rapport basé sur ces données. Malheureusement, les données de cette base de données SQL sont incomplètes et je souhaite inclure dans le jeu de résultats des lignes supplémentaires entrées manuellement dans la feuille de calcul.

Bien que je souhaite, je ne peux pas simplement insérer manuellement ces lignes supplémentaires dans la table, car elles seraient supprimées chaque fois que Excel extrait de nouvelles données de la base de données SQL. Donc, au lieu de cela, j’envisage de créer une table séparée avec les mêmes en-têtes de colonne sur une nouvelle feuille et d’y entrer les données, puis de créer une troisième table sur une autre feuille qui combine les lignes de la table qui extrait les données de SQL et les table où je saisis les données manuellement. Comment puis-je accomplir cela? (Ou alternativement, y a-t-il une meilleure façon de faire cela qui me manque?)


Exemple:

Table 1 (From Database):

  | Person | Week Of | Task | Hours |
  | Bob    | 1/6/13  | Foo  | 12    |
  | Mary   | 1/6/13  | Foo  | 7     |
  | Mary   | 1/6/13  | Bar  | 5     |
  | John   | 1/6/13  | Foo  | 5     |
  | John   | 1/13/13 | Foo  | 13    |

-

Table 2 (Entered Manually): 
  | Person | Week Of | Task | Hours |
  | Bob    | 1/6/13  | Baz  | 3     |
  | Mary   | 1/6/13  | Baz  | 2     |
  | John   | 1/13/13 | Baz  | 5     |

-

Result:
  | Person | Week Of | Task | Hours |
  | Bob    | 1/6/13  | Foo  | 12    |
  | Mary   | 1/6/13  | Foo  | 7     |
  | Mary   | 1/6/13  | Bar  | 5     |
  | John   | 1/6/13  | Foo  | 5     |
  | John   | 1/13/13 | Foo  | 13    |
  | Bob    | 1/6/13  | Baz  | 3     |
  | Mary   | 1/6/13  | Baz  | 2     |
  | John   | 1/13/13 | Baz  | 5     |
11
Ajedi32

Voici une solution purement Excel sans VBA. Cela fonctionne en utilisant une fonction INDEX pour réduire les lignes et les colonnes des données SQL jusqu'à ce que les valeurs soient épuisées et qu'il en résulte une condition d'erreur. Une fonction IFERROR détecte l'erreur et utilise une seconde fonction INDEX pour réduire les lignes et les colonnes des données saisies manuellement, de nouveau jusqu'à l'épuisement de ces valeurs et l'obtention d'une condition d'erreur. Une deuxième fonction IFERROR détecte l'erreur et renvoie un tiret ("-"). (Les données SQL doivent être actualisées via le ruban pour que les formules produisent un résultat correct.)

Créez une plage nommée dynamique SQLDB pour les données SQL dans la feuille Sheet1 à l'aide de la formule:

=OFFSET(Sheet1!$A$2,0,0,COUNTA(Sheet1!$A:$A)-1,COUNTA(Sheet1!$1:$1))

Créez une deuxième plage dynamique nommée EXCELRNG pour les données entrées manuellement dans la feuille Sheet2 à l'aide de la formule:

=OFFSET(Sheet2!$A$1,1,0,COUNTA(Sheet2!$A:$A)-1,COUNTA(Sheet2!$1:$1))

Ces deux plages nommées supposent que les noms de variables sont entrés dans la ligne 1 de chacune des deux feuilles.

Entrez les noms de variable de la ligne 1 de la feuille 3 (commençant par la cellule A1).

Entrez la formule suivante dans la cellule A2 de la feuille 3:

=IFERROR(INDEX(SQLDB,ROWS(A$2:A2),COLUMN(A2)),IFERROR(INDEX(EXCELRNG,ROWS(A$2:A2)-ROWS(SQLDB),COLUMN(A2)),"-"))

Copiez la formule dans les colonnes du nom de la variable, puis vers le bas des lignes jusqu'à ce que les résultats des formules soient tous constitués de tirets ("-").

La prochaine étape consiste à créer un tableau croisé dynamique dans une autre feuille à des fins d’analyse et d’organisation.

Là encore, la première étape consiste à créer une plage dynamique nommée, par exemple, RESULTRNG, en insérant la formule suivante dans la zone de saisie Gestionnaire de noms pour la plage nommée:

=OFFSET(Sheet3!$A$1,0,0,COUNTA(Sheet1!$A:$A)+COUNTA(Sheet2!$A:$A)-1,COUNTA(Sheet1!$1:$1))

Créez ensuite un tableau croisé dynamique dans une nouvelle feuille en définissant RESULTRNG comme le tableau à analyser. Cela filtrera tous les tirets de fin de la table de formule dans Sheet3.

Cela fonctionne car la formule RESULTRNG compte le nombre total de lignes de la feuille Sheet1 et de la feuille Sheet2 (à l'exclusion de l'en-tête de la feuille Sheet2) et du nombre total de colonnes de la feuille Sheet1, et définit son étendue en fonction de ces comptes, en excluant les tirets des lignes de fin ( ou colonnes) dans le tableau de formules Sheet3.

2
chuff

J'ai trouvé un moyen de le faire. Cette solution est un peu délicate et nécessite que les deux tables aient leurs propres feuilles séparées (sans rien d’autre sur elles), mais à part cela, elles font presque exactement ce que je veux. (Il semble également y avoir beaucoup de potentiel ici pour effectuer des opérations plus complexes telles que des jointures.)

Accédez à l'onglet de données du ruban, cliquez sur "À partir d'autres sources", puis sur "À partir de Microsoft Query". Cliquez ensuite sur Fichiers Excel, sélectionnez le fichier sur lequel vous travaillez et cliquez sur OK. Ensuite, appuyez sur Annuler et sur "Oui", une fois promu si vous souhaitez continuer à éditer dans Microsoft Query. À partir de là, vous pouvez cliquer sur le bouton SQL et écrire une requête SQL personnalisée sur n’importe quelle feuille de la feuille de calcul. Dans mon cas:

SELECT *
FROM `'Sheet1$'` `'Sheet1$'`
UNION ALL
SELECT *
FROM `'Sheet2$'` `'Sheet2$'`

Remarque: Pour moi, cette méthode cesse de fonctionner après la fermeture du fichier et sa réouverture. De toute façon, je le publie ici au cas où il s'agirait simplement d'un problème d'ordinateur ou que quelqu'un d'autre puisse le faire fonctionner.

5
Ajedi32

Voici une version de la solution "Pure Excel" de @ (}) de de chuff, spécialement conçue pour fonctionner avec des tableaux. (I.E. Les deux sources de données que vous souhaitez fusionner sont des tables.)

La principale différence entre cette méthode et celle qui a été postée dans sa réponse est qu'il n'est pas nécessaire de définir des plages nommées pour les deux ensembles de données que vous fusionnez, car il s'agit de tables et qu'elles possèdent déjà leur propre plage nommée. Allez-y, nommez votre première table Table1 et votre deuxième table Table2.

Créez maintenant une nouvelle table dans le coin supérieur gauche d'une nouvelle feuille et attribuez-lui les mêmes noms de colonne que les deux autres tables. Puis entrez la formule suivante dans la cellule A2 de la feuille que vous venez de créer:

=IFERROR(INDEX(Table1,ROWS(A$2:A2),COLUMN(A2)), IFERROR(INDEX(Table2,ROWS(A$2:A2)-ROWS(Table1),COLUMN(A2)), "-"))

Ensuite, copiez cette formule dans toutes les colonnes de la table, puis en bas des lignes jusqu'à ce que les résultats des formules soient tous en tirets ("-"). Remarque: le tri de cette nouvelle table n'a aucune incidence, car le contenu de chaque cellule est identique (elles contiennent toutes la même formule).

Si les colonnes du tableau fusionné affichent des 0 alors qu'elles devraient afficher une cellule vide, vous pouvez envelopper la formule dans cette colonne avec la fonction de substitution, comme ceci:

=SUBSTITUTE(<old expression here>, 0, "")

Si vous souhaitez créer un tableau croisé dynamique utilisant les données de ce nouveau tableau, vous devez créer une plage nommée. Commencez par nommer la table Table3. Maintenant, allez dans l'onglet des formules et cliquez sur "Définir un nom". Donnez un nom à la référence, entrez l'équation suivante pour sa valeur ("Fait référence à"):

=OFFSET(Table3[#All],0,0,ROWS(Table1)+ROWS(Table2)+1)

Vous pouvez ensuite utiliser cette référence nommée comme plage pour votre tableau croisé dynamique.

3
Ajedi32

Si vous êtes intéressé par une solution VBA, j'ai pu faire fonctionner ce qui suit:

  • Définissez une plage nommée dynamique pour les données que vous extrayez de SQL Server. Ouvrez le gestionnaire de noms, entrez un nouveau nom (par exemple, "SQLDB") et copiez la formule suivante dans la zone de saisie Fait référence à. J'ai supposé que vos données importées sont dans la feuille Sheet1:

    =OFFSET(Sheet1!$A$1,0,0,COUNTA(Sheet1!$A:$A),COUNTA(Sheet1!$1:$1))
    
  • Définissez une autre plage nommée pour la plage dans laquelle les données manuelles sont entrées. J'ai utilisé le nom EXCELRNG et supposé qu'il était dans la feuille Sheet2. La plage nommée commence à la ligne 2 pour exclure une ligne d'en-tête. La formule ici est identique à la première, à l'exception de la feuille:

    =OFFSET(Sheet2!$A$1,1,0,COUNTA(Sheet2!$A:$A)-1,COUNTA(Sheet2!$1:$1))
    
  • Voici le premier jeu de paramètres que j'ai utilisé pour la connexion à la table SQL. La boîte de dialogue est accessible en sélectionnant Connexions dans l'onglet Données du ruban. La désactivation de l'actualisation en arrière-plan garantit que la macro VBA s'interrompt jusqu'à ce que l'actualisation des données de la feuille Excel soit terminée. Il n'est peut-être pas nécessaire d'actualiser la connexion lorsque la feuille de travail s'ouvre, mais je voulais m'assurer que toute authentification serait effectuée avant l'exécution de la macro.

connection settings

  • Voici le deuxième ensemble de paramètres. Ceux-ci se trouvent dans la section Propriétés de l'onglet Données (alors qu'une cellule de la table SQL importée est sélectionnée). Bien que j'ai choisi l'option "Insérer des lignes entières pour les nouvelles données, supprimer les cellules inutilisées", je n'ai rencontré aucun problème avec l'option "Insérer des cellules ...".

connection properties

  • Enfin, c'est le code VBA. Pour l'insérer, choisissez Visual Basic sous l'onglet Développeur. Mettez en surbrillance le nom de la feuille de travail dans la liste de gauche. Il sera référencé par "Projet VBA (nom de la feuille). Ensuite, choisissez Insérer un module dans la barre de menus en haut de l'écran et collez le code dans le nouveau module. Notez que j'ai mis le tableau consolidé dans Sheet3. Comme écrit, la macro ne trie pas la nouvelle table, bien que cela ne soit pas difficile à ajouter.

    Sub StackTables()
    
       Dim Rng1 As Range, Rng2 As Range
    
       Set Rng1 = ThisWorkbook.Names("SQLDB").RefersToRange
       Set Rng2 = ThisWorkbook.Names("EXCELRNG").RefersToRange
    
       ' refresh the SQL table
       ThisWorkbook.Connections(1).Refresh
    
       ' clear the consolidated table range  
       Sheet3.Cells.ClearContents
    
       ' copy the SQL data into the consolidation range
       Rng1.Copy
       Sheet3.Range("A1").PasteSpecial xlPasteValues
    
       'copy the manually entered data into the consolidate range
       Rng2.Copy
       Sheet3.Range("A1").Offset(Rng1.Rows.Count, 0).PasteSpecial xlPasteValues
       Application.CutCopyMode = False
    
       Sheets("Sheet3").Activate
       ActiveSheet.Range("A1").Select
    
    End Sub
    
3
chuff

Si vous souhaitez simplement obtenir un résultat unique, il existe un site Web qui fusionnera deux tables pour vous: https://office-tools.online/table/merge/

Vous collez les tableaux dans la page Web et sélectionnez les paramètres appropriés. Voici une capture d'écran de l'exemple intégré qui indique comment l'utiliser:

enter image description here

0
Hvg Hng