使用Recordset修改Excel数据透视表并刷新:例外

我在这里处于我的智慧的边缘,并且失去了一整天的时间去做一些不应该那么复杂的事情。

我有一个从Sybase查询返回的logging集。 此logging集用于在Excel中生成数据透视表。 到现在为止还挺好。 我想要更改数据透视表中的值并这样做我使用新值来更新logging集中的某些logging。 我可以在没有任何问题的情况下在RS中进行更新,并在下次迭代时将值保存在RS中。

问题是这些值不会反映在数据透视表中。 我努力了:

  • pivotTable.Refresh();
    • COMException:PivotTable类的RefreshTable方法失败
  • pivotTable.PivotCache().Refresh();
    • ComException:从HRESULTexception:0x800A03EC
  • pivotTable.Update();
    • 没有例外,但是这些更改不会反映在数据透视表中

我也尝试克隆logging集,并创build一个全新的数据透视表,但虽然Recordset有数据, PivotCache.RecordCount为0

码:

 var app = ExcelAppHelper.GetExcelApp(); if (app.ActiveCell == null || app.ActiveCell.PivotTable == null) return; PivotTable pivotTable = app.ActiveCell.PivotTable; var rs = (Recordset)pivotTable.PivotCache().Recordset; rs.MoveFirst(); s_lastSelectedPivotTree = new PivotFilterTree(); RecalculateSelectedValues(vmMain); while (!rs.EOF) { if (s_lastSelectedPivotTree.Contains(rs.Fields)) { foreach (var dataFieldName in s_lastSelectedDataFields) { // update the values in the RS rs.Fields[dataFieldName].Value = newValue; } // commit the modifications into the RS rs.Update(Type.Missing, Type.Missing); } rs.MoveNext(); } rs.MoveFirst(); // here is the magic line that will show me the updated pivot table pivotTable.Update(); 

有人知道如何做到这一点? 修改logging集,然后“刷新”数据透视表,根据logging集重新计算数据透视表。

谢谢肖恩

那我解决了。 看起来,一旦Recordset已被PivotTable “消耗”,你可以修改它所有你想要的,它只是不会在Excel中更新。 尽pipeRecordset包含数据,刷新将清空PivotTable并导致它丢失其数据。

解决方法? 创build一个深层副本(一个Recordset.Clone()将无法工作)的Recordset然后将其提供给PivotTable ,然后每次您要修改其中的值,修改“干净”的副本,做一个新的副本它并将副本传递给PivotTable来使用它。 然后刷新PivotTable

  var newRS = RecordsetDeepCopy(oldRS); newRS.MoveFirst(); oldRS.MoveFirst(); while (!newRS.EOF) { if (s_lastSelectedPivotTree.Contains(newRS.Fields)) { // set the new value in the selected data fields foreach (var dataFieldName in s_lastSelectedDataFields) { oldRS.Fields[dataFieldName].Value = val; newRS.Fields[dataFieldName].Value = val; } newRS.Update(Type.Missing, Type.Missing); oldRS.Update(Type.Missing, Type.Missing); } newRS.MoveNext(); oldRS.MoveNext(); } newRS.MoveFirst(); oldRS.MoveFirst(); pivotCache.Recordset = newRS; pivotCache.Refresh(); 

而logging集深层复制方法(在C#中不容易find网页…)

 private static Recordset RecordsetDeepCopy(Recordset src) { var clone = new Recordset(); int count = src.Fields.Count; var names = new object[count]; int i = 0; foreach (ADODB.Field field in src.Fields) { names[i++] = field.Name; var attr = (FieldAttributeEnum)field.Attributes; clone.Fields._Append(field.Name, field.Type, field.DefinedSize, attr); } clone.Open(Missing.Value, Missing.Value, CursorTypeEnum.adOpenUnspecified, LockTypeEnum.adLockUnspecified, 0); src.MoveFirst(); while (!src.EOF) { var values = new object[count]; i = 0; foreach (ADODB.Field field in src.Fields) { values[i++] = field.Value; } clone.AddNew(names, values); src.MoveNext(); } clone.Update(Missing.Value, Missing.Value); return clone; } 

希望这可以为别人解决一些麻烦

肖恩