使用Python将文本文件添加到现有Excel工作簿

0 投票
3 回答
8088 浏览
提问于 2025-04-18 03:02

抱歉如果这个问题很基础,但假设我有一个名为 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 个回答

0

你应该使用标准库中的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")
0

这活儿可以用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()
1

既然你说你习惯在 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 中):

enter image description here

现在,这是 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 文件将变成这样:

enter image description here

我想说的是,我不太清楚你到底想用制表符分隔的文件中的值做什么,无论你在里面给项目起什么名字,它都会修改 Excel 表格的第一行,然后是第二行……(即使你的第一个 ValueValue-2,上面的代码也不会把这个值放在 Excel 表格的第二行,而是放在第一行)。它只是认为制表符分隔文件的第一行对应 Excel 表格的第一行。

让我用一个稍微修改过的例子来解释:

假设你原来的 Excel 文件看起来和我截图中的原始 Excel 文件一样(满是 | Hello-Ax | Bye-Bx |),但你的制表符分隔文件现在看起来是这样的:

stack37.txt:

foo bar
baz baz2

运行 stack37.py 后,你的 Excel 将变成这样:

enter image description here

(看到了吗?制表符分隔文件的第一行对应 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……谁知道,可能就是这个原因)

撰写回答