How to group the x_axis dates in openpyxl - python

I want to group the x_axis (Date) so that if there is a cell with 01/01/2022 & another 01/01/2022 it will only show one bar with 01/01/2022, here it actualy print each row with a bar
How can i do that in openpyxl please
Thanks in advance
from openpyxl import Workbook
from openpyxl.chart import BarChart, Series, Reference
wb = Workbook(write_only=True)
ws = wb.create_sheet()
rows = [
('Date', 'Batch 1'),
(01/01/2022, 10),
(01/01/2022, 40),
(02/01/2022, 50),
(04/01/2022, 20)
]
for row in rows:
ws.append(row)
chart1 = BarChart()
chart1.type = "col"
chart1.style = 10
chart1.title = "Bar Chart"
chart1.y_axis.title = 'Test number'
chart1.x_axis.title = 'Sample length (mm)'
data = Reference(ws, min_col=2, min_row=1, max_row=5, max_col=2)
cats = Reference(ws, min_col=1, min_row=2, max_row=5)
chart1.add_data(data, titles_from_data=True)
chart1.set_categories(cats)
chart1.shape = 4
ws.add_chart(chart1, "A10")

So you want a stacked chart like this then?
from openpyxl import Workbook
from openpyxl.chart import BarChart, Reference
rows = [
('Date', 'Batch 1', 'Batch 2'),
('01/01/2022', 10, 40),
('02/01/2022', 50, ''),
('04/01/2022', 20, '')
]
wb = Workbook(write_only=True)
ws = wb.create_sheet()
for row in rows:
ws.append(row)
chart1 = BarChart()
chart1.type = "col"
chart1.style = 10
chart1.title = "Bar Chart"
chart1.grouping = "stacked" # Stacked column chart
chart1.overlap = 100 # Set overlap to 100% so top column sits squarely on the bottom column
chart1.y_axis.title = 'Test number'
chart1.x_axis.title = 'Sample length (mm)'
data = Reference(ws, min_col=2, min_row=1, max_row=4, max_col=3)
cats = Reference(ws, min_col=1, min_row=2, max_row=4)
chart1.add_data(data, titles_from_data=True)
chart1.set_categories(cats)
chart1.shape = 4
ws.add_chart(chart1, "A10")
wb.save('new_chart1.xlsx')

Related

Add new sheet with graph

newby question.
I would like to add a new sheet to an existing wb that I've created with xlwings.
It seems that when I try to add e write the 2nd sheet the 1st one going to be overwritten.
Here the code :
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns # library for visualization
sns.set() # this command sets the seaborn chart style as the default
import xlwings as xw
from datetime import datetime
df=pd.read_excel('aspire_1909.xls')
df2=df.drop([0,2])
new_header = df2.iloc[1]
df2 = df2[2:]
df2.columns = new_header
df2=df2.set_index('User')
wb = xw.Book()
sht = wb.sheets[0]
sht.name = "Aspire Manager Graph"
sht.range('R1').value = df3
started=len(df3.loc[df3['Manager Review'] == 'Started'])
complete = len(df3.loc[df3['Manager Review'] == 'Complete'])
complete_reopened = len(df3.loc[df3['Manager Review'] == 'Complete (Reopened)'])
not_started = len(df3.loc[df3['Manager Review'] == 'Not Started'])
past_due = len(df3.loc[df3['Manager Review'] == 'Past Due'])
def insert_heading(rng,text):
rng.value = text
rng.font.bold = True
rng.font.size = 24
rng.font.color = (0,0,139)
insert_heading(sht.range("A2"),f"ASPIRE YEAR END REVIEW - MANAGER STATUS del {datetime.today().strftime('%d-%m-%Y')}")
data = {'Not Started':not_started, 'Started':started, 'Completed':complete,'Reopened' : complete_reopened,'Past Due ' : past_due }
status = list(data.keys())
values = list(data.values())
x_labels = list(a + ' ' + str(b) for (a, b) in zip(status, values))
fig = plt.figure(figsize = (10, 5))
# creating the bar plot
fig, ax = plt.subplots(figsize=(15, 15))
bars = ax.bar(status, values, color =['red','blue','green','yellow','violet'],
width = 0.4)
ax.bar_label(bars, fmt="%d", fontsize=26, rotation=0, padding=3)
plt.bar(status, values, color =['red','blue','green','yellow','violet'],
width = 0.4)
plt.xticks(status, x_labels)
plt.xticks(rotation = 45, fontsize = 13)
plt.xlabel("Year End Review Completion Status")
plt.ylabel("No Users",rotation=45,fontsize = 13)
plt.title("Aspire Mgr Year End Review")
plt.show()
sht.pictures.add(fig,
name = "Aspire Mgr Status Graph",
update = True,
left =sht.range("A4").left,
top = sht.range("A4").top,
height= 500,
width= 700)
sht1 = wb.sheets[0]
wb.sheets.add('Aspire Employees Graph')
sht1.range('R1').value = df2
started=len(df2.loc[df2['Aspire year-end reflection (FY22)'] == 'Started'])
complete = len(df2.loc[df2['Aspire year-end reflection (FY22)'] == 'Complete'])
complete_reopened = len(df2.loc[df2['Aspire year-end reflection (FY22)'] == 'Complete (Reopened)'])
not_started = len(df2.loc[df2['Aspire year-end reflection (FY22)'] == 'Not Started'])
past_due = len(df2.loc[df2['Aspire year-end reflection (FY22)'] == 'Past Due'])
def insert_heading(rng,text):
rng.value = text
rng.font.bold = True
rng.font.size = 24
rng.font.color = (0,0,139)
insert_heading(sht1.range("A2"),f"ASPIRE YEAR END REVIEW EMPLOYEE STATUS del {datetime.today().strftime('%d-%m-%Y')}")
data = {'Not Started':not_started, 'Started':started, 'Completed':complete,'Reopened' : complete_reopened,'Past Due ' : past_due }
status = list(data.keys())
values = list(data.values())
x_labels = list(a + ' ' + str(b) for (a, b) in zip(status, values))
fig = plt.figure(figsize = (10, 5))
# creating the bar plot
fig, ax = plt.subplots(figsize=(15, 15))
bars = ax.bar(status, values, color =['red','blue','green','yellow','violet'],
width = 0.4)
ax.bar_label(bars, fmt="%d", fontsize=26, rotation=0, padding=3)
plt.bar(status, values, color =['red','blue','green','yellow','violet'],
width = 0.4)
plt.xticks(status, x_labels)
plt.xticks(rotation = 45, fontsize = 13)
plt.xlabel("Year End Review Completion Status")
plt.ylabel("Nb. Users",rotation=45,fontsize = 13)
plt.title("Aspire Employee Year End Review")
plt.show()
sht1.pictures.add(fig,
name = "Aspire Employee Status Graph",
update = True,
left =sht.range("A4").left,
top = sht.range("A4").top,
height= 500,
width= 700)
Could someone would be able to help me get what Is wrong ? ( I know ,almost everything :-) )
Thanks a lot in advance
In the second half of the code you have:
sht1 = wb.sheets[0]
wb.sheets.add('Aspire Employees Graph')
sht1.range('R1').value = df2
What wb.sheets[0] is returning is the very first sheet of the workbook. Towards the beginning you have the first section, which is:
sht = wb.sheets[0]
sht.name = "Aspire Manager Graph"
sht.range('R1').value = df3
As you use wb.sheets[0] both times, but haven't inserted a sheet at the beginning, you are just referring to the same sheet. The addition of the new sheet is correct, but you haven't set that as variable sht1.
Instead, for the second section, you could re-write to the following, combining the two lines into one so that the variable is the correct sheet:
sht1 = wb.sheets.add('Aspire Employees Graph')
sht1.range('R1').value = df2
Edit
To change the colour of the sheet tab:
sht1.api.Tab.ColorIndex = 3
The full list of colours can be found in the VBA ColorIndex documentation.
For more specific colours, see the answers to this question.

How to make labels visible inside the pie in openpyxl

I automate some task with openpyxl with xlsx file, i created a piechart but i want the piechart to show the labels and not only the value ( got exemple apple, cherry… will be in text inside the pie is there a way to do that with openpyxl ?
Thanks
from openpyxl import Workbook
from openpyxl.chart import (
PieChart,
ProjectedPieChart,
Reference
)
from openpyxl.chart.series import DataPoint
data = [
['Pie', 'Sold'],
['Apple', 50],
['Cherry', 30],
['Pumpkin', 10],
['Chocolate', 40],
]
wb = Workbook()
ws = wb.active
for row in data:
ws.append(row)
pie = PieChart()
labels = Reference(ws, min_col=1, min_row=2, max_row=5)
data = Reference(ws, min_col=2, min_row=1, max_row=5)
pie.add_data(data, titles_from_data=True)
pie.set_categories(labels)
pie.title = "Pies sold by category"
Do you want to do something like this where name and percent is marked on the segments?
from openpyxl import Workbook
from openpyxl.chart.label import DataLabelList
from openpyxl.chart import (
PieChart,
Reference
)
data = [
['Pie', 'Sold'],
['Apple', 50],
['Cherry', 30],
['Pumpkin', 10],
['Chocolate', 40],
]
wb = Workbook()
ws = wb.active
for row in data:
ws.append(row)
pie = PieChart()
labels = Reference(ws, min_col=1, min_row=2, max_row=5)
data = Reference(ws, min_col=2, min_row=1, max_row=5)
pie.add_data(data, titles_from_data=True)
pie.set_categories(labels)
pie.title = "Pies sold by category"
### Add Label into chart
pie.dataLabels = DataLabelList()
pie.dataLabels.showPercent = True
pie.dataLabels.showCatName = True
ws.add_chart(pie, "A10")
wb.save('test_chart.xlsx')
It should produce a chart like

Is it is possible to reference existing data to create a chart using openpyxl?

I have some data that is already in an xlsx sheet. Is it possible to build a chart using openpyxl with this data that already exists in these cells? The data gets updated monthly.
data
category 3/1/2021 3/8/2021
computer 2646 3000
network 117 200
other 316 20
total 3079 3220
Desired:
A chart month by month chart next to the data
Doing:
from datetime import date
from openpyxl import Workbook
from openpyxl.chart import (
LineChart,
Reference,
)
from openpyxl.chart.axis import DateAxis
wb = Workbook()
ws = wb.active
c2 = LineChart()
c2.title = "Date Axis"
c2.style = 12
c2.y_axis.title = "Size"
c2.y_axis.crossAx = 500
c2.x_axis = DateAxis(crossAx=100)
c2.x_axis.number_format = 'd-mmm'
c2.x_axis.majorTimeUnit = "days"
c2.x_axis.title = "Date"
c2.add_data(data, titles_from_data=True)
dates = Reference(ws, min_col=1, min_row=2, max_row=5)
c2.set_categories(dates)
ws.add_chart(c2, "E1")
Any suggestion is appreciated
#pull in your data
wb_obj = load_workbook(path)
sheet_obj = wb_obj.active
c1 = BarChart()
c1.title = "Test"
c1.y_axis.title = "Test1"
c1.x_axis.title = "Test2"
#reference your data
data = Reference(sheet_obj, min_col=2, min_row=2, max_col=3, max_row=5)
c1.add_data(data, titles_from_data=True)
#save the data
sheet_obj.add_chart(c1, "E1")
wb_obj.save("samples.xlsx")

How to add the Data into the existing Chart dynamically using openpyxl

I am trying add the Data into the existing Line Chart dynamically when new data comes in into the excel using openpyxl. Below is the sample code I tried But when else part is encountered there is no changes in the chart.
Thanks
from openpyxl import load_workbook
from openpyxl.chart import (LineChart, Reference)
wb = load_workbook("Hello.xlsx")
sheet = wb.active
exists = 0
chart = LineChart()
if exists == 1:
values = Reference(sheet, min_col=3, min_row=1, max_row=sheet.max_row)
categories = Reference(sheet, min_col=1, min_row=2, max_row=sheet.max_row,max_col=1)
chart.add_data(values, titles_from_data=True)
chart.set_categories(categories)
chart.title = "sample"
chart.x_axis.title = "date"
chart.y_axis.title = "followers"
sheet.add_chart(chart, "F2")
else:
values_update = Reference(sheet, min_col=3, min_row=1, max_row=sheet.max_row)
chart.add_data(values_update)
wb.save("Hello.xlsx")

Openpyxl not showing second graph

EDIT: Solved, solution in answer below.
I have a graph created with openpyxl that has two y axes sharing a DateAxis. Although the first selection of data is showing on the graph, the second isn't. There's also a strange gray line on the bottom of the graph that wasn't there before. I think it's just a small error I'm missing somewhere, but I can't see where. Especially considering I have my range of cells defined correctly. What could I be doing wrong?
import openpyxl
from openpyxl import Workbook, chart
from openpyxl.chart import LineChart, Reference, Series
from openpyxl.chart.axis import DateAxis
from datetime import date, datetime, timedelta, time
ws2 = wb['sheet2']
dates = chart.Reference(ws2, min_col=1, min_row=2, max_row=sheet.max_row)
vBat = chart.Reference(ws2, min_col=2, min_row=1, max_col=2, max_row=sheet.max_row)
qBat = chart.Reference(ws2, min_col=3, min_row=1, max_col=3)
c1 = chart.LineChart()
c1.title = "SLA Discharge - 5.5A: V_BAT"
c1.style = 12
c1.x_axis.majorTimeUnit = "days"
c1.x_axis = chart.axis.DateAxis()
c1.x_axis.title = "Time"
c1.x_axis.crosses = "min"
c1.x_axis.majorTickMark = "out"
c1.x_axis.number_format = 'd-HH-MM-SS'
c1.add_data(vBat, titles_from_data=True)
c1.set_categories(dates)
c1.y_axis.title = "Battery Voltage"
c1.y_axis.crossAx = 500
c1.y_axis.majorGridlines = None
c2 = chart.LineChart()
c2.x_axis.axId = 500 # same as c1
c2.add_data(qBat, titles_from_data=True, from_rows=True)
c2.set_categories(dates)
c2.y_axis.axId = 200
c2.y_axis.title = "Qbat Percentage"
c2.y_axis.crossAx = 500
c1.y_axis.crosses = "max"
c1 += c2
s1 = c1.series[0]
s1.graphicalProperties.line.solidFill = "BE4B48"
s1.graphicalProperties.line.width = 25000 # width in EMUs.
s1.smooth = True # Make the line smooth
s2 = c2.series[0]
s2.graphicalProperties.line.solidFill = "48BBBE"
s2.graphicalProperties.line.width = 25000 # width in EMUs.
s2.smooth = True # Make the line smooth
ws2.add_chart(c1, "D5")
Interestingly enough,
vBat = chart.Reference(ws2, min_col=2, min_row=1, max_col=2, max_row=sheet.max_row)
is fine. However, doing the same thing to qBat with:
qBat = chart.Reference(ws2, min_col=3, min_row=1, max_col=3, max_row=sheet.max_row)
"corrupts" the workbook and displays an error message upon opening and doesn't print any chart. Removing max_row=sheet.max_row from both lines produces an incorrect DateAxis where there are only two points and they're both the first two values in the time column.
first, in c2.add_data(qBat, titles_from_data=True, from_rows=True), remove from_rows=True.
Then, change qBat to:
qBat = chart.Reference(ws2, min_col=3, min_row=1, max_col=3, max_row=sheet.max_row)

Categories