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