我有一个自定义模板,我想在其中控制(尽我所能)文档中可以存在的内容类型。为此,我禁用了控件,并且还截取了粘贴以删除其中一些内容类型,例如图表。我知道这个内容也可以拖放,所以我稍后也会检查它,但我更愿意尽快停止或警告用户。
我尝试了一些策略:
- 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);
}
问题
我究竟做错了什么?这只是一种糟糕/不可行的方法吗?