我有大量的与数据的文本文件;每个文件都可以分别导入excel。但是,尽管文件之间的大多数列是相同的,但是在许多文件中,添加或缺少一列或两列,因此当我合并所有文本文件并将其放入excel时,许多数据列会发生移位。
我可以对所有可能的数据条目做一个“主列表”,但是我不确定如何告诉excel将某些类型的数据放在特定的列中。
举例来说,如果我有两个文件如下:
和
我该如何在excel中将它们合并:
答案 0 :(得分:1)
问题:将文本文件中的不一致数据合并到一个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()
环绕所有读取 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
...我对您提供的数据进行了一些基本测试,它似乎可以正常工作。如果由于某种原因它无法对您正在使用的数据进行故障转移,而您无法对其进行计算,请告诉我,我将进行修复。
一些要点...
列的顺序取决于文件的顺序以及哪个列首先出现。当然,可以对此进行增强,但这就是现在。
它假定一个文件夹中的所有文件,所有文件都以.txt结尾
每个文件中的分隔符都假定为TAB。
让我知道是否有帮助。