使用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; }
希望这可以为别人解决一些麻烦
肖恩