openpyxl chart error bar styles

不羁岁月 提交于 2019-12-01 11:32:26

问题


I've been assigned a "simple" task of collecting series of data columns to a results workbook. The results workbook contains necessary formulas and charts to analyze the results. The data is generated by an image analysis application I've written in python as series of excel workbooks.

Now the problem is that openpyxl drops any existing charts in excel workbooks. I've spent the day figuring out how to use openpyxl charts for which there is some documentation and chart errorbars for which there are no examples whatsoever. There is the source which has terse comments..

Using win32com extension would allow interacting with Excel directly but that obviously won't work except in windows and if Excel is installed. This may not be the case. Also trying to figure out how interact with Excel that way might take a while instead of doing it from a VBA macro.

..

For setting chart styles there is relatively nice method that works somewhat like this:

valuewidth=openpyxl.utils.units.points_to_pixels(2.25)
valuewidth=openpyxl.utils.units.pixels_to_EMU(valuewidth)
redcolor=openpyxl.drawing.colors.ColorChoice(prstClr="red")
bluecolor=openpyxl.drawing.colors.ColorChoice(prstClr="blue")

xvalues = openpyxl.chart.Reference(exceldata.sheetrep, min_col=exceldata.seriesx['column'], min_row=exceldata.seriesx['row'], max_row=exceldata.seriesx['row']+exceldata.seriesx['rows'])
values = openpyxl.chart.Reference(exceldata.sheetrep, min_col=exceldata.seriesy['column'], min_row=exceldata.seriesy['row'], max_row=exceldata.seriesy['row']+exceldata.seriesy['rows'])
series = openpyxl.chart.Series(values, xvalues, title_from_data=True)
series.graphicalProperties.line.width=valuewidth
series.graphicalProperties.line.solidFill=bluecolor
chart.series.append(series)

Now to work with error bars, they have to be defined and created like this:

errorwidth=openpyxl.utils.units.points_to_pixels(1)
errorwidth=openpyxl.utils.units.pixels_to_EMU(errorwidth)
errorlinetype=openpyxl.drawing.line.LineProperties(w=errorwidth, solidFill=redcolor)
errorline=openpyxl.chart.shapes.GraphicalProperties(ln=errorlinetype)
values = openpyxl.chart.Reference(exceldata.sheetrep, min_col=exceldata.lowerlim['column'], min_row=exceldata.lowerlim['row'])
xvalues = openpyxl.chart.Reference(exceldata.sheetrep, min_col=exceldata.lower['column'], min_row=exceldata.lower['row'])
chart.title="LL"
errorbar=openpyxl.chart.error_bar.ErrorBars(errBarType="minus",errValType="percentage",val=100.0, spPr=errorline)
errorbar.NumDataRef="LL"
series = openpyxl.chart.Series(values, xvalues, title=None, title_from_data=False)
series.errBars=errorbar
chart.series.append(series)

Now I'm wondering if there's a way to skip building that spPr object by first defining those LineProperties used to create GraphicalProperties object which is then fed to the ErrorBars method during instantiation.

That NumDataRef does not seem to do anything. It's not documented.

EDIT That call to NumDataRef is probably wrong in any case. plus and minus parameters expect NumDataSource of which NumDataRef is part of. Proper syntax would be likely again a two-step process of 1st creating the

foo = openpyxl.chart.data_source.NumRef(f="bar") 

and then follow up by

minus = openpyxl.chart.data_source.NumDataSource(numRef="foo")

I'm not sure what the numRef actually refers to, if it's a cell, series name or something else. If anyone can contribute what the "plus", "minus" and "val" parameters do, it'd be helpful.


回答1:


It seems NumVal, NumData and NumDataSource are needed to create ErrorBars from scratch:

# References for X and Y
xvalues = Reference(<worksheet>, min_col=<xcol>, min_row=<min>, max_row=<max>)
yvalues = Reference(<worksheet>, min_col=<ycol>, min_row=<min>, max_row=<max>) 
plus = [<list of error values for plus>]
minus = [<list of error values for minus>]

# Convert lists of error values to ErrorBars object
errorbars = list2errorbars(plus, minus, errDir='y')

# Create series data and set error bar
series = SeriesFactory(yvalues, xvalues, title="y direction error")
series.errBars = errorbars

def list2errorbars(plus, minus, errDir='y', errValType='cust'):
    "Returns ErrorBar from lists of error values"

    #Convert to list of NumVal
    numvals_plus = [NumVal(i, None, v=x) for i,x in enumerate(plus)]
    numvals_minus = [NumVal(i, None, v=x) for i,x in enumerate(minus)]

    # Convert to NumData
    nd_plus = NumData(pt=numvals_plus)
    nd_minus = NumData(pt=numvals_minus)

    # Convert to NumDataSource
    nds_plus = NumDataSource(numLit=nd_plus)
    nds_minus = NumDataSource(numLit=nd_minus)

    return ErrorBars(plus=nds_plus, minus=nds_minus, errDir=errDir, errValType=errValType)

Full example code: https://github.com/uskysd/openpyxl-errorbar

Since I couldn't find good documentation either, I figured out from source code. Let me know if there are any easier ways to do this.



来源:https://stackoverflow.com/questions/36018934/openpyxl-chart-error-bar-styles

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!