使用Python将文本文件添加到现有Excel工作簿
抱歉如果这个问题很基础,但假设我有一个名为 file.txt
的文件,它的格式是用制表符分隔的,内容如下:
Label-A [tab] Value-1
Label-B [tab] Value-2
Label-C [tab] Value-3
[...]
Label-i [tab] Value-n
我想用 xlrd 或者 openpyxl 把这些数据添加到名为 Worksheet
的 Excel 工作表中,这个工作表在文件 workbook.xlsx
里。我希望这些单元格里包含以下的值。我不想影响 workbook.xlsx
中其他部分的内容,只想更改这两列。
A1=Label-A
B1=Value-1
A2=Label-B
B2=Value-2
[etc.]
编辑:解决方案
import sys
import csv
import openpyxl
tab_file = sys.stdin.readlines()
reader = csv.reader(tab_file, delimiter='\t')
first_row = next(reader)
num_cols = len(first_row)
try:
workbook = sys.argv[1]
write_sheet = sys.argv[2]
except Exception:
raise sys.exit("ERROR")
try:
first_col = int(sys.argv[3])
except Exception:
first_col = 0
tab_reader = csv.reader(tab_file, delimiter='\t')
xls_book = openpyxl.load_workbook(filename=workbook)
sheet_names = xls_book.get_sheet_names()
xls_sheet = xls_book.get_sheet_by_name(write_sheet)
for row_index, row in enumerate(tab_reader):
number = 0
col_number = first_col
while number < num_cols:
cell_tmp = xls_sheet.cell(row = row_index, column = col_number)
cell_tmp.value = row[number]
number += 1
col_number += 1
xls_book.save(workbook)
3 个回答
你应该使用标准库中的CSV模块来读取文件。
在openpyxl中,你可以这样做:
from openpyxl import load_workbook
wb = load_workbook('workbook.xlsx')
ws = wb[sheetname]
for idx, line in enumerate(csvfile):
ws.cell(row=idx, column=0) = line[0]
ws.cell(row=idx, column=1) = line[1]
wb.save("changed.xlsx")
这活儿可以用VBA来做,不过如果让我用Python来做,我会这样写:
import Excel
xl = Excel.ExcelApp(False)
wb = xl.app.Workbooks("MyWorkBook.xlsx")
wb.Sheets("Ass'y").Cells(1, 1).Value2 = "something"
wb.Save()
还需要一个辅助的 Excel.py
类,像这样:
import win32com.client
class ExcelApp(object):
def __init__(self, createNewInstance, visible = False):
self._createNewInstance=createNewInstance
if createNewInstance:
self.app = win32com.client.Dispatch('Excel.Application')
if visible:
self.app.Visible = True
else:
self.app = win32com.client.GetActiveObject("Excel.Application")
def __exit__(self):
if self.app and self._createNewInstance:
self.app.Quit()
def __del__(self):
if self.app and self._createNewInstance:
self.app.Quit()
def quit(self):
if self.app:
self.app.Quit()
既然你说你习惯在 Bash 中工作,我猜你是在使用某种 Unix/Linux 系统,所以这里有一些适合 Linux 的内容。
在粘贴代码之前,我想先说几件事:
在 Unix(和 Python)中处理 Excel 文件并不是那么简单。例如,你不能同时打开一个 Excel 表格进行读取和写入(至少我知道的情况是这样,虽然我必须承认我从未使用过 openpyxl
模块)。Python 有两个我比较熟悉的模块,专门用来处理 Excel 表格:一个是用来读取 Excel 表格的(xlrd),另一个是用来写入的(xlwt)。如果你想修改一个已有的表格,就需要先读取这个表格,把它复制到一个可以写入的表格中,然后再进行编辑。你可以查看 这个问题,里面有更详细的解释。
读取用 任意 分隔符的文件要简单得多,这要归功于 csv 模块(它是为逗号分隔的文件准备的,但可以很容易地调整为其他分隔符)。可以去看看。
另外,我不太确定你给的例子中,制表符分隔的文件内容是否以某种方式表示 Excel 表格中的行索引,还是纯粹按位置排列。当你说在制表符分隔的文件中有 Value-2
时,我不确定这个 2
是不是表示 Excel 文件中的第二行,还是只是某个文本的例子。我假设是后者(这样更容易处理),所以在你的制表符分隔文件的第一行中出现的每一对 标签 值 都会成为 Excel 文件第一行的第一对。如果不是这种情况,请留言,我们再处理 ;-)
好的,假设以下场景:
你有一个制表符分隔的文件,内容如下:
stack37.txt:
Label-A Value-1
Label-B Value-2
Label-C Value-3
你想修改的 Excel 文件是 stack37.xls。它只有一个工作表(或者说,你想修改的工作表是文件中的第一个),最开始看起来是这样的(在 LibreOffice Calc 中):
现在,这是 Python 代码(我把它存储在一个叫 stack37.py 的文件中,并且它和制表符分隔的文件以及 Excel 文件在同一个目录下):
import csv
import xlwt
import xlrd
from xlutils import copy as xl_copy
with open('stack37.txt') as tab_file:
tab_reader = csv.reader(tab_file, delimiter='\t')
xls_readable_book = xlrd.open_workbook('stack37.xls')
xls_writeable_book = xl_copy.copy(xls_readable_book)
xls_writeable_sheet = xls_writeable_book.get_sheet(0)
for row_index, row in enumerate(tab_reader):
xls_writeable_sheet.write(row_index, 0, row[0])
xls_writeable_sheet.write(row_index, 1, row[1])
xls_writeable_book.save('stack37.xls')
运行这段代码后,stack37.xls 文件将变成这样:
我想说的是,我不太清楚你到底想用制表符分隔的文件中的值做什么,无论你在里面给项目起什么名字,它都会修改 Excel 表格的第一行,然后是第二行……(即使你的第一个 Value
叫 Value-2
,上面的代码也不会把这个值放在 Excel 表格的第二行,而是放在第一行)。它只是认为制表符分隔文件的第一行对应 Excel 表格的第一行。
让我用一个稍微修改过的例子来解释:
假设你原来的 Excel 文件看起来和我截图中的原始 Excel 文件一样(满是 | Hello-Ax | Bye-Bx |
),但你的制表符分隔文件现在看起来是这样的:
stack37.txt:
foo bar
baz baz2
运行 stack37.py 后,你的 Excel 将变成这样:
(看到了吗?制表符分隔文件的第一行对应 Excel 文件的第一行)
更新 1:
我自己在尝试 openpyxl
模块……理论上(根据文档)下面的代码应该可以工作(注意我把扩展名改成了 Excel 2007/2010 的 .xlsx
):
import csv
import openpyxl
with open('stack37.txt') as tab_file:
tab_reader = csv.reader(tab_file, delimiter='\t')
xls_book = openpyxl.load_workbook(filename='stack37.xlsx')
sheet_names = xls_book.get_sheet_names()
xls_sheet = xls_book.get_sheet_by_name(sheet_names[0])
for row_index, row in enumerate(tab_reader):
cell_tmp1 = xls_sheet.cell(row = row_index, column = 0)
cell_tmp1.value = row[0]
cell_tmp2 = xls_sheet.cell(row = row_index, column = 1)
cell_tmp2.value = row[1]
xls_book.save('stack37_new.xlsx')
但如果我这样做,我的 LibreOffice 就拒绝打开新生成的文件 stack37_new.xlsx
(可能是因为我的 LibreOffice 版本太旧?我在使用 Ubuntu 12.04,LibreOffice 版本是 3.5.7.2……谁知道,可能就是这个原因)