Gráficos de la barra de errores del gráfico openpyxl

Me asignaron una tarea “simple” de recostackr series de columnas de datos en un libro de resultados. El libro de resultados contiene las fórmulas y gráficos necesarios para analizar los resultados. Los datos son generados por una aplicación de análisis de imagen que he escrito en Python como una serie de libros de Excel.

Ahora el problema es que openpyxl elimina los gráficos existentes en los libros de Excel. He pasado el día pensando en cómo usar los gráficos de openpyxl para los que hay alguna documentación y barras de error de gráficos para los que no hay ejemplos en absoluto. Ahí está la fuente que tiene comentarios concisos.

El uso de la extensión win32com permitiría interactuar directamente con Excel, pero eso obviamente no funcionará excepto en Windows y si Excel está instalado. Este puede no ser el caso. También tratar de averiguar cómo interactuar con Excel de esa manera podría tomar un tiempo en lugar de hacerlo desde una macro VBA.

..

Para establecer estilos de gráficos hay un método relativamente bueno que funciona de esta manera:

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) 

Ahora para trabajar con barras de error, deben definirse y crearse así:

 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) 

Ahora me pregunto si hay una manera de omitir la construcción de ese objeto spPr definiendo primero las LineProperties utilizadas para crear el objeto GraphicalProperties que luego se alimenta al método ErrorBars durante la instanciación.

Ese NumDataRef no parece hacer nada. No está documentado.

EDITAR Esa llamada a NumDataRef es probablemente incorrecta en cualquier caso. los parámetros de más y menos esperan que NumDataSource forme parte de NumDataRef. La syntax apropiada sería probablemente nuevamente un proceso de dos pasos para crear el

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

y luego seguir por

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

No estoy seguro de a qué se refiere el numRef, si se trata de una celda, el nombre de una serie o algo más. Si alguien puede contribuir con lo que hacen los parámetros “más”, “menos” y “val”, sería útil.

Parece que se NumVal , NumData y NumDataSource para crear ErrorBars desde cero:

 # References for X and Y xvalues = Reference(, min_col=, min_row=, max_row=) yvalues = Reference(, min_col=, min_row=, max_row=) plus = [] 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) 

Código de ejemplo completo: https://github.com/uskysd/openpyxl-errorbar

Como tampoco pude encontrar buena documentación, me di cuenta del código fuente. Déjame saber si hay maneras más fáciles de hacer esto.