3

我在这里不知所措,一整天都在试图做一些不应该那么复杂的事情。

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

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

谢谢肖恩

4

1 回答 1

3

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

解决方法?在将其提供给之前创建一个深层副本(Recordset.Clone()不会起作用),然后每次要修改其中的值时,修改“干净”副本,制作它的新副本并将副本传递给消费它。然后刷新.RecordsetPivotTablePivotTablePivotTable

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

希望这能让其他人感到头疼......

肖恩

于 2012-10-12T12:47:56.683 回答