I\'m looking for the best approach for inserting a row into a spreadsheet using openpyxl.
Effectively, I have a spreadsheet (Excel 2007) which has a header row, foll
This worked for me:
openpyxl.worksheet.worksheet.Worksheet.insert_rows(wbs,idx=row,amount=2)
Insert 2 rows before row==idx
See: http://openpyxl.readthedocs.io/en/stable/api/openpyxl.worksheet.worksheet.html
Answering this with the code that I'm now using to achieve the desired result. Note that I am manually inserting the row at position 1, but that should be easy enough to adjust for specific needs. You could also easily tweak this to insert more than one row, and simply populate the rest of the data starting at the relevant position.
Also, note that due to downstream dependencies, we are manually specifying data from 'Sheet1', and the data is getting copied to a new sheet which is inserted at the beginning of the workbook, whilst renaming the original worksheet to 'Sheet1.5'.
EDIT: I've also added (later on) a change to the format_code to fix issues where the default copy operation here removes all formatting: new_cell.style.number_format.format_code = 'mm/dd/yyyy'
. I couldn't find any documentation that this was settable, it was more of a case of trial and error!
Lastly, don't forget this example is saving over the original. You can change the save path where applicable to avoid this.
import openpyxl
wb = openpyxl.load_workbook(file)
old_sheet = wb.get_sheet_by_name('Sheet1')
old_sheet.title = 'Sheet1.5'
max_row = old_sheet.get_highest_row()
max_col = old_sheet.get_highest_column()
wb.create_sheet(0, 'Sheet1')
new_sheet = wb.get_sheet_by_name('Sheet1')
# Do the header.
for col_num in range(0, max_col):
new_sheet.cell(row=0, column=col_num).value = old_sheet.cell(row=0, column=col_num).value
# The row to be inserted. We're manually populating each cell.
new_sheet.cell(row=1, column=0).value = 'DUMMY'
new_sheet.cell(row=1, column=1).value = 'DUMMY'
# Now do the rest of it. Note the row offset.
for row_num in range(1, max_row):
for col_num in range (0, max_col):
new_sheet.cell(row = (row_num + 1), column = col_num).value = old_sheet.cell(row = row_num, column = col_num).value
wb.save(file)
Adding an answer applicable to more recent releases, v2.5+, of openpyxl
:
There's now an insert_rows() and insert_cols()
.
insert_rows(idx, amount=1)
Insert row or rows before row==idx
As of openpyxl 1.5 you can now use .insert_rows(idx, row_qty)
from openpyxl import load_workbook
wb = load_workbook('excel_template.xlsx')
ws = wb.active
ws.insert_rows(14, 10)
It will not pick up the formatting of the idx row as it would if you did this manually in Excel. you will have apply the correct formatting i.e. cell color afterwards.
Edited Nick's solution, this version takes a starting row, the number of rows to insert, and a filename, and inserts the necessary number of blank rows.
#! python 3
import openpyxl, sys
my_start = int(sys.argv[1])
my_rows = int(sys.argv[2])
str_wb = str(sys.argv[3])
wb = openpyxl.load_workbook(str_wb)
old_sheet = wb.get_sheet_by_name('Sheet')
mcol = old_sheet.max_column
mrow = old_sheet.max_row
old_sheet.title = 'Sheet1.5'
wb.create_sheet(index=0, title='Sheet')
new_sheet = wb.get_sheet_by_name('Sheet')
for row_num in range(1, my_start):
for col_num in range(1, mcol + 1):
new_sheet.cell(row = row_num, column = col_num).value = old_sheet.cell(row = row_num, column = col_num).value
for row_num in range(my_start + my_rows, mrow + my_rows):
for col_num in range(1, mcol + 1):
new_sheet.cell(row = (row_num + my_rows), column = col_num).value = old_sheet.cell(row = row_num, column = col_num).value
wb.save(str_wb)