简介这份PPT课件系统讲解锂离子动力电池的核心知识面向新能源汽车、电池研发与维护等相关领域的初学者和从业者可作为电动车辆动力电池技术学习的入门与进阶材料。课件从锂离子电池的基本原理出发详细介绍了钴酸锂、锰酸锂、磷酸铁锂等正极材料碳材料、氧化物、合金等负极材料的特点与应用并分析了正极溶解、电解液分解、SEI膜形成等失效机理以及充放电特性、安全性能等关键指标。压缩包内含1个PPTX文件大小4.42MB内容图文并茂配有结构示意图和实际应用案例如北京奥运、上海世博电动客车及日产Leaf、三菱i-MiEV车型已有83人学习。通过这份课件读者可以快速理解锂离子动力电池的选材思路、工作特性与失效原因为后续深入学习电池管理系统或从事相关工程实践打下基础。1. 《锂离子动力电池.pptx》不只是幻灯片还是一层数据容器老是在邮件里收到以《锂离子动力电池.pptx》为名的文件。打开后是电芯参数页、循环容量保持率、DCIR 散点图和分容数据表。可每到月底整合研发数据时这些信息只能一页页抄进 Excel还容易看错行。PPTX 本质是一个 ZIP 包每张幻灯片是 XML表格文本和图表数值都按结构化方式存在同一个包里。把「读 PPTX」当「读数据」就不用手动摘抄还能反过来用脚本批量生成带图表与参数的电池测试报告。这篇文章把这一套读写、兜底和校验方法讲完。适合做电池测试数据分析、BMS 标定或电芯选型数据管理的人。2. 读取锂离子动力电池.pptx先用 python-pptx 扒出表格和曲线数据2.1 先摸清 PPTX 内部结构再动手很多同学拿到 pptx 第一反应是直接用 python-pptx 遍历 shape如果脚本没写全曲线数据很容易漏掉。我一般先解压看结构确定里面有ppt/slides/slide*.xml和ppt/charts/chart*.xml。下面这个命令不打散整个目录只列关键文件import zipfile from pathlib import Path pptx_path Path(锂离子动力电池.pptx) with zipfile.ZipFile(pptx_path) as z: for name in z.namelist(): if (name.startswith(ppt/slides/slide) or name.startswith(ppt/charts/chart) or name.startswith(ppt/tables)): print(name)ZipFile.namelist()把 PPTX 内部所有部件路径列出来ppt/slides/slide1.xml是页面布局与形状ppt/charts/chart1.xml是图表对象。需要注意老版本 WPS 或 PowerPoint 保存的文件不一定有ppt/tables目录表格的 XML 是作为graphicFrame嵌在 slide XML 里的。先看这一步能确认后面解析路径靠不靠谱。看完结构后再用 python-pptx 处理这样遇到读不到数据的问题时不会怀疑是安装出错而能直接判断是不是图表缓存没落盘。2.2 用 python-pptx 把表格转成 DataFrame电池报告里最常见的表格是「电芯基础参数」「分容数据」「SOC-OCV 对应表」。python-pptx 里每个表格是一个Table对象放在 shape 的table属性中。遍历所有 slide 的所有 shape再按has_table判断就可以了。我习惯直接转成 pandas DataFramefrom pptx import Presentation import pandas as pd prs Presentation(锂离子动力电池.pptx) def extract_tables(prs): for slide_no, slide in enumerate(prs.slides, start1): for shape in slide.shapes: if not shape.has_table: continue table shape.table rows [] for row in table.rows: row_data [cell.text.strip() for cell in row.cells] rows.append(row_data) if not rows: continue df pd.DataFrame(rows[1:], columnsrows[0]) df.insert(0, src_slide, slide_no) yield slide_no, df for slide_no, df in extract_tables(prs): print(fslide {slide_no}, shape {df.shape}) print(df.head(3))这里shape.has_table用于过滤形状table.rows返回 Row 对象cell.text拿到的单元格文本已经去掉了换行后的两边空白。把rows[0]当列名其余行当数据是文档型表格最常见的一步操作。df.insert(0, src_slide, slide_no)会给每一行打上页码来源后面核对数据时能快速定位。跑完常见问题是标题行里出现了\n或空格导致列名多出空列。处理办法是加一层列名清洗def clean_columns(df): df.columns [str(c).replace(\n, ).strip() for c in df.columns] df df.loc[:, ~df.columns.duplicated()] df df.dropna(axis1, howall) return dfdropna(axis1, howall)只删除整列全为空值的列不会动部分缺失的数据。清洗后再根据字段单位做类型转换就不容易被各种「Ah」「mΩ」「%」后缀干扰。常见列名典型单位清洗策略电芯编号字符串去除首尾空格统一大小写标准容量Ah转 float「105.3 Ah」这种带单位文本要拆开初始内阻mΩ注意 mΩ 与 Ω 混用按列头还原SOC%区分 0~1 与 0~100 两种写法循环次数cycle转 int可能带「次」后缀2.3 表格背后的图表数值从 chart XML 里读取缓存曲线电池报告里循环寿命图、倍率图、DCIR 曲线通常是以图表形式嵌入的。python-pptx 对图表的支持分两层旧版本只能判断shape.has_chart但拿不到图里的数据点新版本里shape.chart可以访问但很多第三方软件生成的文件图表 XML 甚至没有按标准写入chartSpace。更通用的做法是直接解压 XML。图表数据缓存命名空间是c对应文件叫ppt/charts/chartN.xmlimport zipfile import xml.etree.ElementTree as ET ns_c http://schemas.openxmlformats.org/drawingml/2006/chart ns {c: ns_c} with zipfile.ZipFile(锂离子动力电池.pptx) as z: chart_xmls [n for n in z.namelist() if n.startswith(ppt/charts/) and n.endswith(.xml)] for chart_path in chart_xmls: root ET.fromstring(z.read(chart_path)) series_nodes root.findall(.//c:ser, ns) print(chart_path, series:, len(series_nodes)) for ser in series_nodes: name ser.find(c:tx/c:strCache/c:pt/c:v, ns) num_cache ser.find(c:val/c:numCache, ns) points {} if num_cache is not None: for pt in num_cache.findall(c:pt, ns): idx pt.get(idx) val pt.find(c:v, ns) if idx is not None and val is not None: points[int(idx)] val.text print( , name.text if name is not None else None, points)这段代码把每个chartN.xml里的所有 series 名称和数值缓存打出来。c:numCache是数值缓存c:pt是数据点属性idx表示类别轴上的序号c:v是具体数值。类目轴比如循环次数、SOC 百分比通常放在c:cat/c:strCache里解析方式相同。这里用ET是因为单张图数据量不大如果一份 PPTX 里有几十张图可以把解析结果收集到字典里再pd.DataFrame.from_dict统一处理。这里有一个容易踩的坑图表的「缓存不是最新数据」。如果图表是在 Excel 里做了原始数据更新但忘记刷新或者 WPS 直接把 Excel 图表粘贴成图片numCache里的值可能和原始 CSV 对不上。后面的章节会讲怎么识别这种假一致。3. 把锂离子动力电池测试数据写进 PPTX模板占位与图表落地3.1 从电池原始数据到幻灯片的结构设计如果手上已经有一份「锂离子动力电池.pptx」模板最省人力的方式是保留版式只替换数据。常见做法是针对每个电池型号建一个模板页结构一般这样设计幻灯片区块数据来源写入方式封面批次信息批次元数据 CSV文本占位符电芯参数表电芯规格表表格替换循环寿命曲线循环测试结果插入图表演示SOC-OCV 曲线SOC 标定文件插入图表DCIR 分布脉冲测试统计插入散点图设计时注意把「固定不变」的轴单位写在文本上不要把单位拼进图例里。比如「容量保持率/%」写进坐标轴标题图例里只写电池编号。这样同一个模板能跑几十个批次不至于每次改轴标签。3.2 用占位符把电池参数写回幻灯片python-pptx 里最稳定的替换方式是遍历 shape 里的 text frame按约定的占位符替换比如${batch_id}、${nominal_capacity}from pptx import Presentation prs Presentation(电池报告模板.pptx) report { batch_id: NCM811-2406B, nominal_capacity: 105.3, initial_dcir: 0.82, cycles: 1200, capacity_retention: 92.4, } def render_placeholders(slide, mapping): for shape in slide.shapes: if not shape.has_text_frame: continue for para in shape.text_frame.paragraphs: for run in para.runs: original run.text for key, value in mapping.items(): token ${ key } if token in original: run.text original.replace(token, value) for slide in prs.slides[:4]: render_placeholders(slide, report) prs.save(锂离子动力电池_NCM811-2406B.pptx)注意run.text的替换粒度是 run。PowerPoint 在输入时经常把${batch_id}拆成${batch、_id}等多个 run肉眼看不出来程序却匹配不上。遇到这种情况先拼出整段文本再统一替换def render_paragraph(para, mapping): full_text .join(run.text for run in para.runs) new_text full_text for key, value in mapping.items(): new_text new_text.replace(${ key }, value) if new_text ! full_text: for run in para.runs[1:]: run.text para.runs[0].text new_text这种做法的代价是会丢掉段内局部格式所以模板里这类占位符最好单独成段避免与正文混排。3.3 用 python-pptx 生成循环寿命与 SOC-OCV 曲线文本参数替换之外图表插入是另一个高频需求。python-pptx 自带add_chart方法适合在表格或文本写完后补充一张数据图。以循环寿命曲线为例x 轴放循环次数y 轴放容量保持率from pptx import Presentation from pptx.util import Inches from pptx.chart.data import CategoryChartData from pptx.enum.chart import XL_CHART_TYPE prs Presentation(电池报告模板.pptx) slide prs.slides.add_slide(prs.slide_layouts[5]) # 空白版式 chart_data CategoryChartData() chart_data.categories [0, 200, 400, 600, 800, 1000, 1200] chart_data.add_series(容量保持率, (100.0, 98.7, 96.2, 93.8, 91.0, 88.3, 85.6)) graphic_frame slide.shapes.add_chart( XL_CHART_TYPE.LINE_MARKERS, Inches(0.5), Inches(1.8), Inches(8.5), Inches(4.2), chart_data ) chart graphic_frame.chart chart.has_legend True这段代码里CategoryChartData用来定义类目轴和各个序列add_series的第一个参数是图例名第二个参数必须是元组或列表长度和categories一致。add_chart返回的是GraphicFrame需要.chart才能拿到图表对象去调整图例。LINE_MARKERS对容量保持率这种带离散采集点的曲线比纯折线更直观。但这里要提醒一个坑python-pptx 生成的图表基于 Office 图表渲染引擎PowerPoint 打开后需要本地 Excel 数据源才能编辑。有些只装了 WPS 或非 Office 组件的机器上图表可能显示为「无法编辑图表」的占位块。避免方法是临时把图表数据源也内嵌一份在幻灯片里或者用matplotlib生成 PNG 再贴进 PPTX。后者对发布型报告更稳。两种方式按交付对象决定要做成可继续编辑的交付件时用原生图表只要 PDF 汇报效果时用图片。4. 当 python-pptx 读不到锂离子动力电池.pptx 的数据直接从 XML 还原曲线4.1 场景判断先区分「图表缺失」还是「缓存失效」用 python-pptx 读「锂离子动力电池.pptx」时最常遇到三种异常。第一种是找不到shape.chart因为某些导出工具把图表存成了图片第二种是has_chart为 True 但chart.plots空多出现在图表使用外部 Excel 数据源而没有缓存的情况第三种是能读到数据但和原始报告不一致通常是用户改完 Excel 忘了刷新图表。遇到这些情况别急着换库先拆包看ppt/charts/chartN.xml里有没有c:numCache。4.2 用 zipfile ElementTree 还原充放电数据序列下面这段代码比第 2 章更完整会把图表里的类目和数值缓存拆成 DataFrame并用文件名区分图表来源import zipfile import xml.etree.ElementTree as ET import pandas as pd NS_C http://schemas.openxmlformats.org/drawingml/2006/chart ns {c: NS_C} def chart_xml_to_dataframe(pptx_path, chart_path): with zipfile.ZipFile(pptx_path) as z: root ET.fromstring(z.read(chart_path)) rows [] for ser_idx, ser in enumerate(root.findall(.//c:ser, ns), start1): # 系列名称 name_node ser.find(c:tx/c:strCache/c:pt/c:v, ns) name name_node.text if name_node is not None else fseries_{ser_idx} # 类目缓存兼容 strCache 和 numCache cats [] cat_cache ser.find(c:cat/c:strCache, ns) cat_num_cache ser.find(c:cat/c:numCache, ns) if cat_cache is not None: cats [pt.find(c:v, ns).text for pt in cat_cache.findall(c:pt, ns)] elif cat_num_cache is not None: cats [pt.find(c:v, ns).text for pt in cat_num_cache.findall(c:pt, ns)] # 数值缓存 values [] num_cache ser.find(c:val/c:numCache, ns) if num_cache is not None: values [float(pt.find(c:v, ns).text) for pt in num_cache.findall(c:pt, ns)] for cat, val in zip(cats, values): rows.append({chart: chart_path, series: name, category: cat, value: val}) return pd.DataFrame(rows) with zipfile.ZipFile(锂离子动力电池.pptx) as z: charts [n for n in z.namelist() if n.startswith(ppt/charts/chart) and n.endswith(.xml)] for chart_file in charts: df chart_xml_to_dataframe(锂离子动力电池.pptx, chart_file) print(chart_file, df.head(3).to_string(indexFalse))这个版本把c:ser遍历、类目c:cat、数值c:val一次性处理完。注意c:strCache用于文本类目如果类目是循环次数这类数值Excel 可能写的是c:numCache而不是c:strCache。所以在实现时要兼容两者否则循环寿命图还原出来类目可能全部为空。4.3 兜底解析的边界图表数据刷新与共享公式还有一个在电池报告场景里很常见的边界PPTX 的图表数据源不是内嵌缓存而是指向外部 Excel 工作簿的共享公式。这种情况下c:numCache里的数据会被标记为deletedtrue或只存在c:numRef而不存在c:numCache。此时解析 XML 只能拿到引用关系拿不到数据。遇到这种文件只能回到原始 Excel 工作簿里去取数。如果最终交付物必须是 PPTX那就在 PowerPoint 里打开图表并删除外部数据源让它形成内嵌缓存或者用 LibreOffice headless 转换一次不过转换后版式可能偏移。这类文件在实际工作中并不少见尤其在研发阶段用内网模板分享时外链数据源常被策略拦截。因此第 2 章开头先解压确认结构就是为了提前看到externalData节点。我一般会在解析脚本里加一个判断external root.findall(.//c:externalData, ns) has_num_cache_all len(root.findall(.//c:numCache, ns)) if external and not has_num_cache_all: print(警告图表数据来自外部数据源需要先从 Excel 刷新缓存)提示如果文件是 WPS 直接导出externalData可能不出现但numCache是旧数据。遇到这种文件优先找生成 PPT 的原始数据表核对。这条警告比「图表读不出来」更有用后续对接的同事可以少踩一轮坑。5. 给锂离子动力电池.pptx 做交付前数据一致性校验5.1 比对图表缓存与原始 CSV 的数值指纹模板生成完「锂离子动力电池.pptx」后别急着发。用一段校验脚本把图表缓存里的关键曲线与原始 CSV 做比对能在交付前发现「Excel 改过但 PPT 没刷新」的问题。具体技巧是直接比维度长度和末点值不用做逐点全比import zipfile import xml.etree.ElementTree as ET NS_C http://schemas.openxmlformats.org/drawingml/2006/chart ns {c: NS_C} def read_series_last_values(pptx_path, chart_relchart1.xml): with zipfile.ZipFile(pptx_path) as z: root ET.fromstring(z.read(fppt/charts/{chart_rel})) result {} for ser in root.findall(.//c:ser, ns): name_node ser.find(c:tx/c:strCache/c:pt/c:v, ns) num_cache ser.find(c:val/c:numCache, ns) values [] if num_cache is not None: values [float(pt.find(c:v, ns).text) for pt in num_cache.findall(c:pt, ns)] name name_node.text if name_node is not None else unknown result[name] values return result def check_against_csv(pptx_values, csv_df, series_col, value_col, tol1e-6): source_values csv_df[value_col].astype(float).tolist() target_values pptx_values[series_col] if len(source_values) ! len(target_values): return False, f长度不一致: CSV {len(source_values)} vs PPT {len(target_values)} checks [0, len(source_values) // 2, len(source_values) - 1] diff [abs(source_values[i] - target_values[i]) for i in checks] return (max(diff) tol), f最大偏差 {max(diff):.2e}这段代码先取出 PPTX 某个图表的数值序列再从原始 CSV 里取同名列做三点抽样。三点抽样适合容量保持率这类单调曲线如果数据是 DCIR 脉冲序列中间点可能因测量异常波动建议改成对比最后一个窗口的 10 个点。tol按容量单位决定Ah 级别用1e-6太严可放宽到1e-3。5.2 导出数据来源清单可逆向追踪每一页校验通过后我一般会在同一目录生成一份data_manifest.csv记录每个图表对应哪张原始 CSV、提取时间和数据维度图表部件页面索引系列名原始 CSV数值点数提取时间ppt/charts/chart2.xmlslide 4容量保持率25Ccycle_25C.csv12012026-04-05 11:22:14ppt/charts/chart5.xmlslide 7SOC-OCV 放电soc_ocv.csv412026-04-05 11:22:15生成方式就是继续复用第 4 章的chart_xml_to_dataframe在返回的 DataFrame 里加两列extract_time和source_csv再落盘。这份清单留给做电池数据的同事比在 PPT 备注页里写说明更可复用。最后分享一个小技巧校验结束后不要只检查一个 chart 的 XML把ppt/charts/*.xml全部遍历一遍把有外部数据源的图表单独输出到warnings.txt然后循环ppt/charts/*.xml后统一写pd.DataFrame.to_csv(data_manifest.csv, indexFalse)。配合warnings.txt里的外部数据源列表交付前就能知道哪些图在只装 WPS 的机器上可能渲染不出来这份「锂离子动力电池.pptx」才算完成了数据自检。本文还有配套的精品资源点击获取