当第一个单元格为空时,Filehelpers ExcelStorage.ExtractRecords失败

5
当使用ExcelStorage.ExtractRecords导入Excel表格的第一个单元格为空时,该过程会失败。也就是说,如果数据从列1,行2开始,如果单元格(2,1)的值为空,则该方法将失败。
有人知道如何解决这个问题吗?我尝试添加FieldNullValue属性到映射类中,但没有成功。 这里是一个展示有问题代码的示例项目。
希望有人能帮助我或指引我方向。
谢谢!

我并没有真正使用过这个,只是之前看过一下这个库:FieldOptional属性能帮忙吗? - Denis Biondic
3个回答

4

看起来你在使用FileHelpers时遇到了问题。

发生的情况是ExcelStorage.ExtractRecords方法使用空单元格检查来判断是否已经到达工作表的末尾。这可以在ExcelStorage.cs源代码中看到:

while (CellAsString(cRow, mStartColumn) != String.Empty)
{
    try
    {
        recordNumber++;
        Notify(mNotifyHandler, mProgressMode, recordNumber, -1);

        colValues = RowValues(cRow, mStartColumn, RecordFieldCount);

        object record = ValuesToRecord(colValues);
        res.Add(record);

    }
    catch (Exception ex)
    {
        // Code removed for this example
    }
}


如果任何一行的起始列为空,则假定文件已完成。

以下是一些解决方法:

  1. 不要在第一列位置放置任何空单元格。
  2. 不要使用Excel作为文件格式——先转换为CSV。
  3. 查看是否可以从开发人员那里获得补丁或自己修补源代码。

前两个是解决方法(并不是很好)。第三个选项可能是最好的,但什么是文件结束条件?也许整行为空会是一个足够好的检查(但即使如此,这也可能并不总是适用于所有情况)。


谢谢Tuzo!我会尝试修复它,你给了我一些有用的信息。 - Sebastian

4

感谢Tuzo的帮助,我找到了一种解决方法。 我在ExcelStorage类中添加了一个方法来改变while结束条件。不再只查看第一个单元格是否为空值,而是查看当前行中所有单元格是否为空。如果是这种情况,则将false返回给while。这是对ExtractRecords中while部分的更改:

while (!IsEof(cRow, mStartColumn, RecordFieldCount))

代替
while (CellAsString(cRow, mStartColumn) != String.Empty)

IsEof是一种检查整行是否为空的方法:

    private bool IsEof(int row, int startCol, int numberOfCols)
    {
        bool isEmpty = true;
        string cellValue = string.Empty;

        for (int i = startCol; i <= numberOfCols; i++)
        {
            cellValue = CellAsString(row, i);
            if (cellValue != string.Empty)
            {
                isEmpty = false;
                break;
            }
        }

        return isEmpty;
    }

当然,如果用户在两个数据行之间留下空行,则该行之后的行将不会被处理,但我认为继续改进这一点是有好处的。谢谢。

1
谢谢,我已经进一步完善了你的代码。我需要能够跳过空行。 - Antony Scott
这已经被添加到Github上的FileHelpers源代码中。我还提交了另一个更改到FileHelpers ExcelStorage - "允许Excel表包含一个或多个空行,而不会使读取器停在这些行上,直到达到最大值(ExcelReadStopAfterEmptyRows)" 参见:https://github.com/MarcosMeli/FileHelpers/pull/4 - rohancragg

3

我需要能够跳过空行,因此我已经在FileHelpers库中添加了以下代码。我采用了SebastianIsEof代码,并将方法重命名为IsRowEmpty,并更改了ExtractRecords中的循环...

while (CellAsString(cRow, mStartColumn) != String.Empty)

to ...

while (!IsRowEmpty(cRow, mStartColumn, RecordFieldCount) || !IsRowEmpty(cRow+1, mStartColumn, RecordFieldCount))

我随后更改了此代码以使用新的API密钥。

colValues = RowValues(cRow, mStartColumn, RecordFieldCount);

object record = ValuesToRecord(colValues);
res.Add(record);

转换为这个 ...

bool addRow = true;

if (Attribute.GetCustomAttribute(RecordType, typeof(IgnoreEmptyLinesAttribute)) != null && IsRowEmpty(cRow, mStartColumn, RecordFieldCount))
{
    addRow = false;
}

if (addRow)
{
    colValues = RowValues(cRow, mStartColumn, RecordFieldCount);

    object record = ValuesToRecord(colValues);
    res.Add(record);
}

这使我能够跳过单个空行。文件将被读取,直到找到两个连续的空行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接