24

dotnet OpenXML 利用合并表格单元格在 PPT 文档插入不可见的额外版权信息

 3 years ago
source link: https://lindexi.gitee.io/post/dotnet-OpenXML-%E5%88%A9%E7%94%A8%E5%90%88%E5%B9%B6%E8%A1%A8%E6%A0%BC%E5%8D%95%E5%85%83%E6%A0%BC%E5%9C%A8-PPT-%E6%96%87%E6%A1%A3%E6%8F%92%E5%85%A5%E4%B8%8D%E5%8F%AF%E8%A7%81%E7%9A%84%E9%A2%9D%E5%A4%96%E7%89%88%E6%9D%83%E4%BF%A1%E6%81%AF.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
dotnet OpenXML 利用合并表格单元格在 PPT 文档插入不可见的额外版权信息

本文告诉大家如何利用 Office 对于 OpenXML 支持的特性,在 PPT 的表格里面,通过合并单元格存放一些额外的信息,这些信息对用户来说是不可见的,但是进行拷贝表格等的时候,可以保存此信息内容

在开始之前,期望大家已了解很多 OpenXML 知识,详细请看 Office 使用 OpenXML SDK 解析文档博客目录

在 PPT 的表格里面,采用了 RowSpan 用来表示单元格跨行,对应的在下一行的单元格将会被标记 vMerge="1" 表示此单元格被垂直合并。例如我对第一行第一个单元格设置合并单元格,合并行,那么在第二行的第一列的单元格将被标记 vMerge="1" 表示被合并,如下面表格

lindexi%2F2021911931478851.jpg

在 Office 读取 OpenXML 文档,将无视 vMerge="1" 的存在,也就是此属性只是给开发者看的而已,无论是否存在都不会影响到单元格的合并

但事实上,依然可以在标记了 vMerge="1" 的单元格上面添加内容,例如以下有删减的 OpenXML 文档

  <a:tbl>
    <a:tr h="370840">
      <a:tc rowSpan="2">
        <a:txBody>
          <a:bodyPr />
          <a:lstStyle />
          <a:p>
            <a:r>
              <a:rPr lang="en-US" altLang="zh-CN" dirty="0" smtClean="0" />
              <a:t>123123</a:t>
            </a:r>
            <a:endParaRPr lang="zh-CN" altLang="en-US" dirty="0" />
          </a:p>
        </a:txBody>
        <a:tcPr />
      </a:tc>
      <a:tc></a:tc>
    </a:tr>
    <a:tr h="370840">
      <a:tc vMerge="1">
        <a:txBody>
          <a:bodyPr />
          <a:lstStyle />
          <a:p>
            <a:r>
              <a:rPr lang="en-US" altLang="zh-CN" smtClean="0" />
              <a:t>投毒</a:t>
            </a:r>
            <a:endParaRPr lang="zh-CN" altLang="en-US" />
          </a:p>
        </a:txBody>
        <a:tcPr />
      </a:tc>
      <a:tc></a:tc>
    </a:tr>
  </a:tbl>

如上面文档,给了一个单元格写了“投毒”但在 PPT 打开时,是看不到投毒的,如下面界面

lindexi%2F2021911935277223.jpg

以下是此 Office 文档的页面

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
  <p:cSld>
    <p:spTree>
      <p:nvGrpSpPr>
        <p:cNvPr id="1" name="" />
        <p:cNvGrpSpPr />
        <p:nvPr />
      </p:nvGrpSpPr>
      <p:grpSpPr>
        <a:xfrm>
          <a:off x="0" y="0" />
          <a:ext cx="0" cy="0" />
          <a:chOff x="0" y="0" />
          <a:chExt cx="0" cy="0" />
        </a:xfrm>
      </p:grpSpPr>
      <p:graphicFrame>
        <p:nvGraphicFramePr>
          <p:cNvPr id="4" name="表格 3" />
          <p:cNvGraphicFramePr>
            <a:graphicFrameLocks noGrp="1" />
          </p:cNvGraphicFramePr>
          <p:nvPr />
        </p:nvGraphicFramePr>
        <p:xfrm>
          <a:off x="838200" y="1825625" />
          <a:ext cx="8128000" cy="741680" />
        </p:xfrm>
        <a:graphic>
          <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/table">
            <a:tbl>
              <a:tblPr firstRow="1" bandRow="1">
                <a:tableStyleId>{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}</a:tableStyleId>
              </a:tblPr>
              <a:tblGrid>
                <a:gridCol w="4064000">
                  <a:extLst>
                    <a:ext uri="{9D8B030D-6E8A-4147-A177-3AD203B41FA5}">
                      <a16:colId xmlns:a16="http://schemas.microsoft.com/office/drawing/2014/main" val="1394598003" />
                    </a:ext>
                  </a:extLst>
                </a:gridCol>
                <a:gridCol w="4064000">
                  <a:extLst>
                    <a:ext uri="{9D8B030D-6E8A-4147-A177-3AD203B41FA5}">
                      <a16:colId xmlns:a16="http://schemas.microsoft.com/office/drawing/2014/main" val="3643799610" />
                    </a:ext>
                  </a:extLst>
                </a:gridCol>
              </a:tblGrid>
              <a:tr h="370840">
                <a:tc rowSpan="2">
                  <a:txBody>
                    <a:bodyPr />
                    <a:lstStyle />
                    <a:p>
                      <a:r>
                        <a:rPr lang="en-US" altLang="zh-CN" dirty="0" smtClean="0" />
                        <a:t>123123</a:t>
                      </a:r>
                      <a:endParaRPr lang="zh-CN" altLang="en-US" dirty="0" />
                    </a:p>
                  </a:txBody>
                  <a:tcPr />
                </a:tc>
                <a:tc>
                  <a:txBody>
                    <a:bodyPr />
                    <a:lstStyle />
                    <a:p>
                      <a:endParaRPr lang="zh-CN" altLang="en-US" />
                    </a:p>
                  </a:txBody>
                  <a:tcPr />
                </a:tc>
                <a:extLst>
                  <a:ext uri="{0D108BD9-81ED-4DB2-BD59-A6C34878D82A}">
                    <a16:rowId xmlns:a16="http://schemas.microsoft.com/office/drawing/2014/main" val="3287805416" />
                  </a:ext>
                </a:extLst>
              </a:tr>
              <a:tr h="370840">
                <a:tc vMerge="1">
                  <a:txBody>
                    <a:bodyPr />
                    <a:lstStyle />
                    <a:p>
                      <a:r>
                        <a:rPr lang="en-US" altLang="zh-CN" smtClean="0" />
                        <a:t>投毒</a:t>
                      </a:r>
                      <a:endParaRPr lang="zh-CN" altLang="en-US" />
                    </a:p>
                  </a:txBody>
                  <a:tcPr />
                </a:tc>
                <a:tc>
                  <a:txBody>
                    <a:bodyPr />
                    <a:lstStyle />
                    <a:p>
                      <a:endParaRPr lang="zh-CN" altLang="en-US" dirty="0" />
                    </a:p>
                  </a:txBody>
                  <a:tcPr />
                </a:tc>
                <a:extLst>
                  <a:ext uri="{0D108BD9-81ED-4DB2-BD59-A6C34878D82A}">
                    <a16:rowId xmlns:a16="http://schemas.microsoft.com/office/drawing/2014/main" val="3924701140" />
                  </a:ext>
                </a:extLst>
              </a:tr>
            </a:tbl>
          </a:graphicData>
        </a:graphic>
      </p:graphicFrame>
    </p:spTree>
    <p:extLst>
      <p:ext uri="{BB962C8B-B14F-4D97-AF65-F5344CB8AC3E}">
        <p14:creationId xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" val="840519474" />
      </p:ext>
    </p:extLst>
  </p:cSld>
  <p:clrMapOvr>
    <a:masterClrMapping />
  </p:clrMapOvr>
</p:sld>

此时无论是保存还是拷贝表格,都不会丢失 “投毒” 内容。也就是说可以方便的在合并的单元格里面存放一些版权信息,这些版权信息对于用户来说,除非是特意去更改,否则都会放在文档里面

如果忽略合并单元格,通过 WPF 应用读取文档,使用 DataGrid 在界面显示,那么即可拿到合并单元格的内容

            var file = new FileInfo("Test.pptx");

            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 table = graphicData.GetFirstChild<Table>()!; // a:tbl
            /*
               <a:tbl>
                 <a:tr h="370840">
                   <a:tc rowSpan="2">
                     <a:txBody>
                       <a:bodyPr />
                       <a:lstStyle />
                       <a:p>
                         <a:r>
                           <a:rPr lang="en-US" altLang="zh-CN" dirty="0" smtClean="0" />
                           <a:t>123123</a:t>
                         </a:r>
                         <a:endParaRPr lang="zh-CN" altLang="en-US" dirty="0" />
                       </a:p>
                     </a:txBody>
                     <a:tcPr />
                   </a:tc>
                   <a:tc></a:tc>
                 </a:tr>
                 <a:tr h="370840">
                   <a:tc vMerge="1">
                     <a:txBody>
                       <a:bodyPr />
                       <a:lstStyle />
                       <a:p>
                         <a:r>
                           <a:rPr lang="en-US" altLang="zh-CN" smtClean="0" />
                           <a:t>投毒</a:t>
                         </a:r>
                         <a:endParaRPr lang="zh-CN" altLang="en-US" />
                       </a:p>
                     </a:txBody>
                     <a:tcPr />
                   </a:tc>
                   <a:tc></a:tc>
                 </a:tr>
               </a:tbl>
             */

            var dataTable = new DataTable();
            DataGrid.DataContext = dataTable;
            DataGrid.HeadersVisibility = DataGridHeadersVisibility.None;

            var n = 0;
            foreach (var gridColumn in table.TableGrid!.Elements<GridColumn>())
            {
                var emu = new Emu(gridColumn.Width?.Value ?? 95250);

                DataGrid.Columns.Add(new DataGridTextColumn()
                {
                    Width = emu.ToPixel().Value,
                    Binding = new Binding(n.ToString())
                });

                dataTable.Columns.Add(n.ToString());
                n++;
            }

            foreach (var openXmlElement in table)
            {
                // a:tr 表格的行
                if (openXmlElement is TableRow tableRow)
                {
                    var dataRow = dataTable.NewRow();
                    dataTable.Rows.Add(dataRow);

                    var index = 0;
                    foreach (var tableCell in tableRow.Elements<TableCell>())
                    {
                        var text = tableCell.TextBody!.InnerText;
                        dataRow[index.ToString()] = text;

                        index++;
                    }
                }
            }

执行上面代码的界面如下

lindexi%2F2021911940538181.jpg

本文以上的测试文件和代码放在githubgitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin fd6ad246d15db91342476dae7fc841182179726d

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

获取代码之后,进入 Pptx 文件夹

更多请看 Office 使用 OpenXML SDK 解析文档博客目录


本文会经常更新,请阅读原文: https://blog.lindexi.com/post/dotnet-OpenXML-%E5%88%A9%E7%94%A8%E5%90%88%E5%B9%B6%E8%A1%A8%E6%A0%BC%E5%8D%95%E5%85%83%E6%A0%BC%E5%9C%A8-PPT-%E6%96%87%E6%A1%A3%E6%8F%92%E5%85%A5%E4%B8%8D%E5%8F%AF%E8%A7%81%E7%9A%84%E9%A2%9D%E5%A4%96%E7%89%88%E6%9D%83%E4%BF%A1%E6%81%AF.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

如果你想持续阅读我的最新博客,请点击 RSS 订阅,推荐使用RSS Stalker订阅博客,或者前往 CSDN 关注我的主页

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

无盈利,不卖课,做纯粹的技术博客

以下是广告时间

推荐关注 Edi.Wang 的公众号
lindexi%2F201985113622445

欢迎进入 Eleven 老师组建的 .NET 社区
lindexi%2F20209121930471745.jpg

以上广告全是友情推广,无盈利


Recommend

  • 8

    dotnet OpenXML 从文档生成创建文档的代码的库本文和大家介绍 Serialize.OpenXml.CodeGen 这个支持从某个文档生成用于创建出这个文档的 C# 或 VB 代码的库。作用就是可以让小伙伴在拿到一份模版文件之后,可以通过 Serialize.OpenXml.CodeGen 生成能创建出...

  • 9

    dotnet OpenXML 修复 Office 文档里面包含格式不正确的 Uri 而无法解析在使用 OpenXML 解析 Office 文档,无论是 PPT 还是 Word 还是 Excel 文档,都会使用标准方式解析。而此时的文档如果包含了错误的 Url 格式,例如不正确的邮件名的时候,将会在解析的...

  • 11

    dotnet OpenXML 解析 WPS 不符合压缩文档规范的文档我遇到了有老师给我反馈说用我的小工具去辅助编辑课件的时候,遇到了他使用 WPS 制作的文档打开失败,原因是 WPS 制作的一些文档不符合压缩文档规范。而 Office 的基于 ECMA 376 的文档,都是使用标准的...

  • 16

    dotnet OpenXML 解压缩文档为文件夹工具做 Office 解析,是需要进行不断的测试才能了解 OpenXML 里面的属性的作用。根据 Ecma 376 的定义,文档其实只是一个压缩文件,可以使用压缩工具进行解压缩。但是我需要不断进行修改文档里面的属性,然后用 Office...

  • 2

    dotnet OpenXML 读取 PPT 内嵌 ole 格式 Excel 表格的信息在 Office 中,可以在 PPT 里面插入表格,插入表格有好多不同的方法,对应 OpenXML 文档存储的更多不同的方式。本文来介绍如何读取 PPT 内嵌 ole 格式的 xls+ 表格的方法 在 Office...

  • 7

    dotnet OpenXML 获取 Excel 表格当前激活选择的工作表本文告诉大家如何读取 Excel 里面的信息拿到当前激活选择的工作表 在开始之前,期望大家了解如何使用 OpenXML 读取 Excel 文件,如果对此还不了解,请看

  • 5

    dotnet OpenXML 读取 PPT 内嵌 xlsx 格式 Excel 表格的信息在 Office 中,可以在 PPT 里面插入表格,插入表格有好多不同的方法,对应 OpenXML 文档存储的更多不同的方式。本文来介绍如何读取 PPT 内嵌 xlsx 格式的表格的方法 读取方法和

  • 7

    、慕白 posts - 38, comments - 2, trackbacks - 0, articles - 0

  • 4

    电脑EXCEL怎么合并删除列?表格数据快速删除合并单元格 https://www.chenweiliang.com/cwl-29147.html

  • 6

    C#/VB.NET 如何在Word表格中拆分或合并单元格?​​ 精选 原创 我们在使用Word制作表格时,由于表格较为复杂,只是简单的插入行、...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK