Initial problem: columns are silently grouped, hiding one degroups them and the formatting is lost.
MRE: example.xlsx
Solution : degroup the columns, copy the formatting that got lost by degrouping the columns and now everything works as expected.
However, it doesn't really work as I would want it to (columns B, C, D had larger width and are highlighted in yellow). The width is fixable (cf. code) but not the background colour. I lose the background colour and I can't put it back since openpyxl cannot set a background colour for a whole column, only for already created cells.
I'm using:
Python 3.11.1, openpyxl == 3.1.2
On 14 Apr 2023, at 12:28, Romain Lhotte wrote:
It's probably worth noting that this is a continuation of an issue that isn't a bug:
Initial problem: columns are silently grouped, hiding one degroups them and
the formatting is lost.
MRE: example.xlsx
https://foss.heptapod.net/openpyxl/openpyxl/uploads/1cdea86950184b83e9fd39ab933743d9/example.xlsx
import openpyxl
wb = openpyxl.load_workbook('example.xlsx')
sheet = wb['Sheet1']
hide column 3
sheet.column_dimensions['C'].hidden = True
unhide column 3
sheet.column_dimensions['C'].hidden = False
wb.save("example2.xlsx")
Solution : degroup the columns, copy the formatting that got lost by
degrouping the columns and now everything works as expected.
This is all the information relating to the columns in the actual worksheet.
<:col min="2" max="4" width="20.6328125" style="1" customWidth="1" />
Openpyxl is a library for working with the file format. As such, it does not necessarily replicate functionality found in applications like Excel and which you're seeing here.
Look at the column dimension in openpyxl, this is best as dictionary.
dict(b)
{'width': '20.6328125',
'customWidth': '1',
'style': '1',
'min': '2',
'max': '4'}
However, it doesn't really work as I would want it to (columns B, C, D had
larger width and are highlighted in yellow). The width is fixable (cf.
code) but not the background colour. I lose the background colour and I
can't put it back since openpyxl cannot set a background colour for a whole
column, only for already created cells.
import openpyxl
As I suggested, you need to copy formatting to new entries in the column dimensions.
The easiest way to do this is probably something like this:
from copy import copy
from openpyxl import load_workbook
wb = load_workbook("Issues/bug1988.xlsx")
ws = wb.active
cd = ws.column_dimensions
b = cd['B']
for idx, key in zip(enumerate(["B", "C", "D"), start=2):
col = copy(b)
col.min = col.max = idx
cd[key] = col
I've spent a lot of time with the OOXML Working Group trying to make sense of the specification, which is frankly awful. And have suggested that the Openpyxl implementation be changed in the future to separate grouping (essentially for outline purposes) from formatting. This would mean you couldn't apply formatting to groups, and cannot group formats. I think this would make things a lot clearer and easier to work with.
Charlie
--
Charlie Clark
Managing Director
Clark Consulting & Research
German Office
Sengelsweg 34
Düsseldorf
D- 40489
Tel: +49-203-3925-0390
Mobile: +49-178-782-6226