# com.powerPoint：PowerPoint / WPS 演示

面向 PowerPoint 自动化及 `autos.skills.powerPoint` 的轻量 COM 包装器。参考 `com.excel`、`com.doc` 的代理方式，但**不照搬它们的实例创建与自动退出策略**。

**`com.powerPoint` 通过动态 COM 代理继承 `PowerPoint.Application` 的所有 COM 方法与属性。** AI 可以直接沿用 Microsoft PowerPoint/VBA 对象模型的先验知识：`Presentations`、`ActivePresentation`、`CommandBars`、`Run` 等不需要本库逐个封装。智能提示仅列高频 API，不是可用 API 白名单。`Presentation`、`Slide`、`Shape` 等子对象仍是原生 COM 对象；类型库常量也可以从包装器读取。

这里的“继承”是接口透传，不是注册新的 COM 类型或改变 Office 接口。`Application`/`oPowerPoint` 提供底层原生对象，供事件绑定、底层 COM 操作或现有代码使用。库的 `Add/Open/Save/SaveAs/Release` 等属于便捷扩展；原生集合与子对象接口仍然保持原样。

按顺序兼容 `PowerPoint.Application`、`WPP.Application`、`KWPP.Application`，需要安装提供 COM 自动化接口的 Office PowerPoint 或 WPS 演示。WPS 能力以其实际接口为准，不能把 ProgID 兼容理解为完整实现全部 Office API。

```aardio
import com.powerPoint;
var ppt,err = com.powerPoint();
if(!ppt){ print(err); return; }

var pres = ppt.Add(); //默认有窗口，新文稿成为活动文稿
var slide = pres.Slides.Add(1,12/*_ppLayoutBlank*/);
var shape = slide.Shapes.AddTextbox(1/*_msoTextOrientationHorizontal*/,50,50,600,100);
shape.TextFrame.TextRange.Text = "你好，PowerPoint！";
shape.TextFrame.TextRange.Font.Size = 32;
ppt.SaveAs("/demo.pptx"); //可能覆盖同名文件；路径相对于当前应用基准目录

//保留给用户查看；只释放包装器引用，不退出整个应用。
ppt.Release();
```

## 构造与生命周期

| 调用 | 行为 |
| --- | --- |
| `com.powerPoint()` / `com.powerPoint(true)` | 先依次尝试三个 ProgID 的运行对象；均未连接成功才依次尝试创建 |
| `com.powerPoint(false)` | 仅从 ROT 连接已运行对象，不创建实例 |
| `com.powerPoint(path)` | 创建/获取 COM 对象；文件存在则打开，否则新建并保存，默认有窗口 |

构造失败返回 `null,提示信息,底层错误`。普通 COM 操作保留原生异常，不把异常吞掉或伪装为成功。

**PowerPoint 的 COM 创建可能复用已有进程，而不是像独立工作进程那样供调用方独占。ROT 中的对象也可能是后台自动化实例。** 本库不会根据以下任何单一条件认定所有权：调用过 CreateObject、之前 TryGetObject 失败、Visible 为 false、Presentations.Count 为 0。

任何构造模式都**不注册 `QuitOnClose`，不在垃圾回收时调用 Quit**。默认清理仅依赖正常的 COM 引用回收；需要明确断开包装器时调用 `Release()`。

| 操作 | 语义 |
| --- | --- |
| `Release()` / `release()` | 清除包装器及宏代理的应用引用，不调用 Quit，不关闭文稿 |
| `Close()` / `close()` | Release 的别名；刻意不沿用 com.excel/com.doc 的 Quit 别名 |
| `pres.Close()` | 原生 Presentation.Close，只关闭指定文稿 |
| `Quit()` / `quit()` | 显式调用原生 Application.Quit，随后 Release；影响整个应用 |

Release 不调用 `com.Release(app)` 强制使底层对象失效，外部持有的 `Application` 别名及文稿引用仍然有效。最后一个 COM 引用释放后，应用是否自行退出由 COM 服务决定；“本库不调用 Quit”不等于“保证进程一直驻留”。保存下来的宏代理函数在 Release 后不可再调用。

只有调用方已确认退出整个应用符合用户意图，才可以调用 Quit。自动化任务通常只保存、关闭自己创建/打开的文稿，随后 Release。技能层若维护专用实例，应另行记录可靠的启动归属并确认没有其他文稿/使用者；不能只检查 Count 为 0。

本库不扫描进程、不推断所有权、不自动保存或丢弃文稿、不修改加载项、不点击退出对话框、不强制终止进程。其他原生 COM 引用的生命周期由持有者管理。

PowerPoint 不允许设置 `Visible = false`。构造函数不改变可见状态；显示应用可用 `Visible = true`。

### 如何理解 SingleUse / MultiUse 与 ROT

Microsoft 的《GetObject and CreateObject functions in VBA》资料区分的是 **COM 服务器的 SingleUse/MultiUse 激活方式**：列出的 Word/Excel 版本是 SingleUse，PowerPoint 是 MultiUse。它们不是日常用语“只能一个进程/可以多个进程”的同义词；MultiUse 的关键是多个自动化客户可能复用同一服务器。

这份官方对照表列举的是 Office 97–2007，不能扩展成所有现代版本、会话、权限、WPS 都遵守的绝对保证。本机 PowerPoint 16.0.14228 的实验确认后台实例也会立即注册 ROT，无窗口文稿也会注册文件名，但库不把该观察硬编码成跨版本检测规则。

因此文档不宣称“ROT 永远只有一个对象”“CreateObject 永远新建/永远复用”或“与 AutoCAD 完全一致”。对于库设计，可靠结论只有：**不得把 COM 获取成功当作独占授权，也不得自动退出可能共享的应用。**

## 后台创建、保存与导出

无窗口文稿不一定成为 `ActivePresentation`；存在其他窗口时，活动文稿还可能是另一份文件。**后台操作始终保留并使用返回的文稿对象。** 本库不会用最近打开的文稿偷偷替换 `ActivePresentation`。

下面示例只关闭本次创建的文稿并 Release，不退出整个应用，无需把连接成功误当作独占实例。

```aardio
import com.powerPoint;
var ppt,err = com.powerPoint();
if(!ppt){ print(err); return; }

var pres = ppt.Add(false);
var slide = pres.Slides.Add(1,12/*_ppLayoutBlank*/);
var shape = slide.Shapes.AddTextbox(1,50,50,600,100);
shape.TextFrame.TextRange.Text = "后台生成演示文稿";

ppt.SaveAs("/background.pptx",,pres);
ppt.Save(pres);
ppt.SaveAs("/background.pdf",,pres);
slide.Export(io.fullpath("/first-slide.png"),"PNG",1280,720);

pres.Close();
shape,slide,pres = null,null,null;
ppt.Release();
```

`Save/SaveAs` 保留 COM 原方法的返回值，成功通常返回空值；**不要以返回值为真假判断是否保存成功**。需要检查时可查文件或使用 `call` 捕获原生异常。

## 常用接口

| 接口 | 说明 |
| --- | --- |
| `Add(withWindow=true)` | 新建文稿，返回原生 Presentation |
| `Open(path,readOnly=false,untitled=false,withWindow=true)` | 打开文稿，参数顺序与原生接口一致，自动转换完整路径 |
| `createFile(path,withWindow=true)` | 存在则打开，不存在则创建并保存；返回文稿 |
| `Save(presentation)` | 省略参数时保存活动文稿 |
| `SaveAs(path,format,presentation)` | format 省略时按后缀推断；presentation 省略时操作活动文稿 |
| `eachPresentation()` | 返回 `序号,文稿对象` 迭代器，含无窗口文稿 |
| `eachSlide(presentation)` | 返回 `序号,幻灯片对象` 迭代器；省略参数时遍历活动文稿 |
| `Wps()` | 根据成功的 ProgID 或应用名称识别 WPS，不检查文件名 |
| `alerts` | 布尔快捷属性，映射 DisplayAlerts 的 1/2，不涉及 ScreenUpdating |
| `Application` / `oPowerPoint` | 原始 Application COM 对象；Application 为只读便捷别名 |
| `progId` | 实际连接成功的 ProgID，不是进程所有权标识 |
| `Release()` / `Close()` | 仅清除包装器引用，不退出整个应用 |
| `Quit()` | 显式退出整个应用；调用方必须确认允许退出 |
| `vba` / `jsa` | 同一个宏调用代理，转发 Application.Run |

支持 `add/open/save/saveAs/release/quit/close/wps` 小写开头别名，以及 `Close`。注意 close/Close 是 Release 的别名，不是 Quit。

路径通过 `io.fullpath` 转换，不自动创建父目录；需要时先用 `io.createDir`。`createFile` 创建的是空文稿，不会自动添加幻灯片。

## 打开现有文稿

```aardio
import com.powerPoint;
var ppt,err = com.powerPoint(false);
if(!ppt){ print(err); return; }

//只读、不是副本、无窗口
var pres = ppt.Open("/input.pptx",true,false,false);
for i,slide in ppt.eachSlide(pres){
    print(i,slide.Name);
}
pres.Close();
//共享实例：不调用 ppt.Quit()
ppt.Release();
```

## 保存格式

已定义常用映射：

| 后缀 | 格式数值 |
| --- | --- |
| ppt / pot / pps / ppa | 1 / 5 / 7 / 8 |
| pptx / pptm | 24 / 25 |
| potx / potm | 26 / 27 |
| ppsx / ppsm | 28 / 29 |
| ppam / thmx | 30 / 31 |
| pdf / xps / xml / odp | 32 / 33 / 34 / 35 |
| rtf | 6 |
| wmf / gif / jpg、jpeg / png / bmp / tif、tiff / emf | 15 / 16 / 17 / 18 / 19 / 21 / 23 |

后缀不区分大小写。没有后缀时传 `11`（ppSaveAsDefault），由应用决定默认格式。未知后缀不猜测，要求显式传入原生格式常量。WPS 专有格式和组件特有格式请查对应版本的接口。

格式映射不代表所有 Office/WPS 版本均支持该格式。保存可能覆盖目标文件；PNG/JPG 等整份文稿图片输出可能生成目录。导出单页建议用 `slide.Export`，导出所有页可直接用 `pres.Export`。不封装视频生成或等待流程。

## 原生接口与宏

原生对象模型直接透传，只有少量常用成员加入智能提示。未出现在提示中的成员仍可使用。坐标和字号使用 point；Office RGB 颜色使用 `0xBBGGRR`，图片导出宽高使用像素。

```aardio
import com.powerPoint;
var ppt,err = com.powerPoint(false);
if(!ppt){ print(err); return; }

print(ppt.Version,ppt.Presentations.Count);
print(ppt.ppLayoutBlank); //类型库中的常量，不是库内重新定义的全集
// ppt.vba.MyMacro("参数"); //等同 ppt.Run("MyMacro","参数")
// ppt.jsa.MyMacro(); //仅适用于实际支持 Application.Run 的 WPS 宏环境
```

宏功能取决于组件版本、宏是否存在及安全设置。本库不安装宏组件、不修改宏安全设置。WPS 支持程度以其实际 COM 接口为准；候选 ProgID 兼容不等于全部 Office 对象模型都由 WPS 实现。

## 提示框与加载项

`alerts=false` 仅映射 `DisplayAlerts=1`（ppAlertsNone），`alerts=true` 映射 `2`（ppAlertsAll）；它不是所有对话框的总开关。

第三方加载项可以显示独立提示。库不禁用 COMAddIns，不要求管理权限，不点击退出提示，不强制结束进程。若遇到退出报错，应由应用或加载项配置层单独排查，不能直接据此认定 aardio 或 PowerPoint 资源不足。

## 参考

- [库参考](https://www.aardio.com/zh-cn/docs/library-reference/com/powerPoint/_.html)
- [Microsoft PowerPoint 对象模型](https://learn.microsoft.com/en-us/office/vba/api/overview/powerpoint/object-model)
- [Presentations.Open](https://learn.microsoft.com/en-us/office/vba/api/powerpoint.presentations.open)
- [PpSaveAsFileType](https://learn.microsoft.com/en-us/office/vba/api/powerpoint.ppsaveasfiletype)
- [PpAlertLevel](https://learn.microsoft.com/en-us/office/vba/api/powerpoint.ppalertlevel)
- [Microsoft：GetObject and CreateObject functions in VBA（历史版本资料）](https://learn.microsoft.com/en-us/previous-versions/troubleshoot/microsoft-365/microsoft-365-apps/office-suite-problems/getobject-createobject-behavior)
