使用Recordset和Refresh:Exception修改Excel数据透视表

时间:2012-10-09 16:09:53

标签: excel vsto refresh pivot-table recordset

我站在我的智慧的边缘,并且已经失去了整整一天试图做一些不应该那么复杂的事情。

我有一个从Sybase查询返回的Recordset。此记录集用于在Excel中构建数据透视表。到现在为止还挺好。我想更改数据透视表中的值,并执行此操作我使用新值来更新记录集中的某些记录。我可以在没有任何问题的情况下在RS中进行更新,并且下次迭代它时将值保存在RS中。

问题是这些值未反映在数据透视表中。我试过了:

  • pivotTable.Refresh();
    • COMException:数据透视表类的RefreshTable方法失败
  • pivotTable.PivotCache().Refresh();
    • ComException:来自HRESULT的异常:0x800A03EC
  • pivotTable.Update();
    • 没有例外,但更改未反映在数据透视表中

我还尝试克隆记录集并从中创建一个全新的数据透视表,但尽管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();

有人知道怎么做吗?修改记录集,然后“刷新”数据透视表,以根据记录集重新计算数据透视表。

由于 肖恩

1 个答案:

答案 0 :(得分:3)

好吧,我解决了。似乎RecordsetPivotTable“消耗”后,您可以随意修改它,它只是不会在Excel中更新。尽管Recordset包含PivotTable数据,但刷新会清空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();

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;
}

记录集深度复制方法(在Web上不容易在C#中找到...)

{{1}}

希望这会让其他人感到头痛......

肖恩