aardio 文档

PPTX 生成:文本、形状、图片、表格与动画

从 fsys.openXml 0.6.0 起,可不启动 Office/WPS 生成 .pptx。

直接导入 fsys.openXml.pptx.builder 是纯生成路线:不加载 ZIP 读取器、MSXML、.NET 或技能包。ZIP 写入复用公共 zlib.zip.writeData,不为每个部件创建临时文件。主题与备注母版编译内嵌,运行时不需要参考 PPTX。

最小示例

import fsys.openXml.pptx.builder;
var slides = [{
    background = "F4F7FC";
    notes = "讲解备注";
    transition = {effect="fade";duration=0.7};
    shapes = [{
        kind="text";name="Title";
        x=60;y=60;width=840;height=100;
        text="由 aardio 生成的 PPTX";
        fontSize=36;bold=true;color="18324F";
        animation={effect="fade";trigger="click";duration=0.6};
    }];
}];
var path,err = fsys.openXml.pptx.builder.write("/native.pptx",slides);
if(!path) return null,err;
return path;

write(path,slides,options) 返回完整路径,失败 null,err,默认不覆盖。只有明确指定 {overwrite=true} 才覆盖旧目标。fsys.openXml.pptx.write 与技能 writePptx 为便捷转发;需要最小依赖时用上面的直接导入。

0.12.1:表格边距与垂直对齐兼容修复

表格 margin、valign 的 API 与默认值不变。单元格只通过 a:tcPr 写入四边边距和垂直对齐,内部 a:bodyPr 省略 lIns/rIns/tIns/bIns/anchor,保留 wrap="square" 和 noAutofit。显式写零边距/顶部对齐并不等于省略:WPS 的某些版本会用这些值覆盖 tcPr。

修复仅作用于新生成的表格;普通文本框、形状文字、占位符及备注保持原输出,预检仍只扣一次单元格边距。不要改用空格、段落缩进、缩小字号或在两层重复写边距补偿。旧文稿的编辑保留机制不自动清除这些属性;可重新运行 ~/examples/File/OpenXML/pptx-data.aardio 生成修正版。

用户提供的 WPS Build 12.1.0.16929 对照验证表明:同时省略五属性可恢复 80 个物理格的 9pt 边距及居中,实读字号仍为18pt/15pt。本机 PowerPoint 16 的修前/修后七页同尺寸PNG逐字节相同,实际边距、文本边界、行高与合并格尺寸保持,回存重开也正常。此结论不外推为全部应用版本的字号/排版绝对一致。

0.12.0:二维原生图表

kind="chart";chart={type,categories,series} 支持二维柱状/条形/折线/饼图,每图带独立内嵌XLSX,引用与缓存一致。详见 二维原生图表。完整演示:~/examples/File/OpenXML/pptx-charts.aardio。缺值使用null,与0区分;尾部null通过数组元表length保留。check不模拟图表内部标签排版。

0.11.0:合并单元格与数据模板

表格 merges=[{row,column,rowSpan,colSpan}] 支持横向/纵向/矩形合并,行列从1开始;保留完整物理 rows,覆盖格必须为空。生成与预检共用合并拓扑与总宽高,详见 模板与表格数据。完整演示 ~/examples/File/OpenXML/pptx-data.aardio 还展示 editor 复制/删页与保留格式填值。

0.10.0:页码、超链接、编号与外观

支持 options.slideNumber 自动页码、运行 field="slideNumber"、文字/形状/图片 hyperlink、段落 numbering、外阴影 shadow 与圆角矩形 cornerRadius。详见 页码、超链接、编号与外观细节。完整五页交互演示:~/examples/File/OpenXML/pptx-details.aardio。

0.9.0:标题、标准版式与放映

slide.layout 可为 blank(默认)、title、titleContent、twoContent。标准版式提供真正的标题/正文占位符,并非只有外观的文本框;版式部件、幻灯片及预检共用默认几何。只生成显式提供的 shapes,不自动增加未提供的内容。

import fsys.openXml.pptx.builder;
var slides=[{
    layout="titleContent";
    shapes=[
        {name="Title";placeholder="title";text="按段落讲解"},
        {name="Body";placeholder="body";text='第一点\r\n第二点\r\n第三点';
            animation={effect="fade";byParagraph=true;duration=0.45}}
    ];
}];
return fsys.openXml.pptx.builder.write("/paragraphs.pptx",slides);

完整五页示例:~/examples/File/OpenXML/pptx-show.aardio。第2页点击三次,第3→4页观察 Morph,第5页两栏自动逐段播放。本机 PowerPoint 16 已检查标题 API、段落点击和连续中间帧;用户于2026年10月8日在两台电脑的WPS中验证该演示播放与排版正常(未提供版本号);旧 Office 尚未验收。基础版式不是用户母版导入器。

坐标与颜色

形状描述

每页 shapes 为数组,按数组顺序绘制,后面在上面。名称应唯一;id 默认从 2 递增,不能重复。每项:

kind 内容
text text 字符串或 paragraphs;透明文本框
shape geometry、fill、lineColor;可有文字
image 本地 path 或 data 字节串;只支持 PNG/JPEG
table rows 矩形二维数组;逐格保存值为文本,不重算公式
chart chart 指定类型、分类、系列;原生ChartML与独立内嵌XLSX

通用字段包括 name,id,x,y,width,height,rotation,description,animation。文本样式包括 fontName,fontSize,color,bold,italic,align,valign,margin。对齐为 left/center/right/justify,垂直对齐为 top/center/bottom。矩形几何支持 rect,roundRect,ellipse,triangle,diamond,line,chevron,hexagon;线宽为 0~1584 点。

文本用 CR/LF 分段,垂直制表符 \v 表示软换行;TAB 保留。明确的 paragraphs 每项为字符串或 {text,runs,bullet,level,align}。运行 runs 每项为字符串或 {text,bold,italic,color,fontName,fontSize};运行内部不要放 CR/LF。替换不会把 & 当作预转义实体,所有文字按原样内容转义。非法 XML 控制字符、无效 UTF-8 和孤立代理项拒绝。

import fsys.openXml.pptx.builder;
var slides = [{shapes=[{
    kind="text";name="Body";x=50;y=50;width=800;height=260;
    paragraphs=[
        {runs=[{text="中文 ";bold=true},{text="彩色文字";color="E55A33"}]},
        {text='第一项\v软换行';bullet=true;level=0},
        {text="第二项";bullet=true;level=1}
    ];
}]}];
return fsys.openXml.pptx.builder.write("/rich.pptx",slides);

图片原字节内嵌,不下载 URL、不转码。只给宽或高时保持比例;都省略时按 96 DPI 换算为 point。两者都给时,fit="stretch" 默认保持旧的拉伸行为;0.7.0 起可用 contain 完整等比放入目标框,或 cover 等比铺满并裁切。imageAlignX/imageAlignY 在 0..1 指定锚点,默认 0.5 居中(0=左/上,1=右/下)。contain 改变实际图片形状的尺寸与位置,空余区域没有额外图片背景;cover 保持指定框,用原图裁切比例而不重编码。0.8.0 起内容相同的图片(无论来自 path 还是 data)只嵌入一份,所有页面共用同一媒体部件。

表格每行宽度须一致。中间的 null 显示为空文本,0/false/空串 分别保留;尾部空格请用 "" 明确表示,因为尾部 null 不保留数组长度。0.11.0 起可用 merges 指定矩形合并,不做自适应列宽。默认等分行列,0.7.0 起支持下述细化样式。

0.7.0:填充与精细排版

填充

fill/background/cellFill/bandFill 支持:

文本

表格

import fsys.openXml.pptx.builder;
var slides=[{
    background="F5F7FB";
    shapes=[{
        kind="shape";name="Title";x=50;y=40;width=860;height=110;
        fill={angle=20;stops=[{position=0;color="15314F"},{position=1;color="36798B"}]};
        text="可编辑的排版与样式";fontSize=32;color="FFFFFF";
        margin={left=24;right=24;top=18;bottom=18};valign="center";
    },{
        kind="table";name="Grid";x=50;y=190;width=860;height=180;
        columnWidths=[220,320,320];rowHeights=[50,65,65];
        fontSize=20;valign="center";margin=12;
        cellFill="FFFFFF";bandFill="E9EFF7";
        header={fill="203C61";color="FFFFFF";bold=true};
        rows=[["项目","说明","数值"],["保留类型","零不是缺失值",0],
            ["局部强调",{text="可单独设置颜色";color="168A76";bold=true},false]];
    }];
}];
return fsys.openXml.pptx.builder.write("/styled.pptx",slides);

完整 6 页示例:~/examples/File/OpenXML/pptx-design.aardio,资源在同目录 .pptx-design/。包含封面、叙事卡片、形状柱状图、图片适配、原生表格和点击动画。示例图表数据为虚构展示数据;柱条是普通形状,不是含工作簿的原生 chart。

0.8.0:生成前预检

builder.check(slides,options,checkOptions) 接收与 write 完全相同的参数,不启动 Office、不写文件、不修改输入。先做与生成相同的校验(不合法时返回 null,err),再估算版式:

code 含义
overflow 文字估算高度超过文本区(已扣除内边距);内边距大于形状为 error,其余为 warning
tableGrow 表格某些行放不下内容,PowerPoint 打开时会自动增高;给出每行需要的高度与总增高
offSlide 形状(含旋转后的外接框、表格自动增高后的高度)超出页面
overlap 两个含文字的形状或表格的区域相交;文字叠在无字卡片、图片上不报
import fsys.openXml.pptx.builder;
var slides=[{shapes=[
    {kind="text";name="Title";x=40;y=40;width=300;height=40;fontSize=20;
        text="这个标题太长了,三百点宽的文本框放不下这么多字"}
]}];
var report,err=fsys.openXml.pptx.builder.check(slides);
if(!report) return null,err;
for i,item in report.issues {
    print(item.code,item.message); // overflow 第 1 页形状 Title:文字可能溢出:约需 48pt,可用 32pt(2 行)
}
return report.ok;

返回 {ok,issues,counts,errors,warnings,missingFonts}。每个问题含 code,severity,message,slide,shape 以及细节字段(needed/available/lines、rows/grow、bounds、other/area)。checkOptions 可设 tolerance=0.5(point)、overlapMinArea=4、ignore=["overlap"];单个形状可设 checkIgnore=true 或 checkIgnore=["overflow"],表示该处的重叠或溢出是有意设计。missingFonts 列出系统缺少、测量时已回退到微软雅黑的字体。

估算原理与精度:用 GDI+ 通用排版格式测行数,再按 PowerPoint 行高规律计算(单倍行高 = 1.2×字号;百分比行距时文本框首行只计入约 48% 的额外行距;表格行高 = 内容高度 + 单元格上下边距,空单元格仍占一行)。与本机 PowerPoint 16 实测对照:设计演示 54 个文本框高度平均误差约 0.1%、最大约 1.6%;24 个自动折行样本中 21 个行数完全一致,其余 3 个都是中文窄栏多估 1 行(PowerPoint 允许行尾标点悬挂到边界外,GDI+ 不支持),从未少估;表格自动增高后的 10 行行高全部一致。这些样本中没有少估,但不保证对所有字体与输入都不漏报。它仍是估算,不是排版引擎:不模拟逐运行混排、字距、首字下沉,仅针对 PowerPoint 实测过;WPS 未逐项校准。

0.8.0:字体、语言、备注与线条

import fsys.openXml.pptx.builder;
var slides=[{notes="备注默认 12pt";shapes=[
    {kind="text";name="Mixed";x=60;y=60;width=600;height=60;fontSize=28;
        text="Native PPTX 原生生成";fontNameLatin="Segoe UI";fontNameEa="Microsoft YaHei"},
    {kind="shape";name="Arrow";geometry="line";x=80;y=300;x2=420;y2=180;
        lineColor="E55A33";lineWidth=2;lineDash="dash";lineEnd="triangle"}
]}];
return fsys.openXml.pptx.builder.write("/fonts-lines.pptx",slides,{headingFontName="SimHei"});

动画

shape.animation 可为一个动画表或数组,作用于自身。slide.animations 为按页面指定顺序的动画数组,target 用形状 id 或唯一名称;它追加在形状自身动画之后。

支持:

effect 默认类别 说明
appear entrance 立即出现;exit 为立即消失
fade entrance 淡入/淡出
fly entrance 从指定侧飞入;exit 飞向指定侧
wipe entrance 擦除;exit 为退场擦除
zoom entrance 缩放并淡入;exit 缩小并淡出
spin emphasis angle 默认 360 度,可负值
grow emphasis scale 默认 150,表示百分比

类别字段 category 为 entrance/exit/emphasis;spin/grow 只属于 emphasis,其他属于 entrance/exit。direction 为 top/right/bottom/left,飞入与擦除默认 bottom。这些是本库已验证的名称,不是 COM 的 MsoAnimEffect 数值;COM 常量与 XML presetID 不可混用。

trigger 为 click/with/after:点击开始、与同组前动画同步、等前一并行组结束;首个 with/after 可自动开始。duration/delay 为秒,默认 0.5/0;appear 固定 1 毫秒。after 的起点等待前一并行组最长动画(包括延迟)结束。每次新 click 建立新点击组。

import fsys.openXml.pptx.builder;
var slides=[{shapes=[{
    kind="shape";name="Badge";x=330;y=160;width=220;height=140;
    geometry="roundRect";fill="4472C4";text="动画";color="FFFFFF";
    align="center";valign="center";
    animation=[
        {effect="fly";direction="left";trigger="with";duration=0.7},
        {effect="spin";angle=90;trigger="after";duration=0.5},
        {effect="fade";category="exit";trigger="click";duration=0.4}
    ];
}]}];
return fsys.openXml.pptx.builder.write("/animated.pptx",slides);

支持整形状及逐段落动画、Morph 与明确的 fade 兼容回退;不支持交互触发器、声音、自定义运动路径或所有 PowerPoint 特效。未知效果明确报错,不静默降级。尚未覆盖的复杂时间轴可用 COM 辅助。

幻灯片切换与备注

transition 可含 effect,duration,direction,orientation,advanceOnClick,advanceAfter,option。效果为 none/cut/fade/push/wipe/split/morph;Morph 及其 fade 回退见上面的 0.9.0 一节;push/wipe 用四方向,split 用 direction=in/out,orientation=horz/vert。duration/advanceAfter 为秒,advanceOnClick 默认 true。写出 Office 2010 扩展 Choice 与标准 Fallback;老软件只得到 fast/med/slow 分类,不保证精确时长。

notes 字符串生成逐页备注,空字符串仍生成备注部件;不传则没有。备注母版有独立主题,避免 SDK 良构但 PowerPoint 不能打开的兼容性问题。hidden=true 保存隐藏页。

限额与边界

Markdown 格式