在枚举EPPlus中的范围时,是否始终按以下顺序检索单元格:按行排序,然后按列排序?

时间:2018-05-30 12:17:04

标签: c# excel openxml epplus worksheet

我们说我有以下代码:

using (ExcelPackage package = new ExcelPackage(...))
{
   foreach(var cell in package.Workbook.Worksheets[1].Cells["A1:E5"])
   {
       //do something with "cell"
   }
}

以及以下Excel工作表:

   A      B      C      D      E
1  foo    bar    .      .      .
2  .      .      .      .      .
3  .      .      hello  .      .      
4  .      .      world  .      .
5  .      .      .      .      .

检索到的元素的顺序是否始终为:

foo => bar => hello => world ?

从我到目前为止所做的尝试来看,这似乎总是如此。 但这并不意味着情况总是如此。

似乎Excel在.xlsx文件中依次序列化单元格,即使单元格已按不同顺序编辑。

ExcelWorksheet类中的文档并没有说太多:

//
// Summary:
//     Provides access to a range of cells
public ExcelRange Cells { get; }

1 个答案:

答案 0 :(得分:1)

我回答我自己的问题。

TLTR:在当前的EPPlus版本(v4.5.1)中,给定范围的单元格始终按以下顺序枚举:按行排序,然后按列排序。

通过查看EPPlus implementation我发现了这一点。

给定工作表的单元格存储在.refresh()对象中:

RangeCollection

class ExcelWorksheet { RangeCollection _cells; } 包含单元格列表。此列表始终按RangeCollection排序。 RangeID是行/列/工作表索引的组合。 这允许EPPlus通过执行二进制搜索来快速找到单元格的索引(对于给定的行和列)。

RangeID

在枚举给定范围的单元格时,EPPlus将使用该排序列表枚举范围内的单元格:

class RangeCollection
{
    List<IRangeID> _cells;

    int IndexOf(ulong rangeID)
    {
        return Array.BinarySearch(...);
    }
}

class ExcelCell : IRangeID
{
    ulong RangeID
    {
        get
        {
            return GetCellID(_worksheet.SheetID, Row, Column);
        }
    }

    ulong GetCellID(int SheetID, int row, int col)
    {
        return ((ulong)SheetID) + (((ulong)col) << 15) + (((ulong)row) << 29);
    }
}

class ExcelRange { public bool MoveNext() { _index++; //... if (...) { GetStartIndexEnum(_fromRow, _fromCol, _toRow, _toCol); //... GetNextIndexEnum(_fromRow, _fromCol, _toRow, _toCol); } } object IEnumerator.Current { get { return /*...*/ _worksheet._cells[_index] as ExcelCell /*...*/ } } } GetStartIndexEnum()用于快速跳过当前枚举范围之外的单元格。以与RangeCollection本身相同的顺序检查和枚举单元格,并始终对其进行排序。