Saltar al contenido

Curso sobre como trabajar con hojas de cálculo (Excel, Calc) usando openpyxl en Python (VI)

Índice:

Hasta ahora hemos pasado un poco por encima sobre cómo crear gráficos con openpyxl. Hemos visto como crear hojas de gráfico o chartsheets pero sin redundar mucho en ello. En este nuevo capítulo vamos a ver más en detalle el tema de los gráficos en openpyxl.

Empezamos importando lo que vayamos a necesitar. Veréis que hay unas cuantas cosas que no habíamos utilizado hasta ahora:

import random
from copy import deepcopy

import openpyxl
from openpyxl.chart import (
    LineChart, Reference, ScatterChart, Series, BarChart
)
from openpyxl.styles import colors

Creamos un libro que contendrá una hoja o pestaña y unos datos que usaremos a lo largo del capítulo:

def create_new_wb():
    wb = openpyxl.Workbook()
    ws = wb.active
    ws = wb.active
    header = [f"H{i + 1:02}" for i in range(10)]
    ws.append(header)
    for i in range(10):
        row = [random.random() for _ in range(10)]
        ws.append(row)
    return wb, ws
wb, ws = create_new_wb()

Lo guardamos y visualizamos para que veáis cómo queda:

wb.save("new.xlsx")
wb.close()
Nueva hoja de cálculos

Nuestro primer gráfico

Para empezar, vamos a hacer un gráfico de línea y luego iremos viendo más en detalle las diferentes partes. Lo hacemos y luego lo explicamos:

wb, ws = create_new_wb()

values = Reference(ws, min_col=1, max_col=2, min_row=1, max_row=11)

print(values)
print(type(values))

Lo anterior mostrará:

'Sheet'!$A$1:$B$11
<class 'openpyxl.chart.reference.Reference'>

Lo que acabamos de hacer es coger unos valores usando la clase Reference la cual nos permite seleccionar de qué hoja vamos a coger los valores y qué rango de celdas vamos a usar (las dos primeras columnas).

grafico = LineChart()

Creamos un gráfico de línea usando LineChart.

grafico.add_data(values, titles_from_data=True)

Añadimos los datos. Por defecto usará las columnas como series a no ser que le indiquemos lo contrario.

grafico.title = "Ejemplo"

Añadimos el título del gráfico. Este título puede que aparezca o no dependiendo del estilo que le demos al gráfico.

grafico.style = 10

Luego hablaremos más en detalle sobre esto…

grafico.x_axis.title = "Eje x"
grafico.y_axis.title = "Eje y"

Los títulos de los ejes.

serie = grafico.series[0]
serie.marker.symbol = None
serie.graphicalProperties.line.solidFill = colors.BLACK

Accedemos a la primera serie de datos del LineChart y le indicamos que queremos que use el color negro y que no use marcadores.

serie = grafico.series[1]
serie.marker.symbol = "circle"
serie.graphicalProperties.line.solidFill = colors.BLUE

Lo mismo para la segunda serie, pero en este caso queremos marcadores de tipo diamante y que la línea sea azul.

ws.add_chart(grafico, "K1")

Añadimos el gráfico a la hoja y guardamos y visualizamos para ver el resultado:

wb.save("new.xlsx")
wb.close()
Hoja con gráfico

El mismo gráfico solo se puede usar una vez en la misma hoja, por tanto, lo siguiente dará error:

ws.add_chart(grafico, "K15")
wb.save("new.xlsx")

Si queremos usar el mismo gráfico y modificar esa misma instancia deberemos crear copias. Vamos a crear copias y vamos a mostrar el mismo gráfico solo cambiando el estilo para ver los estilos que tenemos. Regeneramos de nuevo el libro y la hoja para evitar el error anterior:

wb, ws = create_new_wb()
for i in range(1, 30):
    g = deepcopy(grafico)
    g.style = i
    ws.add_chart(g, f"K{i * 15}")

Si lo guardamos y lo visualizamos veremos algo parecido a lo siguiente:

wb.save("new.xlsx")
wb.close()
Mismo gráfico con distintos estilos

Lo de los estilos lo hemos metido numerado y hacen referencia a estilos que vemos en el menú en Microsoft Excel:

Fuente de la imagen anterior.

Como lo anterior y la forma como lo estamos usando no es muy sencilla de ver vamos a ser más explícitos y modificar las partes del gráfico que consideremos sin necesidad de recurrir a estilos que pueden cambiar, no tienen porque verse de forma similar en diferentes programas de hojas de cálculo,…

Anatomía de un gráfico

Antes de nada vamos a reiniciar el libro y la hoja:

wb, ws = create_new_wb()

Vamos a añadir ahora un diagrama de dispersión, ScatterChart, usando dos columnas y sobre esto vamos a ir viendo diferentes cosas del gráfico:

g = ScatterChart()
xvalues = Reference(ws, min_col=1, max_col=1, min_row=2, max_row=11)
yvalues = Reference(ws, min_col=2, max_col=2, min_row=2, max_row=11)
serie = Series(yvalues, xvalues)
g.series.append(serie)

Como hemos visto antes, podemos darle nombre a los ejes:

g.x_axis.title = "Eje x"
g.y_axis.title = "Eje y"

Pero también podemos definir muchas otras cosas:

# Los números eran aleatorios entre 0 y 1
g.x_axis.scaling.min = 0
g.x_axis.scaling.max = 1
g.y_axis.scaling.min = 0
g.y_axis.scaling.max = 1

Definimos el rango del eje usando scaling.min y/o scaling.max.

Podemos elegir si queremos que los valores del eje vayan del mínimo al máximo, forma por defecto, pero también podríamos querer que los valores fueran al reves, con los valores máximos al principio y los mínimos al final:

g.x_axis.scaling.orientation = "maxMin"

print(g.legend)
g.legend = None

El print mostrará:

<openpyxl.chart.legend.Legend object>
Parameters:
legendPos='r', legendEntry=[], layout=None, overlay=None, spPr=None, txPr=None

Podemos eliminar la leyenda o colocarla en otro sitio del que viene por defecto ('r' por right). Podemos elegir entre 'r', ‘l‘, ‘t‘, ‘b‘, right, left, top, bottom, respectivamente, o algunas combinaciones entre ellas. Por ejemplo, podemos combinar cualquiera de izquierda y derecha con cualquiera de arriba y abajo: ‘lb‘, ‘lt‘, ‘rb‘, ‘rt‘ para colocarlas abajo a la izquierda, arriba a la izquierda, abajo a la derecha o arriba a la derecha, respectivamente.

La serie, como es un diagrama de dispersión, querremos que no aparezcan rayas y solo aparezcan puntos con el marcador que consideremos (en este caso voy a usar círculos rojos):

RED = colors.COLOR_INDEX[2]
serie.marker.symbol = "circle"
serie.marker.graphicalProperties.solidFill = RED
serie.graphicalProperties.line.noFill = True

El eje “y” quiero que aparezca en la parte derecha en lugar de en la parte izquierda:

g.y_axis.crossesAt = 1
g.y_axis.crosses = "max"

Añadimos el gráfico y guardamos el documento:

ws.add_chart(g, "K1")
wb.save("new.xlsx")
Hoja con gráfico

Combinar gráficos

Podemos combinar varios gráficos en uno, por ejemplo, un diagrama de barras y un gráfico de línea. Vamos a ver cómo hacer esto. Empezamos creando un libro y hoja nuevos:

wb, ws = create_new_wb()

Instanciamos LineChart y BarChart:

gl = LineChart()
gb = BarChart()

Añadimos los datos que vamos a usar:

values_line = Reference(ws, min_col=1, max_col=1, min_row=2, max_row=11)
values_bar = Reference(ws, min_col=2, max_col=2, min_row=2, max_row=11)
gl.add_data(values_line)
gb.add_data(values_bar)

Eliminamos las leyendas de ambos gráficos:

gl.legend = None
gb.legend = None

Al gráfico de barra le ponemos el eje “y” en la parte derecha del gráfico:

gb.y_axis.crosses = "max"

Damos nombres a los ejes:

gl.x_axis.title = "Eje a a compartir"
gl.y_axis.title = "Eje y línea"
gb.y_axis.title = "Eje y barra"

Fundimos ambos gráficos en uno:

gl += gb

Añadimos el gráfico a la hoja. Y guardamos el gráfico y lo visualizamos:

ws.add_chart(gl, "K1")
wb.save("new.xlsx")
Hoja con gráfico combinado

Tipos de gráficos

Se pueden usar muchos tipos de gráficos. Algunos de ellos ya los hemos visto mientras que otros solo los vamos a nombrar para saber lo que hacen y como usarlos. Me voy a saltar cualquier gráfico 3D porque nunca, repito, ¡¡NUNCA!!, deberéis usarlos ya que siempre hay alternativas mejores de visualizar datos sin recurrir a una supuesta tercera dimensión en una pantalla o papel:

  • LineChart: Para dibujar gráficos de línea. Hemos visto algún ejemplo más arriba.
  • ScatterChart: Para dibujar diagramas de dispersión. Hemos visto algún ejemplo más arriba.
  • BarChart: Para dibujar gráficos de columnas. Hemos visto algún ejemplo más arriba.
  • AreaChart: Son similares a los gráficos de línea pero el área por debajo de la línea se rellena hasta el eje horizontal.
  • BubbleChart: Son similares a los gráficos de dispersión pero nos permiten añadir una tercera dimensión que lo representamos mediante el tamaño del círculo. Una cuarta dimensión se podría representar con el color del círculo.
  • PieChart: Son gráficos de quesitos. Ideales para mostrar porcentajes.
  • DoughnutChart: Similares a los gráficos de quesitos.
  • RadarChart: Podríamos verlo como un gráfico de área pero en coordenadas polares.
  • StockChart: Útiles para mostrar gráficos agregados. Parecido a lo que puede hacer un un gráfico de caja o de bigotes.
  • SurfaceChart: Útiles para dibujar datos en un grid como contornos o isolíneas.

Más información sobre todo esto aquí.

Hojas de gráficos

Desde un principio vimos que podíamos crear hojas de gráficos (chartsheets) pero no hemos vuelto a hablar de ello hasta ahora. Ahora, que hemos visto los gráficos por encima, ha llegado el momento de hablar de las hojas de gráfico.

Básicamente, una hoja de gráfico es una hoja o pestaña dedicada únicamente a mostrar un gráfico.

Vamos a empezar creando un libro y hoja nuevos:

wb, ws = create_new_wb()

Creamos, además, una nueva hoja de gráfico:

cs = wb.create_chartsheet()

Creamos un nuevo gráfico:

g = BarChart()
values = Reference(ws, min_col=1, max_col=1, min_row=2, max_row=11)
g.add_data(values)
g.legend = None

Y, en el momento que tenemos el gráfico como queremos, lo añadimos a una hoja de gráfico en lugar de añadirlo a una posición (celda) en una hoja de trabajo. Lo podemos hacer de la siguiente forma:

cs.add_chart(g)

Si ahora guardamos y visualizamos no funcionará en LibreOffice Calc…:

wb.save("new.xlsx")

Resumiendo

Hemos visto de forma superficial como poder insertar gráficos en una hoja de cálculos o en una hoja dedicada (chartsheet). En general, se pueden hacer gráficos simples con excel pero para cosas avanzadas quizá siga siendo mejor recurrir a otras librerías y luego incrustar la imagen como pudimos ver en anteriores capítulos. Muchas de las cosas relacionadas con gráficos no me han estado funcionando en LibreOffice Calc por lo que parece que Microsoft Excel es superior en este sentido y algún código que escribáis con openpyxl no se verá como esperas en LibreOffice 🙁

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

− three = five

Pybonacci