使用openpyxl

时间:2018-02-07 07:07:08

标签: python openpyxl

我目前正在磨练我的python / excel技能,并遇到了openpyxl的问题

我正在尝试打开工作簿,替换现有表中的行,然后再次保存工作簿。

理想情况下,我还希望首先删除表格中的所有行(虽然保留了表格结构)

我的初始工作簿包含一个名为" inputData"的工作表。在这里,我有一个名为" Data"列A,B,C和2行数据。

我还有一个名为" input.csv"的csv文件。包含相同的列,但包含4行数据。

当我运行我的代码时,数据被写入工作表,但表结构未扩展为包含两行新数据。

有关如何使用openpyxl更改命名表结构的数据源的任何想法吗?

import csv
from openpyxl import load_workbook
from openpyxl.worksheet.table import Table, TableStyleInfo

wb = load_workbook(filename = 'workbook.xlsx')
ws = wb["inputData"]

with open('input.csv', newline='', encoding='utf-8-sig') as f:
    reader = csv.reader(f, delimiter=';')
    for i, row in enumerate(reader):
        if not i == 0:
            for j, cell in enumerate(row): 
                ws.cell(row=i+1, column=j+1).value = cell

wb.save('output.xlsx')

Link to files

3 个答案:

答案 0 :(得分:4)

我找到了问题的答案。

我可以从openpyxl访问该表,更改ref(范围),然后再将其保存。

这使我能够在同一个表格中输入更多数据,并让我的其他工作表上的公式考虑新数据。

这将是一个非常有用的功能,当我需要将大量数据推送到现有的Excel工作表而不会在将来破坏引用时。

import csv
from openpyxl import load_workbook
from openpyxl.worksheet.table import Table, TableStyleInfo
tableName = 'Data'

style = TableStyleInfo(name="TableStyleMedium9", showFirstColumn=False,
                       showLastColumn=False, showRowStripes=True, showColumnStripes=False)

def colnum_string(n):
    string = ""
    while n > 0:
        n, remainder = divmod(n - 1, 26)
        string = chr(65 + remainder) + string
    return string

wb = load_workbook(filename = 'workbook.xlsx')
ws = wb["inputData"]

with open('input.csv', newline='', encoding='utf-8-sig') as f:
    reader = csv.reader(f, delimiter=';')
    for i, row in enumerate(reader):
        for j, cell in enumerate(row): 
            if not i == 0:
                ws.cell(row=i+1, column=j+1).value = float(cell)
            else:
                ws.cell(row=i+1, column=j+1).value = cell

            maxRef = [i,j]

for i, table in enumerate(ws._tables):
    if table.name == tableName:
        tableRef = i

resTable = Table(displayName="Data", ref="A1:{}{}".format(colnum_string(maxRef[0]), maxRef[1]))
resTable.tableStyleInfo = style

ws._tables[tableRef] = resTable

wb.save('output.xlsx')

答案 1 :(得分:2)

首先,感谢您的关注。我尝试在现有的excel文件(模板的副本)中扩展现有的表。我只是无法将表扩展到我实际放置数据的范围(备注:某些表元素包含我需要保留的公式)

我要做的是,打开Excel文件,将数据复制并粘贴到正确的工作表和正确的单元格中。这按预期工作。不起作用的是扩展表的范围,该表最初仅覆盖第一行(标题除外)。

使用上述代码,我能够识别表格,并尝试复制样式:

for i, table in enumerate(ws._tables):
        if table.name == 'Template':
            tableRef = i
            mystyle = table.tableStyleInfo
resTable = Table(displayName="Template", ref="A7:{}{}".format(colnum_string(maxRef[1]), maxRef[0]))
resTable.tableStyleInfo = mystyle
ws._tables[tableRef] = resTable

由于它不起作用,我可能会忽略这里的内容。该表不扩展。任何帮助将不胜感激。

为了更好地理解问题,
表格标题为A7:BA7
第一行(空),一些带有公式和格式的元素:A8:BA8
复制数据后的最终数据范围(例如,计算正确):A8:BA255

答案 2 :(得分:2)

在openpyxl == 3.0.5时偶然发现了这个问题2020 希望也可以与处于相同情况的其他人分享我的解决方案。

目标:从data.csv中读取新数据并添加到现有的file.xlsx中,因此公式仍然有效。列名保持不变。

输入:

  1. XLSX模板文件在一张纸上具有公式,而在另一张纸上具有数据(file.xlsx)
  2. data.csv和新数据

输出:XLSX文件,其中包含公式中使用的新数据和更新的表范围

"""python imports"""
import openpyxl
import pandas

"""Load input workbook"""
wb = openpyxl.load_workbook(filename='file.xlsx')

"""Activate worksheet named 'data'."""
ws = wb['data']

"""Read in new data from data1.csv to pandas.dataframe"""
new_dataframe = pandas.read_csv("data1.csv")

"""Iterate over dataframe rows and write values to worksheet"""
for i, row in new_dataframe.iterrows():
    # ws.append leaves first line empty
    # to get data written from first row,  need to use writing to cell
    if i == 0:
        for c, value in enumerate(row, start=1):
            ws.cell(row=2, column=c).value = value
    else:
        current_row = [row.col1, row.col2, row.col3]
        ws.append(current_row)

"""Change table range"""
ws.tables['MyTable'].ref = "A1:E5"

"""Save workbook"""
wb.save(filename='file.xlsx')

回答Ethan问题:如何更改范围:

# Find right table
my_table = ws.tables['Template']
# Change range
my_table.ref = ref="A7:{}{}".format(column_string(maxRef[1], maxRef[0]))
# change style
my_table.tableStyleInfo = my_style
wb.save('WorkbookName')