Can’t set chart fill using RGBPercent
Hello,
I’m using openpyxl 3.0.9 with python 3.8. It looks like the existing handler for the RGB Color Model, Percentage Variant isn’t producing the expected results. Here’s a basic example to demonstrate the issue:
The code below is meant to generate a chart, then set the chart series fill color using the RGBPercent
object. The expected result is a chart with bars having 100% red fill. However, the actual result is a bar chart with blue (probably the default color?) filled bars.
from openpyxl import Workbook
from openpyxl.chart import BarChart, Reference
from openpyxl.drawing.colors import ColorChoice, RGBPercent
wb = Workbook()
ws = wb.active
for i in range(10):
ws.append([i])
values = Reference(ws, min_col=1, min_row=1, max_col=1, max_row=10)
chart = BarChart()
chart.add_data(values)
red = RGBPercent(r=100, g=0, b=0)
series = chart.series[0]
series.graphicalProperties.solidFill = ColorChoice(scrgbClr=red)
ws.add_chart(chart)
wb.save('test_charts.xlsx')
Here’s the chart:
And here’s the XML generated for the <scrgbClr>
child of the chart series <spPr>
tag:
<scrgbClr r="100" g="0" b="0" />
I think the issue is that the XML doesn’t conform to spec as described in ECMA-376 §20.1.2.3.30. The definition for the RGB Percent color model states that the red, green and blue components should be expressed as percentages (ie, ST_Percentage) from 0 to 100% with the trailing percent sign. (More specifically, §22.9.2.9 indicates that this type’s contents should match regex pattern -?[0-9]+(\.[0-9]+)?%
).
So the generated XML should probably be something like this (adding the namespace too):
<a:scrgbClr r="100%" g="0%" b="0%" />
Oddly, the examples in other sections of the spec don’t conform to the definition in §20.1.2.3.30 and leave off the trailing percent sign (e.g §20.1.4.2.11, among others). My guess is that the spec was revised, but the examples in other parts of the document were never updated.
Is it okay to change the data type of the RGBPercent
constructor’s parameters? If so, I can submit a pull request that fixes this issue by changing r
, g
and b
from MinMax
to MatchPattern
types. This would require the consumer to pass strings with a trailing percent to the constructor, thus matching the spec:
RGBPercent(r="100%", g="0%", b="0%")