【问题标题】:Modify an Excel PivotTable with a Recordset and Refresh: Exception使用记录集修改 Excel 数据透视表并刷新:异常
【发布时间】:2012-09-30 00:35:03
【问题描述】:

在这里,我正处于我的智慧边缘,花了一整天的时间来尝试做一些不应该如此复杂的事情。

我有一个从 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();

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

谢谢 肖恩

【问题讨论】:

    标签: excel vsto refresh pivot-table recordset


    【解决方案1】:

    好吧,我解决了。似乎一旦RecordsetPivotTable“使用”,您就可以随意修改它,只是不会在Excel 中更新。尽管Recordset 包含数据,但刷新将清空PivotTable 并导致其丢失数据。

    解决方法?创建Recordset 的深层副本(Recordset.Clone() 不起作用),然后将其提供给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();
    

    还有recordset深拷贝的方法(网上C#不好找……)

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

    希望这可以避免其他人头疼...

    肖恩

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-14
      • 2018-12-30
      • 2015-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-16
      相关资源
      最近更新 更多