我们说我有以下代码:
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; }
答案 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本身相同的顺序检查和枚举单元格,并始终对其进行排序。