将文本文件中的不一致数据合并到单个excel电子表格中

时间:2019-02-03 02:36:41

标签: python excel openpyxl

我有大量的与数据的文本文件;每个文件都可以分别导入excel。但是,尽管文件之间的大多数列是相同的,但是在许多文件中,添加或缺少一列或两列,因此当我合并所有文本文件并将其放入excel时,许多数据列会发生移位。

我可以对所有可能的数据条目做一个“主列表”,但是我不确定如何告诉excel将某些类型的数据放在特定的列中。

举例来说,如果我有两个文件如下:

  • 名称年份食用颜色
  • Bob 2018蛋糕蓝
  • 查理2017无花果红

  • 姓氏名称账龄颜色尺寸
  • 百合詹姆斯17 2021绿色0

我该如何在excel中将它们合并:

  • 姓氏名称账龄食品颜色尺寸
  • NA NA鲍勃2018蛋糕蓝NA
  • NA NA查理图2017年红NA
  • 百合詹姆斯17 2021 NA绿色0

2 个答案:

答案 0 :(得分:1)

  

问题:将文本文件中的不一致数据合并到一个Excel电子表格中

此解决方案使用以下build-inmoudules

此解决方案的核心是使用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()
    
  • 环绕所有读取 all 行的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

答案 1 :(得分:0)

如果您很乐意直接在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。

让我知道是否有帮助。