使用C#.NET向工作表添加“SUMIF”函数后,Excel文件无法读取

时间:2012-02-13 14:56:55

标签: c# excel openxml-sdk

当我尝试将SUMIF公式添加到包含数据的Excel文件时,Excel表示该文件具有“不可读内容”,并询问是否必须尝试恢复该文件的内容。如果我然后单击“是”,它将删除所述公式并打开文件。

当我尝试复制粘贴手动生成的Excel文件中的相同SUMIF公式时,它可以正常工作。当我尝试另一个公式(例如一个简单的“SUM”)时,它可以工作。

有没有人知道可能出现什么问题?

我正在使用OpenXML SDK from Microsoft写入Excel文件。同样,此代码适用于某些公式(例如SUM),但不适用于SUMIF。

/// <summary>
/// Gets or set the cell formula
/// </summary>
public string Formula
    {
        get
        {
            return _cell.CellFormula.Text;
        }
        set
        {
            if(_cell.CellFormula == null) 
                _cell.CellFormula = new CellFormula(); 

            _cell.CellFormula.Text = value;
        } 
    }

编辑:打开Excel文件并检查其中的xml文件后,我发现SUMIF函数的保存方式与SUM函数完全相同(“= SUMIF(J3:J33; L34; N3:N33)”和“= SUM(N3:N33)”,两者都没有引号),因此公式写入文件的方式没有实际区别。

提前致谢!

- 剧透:解决方案是使用“,”而不是“;”在代码中使用公式时。

1 个答案:

答案 0 :(得分:1)

每当我在使用Open XML SDK时出现无法读取的内容错误时,我都会创建一个空白工作表,并将导致错误的部分添加到该工作表中。然后我将使用Open XML SDK 2.0 Productivity Tool来查看幕后生成的内容,并使用它生成的代码来消除不可读的内容错误。

我执行了这些步骤并注意到在添加SUMIF公式时添加了以下内容。首先,您需要使用以下代码将公式添加到单元格中:

    // Creates an Cell instance and adds its children.
    public Cell GenerateCell()
    {
        Cell cell1 = new Cell(){ CellReference = "A1" };
        CellFormula cellFormula1 = new CellFormula();
        cellFormula1.Text = "SUMIF(J3:J33,L34,N3:N33)";
        CellValue cellValue1 = new CellValue();
        cellValue1.Text = "0";

        cell1.Append(cellFormula1);
        cell1.Append(cellValue1);
        return cell1;
    }

这将生成以下XML:

<x:c r="A1" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
  <x:f>SUMIF(J3:J33,L34,N3:N33)</x:f>
  <x:v>0</x:v>
</x:c>

文本值只是求和的结果,在我的情况下为零,因为我定义的范围是空的。

接下来,您需要确保worksheet包含sheetDimension,其定义为:

  

此元素指定工作表的使用范围。它指定   工作表中已使用单元格的行和列边界。这是   可选,不是必需的。使用过的细胞包括配方细胞,   文本内容和单元格格式。格式化整个列时   只考虑该列中的第一个单元格。

代码为我生成的代码是:

 // Creates an SheetDimension instance and adds its children.
 public SheetDimension GenerateSheetDimension()
 {
    SheetDimension sheetDimension1 = new SheetDimension(){ Reference = "A1" };
    return sheetDimension1;
 }

XML看起来像:

<x:dimension ref="A1" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" />

接下来,您需要确保worksheetPart包含calcChainPartcalcChain元素包含calculationCell子元素。

  

此元素表示单个单元格,其中应包含公式,   在计算链中。以与c相同的顺序计算细胞   元素出现在计算链部分中。

这只是告诉excel哪个工作表包含公式以及它应用于哪个单元格。我的代码和XML是:

// Creates an CalculationCell instance and adds its children.
public CalculationCell GenerateCalculationCell()
{
   CalculationCell calculationCell1 = new CalculationCell(){ CellReference = "A1", SheetId = 1 };
   return calculationCell1;
}

<x:c r="A1" i="1" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" />

最后,workbookPart需要一个calculationProperties元素,该元素定义应用程序用于记录计算状态和详细信息的属性集合。计算是计算公式然后在包含公式的单元格中将结果显示为值的过程。

// Creates an CalculationProperties instance and adds its children.
public CalculationProperties GenerateCalculationProperties()
{
   CalculationProperties calculationProperties1 = new CalculationProperties(){ CalculationId = (UInt32Value)125725U };
   return calculationProperties1;
}

<x:calcPr calcId="125725" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" />

正如您所看到的,当您在使用Excel时向单元格添加公式时,会在幕后为您创建所有这些不同的元素和部件。不幸的是,您负责在使用Open XML SDK添加公式时添加必要的元素。很可能Excel文档中缺少其中一个元素,这就是为什么在打开Excel文档时可能会出现无法读取的内容错误的原因。