Comment fusionner les données de deux fichiers Excel structurés différemment?

0

J'ai deux très gros fichiers Excel contenant des données financières. J'ai besoin de combiner les données d'un fichier avec les données de l'autre. Un code de catégorie est attribué à toutes les lignes du premier fichier. Certaines lignes du deuxième fichier peuvent avoir le même code.
J'ai besoin de combiner toutes les lignes du premier fichier avec toutes les lignes correspondantes avec le même code du deuxième fichier. Les fichiers ont un nombre différent de colonnes.

Comment devrais-je m'y attaquer?

JackStoneS
la source

Réponses:

1

Tout d'abord, ajoutez quelques colonnes au fichier qui en a besoin pour aligner les données, puis coupez et collez les données du fichier le plus petit au plus grand, puis triez-les selon votre code de catégorie.

Voici une façon de le faire dans VBA. Ce code ne sera copié que si la cellule contenant la valeur NACE est identique, mais vous pouvez le modifier selon vos besoins. Pour le moment, il copie simplement la ligne entière dans le premier classeur.

Private Sub CopyRows()

Dim FirstSheet As Range
Dim SecondSheet As Range
Dim s1col As Integer, s2col As Integer
Dim nextrow As Integer, secondendrow As Integer
Dim copyrow As Range, col As Range
Dim firstsheetrow As Range, secondsheetrow As Range
Dim NACE() As String, Limit As Integer, Index As Integer
Dim testrange As Range

Set FirstSheet = ActiveSheet.UsedRange
Set SecondSheet = Workbooks("Book2").Sheets("Sheet1").UsedRange

For Each col In FirstSheet.Columns
    If Not col.Cells(1).Find("NACE") Is Nothing Then
        s1col = col.Column
        Exit For
    End If
Next col

For Each col In SecondSheet.Columns
    If Not col.Cells(1).Find("NACE") Is Nothing Then
        s2col = col.Column
        Exit For
    End If
Next col


''//Fill NACE array with distinct entries from first sheet
nextrow = FirstSheet.Rows.Count + 1

ReDim Preserve NACE(1 To 1)
NACE(1) = FirstSheet.Rows(2).Cells(1, s1col).Value

For Each firstsheetrow In FirstSheet.Range("3:" & nextrow - 1).Rows
    Limit = UBound(NACE)
    If instrArray(NACE, firstsheetrow.Cells(1, s1col).Value) = 0 Then
        ReDim Preserve NACE(1 To Limit + 1)
        NACE(Limit + 1) = firstsheetrow.Cells(1, s1col).Value
    End If
Next firstsheetrow

''//Copy lines from second sheet that match a NACE value on the first sheet
secondendrow = SecondSheet.Rows.Count

For Each secondsheetrow In SecondSheet.Range("2:" & secondendrow).Rows
    Index = instrArray(NACE, secondsheetrow.Cells(1, s2col).Value)
    If Index > 0 Then
        secondsheetrow.Copy
        ActiveSheet.Rows(nextrow).PasteSpecial (xlPasteValues)
    End If
Next secondsheetrow

End Sub

Ce code doit aller dans un module pour supporter la routine principale:

Public Declare Sub CopyMemory Lib "kernel32" _
   Alias "RtlMoveMemory" _
  (pDest As Any, _
   pSrc As Any, _
   ByVal ByteLen As Long)

Public Function GetArrayDimensions(ByVal arrPtr As Long) As Integer

   Dim address As Long
  'get the address of the SafeArray structure in memory

   CopyMemory address, ByVal arrPtr, ByVal 4

  'if there is a dimension, then
  'address will point to the memory
  'address of the array, otherwise
  'the array isn't dimensioned
   If address <> 0 Then

     'fill the local variable with the first 2
     'bytes of the safearray structure. These
     'first 2 bytes contain an integer describing
     'the number of dimensions
      CopyMemory GetArrayDimensions, ByVal address, 2

   End If

End Function

Public Function VarPtrArray(arr As Variant) As Long

  'Function to get pointer to the array
   CopyMemory VarPtrArray, ByVal VarPtr(arr) + 8, ByVal 4

End Function

Function instrArray(strArray, strWanted, _
    Optional CaseCrit As Boolean = False, _
    Optional FirstOnly As Boolean = True, _
    Optional Location As String = "exact") As Long
     '
     '****************************************************************************************
     '       Title       instrArray
     '       Target Application:  any
     '       Function:   searches string array for some "wanted" text
     '       Limitations:
     '       Passed Values:
     '           strArray    [in, string array]  array to be searched
     '           strWanted   [in, string]  text for which strArray is searched
     '           CaseCrit    [in, Boolean, Optional]
     '               if true, case (upper/lower) of each character is critical and must match
     '               if false, case is not critical {default}
     '           FirstOnly   [in, Boolean, Optional]
     '               if true, proc exits after first instance is found {default}
     '               if false, proc search to end of array and last instance # is returned
     '           Location    [in, string, Optional] text matching constraint:
     '               = "any"     as long as strWanted is found anywhere in strArray(k),i.e.,
     '                               instr(strArray(k),strWanted) > 0, then instrArray = K
     '               = "left"    match is successful only if
     '                               Left(strArray(K),Len(strWanted) = StrWanted
     '               = "right"    match is successful only if
     '                               Right(strArray(K),Len(strWanted) = StrWanted
     '               = "exact"    match is successful only if
     '                               strArray(K) = StrWanted       {default}
     '
     '****************************************************************************************
     '
     '
    Dim I       As Long
    Dim Locn    As String
    Dim strA    As String
    Dim strB    As String

    instrArray = 0
    Locn = LCase(Location)
    Select Case FirstOnly
        Case True
            For I = LBound(strArray) To UBound(strArray)
                Select Case CaseCrit
                Case True
                    strA = strArray(I):     strB = strWanted
                Case False
                    strA = LCase(strArray(I)):  strB = LCase(strWanted)
                End Select
                If instrArray2(Locn, strA, strB) > 0 Then
                    instrArray = I
                    Exit Function
                End If
            Next I
        Case False
            For I = UBound(strArray) To LBound(strArray) Step -1
                Select Case CaseCrit
                Case True
                    strA = strArray(I):     strB = strWanted
                Case False
                    strA = LCase(strArray(I)):  strB = LCase(strWanted)
                End Select
                If instrArray2(Locn, strA, strB) > 0 Then
                    instrArray = I
                    Exit Function
                End If
            Next I
    End Select

End Function

Function instrArray2(Locn, strA, strB)
     '
     '****************************************************************************************
     '       Title       instrArray2
     '       Target Application:  any
     '       Function    called by instrArray to complete test of strB in strA
     '       Limitations:    NONE
     '       Passed Values:
     '           Locn    [input, string] text matching constraint (see instrArray)
     '           strA    [input, string] 1st character string
     '           strB    [input, string] 2nd character string
     '
     '****************************************************************************************
     '
     '

    Select Case Locn
    Case "any"
        instrArray2 = InStr(strA, strB)
    Case "left"
        If Left(strA, Len(strB)) = strB Then instrArray2 = 1
    Case "right"
        If Right(strA, Len(strB)) = strB Then instrArray2 = 1
    Case "exact"
        If strA = strB Then instrArray2 = 1
    Case Else
    End Select

End Function

Le code utilitaire a été trouvé ici et ici .

Lance Roberts
la source
Intelligent. Cela fonctionne, mais cela devient difficile si cela doit être fait beaucoup de fois. Je dois souvent faire la même chose, alors je cherche une méthode pour semi-automatiser cela. Avez-vous des idées pour cela?
JackStoneS
@JackStoneS, je pense que cela pourrait être fait facilement dans VBA, donnez-moi quelques détails sur la mise en page.
Lance Roberts
Merci pour votre réponse! Les deux fichiers contiennent des données financières. Le fichier plus petit contient une liste des offres publiques initiales, ainsi que certaines données des sociétés. Pour moi, la partie la plus importante du fichier est la cellule avec les codes NACE. Il s'agit d'un code pour un secteur particulier et plusieurs codes sont répertoriés par cellule. Je veux trouver toutes sortes de données de l'industrie pour toutes les entreprises avec le même code dans le deuxième fichier. Cela pourrait être: les ventes des années 2000-2010 ou les actifs de ces années. Je veux faire cela pour chaque entreprise dans le premier fichier. Cela clarifie-t-il la situation?
JackStoneS
@ Jack, Devez-vous extraire votre code de la cellule NACE ou pouvez-vous simplement comparer avec la cellule entière? Vous dites donc qu'à différents moments, vous souhaiterez obtenir différentes colonnes du deuxième fichier?
Lance Roberts
@ Lance, je dois extraire les codes, mais ce n'est pas la partie la plus difficile. Tous les codes (s'il y en a plus d'un) sont séparés par un '/' afin qu'une combinaison de FIND et LEFT (ou MID) puisse extraire le code approprié. En ce moment, je travaille avec un deuxième fichier de 28 colonnes, mais le montant exact peut différer. J'aurais besoin de toutes les colonnes non vides à chaque fois. Le fichier est un cliché d'une base de données à laquelle je n'ai pas accès. Je n'ai pas à extraire les codes du deuxième fichier.
JackStoneS
2

Ce type de tâche est l’objet de l’accès Microsoft et est appelé une "jointure à gauche". Mais vous pouvez toujours le faire dans Excel en utilisant vlookup ou en utilisant la fonction match et la fonction index. Personnellement je préfère match / index.

Supposons que Sheet1 A: F est le premier fichier et que vous placez le second fichier sur Sheet2 A1: Q500. Disons que vos codes sont dans la colonne A des deux. Puis sur la feuille 1 dans G2, tapez ceci:

=MATCH(A2,Sheet2!A$1:A$500,0)

Puis en type H2:

=INDEX(Sheet2!B$1:B$500,$G2)

Ensuite, faites-le glisser, et faites-les glisser vers le bas.

Jarvin
la source
C'est vraiment utile, merci, mais cela ne correspond qu'à une ligne. Pour chaque ligne de la première feuille, il peut y avoir plus d'une correspondance dans le deuxième fichier. Est-il possible de faire cela, avec cette méthode, ou devrais-je recourir à l'accès après tout?
JackStoneS
@JackStoneS: Pour faire une multi-correspondance, vous devrez faire quelque chose de plus similaire à la réponse de Lance ... après quoi il faut déplacer manuellement les lignes pour qu'elles correspondent ou utiliser une macro pour le faire. L'utilisation de l'accès est probablement votre meilleure solution.
Jarvin
+1 pour suggérer l'utilisation de l'accès. toute base de données à laquelle vous pouvez lier ces fichiers Excel vous donnerait l’avantage de nombreuses options d’interrogation
datatoo
Vous auriez pu faire un exemple plus simple - mais cela a fonctionné comme un charme pour moi :-)
Morten Repsdorph Husfeldt
0

En fonction de la taille des 2 fichiers, vous pouvez également essayer d’utiliser Query from Excel Files:

  • Définir le nom de la première table Excel (onglet Formules -> Définir le nom)
  • Définir le nom de la deuxième table Excel
  • Allez dans l'onglet Données, sélectionnez "À partir d'autres sources", et dans le menu déroulant, sélectionnez "À partir de Microsoft Query".
  • Sélectionnez votre fichier de classeur et confirmez que vous souhaitez fusionner les colonnes manuellement.
  • Dans la fenêtre suivante "Requête à partir de fichiers Excel", faites glisser la première colonne du premier tableau dans la première colonne du deuxième tableau - un lien sera créé entre ces colonnes
  • Allez dans le menu Fichier, cliquez sur "Renvoyer les données vers MS Office Excel", une boîte de dialogue d'importation de données apparaîtra.
  • Sélectionnez la feuille dans laquelle vous souhaitez importer les données correspondantes.
  • Cliquez sur OK -> vous devriez voir les données correspondantes avec les colonnes des deux tables

Si vous ne pouvez pas utiliser Excel ou une base de données locale, vous pouvez envisager de télécharger les fichiers sur un service en ligne tel que http://www.gridoc.com/join-tables et de fusionner les tableaux à l'aide de la fonction glisser-déposer (Avertissement: je suis l'auteur de l'outil).

J'espère que cela t'aides.

Endriju
la source