尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

python-pptx与YAML:建筑节能课件自动化生成与图表嵌入

python-pptx与YAML:建筑节能课件自动化生成与图表嵌入 简介面向建筑环境与设备工程、土木工程及暖通空调相关专业师生的一份教学演示课件围绕建筑节能新技术应用与专业建设情况展开可用于课堂讲授、专业导论学习与课程汇报参考。包内仅含1个pptx文件压缩包体积约2.28MB文件为可直接编辑的演示文稿共31页按专业现状、师资力量、实验条件、培养方案、就业状况与热点问题等模块组织可据此快速梳理广州大学该专业的学科沿革、重点实验室配置、实验设备清单与课程体系。内容中还收录了建筑能耗调查、民用建筑节能技术措施、室内环境质量分析等论文选题方向以及挑战杯、大学生创新研究项目等课外科技活动信息便于读者了解建筑节能领域的研究切入点与实践路径。目前已有79人浏览学习适合需要制作专业介绍或节能技术综述课件的高校师生参考借鉴。1. 建筑节能新技术应用课件一个 pptx 文件的工程视角拿到「建筑节能新技术应用广州大学PPT课件.pptx」这样的文件多数人的动作是双击打开、翻页看内容。做课程平台、企业知识库或者资料归档的工程师关心的顺序往往相反这份 pptx 能不能被程序读出来标题和正文分别挂在哪个占位符上里面的能耗参数表是不是还停留在三年前的版本。一份六十页的节能课件通常有三十来张图、上百个文本框数据一更新就得通宵手工改改完还容易漏页、错位。建筑节能新技术的知识点本身是稳定的——被动式设计、围护结构、暖通空调、可再生能源、智慧运维这几条主线几年内不会大改变的是参数口径和案例数据。把这层「会变的东西」从版式里剥出来做成「内容源文件 渲染脚本」的流水线是这类课件可持续维护的前提。下面讲的都是可复现的工程动作用 python-pptx 摸清模板结构、用 YAML 承载节能技术要点、用 matplotlib 出能耗对比图、再用几条命令做批量校验和转档。适合两类人需要批量生成或解析课件的后端、数据工程师以及自己做节能课程材料、又愿意写一点 Python 的建筑技术岗。2. 建筑节能新技术应用课件的内容骨架与 python-pptx 环境2.1 先把五类建筑节能新技术拆成可渲染的结构课件难维护的根因不在排版在于内容没有结构。如果每页都是「标题 一大段话 一张截图」脚本只能全量覆盖如果每页都能拆成「技术主线、典型措施、量化指标、图表数据」四个槽位那渲染就是填空题。建筑节能领域天然适合这种拆法因为它的每个技术点最后都要落到一个能被测量的数上。技术主线课件里的典型措施可量化指标建议图型被动式设计建筑朝向、体形系数、外遮阳体形系数、各向窗墙比朝向—负荷曲线围护结构外墙外保温、Low-E 中空玻璃、反射屋面传热系数 K、太阳得热系数 SHGCK 值对比柱状图暖通空调与冷源变频冷水机组、温湿度独立控制、排风热回收COP、EER、系统能效比逐时冷负荷曲线可再生能源屋面光伏、太阳能热水、地源热泵年发电量、替代率月度发电量堆叠图智慧运维分项计量、能耗监测平台、数字孪生单位面积能耗 kWh/(m²·a)分项能耗占比图广州属于夏热冬暖地区这套骨架在参数上要跟气候区绑定同样是外墙传热系数夏热冬暖的外墙限值和严寒地区差出一大截课件里如果直接抄北方的案例数据学生在课程设计时按这个值去算冷负荷结论会偏。常见做法是在 YAML 里加一个climate_zone字段渲染时按气候区挑参数表而不是把数字写死在正文里。2.2 python-pptx 与绘图依赖的最小安装固定的环境比「我这台机器能跑」重要得多因为课件一般是几个人协作维护的。# 用独立虚拟环境避免和系统里的 Office 相关库冲突 python -m venv .venv source .venv/bin/activate # Windows 下换成 .venv\Scripts\activate # python-pptx 负责读写 pptxmatplotlib 出图PyYAML 读内容源 pip install python-pptx1.0.2 matplotlib3.9.2 PyYAML6.0.2 Pillow10.4.0 # 冻结版本交给同事复现 pip freeze requirements.txt几个依赖各管一段python-pptx底层依赖lxml负责操作 OOXMLPillow在插入图片时被调用来判断像素尺寸缺了它add_picture会直接抛错。版本上没必要追最新课件脚本用的是相当稳定的 API锁死一个大版本反而省事。如果团队里有人用 WPS 打开成品建议把输出格式固定成.pptx而不是.ppt老二进制格式的兼容层坑太多。2.3 用脚本探查模板的版式与占位符索引直接add_slide之前必须知道目标模板有哪些版式、每个版式里的占位符 idx 是多少。这一步花十分钟能省掉后面两小时的「文字跑到了标题框里」。from pptx import Presentation from pptx.util import Emu prs Presentation(template.pptx) # 1) 列出所有版式及其占位符idx 是后续填内容的唯一钥匙 for i, layout in enumerate(prs.slide_layouts): print(f[layout {i}] {layout.name}) for ph in layout.placeholders: print(f idx{ph.placeholder_format.idx} ftype{ph.placeholder_format.type} fname{ph.name}) # 2) 看看已有页面里形状的绝对位置和尺寸作为排版基线 for s_idx, slide in enumerate(prs.slides): print(f--- slide {s_idx} ---) for shape in slide.shapes: print(shape.shape_type, shape.name, Emu(shape.left).inches, Emu(shape.top).inches, Emu(shape.width).inches, Emu(shape.height).inches)输出里的idx是占位符的稳定编号type说明它是标题、正文还是图片位位置和尺寸统一换算成英寸看比 EMU 直观得多。判断推演逻辑就一句话排版基线来自模板里已经调好的页面脚本只负责往同样的坐标里塞新内容不要自己在代码里硬编码leftInches(0.8)这类数字否则换个模板整篇都要重调。两个高频坑一是母版继承某些版式的占位符是从上一级继承来的layout.placeholders里能看见但add_slide之后slide.placeholders[idx]取不到这时要回母版去补二是「空白」版式没有任何占位符想用它就得自己add_textbox标题层级语义会丢后续做无障碍导出或文本抽取时标题会识别不出来。2.4 内容块到版式的映射表摸清结构后把映射关系写成配置渲染脚本只认这张表内容块使用版式占位符 idx补充说明封面版式 00 标题 / 1 副标题副标题放课程名、学期章节过渡页版式 10 标题不填内容框留白正文单栏版式 10 标题 / 1 正文正文框宽度别超过版心参数表页空白版式无表格由脚本插入要点回顾页版式 10 标题 / 1 正文只放三条以内的短句映射表一旦固定后面加技术点只是往 YAML 里加条目不再动渲染代码这才是这套流水线真正的收益点。3. 用 YAML 内容源批量渲染建筑节能课件页3.1 一页一节的 YAML 内容源怎么写内容源的目标是「非程序员也能改」。建筑专业的老师改一段文字不需要懂 Python所以选 YAML 而不是直接写 Python 数据结构。# content.yml —— 每一条对应课件的一页 meta: course: 建筑节能新技术应用 climate_zone: 夏热冬暖 term: 2025 秋 sections: - id: envelope-01 title: 围护结构外墙与屋面 layout: content bullets: - 外墙外保温系统的构造层次与热桥处理 - 屋面反射涂料的太阳反射比要求 - 传热系数 K 与热惰性指标 D 的取值来源 table: k_values # 引用下面 tables 里的键 chart: envelope_k # 引用图表配置 notes: 提醒学生对照本地气候区限值不要直接抄北方案例。 tables: k_values: caption: 典型围护结构传热系数参考 columns: [构造做法, 传热系数 K W/(m²·K), 备注] rows: - [200mm 加气混凝土砌块, 0.85, 需附加保温层] - [外保温 200mm 砌块, 0.45, 常见做法] - [Low-E 中空玻璃外窗, 2.20, 遮阳系数另计]id用来做增量更新时比对layout决定走哪条渲染分支table和chart用键引用而不是内联好处是同一张参数表可以被多页复用改一处全篇同步。notes写进演讲者备注不占页面空间也方便后续做讲师手册导出。3.2 渲染引擎按版式填充标题、正文与备注核心就是一个循环加几个分支代码量不大但每一行的意图要清楚。import yaml from pptx import Presentation from pptx.util import Pt from pptx.oxml.ns import qn def set_font(run, name微软雅黑, size18, boldFalse): 同时设置西文字体与中文字体否则中文会回退成宋体 run.font.name name run.font.size Pt(size) run.font.bold bold rPr run._r.get_or_add_rPr() ea rPr.makeelement(qn(a:ea), {typeface: name}) rPr.append(ea) def render(content_path, template_path, out_path): cfg yaml.safe_load(open(content_path, encodingutf-8)) prs Presentation(template_path) body_layout prs.slide_layouts[1] # 正文版式 blank_layout prs.slide_layouts[6] # 空白版式 for sec in cfg[sections]: layout blank_layout if sec.get(table) else body_layout slide prs.slides.add_slide(layout) slide.shapes.title.text sec[title] for p in slide.shapes.title.text_frame.paragraphs: for r in p.runs: set_font(r, size28, boldTrue) if sec.get(bullets): body slide.placeholders[1].text_frame body.clear() for i, item in enumerate(sec[bullets]): para body.paragraphs[0] if i 0 else body.add_paragraph() para.text item para.level 0 for r in para.runs: set_font(r, size18) slide.notes_slide.notes_text_frame.text sec.get(notes, ) prs.save(out_path) print(fsaved: {out_path}, slides{len(prs.slides.__iter__.__self__._sldIdLst)})逻辑上分四步读内容源、按是否有表格选版式、往占位符里灌文本、把备注单独写进 notes。set_font里那段qn(a:ea)是整个脚本最容易被忽略的地方——python-pptx 的font.name只设置西文字体中文会走主题里的东亚字体在部分机器上渲染结果是宋体和同学交上来的作业风格完全不一致。参数说明size28给标题18给正文这是 16:9 版面上比较安全的组合正文超过 20 号每页就放不下三条要点para.level 0强制一级项目符号避免继承模板里的多级缩进body.clear()清掉占位符自带的提示文字不清会出现「单击此处添加文本」混在正文里。一个常见的误用是每页add_slide之后重新设置整个版式的字体。版式对象是全篇共享的改了会污染其他页正确定位到run级别只改这一页这几个 run。3.3 插入节能参数表列宽、字号与行高参数表是节能课件里信息密度最高的部分默认样式几乎一定要调。from pptx.util import Inches, Pt, Cm def add_table(slide, spec, leftInches(0.8), topInches(1.8), widthInches(11.5), heightInches(4.2)): rows, cols len(spec[rows]) 1, len(spec[columns]) frame slide.shapes.add_table(rows, cols, left, top, width, height) table frame.table # 列宽按内容长度粗分避免数值列过宽、文字列被挤断 table.columns[0].width Cm(7.0) for c in range(1, cols): table.columns[c].width Cm((width.cm - 7.0) / max(cols - 1, 1)) for c, name in enumerate(spec[columns]): cell table.cell(0, c) cell.text str(name) cell.vertical_anchor 3 # 3 居中 for p in cell.text_frame.paragraphs: for r in p.runs: set_font(r, size14, boldTrue) for r_idx, row in enumerate(spec[rows], start1): table.rows[r_idx].height Cm(0.9) for c_idx, val in enumerate(row): cell table.cell(r_idx, c_idx) cell.text str(val) cell.margin_left Cm(0.15) cell.margin_right Cm(0.15) for p in cell.text_frame.paragraphs: for r in p.runs: set_font(r, size12) return table关键参数就三个table.columns[i].width决定列宽数值列给 3 厘米左右足够放0.45这种值文字列给 7 厘米以上table.rows[i].height是最小行高内容多了 PowerPoint 会自动撑高所以设 0.9 厘米是留余量而不是卡死cell.margin_left/right各 0.15 厘米能防止数字贴边。表格整体高度给 4.2 英寸是为了留出标题和页脚超了会把表压出页面下沿而 pptx 不会报错只是打印或转档时被裁掉。4. 能耗数据出图并嵌入 pptx指标口径与尺寸对齐4.1 指标单位口径决定图型选择图表选错的代价比排版错更大学生会照着图理解概念。指标标准单位推荐图型容易踩的坑传热系数 KW/(m²·K)分组柱状图把设计值与限值画在同一根柱上逐时冷负荷kW折线图时间轴跨零点不连续年发电量kWh月度堆叠柱状图单位混用 kWh 与 MWh单位面积能耗kWh/(m²·a)横向条形图面积口径未说明是否含地下车库分项能耗占比%饼图或环形图项数超过 6 项颜色分不清同一页里不要出现两种量纲的柱子。把「设计值 vs 标准限值」放在同一张图里是对的但要用两种描边样式区分而不是两根同色柱子。4.2 matplotlib 中文字体与 DPI 设置生成的图要能直接贴进课件字号和图幅都得按最终显示尺寸倒推。import matplotlib matplotlib.use(Agg) # 无显示环境服务器上也能跑 import matplotlib.pyplot as plt # 中文字体按可用性排序Linux 上常见的 Noto 排第一位 plt.rcParams[font.sans-serif] [Noto Sans CJK SC, Microsoft YaHei, SimHei] plt.rcParams[axes.unicode_minus] False # 负号显示成方块的老问题 def bar_k_values(labels, design, limit, outk.png): # figsize 用英寸配合 dpi 反推像素10 * 200 2000px投屏足够 fig, ax plt.subplots(figsize(10, 5), dpi200) x range(len(labels)) ax.bar([i - 0.2 for i in x], design, width0.4, label设计值) ax.bar([i 0.2 for i in x], limit, width0.4, label标准限值) ax.set_xticks(list(x)) ax.set_xticklabels(labels, fontsize12) ax.set_ylabel(传热系数 K W/(m²·K), fontsize12) ax.legend(fontsize11) ax.grid(axisy, linestyle--, alpha0.4) fig.tight_layout() fig.savefig(out, bbox_inchestight) plt.close(fig)matplotlib.use(Agg)是必须的脚本跑在无声环境的构建机上默认后端会因为找不到显示服务直接崩。dpi200配合figsize(10, 5)得到 2000×1000 像素插进 16:9 页面占半页宽度时清晰度足够如果想再省体积把 dpi 降到 150 也够但别低于 120投影放大后边缘会发虚。bbox_inchestight裁掉四周空白否则嵌入时你算的宽高比和图里实际的绘图区宽高比不一致柱子看起来会被压扁。4.3 add_picture 的尺寸换算与三类常见报错from pptx.util import Inches # 只给 widthpython-pptx 按原始像素比例自动算高度绝不会变形 slide.shapes.add_picture(k.png, leftInches(0.9), topInches(2.0), widthInches(11.0))三类报错固定出现一是KeyError: a:ea之类的命名空间错误通常是把字体设置写在run之外的对象上回到run._r这一层就好二是UnidentifiedImageError多半是 matplotlib 输出成了 SVG 或 PDFadd_picture只认 PNG、JPEG、GIF、BMP、TIFF三是图被拉伸根因是同时传了width和height此时 python-pptx 不会再做比例校正。只给一个维度是这套流程里最省心的约定。还有一点容易被忽略add_picture的left/top是图片左上角坐标如果图片在版式上要和占位符对齐最好先读模板里图占位符的坐标再复用而不是每次都手调。5. 建筑节能课件批量校验与交付的收尾技巧5.1 空占位符与文本溢出检查渲染脚本不报错不等于成品没问题。批量生成后跑一遍自检比人工翻六十页快得多。from pptx import Presentation WARN 40 # 单行字符数阈值中文按 1 个字符算 def audit(path): prs Presentation(path) for i, slide in enumerate(prs.slides, start1): for shape in slide.shapes: if not shape.has_text_frame: continue txt shape.text_frame.text.strip() if not txt: print(fslide {i}: 空文本框 {shape.name}) for line in txt.splitlines(): if len(line) WARN: print(fslide {i}: 可能溢出 {len(line)} 字 - {line[:20]}...) print(ftotal slides: {len(prs.slides._sldIdLst)}) audit(out.pptx)阈值WARN40是按正文框宽度 20 厘米、18 号字估出来的超过就大概率折行到第二行甚至溢出边框。空文本框必须查因为占位符没填内容时在编辑态看得见提示文字放映态是空的人工翻页很容易漏过去。5.2 无 Office 环境下的 PDF 转档命令交付给教务或归档时通常要 PDF构建机上一般没装 Office用 LibreOffice 的命令行即可。# --headless 无界面--convert-to 指定输出格式--outdir 指定输出目录 soffice --headless --convert-to pdf --outdir ./dist ./out.pptx # 批量转换整个目录 find ./ppt -name *.pptx -exec soffice --headless \ --convert-to pdf --outdir ./dist {} \;转档前把字体装全缺字体时 LibreOffice 会静默替换页面上中文字号会整体变宽原本刚好一行的标题可能折成两行——这也是为什么前面反复强调字体要在脚本里显式指定别指望渲染环境。5.3 把数据版本写进备注页最后这个技巧成本最低、收益最高在渲染时往每页备注里追加一行来源信息包括内容源文件的提交号和参数表快照日期。import subprocess, datetime rev subprocess.check_output([git, rev-parse, --short, HEAD]).decode().strip() stamp datetime.date.today().isoformat() slide.notes_slide.notes_text_frame.text f\n[source {rev} / {stamp}]过一学期有人问「这页的 COP 是哪个版本的规范口径」打开备注页就有答案不用去翻聊天记录。同一个提交号还能让你在改动内容源之后用git diff精确看出是哪几页发生了变化重新出片时只需要重点复查这几页而不是整本重看一遍。本文还有配套的精品资源点击获取
返回列表