Chart with secondary y-axis and x-axis as dates

2024/10/6 6:03:48

I'm trying to create a chart in openpyxl with a secondary y-axis and an DateAxis for the x-values.

For this MWE, I've adapted the secondary axis example with the DateAxis example.

from datetime import datetime
from openpyxl import Workbook, chart# set to True to fail/create an invalid document
# set to False to generate a valid, but ugly/useless chart
DATES_ON_2ND = Truewb = Workbook()
ws = wb.activexvals = ['date', *[datetime(2018, 11, d, d+12) for d in range(1, 7)]]
avals = ['aliens', 6, 3, 4, 3, 6, 7]
hvals = ['humans', 10, 40, 50, 20, 10, 50]for row in zip(xvals, avals, hvals):ws.append(row)dates = chart.Reference(ws, min_row=2, max_row=7, min_col=1, max_col=1)
aliens = chart.Reference(ws, min_row=1, max_row=7, min_col=2, max_col=2)
humans = chart.Reference(ws, min_row=1, max_row=7, min_col=3, max_col=3)c1 = chart.LineChart()
c1.x_axis = chart.axis.DateAxis(crossAx=100)
c1.x_axis.title = "Date"
c1.x_axis.crosses = "min"
c1.x_axis.majorTickMark = "out"
c1.x_axis.number_format = "yyyy-mmm-dd"c1.add_data(aliens, titles_from_data=True)
c1.set_categories(dates)
c1.y_axis.title = 'Aliens'# Create a second chart
c2 = chart.LineChart()
if DATES_ON_2ND:c2.x_axis = chart.axis.DateAxis(crossAx=100)c2.x_axis.number_format = "yyyy-mmm-dd"c2.x_axis.crosses = "min"
c2.add_data(humans, titles_from_data=True)
c2.set_categories(dates)# c2.y_axis.axId = 200
c2.y_axis.title = "Humans"# Display y-axis of the second chart on the right
# by setting it to cross the x-axis at its maximum
c1.y_axis.crosses = "max"
c1 += c2ws.add_chart(c1, "E4")
wb.save("secondary.xlsx")

When I leave the secondary x axis as a categorical axis, a valid Excel document is created, even if the chart isn't what I want. But setting the secondary axis as a DateAxis the same way as the primary axis generates an invalid corrupted file that fails to show any chart.

Is there a trick to this that I'm missing?

Answer

So, as noted in my comments, there isn't really much benefit in DateAxes but if you use them then they have a default id of 500. This is important because it is the value that the y-axes need to cross. CrossAx for the category/date axis doesn't seen to matter. The following works for me:

from datetime import datetime
from openpyxl import Workbook, chartwb = Workbook()
ws = wb.activexvals = ['date', *[datetime(2018, 11, d, d+12) for d in range(1, 7)]]
avals = ['aliens', 6, 3, 4, 3, 6, 7]
hvals = ['humans', 10, 40, 50, 20, 10, 50]for row in zip(xvals, avals, hvals):ws.append(row)dates = chart.Reference(ws, min_row=2, max_row=7, min_col=1, max_col=1)
aliens = chart.Reference(ws, min_row=1, max_row=7, min_col=2, max_col=2)
humans = chart.Reference(ws, min_row=1, max_row=7, min_col=3, max_col=3)c1 = chart.LineChart()
c1.x_axis = chart.axis.DateAxis() # axId defaults to 500
c1.x_axis.title = "Date"
c1.x_axis.crosses = "min"
c1.x_axis.majorTickMark = "out"
c1.x_axis.number_format = "yyyy-mmm-dd"c1.add_data(aliens, titles_from_data=True)
c1.set_categories(dates)
c1.y_axis.title = 'Aliens'
c1.y_axis.crossAx = 500
c1.y_axis.majorGridlines = None# Create a second chart
c2 = chart.LineChart()
c2.x_axis.axId = 500 # same as c1c2.x_axis.crosses = "min"
c2.add_data(humans, titles_from_data=True)
c2.set_categories(dates)c2.y_axis.axId = 20
c2.y_axis.title = "Humans"
c2.y_axis.crossAx = 500# Display y-axis of the second chart on the right
# by setting it to cross the x-axis at its maximum
c1.y_axis.crosses = "max"
c1 += c2ws.add_chart(c1, "E4")
wb.save("secondary.xlsx")
https://en.xdnf.cn/q/118986.html

Related Q&A

Env var is defined on docker but returns None

I am working on a docker image I created using firesh/nginx-lua (The Linux distribution is Alpine): FROM firesh/nginx-luaCOPY ./nginx.conf /etc/nginx COPY ./handler.lua /etc/nginx/ COPY ./env_var_echo.…

No Browser is Open issue is coming when running the Robot framework script

I have created Test.py file which has some function in it and using those function names as Keywords in sample.robot file. Ex: - Test.pydef Launch_URL(url):driver.get(url)def article(publication): do…

How to run python file in Tkinter

Im a beginner in Python, hence the question. i would like to run a python file (smileA.py) in Tkinter. How would i start? I do not wish for it to run when clicking a button, but the file to run automa…

Discord.py Cogs “Command [ ] is not found”

I am recoding my discord.py bot using cogs as it wasnt very nice before. I tried this code: import discord import os import keep_alive from discord.ext import commands from discord.ext.commands import …

Binomial distribution CDF using scipy.stats.binom.cdf [duplicate]

This question already has answers here:Alternatives for returning multiple values from a Python function [closed](14 answers)Closed 2 years ago.I wrote below code to use binomial distribution CDF (by u…

How to get Cartesian product of two iterables when one of them is infinite

Lets say I have two iterables, one finite and one infinite:import itertoolsteams = [A, B, C] steps = itertools.count(0, 100)I was wondering if I can avoid the nested for loop and use one of the infinit…

Function to create nested dictionary from lists [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.This question was caused by a typo or a problem that can no longer be reproduced. While similar q…

Pygame not using specified font

So I am having a problem in pygame where I specify the font and size to use, but when my program is run, the font and size are the default.Here is where I define the textdef font(self):*****FATAL - THI…

port management in python/flask application

I am writing a REST API using the micro framework Flask with python programming language. In the debug mode the application detect any change in source code and restart itself using the same host and p…

using def with tkinter to make simple wikipedia app in python

I am beginner in python. I am trying to make a python wiki app that gives you a summary of anything that you search for. My code is below:import wikipediaquestion = input("Question: ")wikiped…