我有一个excel 2007文件(OpenXML格式),它与xml文件有连接。此连接生成excel表和数据透视表。
我正在尝试使用OpenXML SDK v2找到一种与Excel中的“全部刷新”按钮相同的方法。这样我就可以在提供新的xml文件后自动更新我的文件。
谢谢。
答案 0 :(得分:11)
对此有很好的解决方法。 使用OpenXML,您可以在数据透视表中打开“打开文件时刷新数据”选项(右键单击数据透视表 - >数据透视表选项 - >数据选项卡)。 当用户首次打开电子表格时,这会导致自动刷新数据透视表。 代码:
using (var document = SpreadsheetDocument.Open(newFilePath, true))
{
var uriPartDictionary = BuildUriPartDictionary(document);
PivotTableCacheDefinitionPart pivotTableCacheDefinitionPart1 = (PivotTableCacheDefinitionPart)uriPartDictionary["/xl/pivotCache/pivotCacheDefinition1.xml"];
PivotCacheDefinition pivotCacheDefinition1 = pivotTableCacheDefinitionPart1.PivotCacheDefinition;
pivotCacheDefinition1.RefreshOnLoad = true;
}
您需要为您的pivotCacheDefinition确定“路径” - 使用OpenXML SDK 2.0 Productivity Tool查找它。
BuildUriPartDictionary 是OpenXML SDK 2.0 Productivity Tool生成的标准方法
protected Dictionary<String, OpenXmlPart> BuildUriPartDictionary(SpreadsheetDocument document)
{
var uriPartDictionary = new Dictionary<String, OpenXmlPart>();
var queue = new Queue<OpenXmlPartContainer>();
queue.Enqueue(document);
while (queue.Count > 0)
{
foreach (var part in queue.Dequeue().Parts.Where(part => !uriPartDictionary.Keys.Contains(part.OpenXmlPart.Uri.ToString())))
{
uriPartDictionary.Add(part.OpenXmlPart.Uri.ToString(), part.OpenXmlPart);
queue.Enqueue(part.OpenXmlPart);
}
}
return uriPartDictionary;
}
另一种解决方案是将您的电子表格转换为macroenabled,并在其中嵌入一个将刷新所有数据透视表的VBA脚本。 这可以在按钮单击时发生,或在用户打开电子表格时再次发生。 在这里,您可以找到VBA代码来刷新数据透视表: http://www.ozgrid.com/VBA/pivot-table-refresh.htm
答案 1 :(得分:2)
我认为你能做到这一点的唯一方法是遵循这种方法..
ThisWorkbook.PivotCaches(yourIndex).Refresh();
或
ThisWorkbook.RefreshAll();
虽然我非常确定RefreshAll也可以使用。
答案 2 :(得分:2)
使用Open XML无法做到这一点。 Open XML允许您处理存储在文件中的数据,并更改数据,公式和定义等。它实际上没有做任何计算。
Excel自动化在技术上是可行的,但绝对不建议用于服务器环境,如果可能的话,最好避免在桌面上使用。
答案 3 :(得分:0)
Bartosz Strutyński提供的解决方案仅在工作簿确实包含数据透视表并且共享相同的缓存时才有效。如果工作簿不包含数据透视表,则代码将引发NullPointerException
。如果工作簿包含使用不同缓存的数据透视表(数据源不同时就是这种情况),则只会刷新使用同一缓存的一组数据透视表。以下是基于Bartosz Strutyński的代码的代码,没有上述限制,并且不依赖于了解PivotCacheDefinition对象的“路径”。该代码还内联了BuildUriPartDictionary,它可以避免在其他地方未使用的情况下枚举uriPartDictionary
的情况,并使用显式类型,以简化搜索使用过的类的文档。
Dictionary<String, OpenXmlPart> uriPartDictionary = new Dictionary<String, OpenXmlPart>();
Queue<OpenXmlPartContainer> queue = new Queue<OpenXmlPartContainer>();
queue.Enqueue(document);
while (queue.Count > 0)
{
foreach (IdPartPair part in queue.Dequeue().Parts.Where(part => !uriPartDictionary.Keys.Contains(part.OpenXmlPart.Uri.ToString())))
{
uriPartDictionary.Add(part.OpenXmlPart.Uri.ToString(), part.OpenXmlPart);
queue.Enqueue(part.OpenXmlPart);
PivotTableCacheDefinitionPart pivotTableCacheDefinitionPart;
if ((pivotTableCacheDefinitionPart = part.OpenXmlPart as PivotTableCacheDefinitionPart) != null)
{
pivotTableCacheDefinitionPart.PivotCacheDefinition.RefreshOnLoad = true;
}
}
}