При перечислении диапазона в EPPlus ячейки всегда извлекаются в следующем порядке: сортировка по строке, а затем по столбцу? - PullRequest
0 голосов
/ 30 мая 2018

Допустим, у меня есть следующий код:

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 голосов
/ 05 июня 2018

Я отвечаю на свой вопрос.

TLTR: в текущей версии EPPlus (v4.5.1) ячейки данного диапазона всегда перечисляются в следующем порядке: сортировка по строке, затем по столбцу.


Я выяснил это, взглянув на реализацию EPPlus .

Ячейки данного листа хранятся в объекте RangeCollection:

class ExcelWorksheet
{
    RangeCollection _cells;
}

RangeCollection содержит список ячеек.Этот список всегда сортируется по RangeID.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);
    }
}

При перечислении ячеек данного диапазона EPPlus будет использовать этот отсортированный список для перечисленияячейки внутри диапазона:

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() и GetNextIndexEnum() используются для быстрого пропуска ячеек, которые находятся за пределами диапазона, перечисленного в настоящее время.Ячейки проверяются и нумеруются в том же порядке, что и сама RangeCollection, которая всегда сортируется.

...