I\'m currently honing my python / excel skills, and have run into an issue with openpyxl
I am trying to open a workbook, replace rows in an existing table, and save
I figured out the answer to my question.
I am able to access the table from openpyxl, change the ref (range) and then save it back again.
This enables me to enter more data into the same table, and have my formulas on my other worksheet take the new data into account.
This will be a very helpful feature, when I need to push a lot of data into an existing excel sheet without breaking references in the future.
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')
Stumbled across this problem 2020 with openpyxl==3.0.5 Hope it is okay to share my solution as well for others who might be in the same situation.
Goal: to read in new data from data.csv and add to the existing file.xlsx, so the formulas still work. Column names stay the same.
Input:
Output: XLSX file with new data and updated table range used in formula
"""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')
Answer to Ethan problem: how to just change range:
# 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')
First of all, thank you for this thread. I try to extend an existing table within an existing excel file (copy of a template). I simply fail to extend the table to the range i actually put data in (Remark: Some table elements contain formulas which i need to preserve)
What i do is, open the excel file, copy and paste data to the correct worksheet and the correct cells. That works as intended. What does not work is extending the range of the table which initially covers only the first row (apart from the header).
Using above code, i am able to identify the table and i tried copying the style:
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
I might overlook something here since it does not work. The table does not extend. Any help is greatly appreciated.
For better understanding of the problem:
Table header is A7:BA7
First (empty) row, some element with formulas and formatting: A8:BA8
Final data range after copying data (as example, calculation is correct): A8:BA255