public void Add(Int32 row, Int32 column, XLCell cell)
        {
            Count++;

            IncrementUsage(RowsUsed, row);
            IncrementUsage(ColumnsUsed, column);

            if (!RowsCollection.TryGetValue(row, out Dictionary <int, XLCell> columnsCollection))
            {
                columnsCollection = new Dictionary <int, XLCell>();
                RowsCollection.Add(row, columnsCollection);
            }
            columnsCollection.Add(column, cell);
            if (row > MaxRowUsed)
            {
                MaxRowUsed = row;
            }
            if (column > MaxColumnUsed)
            {
                MaxColumnUsed = column;
            }

            if (Deleted.TryGetValue(row, out HashSet <int> delHash))
            {
                delHash.Remove(column);
            }
        }
        public int FirstColumnUsed(int rowStart, int columnStart, int rowEnd, int columnEnd, XLCellsUsedOptions options,
                                   Func <IXLCell, Boolean> predicate = null)
        {
            int finalRow        = rowEnd > MaxRowUsed ? MaxRowUsed : rowEnd;
            int finalColumn     = columnEnd > MaxColumnUsed ? MaxColumnUsed : columnEnd;
            int firstColumnUsed = finalColumn;
            var found           = false;

            for (int ro = rowStart; ro <= finalRow; ro++)
            {
                if (RowsCollection.TryGetValue(ro, out Dictionary <Int32, XLCell> columnsCollection))
                {
                    for (int co = columnStart; co <= firstColumnUsed; co++)
                    {
                        if (columnsCollection.TryGetValue(co, out XLCell cell) &&
                            !cell.IsEmpty(options) &&
                            (predicate == null || predicate(cell)) &&
                            co <= firstColumnUsed)
                        {
                            firstColumnUsed = co;
                            found           = true;
                            break;
                        }
                    }
                }
            }

            return(found ? firstColumnUsed : 0);
        }
        public Int32 MaxColumnInRow(Int32 row)
        {
            if (RowsCollection.TryGetValue(row, out Dictionary <Int32, XLCell> columnsCollection) &&
                columnsCollection.Any())
            {
                return(columnsCollection.Keys.Max());
            }

            return(0);
        }
        public Int32 MaxRowInColumn(Int32 column)
        {
            for (int row = MaxRowUsed; row >= 1; row--)
            {
                if (RowsCollection.TryGetValue(row, out Dictionary <Int32, XLCell> columnsCollection) &&
                    columnsCollection.ContainsKey(column))
                {
                    return(row);
                }
            }

            return(0);
        }
        public XLCell GetCell(Int32 row, Int32 column)
        {
            if (row > MaxRowUsed || column > MaxColumnUsed)
            {
                return(null);
            }

            if (RowsCollection.TryGetValue(row, out Dictionary <Int32, XLCell> columnsCollection))
            {
                return(columnsCollection.TryGetValue(column, out XLCell cell) ? cell : null);
            }
            return(null);
        }
 internal IEnumerable <XLCell> GetCells(Func <IXLCell, Boolean> predicate)
 {
     for (int ro = 1; ro <= MaxRowUsed; ro++)
     {
         if (RowsCollection.TryGetValue(ro, out Dictionary <Int32, XLCell> columnsCollection))
         {
             for (int co = 1; co <= MaxColumnUsed; co++)
             {
                 if (columnsCollection.TryGetValue(co, out XLCell cell) &&
                     (predicate == null || predicate(cell)))
                 {
                     yield return(cell);
                 }
             }
         }
     }
 }
        public void Remove(Int32 row, Int32 column)
        {
            Count--;
            var rowRemoved    = DecrementUsage(RowsUsed, row);
            var columnRemoved = DecrementUsage(ColumnsUsed, column);

            if (rowRemoved && row == MaxRowUsed)
            {
                MaxRowUsed = RowsUsed.Keys.Any()
                    ? RowsUsed.Keys.Max()
                    : 0;
            }

            if (columnRemoved && column == MaxColumnUsed)
            {
                MaxColumnUsed = ColumnsUsed.Keys.Any()
                    ? ColumnsUsed.Keys.Max()
                    : 0;
            }

            if (Deleted.TryGetValue(row, out HashSet <Int32> delHash))
            {
                if (!delHash.Contains(column))
                {
                    delHash.Add(column);
                }
            }
            else
            {
                delHash = new HashSet <int>();
                delHash.Add(column);
                Deleted.Add(row, delHash);
            }

            if (RowsCollection.TryGetValue(row, out Dictionary <Int32, XLCell> columnsCollection))
            {
                columnsCollection.Remove(column);
                if (columnsCollection.Count == 0)
                {
                    RowsCollection.Remove(row);
                }
            }
        }
        public IEnumerable <XLSheetPoint> GetSheetPoints(Int32 rowStart, Int32 columnStart,
                                                         Int32 rowEnd, Int32 columnEnd)
        {
            int finalRow    = rowEnd > MaxRowUsed ? MaxRowUsed : rowEnd;
            int finalColumn = columnEnd > MaxColumnUsed ? MaxColumnUsed : columnEnd;

            for (int ro = rowStart; ro <= finalRow; ro++)
            {
                if (RowsCollection.TryGetValue(ro, out Dictionary <Int32, XLCell> columnsCollection))
                {
                    for (int co = columnStart; co <= finalColumn; co++)
                    {
                        if (columnsCollection.ContainsKey(co))
                        {
                            yield return(new XLSheetPoint(ro, co));
                        }
                    }
                }
            }
        }
        public void RemoveAll(Int32 rowStart, Int32 columnStart,
                              Int32 rowEnd, Int32 columnEnd)
        {
            int finalRow    = rowEnd > MaxRowUsed ? MaxRowUsed : rowEnd;
            int finalColumn = columnEnd > MaxColumnUsed ? MaxColumnUsed : columnEnd;

            for (int ro = rowStart; ro <= finalRow; ro++)
            {
                if (RowsCollection.TryGetValue(ro, out Dictionary <int, XLCell> columnsCollection))
                {
                    for (int co = columnStart; co <= finalColumn; co++)
                    {
                        if (columnsCollection.ContainsKey(co))
                        {
                            Remove(ro, co);
                        }
                    }
                }
            }
        }
        internal IEnumerable <XLCell> GetCells(Int32 rowStart, Int32 columnStart,
                                               Int32 rowEnd, Int32 columnEnd,
                                               Func <IXLCell, Boolean> predicate = null)
        {
            int finalRow    = rowEnd > MaxRowUsed ? MaxRowUsed : rowEnd;
            int finalColumn = columnEnd > MaxColumnUsed ? MaxColumnUsed : columnEnd;

            for (int ro = rowStart; ro <= finalRow; ro++)
            {
                if (RowsCollection.TryGetValue(ro, out Dictionary <Int32, XLCell> columnsCollection))
                {
                    for (int co = columnStart; co <= finalColumn; co++)
                    {
                        if (columnsCollection.TryGetValue(co, out XLCell cell) &&
                            (predicate == null || predicate(cell)))
                        {
                            yield return(cell);
                        }
                    }
                }
            }
        }
        public int LastRowUsed(int rowStart, int columnStart, int rowEnd, int columnEnd, XLCellsUsedOptions options,
                               Func <IXLCell, Boolean> predicate = null)
        {
            int finalRow    = rowEnd > MaxRowUsed ? MaxRowUsed : rowEnd;
            int finalColumn = columnEnd > MaxColumnUsed ? MaxColumnUsed : columnEnd;

            for (int ro = finalRow; ro >= rowStart; ro--)
            {
                if (RowsCollection.TryGetValue(ro, out Dictionary <Int32, XLCell> columnsCollection))
                {
                    for (int co = finalColumn; co >= columnStart; co--)
                    {
                        if (columnsCollection.TryGetValue(co, out XLCell cell) &&
                            !cell.IsEmpty(options) &&
                            (predicate == null || predicate(cell)))
                        {
                            return(ro);
                        }
                    }
                }
            }
            return(0);
        }
 public Boolean Contains(Int32 row, Int32 column)
 {
     return(RowsCollection.TryGetValue(row, out Dictionary <Int32, XLCell> columnsCollection) &&
            columnsCollection.ContainsKey(column));
 }