0

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

我尝试了一些策略:

  • RTF 操作
  • 打开 XML 操作

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

开放式 XML 操作

奇妙的未记录(据我所知)“嵌入源”似乎包含一个复合文档对象,我可以使用它来修改使用 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);
}

问题

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

4

0 回答 0