我只在 .docx 上下文中使用过 Open XML,但我怀疑您在想更新文档中的一些嵌入字符时遇到了同样的问题。
假设我采用的相同方法对 Power Point 有效,则图表在包含所有文件的 zip 包中具有两个数据点。首先,您有 excel 文件中的数据条目(在 word 文档中将位于 /word/embeddings 中)此外,您还有一个数据缓存,其中包含(出于某种原因)文件中显示的数据缓存xml 格式。(位于 /word/charts 中)为了让您的新数据在文件打开时立即生效,您还需要更新这些文件。
我首先抓住图表部分解决了这个问题
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(name, true))
{
var mainPart = wordDoc.MainDocumentPart; //indlæs hovedpart af dokumentet
DocumentFormat.OpenXml.Packaging.ChartPart[] charts = mainPart.ChartParts.ToArray(); //hent grafer
}
您需要在要编辑的图表上挖掘 DocumentFormat.OpenXml.Drawing 然后隔离 DocumentFormat.OpenXml.Drawing.Charts.ChartReference 从那里您可以获得图表 ID,您可以在 Rels 文件中查找到获取您需要编辑的图表 xml 的路径。
我没有在项目中编写那部分代码,但我可以自由分享这些混乱,所以你去吧。这是从 BookmarkStart 挖掘到 ChartReference 的一种丑陋方式。
[注:RelsRID 是一个以 ID 为键,文件名为值的字典。]
private String grab(BookmarkStart bookmarkStart)
{
//isolate chart
#region grab
var rids = RelsRID;
DocumentFormat.OpenXml.Wordprocessing.Drawing elem = null;
DocumentFormat.OpenXml.Drawing.Charts.ChartReference gd = null;
try
{
elem = bookmarkStart.NextSibling().Elements<Drawing>().ElementAt(0); //første forsøg på at finde vores graf
}
catch (Exception)
{ //forsøg nummer 2
OpenXmlElement testE = bookmarkStart.NextSibling();
while (testE.LocalName.ToLower() != "drawing")
{
testE = testE.NextSibling();
for (int i = 0; i < testE.Elements().Count(); i++)
if (testE.ElementAt(i).LocalName.ToLower() == "drawing") testE = testE.ElementAt(i);
}
elem = (DocumentFormat.OpenXml.Wordprocessing.Drawing)testE;
}
try
{ //first try at grabbing graph data
gd = (DocumentFormat.OpenXml.Drawing.Charts.ChartReference)elem.Inline.Graphic.GraphicData.ElementAt(0);
}
catch (Exception)
{ //second possible route
gd = (DocumentFormat.OpenXml.Drawing.Charts.ChartReference)elem.Anchor.Elements<Graphic>().First().Elements<GraphicData>().First().ElementAt(0);
}
var id = gd.Id;
String matchname = "/word/" + rids[id.ToString()]; //create filepath
#endregion
return matchname;
}
如何处理获取图表 xml 的文件路径取决于您。我真的不赞成这种方式,但它应该让你知道如何处理它。
当你把路径整理好后,你可以做这样的事情(使用我们在第一个代码段中提取的图表
public void EditGraph(BookmarkStart bookmarkStart, DocumentFormat.OpenXml.Packaging.ChartPart[] charts)
{
String check = grab(bookmarkStart);
ChartPart chart = null;
for (int i = 0; i < charts.Count(); i++) //loop th
{
chart = charts[i];
if (check.ToLower().Equals(chart.Uri.ToString().ToLower()))
break;
}
//chart now contains the chart-cache you are looking to edit.
}
您现在可以选择编辑其中包含的数据的方式。我选择从图表中拉出绘图 xml,将其从图表中删除,编辑我拉出的 xml 并将其放回。但我确信您也可以直接使用 open-xml 来完成。你得到这样的情节元素
var plots = chart.ChartSpace.Elements<DocumentFormat.OpenXml.Drawing.Charts.Chart>();
我希望我知道一种更简单的方法来解释它,但这是我能做的最好的事情。
最后,我从来没有真正找到从文档中提取 Rels 的好方法,所以我最终只是跳入 zip 文件并将其拉出。
我像这样构建以前使用的 rels-dictionary
private Dictionary<String, String> RelsRIDToFile()
{
String rels;
using (MemoryStream memory = new MemoryStream())
{
using (ZipFile zip = ZipFile.Read("wordfile.docx"))
{
ZipEntry e = zip["word/_rels/document.xml.rels"];
e.Extract(memory);
}
using (StreamReader reader = new StreamReader(memory))
{
memory.Seek(0, SeekOrigin.Begin);
rels = reader.ReadToEnd();
}
}
XmlDataDocument xml = new XmlDataDocument();
xml.LoadXml(rels);
XmlNodeList xmlnode;
xmlnode = xml.GetElementsByTagName("Relationship");
Dictionary<String, String> result = new Dictionary<string, string>();
for (int i = 0; i < xmlnode.Count; i++)
{
var node = xmlnode[i];
var atts = node.Attributes;
String id = "";
String target = "";
for (int ii = 0; ii < atts.Count; ii++)
{
var att = atts[ii];
if (att.Name.ToLower() == "id") id = att.Value;
if (att.Name.ToLower() == "target") target = att.Value;
}
result[id] = target;
}
return result;
}
祝你好运,如果我能澄清一些事情,请告诉我。