Объединение противоречивых данных в текстовых файлах в одну таблицу Excel - PullRequest
0 голосов
/ 03 февраля 2019

У меня большое количество текстовых файлов с данными;каждый файл может быть импортирован в Excel отдельно.Однако, хотя большинство столбцов между файлами одинаковы, во многих файлах есть один или два добавленных / отсутствующих столбца, поэтому, когда я объединяю все текстовые файлы и помещаю их в Excel, многие столбцы данных сдвигаются.

Я могу составить «основной список» всех возможных записей данных, но я не совсем уверен, как сказать Excel, чтобы поместить определенные типы данных в определенные столбцы.

Например, если у меня есть два файла, которые выглядят следующим образом:

  • Название Год Цвет еды
  • Боб 2018 Голубой торт
  • Чарли 2017 ИнжирКрасный

и

  • Фамилия Имя Возраст Год Цвет Размер
  • Лили Джеймс 17 2021 зеленый 0

Как бы явот как можно объединить их в Excel:

  • Фамилия Имя Возраст Год Цвет еды Размер
  • на Боб на 2018 Торт Синий на
  • на Чарли на 2017 Инжир Красныйнет
  • Лили Джеймс 17 2021 нет зеленого 0

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

Вопрос : объединение несовместимых данных в текстовых файлах в одну таблицу Excel

В этом решении используются следующие build-in и moudules:

Суть этого решения заключается в нормализации имен столбцов с использованием объекта set() и
параметра .DictWriter(..., extrasaction='ignore') для обработки несовместимых столбцов.

Выходной формат: CSV, который можно прочитать из MS-Excel.


  • Указанные данные,разделенные blank

    text1 = """Name Year Food Color
    Bob 2018 Cake Blue
    Charlie 2017 Figs Red
    """
    text2 = """LastName Name Age Year Color Size
    Lily James 17 2021 green 0
    """
    
  • Открыть три файла и получить заголовки.
    Объединить все имена столбцов, удалить двойные имена, используя set().
    Создать объект DictReader для файлов in_*.

    Примечание : заменить io.StringIO(... на open(<Path to file>)

    with io.StringIO(text1) as in_text1, \
         io.StringIO(text2) as in_text2, \
         io.StringIO() as out_csv:
    
        columns = set()
        reader = []
        for n, fh in enumerate([in_text1, in_text2]):
            fieldnames = fh.readline().rstrip().split()
            [columns.add(name) for name in fieldnames]
            reader.append(csv.DictReader(fh, delimiter=' ', fieldnames=fieldnames))
    
  • Создать объект DictWriter, используя нормализованные имена столбцов.Параметр extrasaction='ignore' обрабатывает несогласованные столбцы.

    Примечание : порядок столбцов не гарантируется.Если вам нужен определенный порядок, сортируйте list(columns) в соответствии с вашими потребностями, прежде чем присваивать fieldnames=.

        writer = csv.DictWriter(out_csv, fieldnames=list(columns), , extrasaction='ignore')
        writer.writeheader()
    
  • Зацикливать все DictReader объекты на чтение все строк и записать его в целевой файл .csv.

        for dictReader in reader:
            for _dict in dictReader:
                writer.writerow(_dict)
    

Вывод :

print(out_csv.getvalue())

Color,LastName,Year,Food,Age,Name,Size
Blue,,2018,Cake,,Bob,
Red,,2017,Figs,,Charlie,
green,Lily,2021,,17,James,0

Проверено на Python: 3.4.2

0 голосов
/ 03 февраля 2019

Если вы были рады работать с текстовыми файлами непосредственно в Excel ... это сработает, но может потребовать некоторой доработки от вас.

Я понимаю, что это, вероятно, не то, что вы ищете, но это обеспечиваетдругой вариант.

Откройте редактор Visual Basic, добавьте новый модуль, скопируйте приведенный ниже код и вставьте ...

Public Sub ReadAndMergeTextFiles()
    Dim strSrcFolder As String, strFileName As String, strLine As String, strPath As String, bFirstLine As Boolean
    Dim arrHeaders() As String, lngHeaderIndex As Long, arrFields, i As Long, objDestSheet As Worksheet, bFound As Boolean
    Dim objLastHeader As Range, x As Long, lngLastColumn As Long, lngHeaderCol As Long, arrHeaderCols() As Long
    Dim lngWriteRow As Long

    lngLastColumn = 1
    lngWriteRow = 2

    Application.EnableEvents = False
    Application.ScreenUpdating = False

    ' Change the sheet name being assigned to your destination worksheet name.
    ' Alternatively, display a prompt that asks for the sheet or simply uses the active sheet.
    Set objDestSheet = Worksheets("Result")

    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "Select Source Folder"
        .Show

        If .SelectedItems.Count = 1 Then
            objDestSheet.Cells.Clear

            strSrcFolder = .SelectedItems(1)

            strFileName = Dir(strSrcFolder & "\*.txt")

            Do While Len(strFileName) > 0
                strPath = strSrcFolder & "\" & strFileName

                Open strPath For Input As #1

                bFirstLine = True

                Do Until EOF(1)
                    Line Input #1, strLine

                    arrFields = Split(strLine, vbTab, , vbTextCompare)

                    lngHeaderIndex = -1

                    For i = 0 To UBound(arrFields)
                        If bFirstLine Then
                            ' Loop through the header fields already written to the destination worksheet and find a match.
                            For x = 1 To objDestSheet.Columns.Count
                                bFound = False

                                If Trim(objDestSheet.Cells(1, x)) = "" Then Exit For

                                If UCase(objDestSheet.Cells(1, x)) = UCase(arrFields(i)) Then
                                    lngHeaderCol = x
                                    bFound = True
                                    Exit For
                                End If
                            Next

                            If Not bFound Then
                                objDestSheet.Cells(1, lngLastColumn) = arrFields(i)
                                lngHeaderCol = lngLastColumn
                                lngLastColumn = lngLastColumn + 1
                            End If

                            lngHeaderIndex = lngHeaderIndex + 1
                            ReDim Preserve arrHeaderCols(lngHeaderIndex)
                            arrHeaderCols(lngHeaderIndex) = lngHeaderCol
                        Else
                            ' Write out each value into the column found.
                            objDestSheet.Cells(lngWriteRow, arrHeaderCols(i)) = "'" & arrFields(i)
                        End If
                    Next

                    If Not bFirstLine Then
                        lngWriteRow = lngWriteRow + 1
                    End If

                    bFirstLine = False
                Loop

                Close #1

                strFileName = Dir
            Loop

            objDestSheet.Columns.AutoFit
        End If
    End With

    Application.ScreenUpdating = True
    Application.EnableEvents = True
End Sub

... Я провел базовое тестирование с даннымиВы обеспечили, и это, казалось, работалоЕсли по какой-то причине происходит сбой данных, которые вы используете, и вы не можете их обработать, дайте мне знать, и я внесу исправление.

Некоторые моменты ...

  1. Порядок столбцов зависит от порядка файлов и того, какие столбцы появляются первыми.Конечно, это может быть улучшено, но это то, чем оно является сейчас.

  2. Предполагается, что все файлы в одной папке и все файлы заканчиваются на .txt

  3. Предполагается, что разделителем в каждом файле является TAB.

Дайте мне знать, если это поможет.

...