以下均直接调用 SDK,不经过 Office/WPS。文件示例中的 /example.xlsx、/example.pptx 需替换为实际输入;确定性内存示例可直接运行。外部输入的完整错误边界见结构验证。
import DocumentFormat.OpenXml;
var ox = DocumentFormat.OpenXml;
var stream = System.IO.MemoryStream();
var doc = ox.Packaging.WordprocessingDocument.Create(stream);
var part = doc.AddMainDocumentPart();
var root = ox.Wordprocessing.Document();
var body = ox.Wordprocessing.Body();
var paragraph = ox.Wordprocessing.Paragraph();
var run = ox.Wordprocessing.Run();
run.Append([ox.Wordprocessing.Text("Hello, Open XML!")]);
paragraph.Append([run]);
body.Append([paragraph]);
root.Append([body]);
part.Document = root;
doc.Dispose(); // 默认 AutoSave=true;完成包写入,但不释放调用方的流
stream.Position = 0;
var reopened = ox.Packaging.WordprocessingDocument.Open(stream);
var text = reopened.MainDocumentPart.Document.Body.InnerText;
reopened.Dispose();
stream.Dispose();
return text;
创建到文件只需将 Create 首参换为输出路径,并去掉流重开部分。该入口会覆盖已有文件;模板编辑应先复制文件,再对副本 Open(path,true)。
import DocumentFormat.OpenXml;
var doc = DocumentFormat.OpenXml.Packaging.SpreadsheetDocument.Open("/example.xlsx");
var ok,rows = call(function(){
var workbookPart = doc.WorkbookPart;
var sheets = workbookPart.Workbook.Sheets;
var result = [];
if(sheets) for i,sheet in dotNet.each(sheets.ChildElements) {
var relationshipId = sheet.Id.Value;
var part = workbookPart.GetPartById(relationshipId);
table.push(result,{
name = sheet.Name.Value;
sheetId = sheet.SheetId.Value;
relationshipId = relationshipId;
part = tostring(part.Uri);
});
}
return result;
},null);
doc.Dispose();
if(!ok) return null,rows;
return rows;
SheetId、关系 ID 和工作表在集合中的位置不是同一概念。根据关系获取的部件还可能是图表工作表等类型,不能一概当作 WorksheetPart。
读取单元格时应区分共享字符串、内联字符串、布尔值、数值及公式缓存;日期还涉及样式与日期系统。CellValue.Text 不是通用的最终显示值。本页不封装整套 Excel 解释器或公式计算器。
import DocumentFormat.OpenXml;
var doc = DocumentFormat.OpenXml.Packaging.PresentationDocument.Open("/example.pptx");
var ok,rows = call(function(){
var presentationPart = doc.PresentationPart;
var slideIds = presentationPart.Presentation.SlideIdList;
var result = [];
if(slideIds) for i,slideId in dotNet.each(slideIds.ChildElements) {
var slidePart = presentationPart.GetPartById(slideId.RelationshipId.Value);
table.push(result,{
id = slideId.Id.Value;
text = slidePart.Slide.InnerText;
});
}
return result;
},null);
doc.Dispose();
if(!ok) return null,rows;
return rows;
使用 SlideIdList 决定顺序,不依赖 SlideParts 的枚举顺序。InnerText 不保留形状或段落边界,不包含图片 OCR、备注部件,也不等于视觉阅读顺序。
需要筛选后代元素、添加部件或处理类型化值时,先看 .NET 互操作。具体文档格式的完整 API 直接查 微软 Open XML 文档,不在本库参考中重复罗列。