重新分配单元格值后Excel公式丢失

时间:2011-09-07 03:53:58

标签: c# .net excel interop excel-interop

以下是示例代码

XL.Worksheet worksheet = Globals.ThisAddIn.Application.ActiveSheet;
XL.Range range = worksheet.UsedRange;
arrValue = (object[,])range.get_Value(XL.XlRangeValueDataType.xlRangeValueDefault);

for (int iRow = 1; iRow <= arrValue.GetLength(0); iRow++)
{
    for (int iCol = 1; iCol <= arrValue.GetLength(1); iCol++)
    {
         if (range.Cells[iRow, iCol].Formula != null)
              range.Cells[iRow, iCol].Formula = "=" + kvp.Value.ToString();  // assign underlying formula (kvp is keyValuePair of dictionary) to the cell

         range.Cells[iRow, iCol].Value = evalResults[count].ToString(); // assign value to the cell 
         count++;
    }

} 

我想知道Cells.Value和Cells.Formula是否会互相覆盖。如果我想同时分配它们,那么最好的方法是什么?

感谢。

2 个答案:

答案 0 :(得分:3)

无法将值和公式分配给excel单元格(即使以正常的交互方式使用excel也不能这样做),因为结果将是未定义的,即如果公式的结果与你在单元格中显示的值有什么不同?

由于您希望保留您的公式以供将来重用,您可以使用Recalculate方法应用公式,将它们保存到字典中(并且您已经有类似的东西,不是吗?),然后设置具有当前值的单元格的值(根据公式计算)。
也许这就是你在这里已经做过的事情,但它不是那么清楚,因为我不明白evalResults是什么。无论如何,我的意思是这样的:

private Dictionary<int,Dictionary<int,string>> formulas = new Dictionary<int,Dictionary<int,string>>(); // this has to be initialized according to your formulas
public void Recalculate()
{
    XL.Worksheet worksheet = Globals.ThisAddIn.Application.ActiveSheet;
    XL.Range range = worksheet.UsedRange;

    for (int iRow = 1; iRow <= arrValue.GetLength(0); iRow++)
    {
        for (int iCol = 1; iCol <= arrValue.GetLength(1); iCol++)
        {
            range.Cells[iRow, iCol].Formula = "=" + formulas[iRow][iCol];  
            range.Cells[iRow, iCol].Value = range.Cells[iRow, iCol].Value; 
        }

    }
}

如果你想将公式保存在excel工作簿而不是内存中(在字典中),解决方案可能是有一个隐藏的工作表,你将公式存储为字符串(即没有'=')按顺序避免他们的评估和性能问题。因此,您将拥有与您的代码非常相似的SetFormulas和Recalculate方法:

public void SetFormulas()
{
    XL.Worksheet worksheet = Globals.ThisAddIn.Application.ActiveSheet;
    XL.Worksheet formulasWorksheet = Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets["formulas"];
    XL.Range range = worksheet.UsedRange;
    arrValue = (object[,])range.get_Value(XL.XlRangeValueDataType.xlRangeValueDefault);

    for (int iRow = 1; iRow <= arrValue.GetLength(0); iRow++)
    {
        for (int iCol = 1; iCol <= arrValue.GetLength(1); iCol++)
        {
             if (range.Cells[iRow, iCol].Formula != null)
             {
                  range.Cells[iRow, iCol].Formula = "=" + kvp.Value.ToString();  // assign underlying formula (kvp is keyValuePair of dictionary) to the cell
                  formulasWorksheet.Cells[iRow, iCol].Value = kvp.Value.ToString(); // storing the formula here
             }
             range.Cells[iRow, iCol].Value = evalResults[count].ToString(); // assign value to the cell 
             count++;
        }

    }
}



public void Recalculate()
{
    XL.Worksheet worksheet = Globals.ThisAddIn.Application.ActiveSheet;
    XL.Worksheet formulasWorksheet = Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets["formulas"];
    XL.Range range = worksheet.UsedRange;
    arrValue = (object[,])range.get_Value(XL.XlRangeValueDataType.xlRangeValueDefault);

    for (int iRow = 1; iRow <= arrValue.GetLength(0); iRow++)
    {
        for (int iCol = 1; iCol <= arrValue.GetLength(1); iCol++)
        {
             if (!string.IsNullOrEmpty(formulasWorksheet.Cells[iRow, iCol].Text))
             {
                  range.Cells[iRow, iCol].Formula = "=" + formulasWorksheet.Cells[iRow, iCol].Text; // restoring the formula
                  range.Cells[iRow, iCol].Value = range.Cells[iRow, iCol].Value // replacing the formula with the value
             }
        }

    }
}

答案 1 :(得分:0)

在您的评论中,您说明了您真正关心的问题,即如果自动重新计算单元格公式,性能将受到影响。然后解决方案是防止自动重新计算,即手动重新计算:

Application.Calculation = xlCalculationManual

其中xlCalculationManual是一个等于-4135的内置常量。您可以稍后将其重新设置为xlCalculationAutomatic或-4105。

只需在那里留下公式,不要编辑值,让Excel找出结果。

在手动模式下,用户可以使用 F9 强制重新计算,或者您可以使用Application.Calculate以编程方式执行此操作。

所有这些也可以在Excel用户界面中使用:工具&gt;选项&gt;计算