4.7 KiB
Executable File
4.7 KiB
Executable File
Chart Templates — Implementation Code
Load on demand when you need specific chart code. Do NOT load upfront.
Native Excel Charts (openpyxl.chart)
Bar Chart
from openpyxl.chart import BarChart, Reference
from templates.base import make_chart_title
chart = BarChart()
chart.type = "col"
chart.title = make_chart_title("Revenue by Product", 14)
chart.y_axis.title = make_chart_title("Revenue ($)", 10, bold=False, axis=True)
chart.x_axis.title = make_chart_title("Product", 10, bold=False)
data = Reference(ws, min_col=3, min_row=4, max_col=3, max_row=last_row)
cats = Reference(ws, min_col=2, min_row=5, max_row=last_row)
chart.add_data(data, titles_from_data=True)
chart.set_categories(cats)
chart.shape = 4
chart.width = 18
chart.height = 10
ws.add_chart(chart, "J4")
Line Chart
from openpyxl.chart import LineChart, Reference
from templates.base import make_chart_title
chart = LineChart()
chart.title = make_chart_title("Monthly Trend", 14)
chart.y_axis.title = make_chart_title("Amount", 10, bold=False, axis=True)
chart.style = 10
data = Reference(ws, min_col=3, max_col=5, min_row=4, max_row=last_row)
cats = Reference(ws, min_col=2, min_row=5, max_row=last_row)
chart.add_data(data, titles_from_data=True)
chart.set_categories(cats)
for series in chart.series:
series.smooth = True
ws.add_chart(chart, "J4")
Pie Chart
from openpyxl.chart import PieChart, Reference
from openpyxl.chart.label import DataLabelList
from templates.base import make_chart_title
chart = PieChart()
chart.title = make_chart_title("Market Share", 14)
data = Reference(ws, min_col=3, min_row=4, max_row=last_row)
cats = Reference(ws, min_col=2, min_row=5, max_row=last_row)
chart.add_data(data, titles_from_data=True)
chart.set_categories(cats)
chart.dataLabels = DataLabelList()
chart.dataLabels.dLblPos = 'bestFit'
chart.dataLabels.showLeaderLines = True
chart.dataLabels.showCatName = True
chart.dataLabels.showPercent = True
chart.dataLabels.showVal = False
ws.add_chart(chart, "J4")
Combo Chart (Bar + Line, dual axis)
from openpyxl.chart import BarChart, LineChart, Reference
from templates.base import make_chart_title
bar = BarChart()
bar.add_data(Reference(ws, min_col=2, max_col=2, min_row=1, max_row=10), titles_from_data=True)
bar.title = make_chart_title("Revenue vs Growth", 14)
bar.y_axis.title = make_chart_title("Revenue ($)", 10, bold=False, axis=True)
line = LineChart()
line.add_data(Reference(ws, min_col=3, max_col=3, min_row=1, max_row=10), titles_from_data=True)
line.y_axis.title = make_chart_title("Growth %", 10, bold=False, axis=True)
line.y_axis.axId = 200
bar += line
ws.add_chart(bar, "E2")
Matplotlib Charts (embedded as images)
Chinese Font Setup
import matplotlib
import matplotlib.pyplot as plt
import os
_font_path = os.path.join(os.path.dirname(__file__), '..', '..', '..', 'fonts', 'truetype', 'chinese', 'SimHei.ttf')
if not os.path.exists(_font_path):
# Fallback: try workspace fonts
_font_path = os.path.expanduser('/usr/share/fonts/truetype/chinese/SimHei.ttf')
if os.path.exists(_font_path):
matplotlib.font_manager.fontManager.addfont(_font_path)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
Standard Template
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(categories, values, color='#4A90D9')
ax.set_title('Chart Title', fontsize=14, fontweight='bold', pad=15)
ax.set_xlabel('X Label', fontsize=11)
ax.set_ylabel('Y Label', fontsize=11)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.tick_params(axis='x', rotation=45)
fig.tight_layout(pad=2.0)
plt.legend(loc='best', fontsize='small')
fig.savefig('chart.png', dpi=150, bbox_inches='tight', facecolor='white')
plt.close()
Embed in Excel (preserving aspect ratio)
from openpyxl.drawing.image import Image as XlImage
from PIL import Image as PILImage
pil_img = PILImage.open('chart.png')
orig_w, orig_h = pil_img.size
target_w = 600
scale = target_w / orig_w
xl_img = XlImage('chart.png')
xl_img.width = target_w
xl_img.height = int(orig_h * scale)
ws.add_image(xl_img, 'B20')
Smart Chart Recommend Function
def recommend_chart(df, x_col, y_cols):
if pd.api.types.is_datetime64_any_dtype(df[x_col]):
return "line"
n_categories = df[x_col].nunique()
n_series = len(y_cols)
if n_series == 1:
vals = df[y_cols[0]]
if vals.sum() > 95 and vals.sum() < 105:
return "pie" if n_categories <= 5 else "bar_horizontal"
if n_categories <= 6:
return "bar_grouped" if n_series > 1 else "bar"
elif n_categories <= 15:
return "bar_horizontal"
else:
return "bar_top10"