如何使用Open XML SDK编辑粘贴的内容

时间:2016-05-31 13:03:33

标签: ms-word vsto office-interop openmcdf

我有一个自定义模板,我希望控制(尽我所能)文档中可能存在的内容类型。为此,我禁用了控件,并且还拦截了粘贴以删除其中一些内容类型,例如图表。我知道这个内容也可以拖放,所以我也会稍后检查,但我希望尽快停止或警告用户。

我尝试了一些策略:

  • RTF操作
  • 打开XML操作
到目前为止,RTF操作工作得相当好,但我真的更喜欢使用Open XML,因为我希望它在未来更有用。我无法让它发挥作用。

打开XML操作

奇妙的无证(据我所知)" Embed Source" appears包含复合文档对象,我可以使用它来使用Open XML SDK修改复制的内容。但是我无法将修改后的内容放回到可以正确粘贴的对象中。

修改部分似乎工作正常。我可以看到,如果我将修改后的内容保存到临时的.docx文件中,则表明正在进行更改。回到剪贴板似乎给我带来了麻烦。

我尝试将Embed Source对象重新分配回剪贴板(以便其他类型如RTF被清除),在这种情况下,什么都没有被粘贴。我还尝试将Embed Source对象重新分配回剪贴板的数据对象,以便其余的数据类型仍然存在(但可能包含不匹配的内容),这会导致嵌入的文档为空粘贴。

以下是我在使用Open XML时所做的一些示例:

using OpenMcdf;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

...

object dataObj = Forms.Clipboard.GetDataObject();
object embedSrcObj = dateObj.GetData("Embed Source");
if (embedSrcObj is Stream)
{
  // read it with OpenMCDF

  Stream stream = embedSrcObj as Stream;
  CompoundFile cf = new CompoundFile(stream);
  CFStream cfs = cf.RootStorage.GetStream("package");
  byte[] bytes = cfs.GetData();
  string savedDoc = Path.GetTempFileName() + ".docx";
  File.WriteAllBytes(savedDoc, bytes);

  // And then use the OpenXML SDK to read/edit the document:

  using (WordprocessingDocument openDoc = WordprocessingDocument.Open(savedDoc, true))
  {
    OpenXmlElement body = openDoc.MainDocumentPart.RootElement.ChildElements[0];
    foreach (OpenXmlElement ele in body.ChildElements)
    {
      if (ele is Paragraph)
      {
        Paragraph para = (Paragraph)ele;
        if (para.ParagraphProperties != null && para.ParagraphProperties.ParagraphStyleId != null)
        {
          string styleName = para.ParagraphProperties.ParagraphStyleId.Val;

          Run run = para.LastChild as Run; // I know I'm assuming things here but it's sufficient for a test case
          run.RunProperties = new RunProperties();
          run.RunProperties.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Text("test"));
        }
      }
      // etc.
    }

    openDoc.MainDocumentPart.Document.Save(); // I think this is redundant in later versions than what I'm using
  }

  // repackage the document

  bytes = File.ReadAllBytes(savedDoc);
  cf.RootStorage.Delete("Package");
  cfs = cf.RootStorage.AddStream("Package");
  cfs.Append(bytes);

  MemoryStream ms = new MemoryStream();
  cf.Save(ms);
  ms.Position = 0;

  dataObj.SetData("Embed Source", ms);
  // or,
  // Clipboard.SetData("Embed Source", ms);
}

问题

我做错了什么?这只是一种糟糕/不可行的方法吗?

0 个答案:

没有答案