dotnet OpenXML 读取 PPT 内嵌 xlsx 格式 Excel 表格的信息
在 Office 中,可以在 PPT 里面插入表格,插入表格有好多不同的方法,对应 OpenXML 文档存储的更多不同的方式。本文来介绍如何读取 PPT 内嵌 xlsx 格式的表格的方法
读取方法和 dotnet OpenXML 读取 PPT 内嵌 ole 格式 Excel 表格的信息 差不多,对于 Office 2019 以上版本,插入 Excel 表格用的不是 OLE 文件的方式,而是放入一个 xlsx 文件
在 Slide.xml 页面里面,存放的是在 GraphicFrame 下的内容,简化的 OpenXML 文档如下
<p:graphicFrame>
<p:nvGraphicFramePr>
<p:cNvPr id="9" name="表格 1" />
</p:nvGraphicFramePr>
<p:xfrm>
<a:off x="5405438" y="3241675" />
<a:ext cx="3438525" cy="2009775" />
</p:xfrm>
<a:graphic>
<a:graphicData uri="http://schemas.openxmlformats.org/presentationml/2006/ole">
<mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<mc:Choice xmlns:v="urn:schemas-microsoft-com:vml" Requires="v">
<p:oleObj spid="_x0000_s1026" name="工作表" r:id="rId3" imgW="3438630" imgH="2009788" progId="Excel.Sheet.12">
<p:embed />
</p:oleObj>
</mc:Choice>
<mc:Fallback>
<!-- 忽略 -->
</mc:Fallback>
</mc:AlternateContent>
</a:graphicData>
</a:graphic>
</p:graphicFrame>
插入的 rId3 的资源对应的内容如下
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/package" Target="../embeddings/Microsoft_Excel_Worksheet.xlsx" />
</Relationships>
也就是说插入到页面的对应的 xlsx 文件存放路径如下
ppt\embeddings\Microsoft_Excel_Worksheet.xlsx
和读取 OLE 的 xls+ 方式不同的在于不需要读取 OLE 文件拿到 xlsx 文件,只需要通过 Part 读取即可。通过如上代码可以看到在 Slide 页面存放的代码几乎相同,需要加上一点判断逻辑,才能决定是从 Part 读取还是从 OLE 文件读取
通过判断 part.ContentType 是 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" 的内容,即可了解是嵌入 xlsx 文件,而不是 ole 格式文件
读取的逻辑如下
using var presentationDocument = PresentationDocument.Open(file.FullName, false);
var slide = presentationDocument.PresentationPart!.SlideParts.First().Slide;
var graphicFrame = slide.CommonSlideData!.ShapeTree!.GetFirstChild<GraphicFrame>()!;
var graphic = graphicFrame.Graphic!;
var graphicData = graphic.GraphicData!;
var alternateContent = graphicData.GetFirstChild<AlternateContent>()!;
var choice = alternateContent.GetFirstChild<AlternateContentChoice>()!;
var oleObject = choice.GetFirstChild<OleObject>()!;
Debug.Assert(oleObject.GetFirstChild<OleObjectEmbed>() != null);
var id = oleObject.Id!;
var part = slide.SlidePart!.GetPartById(id!);
Debug.Assert(part.ContentType == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
再加上判断当前的 Graphic 期望使用的应用
// 预期字符串是 “Excel.Sheet.12” 等内容
var isEmbedExcel = oleObject.ProgId?.Value?.StartsWith("Excel.Sheet", StringComparison.OrdinalIgnoreCase) is true;
Debug.Assert(isEmbedExcel);
将 Part 读取放入到本地文件,用于后续解析 Xlsx 文件。为什么不能通过 part.GetStream 的方式,对返回的 Stream 进行读取即可?原因是此 Stream 是不支持随机访问的,这个 Stream 是从 System.IO.Packaging 拿到的,为了解决 N 多的坑,设计为不支持随机读取,只能顺序读取。而在解析 Xlsx 时,需要进行随机读取,否则就需要将整个文件内容都加载到内存,为了减少内存的占用,存放到文件
var tempFolder = @"F:\temp";
if (!Directory.Exists(tempFolder))
{
tempFolder = System.IO.Path.GetTempPath();
}
var xlsxFile = System.IO.Path.Combine(tempFolder, System.IO.Path.GetRandomFileName() + ".xlsx");
using (var fileStream = File.OpenWrite(xlsxFile))
{
using var partStream = part.GetStream(FileMode.Open,FileAccess.Read);
partStream.CopyTo(fileStream);
}
后续就是读取 xlsx 的逻辑
using var spreadsheetDocument = SpreadsheetDocument.Open(xlsxFile, false);
var sheets = spreadsheetDocument.WorkbookPart!.Workbook.Sheets;
更多读取 Excel 的方法请看 C# dotnet WPF 使用 OpenXml 解析 Excel 文件
本文以上的测试文件和代码放在github 和 gitee 欢迎访问
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 75c6c17055d7c254e648b7c1836f0657c72fc77a
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
获取代码之后,进入 Pptx 文件夹
更多请看 Office 使用 OpenXML SDK 解析文档博客目录
更多参考:
- [MS-OFFDI].pdf
- [MS-XLS].pdf
- [MS-OI 29500].pdf
dotnet OpenXML 读取 PPT 内嵌 xlsx 格式 Excel 表格的信息的更多相关文章
- dotnet OpenXML 读取 PPT 内嵌 ole 格式 Excel 表格的信息
在 Office 中,可以在 PPT 里面插入表格,插入表格有好多不同的方法,对应 OpenXML 文档存储的更多不同的方式.本文来介绍如何读取 PPT 内嵌 ole 格式的 xls+ 表格的方法 在 ...
- C内嵌汇编-格式
C内嵌汇编-格式: __asm__(汇编语句部分:输出部分:输入部分破坏描述部分);C内嵌汇编以关键字"__asm__"或"asm"开始, 下辖四个部分, 各部 ...
- C# Aspose.Cells导出xlsx格式Excel,打开文件报“Excel 已完成文件级验证和修复。此工作簿的某些部分可能已被修复或丢弃”
报错信息: 最近打开下载的 Excel,会报如下错误.(xls 格式不受影响) 解决方案: 下载代码(红色为新添代码) public void download() { string fileName ...
- PPT内嵌视频(指发布时只需要ppt一个文件即可)
做实验时用手机拍了视频,想把视频嵌入到PPT中.只是单纯的嵌入很容易,但是我想将PPT推送给其他人时,不需要再传视频文件.搜了一下做法,可以通过flash视频格式实现.电脑为thinkpad笔记本,w ...
- C# .NET 使用 NPOI 读取 .xlsx 格式 Excel
string filePath = @"C:\Users\yangqinglin\Desktop\test.xlsx"; IWorkbook wk = null; string e ...
- C# .NET 使用 NPOI 生成 .xlsx 格式 Excel
IWorkbook workbook = new XSSFWorkbook(); ISheet sheet = workbook.CreateSheet("-"); IRow ro ...
- .NET Core的文件系统[4]:由EmbeddedFileProvider构建的内嵌(资源)文件系统
一个物理文件可以直接作为资源内嵌到编译生成的程序集中.借助于EmbeddedFileProvider,我们可以统一的编程方式来读取内嵌于某个程序集中的资源文件,不过在这之前我们必须知道如何将一个项目文 ...
- MongoDB 内嵌文档
MongoDB是文档型的数据库系统,doc是MongoDB的数据单位,每个doc相当于关系型数据库的数据行(row),doc和row的区别在于field的原子性:row中的column是不和分割的原子 ...
- 由EmbeddedFileProvider构建的内嵌(资源)文件系统
由EmbeddedFileProvider构建的内嵌(资源)文件系统 一个物理文件可以直接作为资源内嵌到编译生成的程序集中.借助于EmbeddedFileProvider,我们可以统一的编程方式来读取 ...
- [ASP.NET Core 3框架揭秘] 文件系统[4]:程序集内嵌文件系统
一个物理文件可以直接作为资源内嵌到编译生成的程序集中.借助于EmbeddedFileProvider,我们可以采用统一的编程方式来读取内嵌的资源文件,该类型定义在 "Microsoft.Ex ...
随机推荐
- 关于三维模型OBJ格式轻量化压缩必要性探讨
关于三维模型OBJ格式轻量化压缩必要性探讨 三维模型的OBJ格式轻量化压缩在当前的计算机图形学和虚拟现实应用中具有重要的必要性.以下是对三维模型OBJ格式轻量化压缩必要性的分析: 1.提高加载和传输效 ...
- ArcMap的mxd文件没有数据、显示感叹号怎么办?
本文介绍在ArcMap软件中,导入.mxd地图文档文件后图层出现感叹号.地图显示空白等情况的解决办法. 在ArcMap软件使用过程中,我们经常会需要将包含有多个图层的.mxd地图文档文件导入软 ...
- elementui树形表格分页
效果图 如果你刚好需求中需要如上效果那么只需要吧代码复制过去直接用即可,注意写在nextTick中 前提是vue加elementui 代码如下 /** * 树形表格分页 * @param ...
- HttpWebRequest GetResponse操作超时
request.GetResponse()超时问题的解决 解决办法 1.将http的request的keepAlive设置为false //如果不是必须的要keepalive的,那么就要设置Keep ...
- mybatis调用Oracle存储过程 带游标
存储过程 CREATE OR REPLACE PROCEDURE proc_test2(p_id IN NUMBER, v_cur OUT SYS_REFCURSOR, p_result_code O ...
- Avalonia的Window生命周期
Avalonia中的Window 在Avalonia中,Window是一个基本的UI元素,它代表了一个应用程序的窗口.每个Window都可以包含其他的UI元素,如按钮.文本框等,并可以响应各种用户输入 ...
- #dp,齐肯多夫定理#CF126D Fibonacci Sums
题目 \(T(T\leq 10^5)\) 组数据,每次给定数字 \(n(n\leq 10^{18})\), 问有多少种方案将 \(n\) 分解成若干个互不相同的斐波那契数 分析 如果找到一个方案使得所 ...
- #离线,倒序,线段树#Comet OJ - Contest #15 E 栈的数据结构题
题目 初始时有 \(N\) 个空的栈,编号为 \(1 \sim N\),有以下三种类型的指令: push \(L\) \(R\) \(v\):把编号 \(L \sim R\) 这连续 \(R-L+1\ ...
- #Pollard-Rho,高精度#洛谷 3499 [POI2010]NAJ-Divine Divisor
题目 给定\(m\)个数\(a_i\),令\(n=\prod_{i=1}^m a_i\), 问有多少个大于1的正整数\(d\)满足\(d^{\max k}|n\) 并输出\(\max k\),\(m\ ...
- FastWiki发布`0.2.4`支持js 函数
FastWiki发布0.2.4支持js 函数 Release v0.2.4 · AIDotNet/fast-wiki (github.com) 支持JS动态functioncall调用 支持动态fun ...