I have been trying to copy a cell from one workbook to another with formatting only to fail. I have tried numerous suggestion but nothing works.
I have tried:
def copyCellStyle(new_cell,cell): new_cell.font = copy(cell.font) new_cell.border = copy(cell.border) new_cell.fill = copy(cell.fill) new_cell.number_format = copy(cell.number_format) new_cell.protection = copy(cell.protection) new_cell.alignment = copy(cell.alignment)
then use it like:
It runs without errors but the job is not done.
I get errors with the other methods in the styles class. When
new_cell._style = copy(old_cell._style)
this is used I get this error while I am saving the copied file.
Traceback (most recent call last): File "C:\Python Programs\test\test2.py", line 40, in <module> wb2.save("Test3.xlsx") File "C:\Anaconda3\lib\site-packages\openpyxl\workbook\workbook.py", line 392, in save save_workbook(self, filename) File "C:\Anaconda3\lib\site-packages\openpyxl\writer\excel.py", line 293, in save_workbook writer.save() File "C:\Anaconda3\lib\site-packages\openpyxl\writer\excel.py", line 275, in save self.write_data() File "C:\Anaconda3\lib\site-packages\openpyxl\writer\excel.py", line 84, in write_data stylesheet = write_stylesheet(self.workbook) File "C:\Anaconda3\lib\site-packages\openpyxl\styles\stylesheet.py", line 240, in write_stylesheet xf.alignment = wb._alignments[style.alignmentId] IndexError: list index out of range
Also when I check if cell has style like:
Traceback (most recent call last) File "C:\Python Programs\test\test2.py", line 37, in <module> if cell.has_style: AttributeError: module 'openpyxl.cell' has no attribute 'has_style'
I am using python 3.x.
Can anyone tell me a working proper method to achieve this.
Thanks in advance!
You need to understand what does
copy(cell._style) does to understand that exception. Behind the scenes each
openpyxl workbook has protected attributes for different styles. For example the attribute
_alignments will hold a
list with the alignments in the workbook, such as these:
_style is a list that only refers to the mentioned attributes by their index, as such:
So, lets take for example a workbook with no alignment styles applied. in that case the
_alignments list attribute of the workbook will have only 1 item which is the defualt (empty) alignment so:
len(new_workbook._alignments) == 1
copy(cell._style) to the new workbook it tries to get its new style by reffering to the protected attributes styles (alignments, borders, etc.). But, as the new workbook has no styles the reference
_alignment will raise an
IndexError as the new workbook list has only one item on that list, the default one (which is stored in
Your initial approach is the correct one. If you are copying to a new workbook you should iterate over the cells of the sheet copying the value and then the individual styles:
from openpyxl import load_workbook, Workbook from copy import copy original_wb = load_workbook('example.xlsx') original_sheet = original_wb['Sheet1'] new_wb = Workbook() new_ws = new_wb.active for row in original_sheet.rows: for cell in row: new_ws[cell.coordinate] = cell.value new_cell = new_ws[cell.coordinate] if cell.has_style: new_cell.font = copy(cell.font) new_cell.border = copy(cell.border) new_cell.fill = copy(cell.fill) new_cell.number_format = copy(cell.number_format) new_cell.protection = copy(cell.protection) new_cell.alignment = copy(cell.alignment) new_wb.save('new.xlsx')
_style method will not work when trying to copy to a new workbook and is not necessary within the same workbook as you can use