Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions main/HSSF/UserModel/HSSFRow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public class HSSFRow : IRow, IComparable<HSSFRow>

private int rowNum;
private Dictionary<int, ICell> cells = new Dictionary<int, ICell>();
private List<ICell> _sortedCellCache;

/**
* reference to low level representation
Expand Down Expand Up @@ -177,7 +178,7 @@ private void RemoveCell(ICell cell, bool alsoRemoveRecords)
((HSSFCell)cell).NotifyArrayFormulaChanging();
}
cells.Remove(column);

_sortedCellCache = null;

if (alsoRemoveRecords)
{
Expand Down Expand Up @@ -402,6 +403,7 @@ private void AddCell(ICell cell)
// Array.Copy(oldCells, 0, cells, 0, oldCells.Length);
//}
cells[column] = cell;
_sortedCellCache = null;

// fix up firstCol and lastCol indexes
if (row.IsEmpty|| column < row.FirstCol)
Expand Down Expand Up @@ -680,7 +682,7 @@ private short FindFirstCell(int firstcell)
public List<ICell> Cells
{
get {
return new List<ICell>(this.cells.Values);
return new List<ICell>(GetSortedCells());
}
}

Expand Down Expand Up @@ -720,7 +722,7 @@ public bool? Collapsed
/// </remarks>
public IEnumerator<ICell> GetEnumerator()
{
return this.cells.Values.GetEnumerator();
return GetSortedCells().GetEnumerator();
}

/// <summary>
Expand Down Expand Up @@ -789,5 +791,14 @@ public bool HasCustomHeight()
{
throw new NotImplementedException();
}

private List<ICell> GetSortedCells()
{
if (_sortedCellCache == null)
{
_sortedCellCache = cells.OrderBy(kv => kv.Key).Select(kv => kv.Value).ToList();
}
return _sortedCellCache;
}
}
}
16 changes: 14 additions & 2 deletions ooxml/XSSF/Streaming/SXSSFRow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class SXSSFRow : IRow, IComparable<SXSSFRow>
{
private readonly SXSSFSheet _sheet; // parent sheet
private readonly Dictionary<int, SXSSFCell> _cells = new Dictionary<int, SXSSFCell>();
private List<ICell> _sortedCellCache;
private short _style = -1; // index of cell style in style table
private bool _zHeight; // row zero-height (this is somehow different than being hidden)
private float _height = -1;
Expand All @@ -53,7 +54,7 @@ public virtual bool HasCustomHeight()

public List<ICell> Cells
{
get { return _cells.Values.Select(cell => (ICell) cell).ToList(); }
get { return new List<ICell>(GetSortedCells()); }
}

public short FirstCellNum
Expand Down Expand Up @@ -235,6 +236,7 @@ public ICell CreateCell(int column, CellType type)
CheckBounds(column);
SXSSFCell cell = new SXSSFCell(this, type);
_cells[column] = cell;
_sortedCellCache = null;
UpdateIndexWhenAdd(column);
return cell;
}
Expand Down Expand Up @@ -299,7 +301,7 @@ public ICell GetCell(int cellnum, MissingCellPolicy policy)
}
public IEnumerator<ICell> GetEnumerator()
{
return _cells.Values.GetEnumerator();
return GetSortedCells().GetEnumerator();
}

public void MoveCell(ICell cell, int newColumn)
Expand All @@ -311,6 +313,7 @@ public void RemoveCell(ICell cell)
{
int index = GetCellIndex((SXSSFCell)cell);
_cells.Remove(index);
_sortedCellCache = null;
if (index == _firstCellNum)
{
InvalidateFirstCellNum();
Expand Down Expand Up @@ -373,6 +376,15 @@ IEnumerator IEnumerable.GetEnumerator()
return this.GetEnumerator();
}

private List<ICell> GetSortedCells()
{
if (_sortedCellCache == null)
{
_sortedCellCache = _cells.OrderBy(kv => kv.Key).Select(kv => (ICell)kv.Value).ToList();
}
return _sortedCellCache;
}

/**
* Create an iterator over the cells from [0, getLastCellNum()).
* Includes blank cells, excludes empty cells
Expand Down
52 changes: 34 additions & 18 deletions ooxml/XSSF/UserModel/XSSFRow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ public class XSSFRow : IRow, IComparable<XSSFRow>
/// Avoids O(n) LINQ Max() scan on every LastCellNum access.
/// </summary>
private int _cachedLastCellNum = -1;

/// <summary>
/// Lazily-built list of cells sorted by column index.
/// Null when invalidated; rebuilt on first read access.
/// </summary>
private List<ICell> _sortedCellCache;
#endregion

#region Public properties
Expand Down Expand Up @@ -561,8 +567,8 @@ public CT_Row GetCTRow()
/// </summary>
internal void OnDocumentWrite()
{
var orderedCells = _cells.OrderBy(kv => kv.Key).Select(kv => (XSSFCell)kv.Value).ToList();
var sortedCells = GetSortedCells();

bool isOrdered = true;
if (_row.SizeOfCArray() != _cells.Count)
{
Expand All @@ -571,9 +577,9 @@ internal void OnDocumentWrite()
else
{
int i = 0;
foreach (XSSFCell cell in orderedCells)
foreach (ICell cell in sortedCells)
{
CT_Cell c1 = cell.GetCTCell();
CT_Cell c1 = ((XSSFCell)cell).GetCTCell();
CT_Cell c2 = _row.GetCArray(i++);

string r1 = c1.r;
Expand All @@ -590,7 +596,7 @@ internal void OnDocumentWrite()
{
CT_Cell[] cArray = new CT_Cell[_cells.Count];
int i = 0;
foreach (XSSFCell c in orderedCells)
foreach (XSSFCell c in sortedCells.Cast<XSSFCell>())
{
cArray[i++] = c.GetCTCell();
}
Expand Down Expand Up @@ -653,28 +659,29 @@ internal void RebuildCells()
_row.c.Sort((col1, col2) => col1.r.CompareTo(col2.r));

// Cache is invalid after rebuild — keys may have changed
_sortedCellCache = null;
_cachedFirstCellNum = -1;
_cachedLastCellNum = -1;
}
#endregion

#region IEnumerable and IComparable members
/// <summary>
/// Cell iterator over the physically defined cell
/// Cell iterator over the physically defined cells, sorted by column index.
/// </summary>
/// <returns>an iterator over cells in this row.</returns>
public Dictionary<int, ICell>.ValueCollection.Enumerator CellIterator()
/// <returns>an iterator over cells in this row in ascending column order.</returns>
public IEnumerator<ICell> CellIterator()
{
return _cells.Values.GetEnumerator();
return GetSortedCells().GetEnumerator();
}

/// <summary>
/// Alias for <see cref="CellIterator"/> to allow foreach loops
/// </summary>
/// <returns>an iterator over cells in this row.</returns>
/// <returns>an iterator over cells in this row in ascending column order.</returns>
public IEnumerator<ICell> GetEnumerator()
{
return _cells.Values.GetEnumerator();
return GetSortedCells().GetEnumerator();
}

/// <summary>
Expand Down Expand Up @@ -723,13 +730,7 @@ public List<ICell> Cells
{
get
{
List<ICell> cells = new List<ICell>();
foreach (ICell cell in _cells.Values)
{
cells.Add(cell);
}

return cells;
return new List<ICell>(GetSortedCells());
}
}

Expand Down Expand Up @@ -836,11 +837,25 @@ private int GetLastKey()
return _cells.Keys.Max();
}

/// <summary>
/// Returns cells sorted by column index, using a lazily-built cache.
/// The cache is invalidated on any cell mutation (add/remove/rebuild).
/// </summary>
private List<ICell> GetSortedCells()
{
if (_sortedCellCache == null)
{
_sortedCellCache = _cells.OrderBy(kv => kv.Key).Select(kv => kv.Value).ToList();
}
return _sortedCellCache;
}

/// <summary>
/// Update cached min/max on cell addition. O(1) — just compare with current bounds.
/// </summary>
private void UpdateCacheOnAdd(int columnIndex)
{
_sortedCellCache = null;
if (_cachedFirstCellNum < 0 || columnIndex < _cachedFirstCellNum)
{
_cachedFirstCellNum = columnIndex;
Expand All @@ -857,6 +872,7 @@ private void UpdateCacheOnAdd(int columnIndex)
/// </summary>
private void InvalidateCacheOnRemove(int removedIndex)
{
_sortedCellCache = null;
if (_cells.Count == 0)
{
_cachedFirstCellNum = -1;
Expand Down
Loading