Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/EPPlus-4.0.3/CellStore.cs @ 12074

Last change on this file since 12074 was 12074, checked in by sraggl, 9 years ago

#2341: Added EPPlus-4.0.3 to ExtLibs

File size: 71.2 KB
Line 
1/*******************************************************************************
2 * You may amend and distribute as you like, but don't remove this header!
3 *
4 * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
5 * See http://www.codeplex.com/EPPlus for details.
6 *
7 * Copyright (C) 2011  Jan Källman
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
17 * See the GNU Lesser General Public License for more details.
18 *
19 * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
20 * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
21 *
22 * All code and executables are provided "as is" with no warranty either express or implied.
23 * The author accepts no liability for any damage or loss of business that this product may cause.
24 *
25 * Code change notes:
26 *
27 * Author             Change            Date
28 * ******************************************************************************
29 * Jan Källman        Added                   2012-11-25
30 *******************************************************************************/
31using System;
32using System.Collections.Generic;
33using System.Linq;
34using System.Text;
35using System.Collections;
36using OfficeOpenXml;
37    internal class IndexBase : IComparable<IndexBase>
38    {       
39        internal short Index;
40        public int CompareTo(IndexBase other)
41        {
42            return Index < other.Index ? -1 : Index > other.Index ? 1 : 0;
43        }
44    }
45    internal class IndexItem :  IndexBase
46    {
47        internal int IndexPointer
48        {
49            get;
50            set;
51        }
52    }       
53    internal class ColumnIndex : IndexBase, IDisposable
54    {
55        internal IndexBase _searchIx=new IndexBase();
56        public ColumnIndex ()
57      {
58            _pages=new PageIndex[CellStore<int>.PagesPerColumnMin];
59            PageCount=0;
60      }
61        ~ColumnIndex()
62      {
63            _pages=null;           
64      }
65        internal int GetPosition(int Row)
66        {
67            var page = (short)(Row >> CellStore<int>.pageBits);
68            _searchIx.Index = page;
69            var res = Array.BinarySearch(_pages, 0, PageCount, _searchIx);
70            if (res >= 0)
71            {
72                GetPage(Row, ref res);
73                return res;
74            }
75            else
76            {
77                var p = ~res;
78               
79                if (GetPage(Row, ref p))
80                {
81                    return p;
82                }
83                else
84                {
85                    return res;
86                }
87            }
88        }
89
90        private bool GetPage(int Row, ref int res)
91        {
92            if (res < PageCount && _pages[res].MinIndex <= Row && _pages[res].MaxIndex >= Row)
93            {
94                return true;
95            }
96            else
97            {
98                if (res + 1 < PageCount && _pages[res + 1].MinIndex <= Row)
99                {
100                    do
101                    {
102                        res++;
103                    }
104                    while (res + 1 < PageCount && _pages[res + 1].MinIndex <= Row);
105                    //if (res + 1 < PageCount && _pages[res + 1].MaxIndex >= Row)
106                    //{
107                        return true;
108                    //}
109                    //else
110                    //{
111                    //    return false;
112                    //}
113                }
114                else if (res - 1 >= 0 && _pages[res - 1].MaxIndex >= Row)
115                {
116                    do
117                    {
118                        res--;
119                    }
120                    while (res-1 > 0 && _pages[res-1].MaxIndex >= Row);
121                    //if (res > 0)
122                    //{
123                        return true;
124                    //}
125                    //else
126                    //{
127                    //    return false;
128                    //}
129                }
130                return false;
131            }
132        }
133        internal int GetNextRow(int row)
134        {
135            //var page = (int)((ulong)row >> CellStore<int>.pageBits);
136            var p = GetPosition(row);
137            if (p < 0)
138            {
139                p = ~p;
140                if (p >= PageCount)
141                {
142                    return -1;
143                }
144                else
145                {
146
147                    if (_pages[p].IndexOffset + _pages[p].Rows[0].Index < row)
148                    {
149                        if (p + 1 >= PageCount)
150                        {
151                            return -1;
152                        }
153                        else
154                        {
155                            return _pages[p + 1].IndexOffset + _pages[p].Rows[0].Index;
156                        }
157                    }
158                    else
159                    {
160                        return _pages[p].IndexOffset + _pages[p].Rows[0].Index;
161                    }
162                }
163            }
164            else
165            {
166                if (p < PageCount)
167                {
168                    var r = _pages[p].GetNextRow(row);
169                    if (r >= 0)
170                    {
171                        return _pages[p].IndexOffset + _pages[p].Rows[r].Index;
172                    }
173                    else
174                    {
175                        if (++p < PageCount)
176                        {
177                            return _pages[p].IndexOffset + _pages[p].Rows[0].Index;
178                        }
179                        else
180                        {
181                            return -1;
182                        }
183                    }
184                }
185                else
186                {
187                    return -1;
188                }
189            }
190        }
191        internal int FindNext(int Page)
192        {
193            var p = GetPosition(Page);
194            if (p < 0)
195            {
196                return ~p;
197            }
198            return p;
199        }
200        internal PageIndex[] _pages;
201        internal int PageCount;
202
203        public void Dispose()
204        {
205            for (int p = 0; p < PageCount; p++)
206            {
207                ((IDisposable)_pages[p]).Dispose();
208            }
209            _pages = null;
210        }
211
212    }
213    internal class PageIndex : IndexBase, IDisposable
214    {
215        internal IndexBase _searchIx = new IndexBase();
216        public PageIndex()
217      {
218            Rows = new IndexItem[CellStore<int>.PageSizeMin];
219            RowCount = 0;
220      }
221        public PageIndex(IndexItem[] rows, int count)
222        {
223            Rows = rows;
224            RowCount = count;
225        }
226        public PageIndex(PageIndex pageItem, int start, int size)
227            :this(pageItem, start, size, pageItem.Index, pageItem.Offset)
228        {
229
230        }
231        public PageIndex(PageIndex pageItem, int start, int size, short index, int offset)
232        {
233            Rows = new IndexItem[CellStore<int>.GetSize(size)];
234            Array.Copy(pageItem.Rows, start, Rows,0,size);
235            RowCount = size;
236            Index = index;
237            Offset = offset;
238        }
239        ~PageIndex()
240      {
241            Rows=null;
242      }
243        internal int Offset = 0;
244        internal int IndexOffset
245        {
246            get
247            {
248                return IndexExpanded + (int)Offset;
249            }
250        }
251        internal int IndexExpanded
252        {
253            get
254            {
255                return (Index << CellStore<int>.pageBits);
256            }
257        }
258        internal IndexItem[] Rows { get; set; }
259        internal int RowCount;
260
261        internal int GetPosition(int offset)
262        {
263            _searchIx.Index = (short)offset;
264            return Array.BinarySearch(Rows, 0, RowCount, _searchIx);
265        }
266        internal int GetNextRow(int row)
267        {
268            int offset = row - IndexOffset;
269            var o= GetPosition(offset);
270            if (o < 0)
271            {
272                o = ~o;
273                if (o < RowCount)
274                {
275                    return o;
276                }
277                else
278                {
279                    return -1;
280                }
281            }
282            return o;
283        }
284
285        public int MinIndex
286        {
287            get
288            {
289                if (Rows.Length > 0)
290                {
291                    return IndexOffset + Rows[0].Index;
292                }
293                else
294                {
295                    return -1;
296                }
297            }
298        }
299        public int MaxIndex
300        {
301            get
302            {
303                if (RowCount > 0)
304                {
305                    return IndexOffset + Rows[RowCount-1].Index;
306                }
307                else
308                {
309                    return -1;
310                }
311            }
312        }
313        public int GetIndex(int pos)
314        {
315            return IndexOffset + Rows[pos].Index;
316        }
317        public void Dispose()
318        {
319            Rows = null;
320        }
321    }
322    /// <summary>
323    /// This is the store for all Rows, Columns and Cells.
324    /// It is a Dictionary implementation that allows you to change the Key (the RowID, ColumnID or CellID )
325    /// </summary>
326    internal class CellStore<T> : IDisposable// : IEnumerable<ulong>, IEnumerator<ulong>
327    {
328        /**** Size constants ****/
329        internal const int pageBits = 10;   //13bits=8192  Note: Maximum is 13 bits since short is used (PageMax=16K)
330        internal const int PageSize = 1 << pageBits;
331        internal const int PageSizeMin = 1<<10;
332        internal const int PageSizeMax = PageSize << 1; //Double page size
333        internal const int ColSizeMin = 32;
334        internal const int PagesPerColumnMin = 32;
335
336        List<T> _values = new List<T>();
337        internal ColumnIndex[] _columnIndex;
338        internal IndexBase _searchIx = new IndexBase();
339        internal int ColumnCount;
340        public CellStore ()
341      {
342            _columnIndex = new ColumnIndex[ColSizeMin];
343      }
344        ~CellStore()
345      {
346            if (_values != null)
347            {
348                _values.Clear();
349                _values = null;
350            }
351            _columnIndex=null;
352      }
353        internal int GetPosition(int Column)
354        {
355            _searchIx.Index = (short)Column;
356            return Array.BinarySearch(_columnIndex, 0, ColumnCount, _searchIx);
357        }
358        internal CellStore<T> Clone()
359        {
360            int row,col;
361            var ret=new CellStore<T>();
362            for (int c = 0; c < ColumnCount; c++)
363            {
364                col = _columnIndex[c].Index;
365                for (int p = 0;p < _columnIndex[c].PageCount; p++)
366                {
367                    for (int r = 0; r < _columnIndex[c]._pages[p].RowCount; r++)
368                    {
369                        row = _columnIndex[c]._pages[p].IndexOffset + _columnIndex[c]._pages[p].Rows[r].Index;
370                        ret.SetValue(row, col, _values[_columnIndex[c]._pages[p].Rows[r].IndexPointer]);
371                    }
372                }
373            }
374            return ret;
375        }
376        internal int Count
377        {
378            get
379            {
380                int count=0;
381                for (int c = 0; c < ColumnCount; c++)
382                {
383                    for (int p = 0; p < _columnIndex[c].PageCount; p++)
384                    {
385                        count += _columnIndex[c]._pages[p].RowCount;
386                    }
387                }
388                return count;
389            }
390        }
391        internal bool GetDimension(out int fromRow, out int fromCol, out int toRow, out int toCol)
392        {
393            if (ColumnCount == 0)
394            {
395                fromRow = fromCol = toRow = toCol = 0;
396                return false;
397            }
398            else
399            {
400                fromCol=_columnIndex[0].Index;
401                var fromIndex = 0;
402                if (fromCol <= 0 && ColumnCount > 1)
403                {
404                    fromCol = _columnIndex[1].Index;
405                    fromIndex = 1;
406                }
407                else if(ColumnCount == 1 && fromCol <= 0)
408                {
409                    fromRow = fromCol = toRow = toCol = 0;
410                    return false;
411                }
412                var col = ColumnCount - 1;
413                while (col > 0)
414                {
415                    if (_columnIndex[col].PageCount == 0 || _columnIndex[col]._pages[0].RowCount > 1 || _columnIndex[col]._pages[0].Rows[0].Index > 0)
416                    {
417                        break;
418                    }
419                    col--;
420                }
421                toCol=_columnIndex[col].Index;
422                if (toCol == 0)
423                {
424                    fromRow = fromCol = toRow = toCol = 0;
425                    return false;                   
426                }
427                fromRow = toRow= 0;
428
429                for (int c = fromIndex; c < ColumnCount; c++)
430                {                   
431                    int first, last;
432                    if (_columnIndex[c].PageCount == 0) continue;                   
433                    if (_columnIndex[c]._pages[0].RowCount > 0 && _columnIndex[c]._pages[0].Rows[0].Index > 0)
434                    {
435                        first = _columnIndex[c]._pages[0].IndexOffset + _columnIndex[c]._pages[0].Rows[0].Index;
436                    }
437                    else
438                    {
439                        if(_columnIndex[c]._pages[0].RowCount>1)
440                        {
441                            first = _columnIndex[c]._pages[0].IndexOffset + _columnIndex[c]._pages[0].Rows[1].Index;
442                        }
443                        else if (_columnIndex[c].PageCount > 1)
444                        {
445                            first = _columnIndex[c]._pages[0].IndexOffset + _columnIndex[c]._pages[1].Rows[0].Index;
446                        }
447                        else
448                        {
449                            first = 0;
450                        }
451                    }
452                    var lp = _columnIndex[c].PageCount - 1;
453                    while(_columnIndex[c]._pages[lp].RowCount==0 && lp!=0)
454                    {
455                        lp--;
456                    }
457                    var p = _columnIndex[c]._pages[lp];
458                    if (p.RowCount > 0)
459                    {
460                        last = p.IndexOffset + p.Rows[p.RowCount - 1].Index;
461                    }
462                    else
463                    {
464                        last = first;
465                    }
466                    if (first > 0 && (first < fromRow || fromRow == 0))
467                    {
468                        fromRow=first;
469                    }
470                    if (first>0 && (last > toRow || toRow == 0))
471                    {
472                        toRow=last;
473                    }
474                }
475                if (fromRow <= 0 || toRow <= 0)
476                {
477                    fromRow = fromCol = toRow = toCol = 0;
478                    return false;
479                }
480                else
481                {
482                    return true;
483                }
484            }
485        }
486        internal int FindNext(int Column)
487        {
488            var c = GetPosition(Column);
489            if (c < 0)
490            {
491                return ~c;
492            }
493            return c;
494        }
495        internal T GetValue(int Row, int Column)
496        {
497            int i = GetPointer(Row, Column);
498            if (i >= 0)
499            {
500                return _values[i];
501            }
502            else
503            {
504                return default(T);               
505            }
506            //var col = GetPosition(Column);
507            //if (col >= 0) 
508            //{
509            //    var pos = _columnIndex[col].GetPosition(Row);
510            //    if (pos >= 0)
511            //    {
512            //        var pageItem = _columnIndex[col].Pages[pos];
513            //        if (pageItem.MinIndex > Row)
514            //        {
515            //            pos--;
516            //            if (pos < 0)
517            //            {
518            //                return default(T);
519            //            }
520            //            else
521            //            {
522            //                pageItem = _columnIndex[col].Pages[pos];
523            //            }
524            //        }
525            //        short ix = (short)(Row - pageItem.IndexOffset);
526            //        var cellPos = Array.BinarySearch(pageItem.Rows, 0, pageItem.RowCount, new IndexBase() { Index = ix });
527            //        if (cellPos >= 0)
528            //        {
529            //            return _values[pageItem.Rows[cellPos].IndexPointer];
530            //        }
531            //        else //Cell does not exist
532            //        {
533            //            return default(T);
534            //        }
535            //    }
536            //    else //Page does not exist
537            //    {
538            //        return default(T);
539            //    }
540            //}
541            //else //Column does not exist
542            //{
543            //    return default(T);
544            //}
545        }
546        int GetPointer(int Row, int Column)
547        {
548            var col = GetPosition(Column);
549            if (col >= 0)
550            {
551                var pos = _columnIndex[col].GetPosition(Row);
552                if (pos >= 0 && pos < _columnIndex[col].PageCount)
553                {
554                    var pageItem = _columnIndex[col]._pages[pos];
555                    if (pageItem.MinIndex > Row)
556                    {
557                        pos--;
558                        if (pos < 0)
559                        {
560                            return -1;
561                        }
562                        else
563                        {
564                            pageItem = _columnIndex[col]._pages[pos];
565                        }
566                    }
567                    short ix = (short)(Row - pageItem.IndexOffset);
568                    _searchIx.Index = ix;
569                    var cellPos = Array.BinarySearch(pageItem.Rows, 0, pageItem.RowCount, _searchIx);
570                    if (cellPos >= 0)
571                    {
572                        return pageItem.Rows[cellPos].IndexPointer;
573                    }
574                    else //Cell does not exist
575                    {
576                        return -1;
577                    }
578                }
579                else //Page does not exist
580                {
581                    return -1;
582                }
583            }
584            else //Column does not exist
585            {
586                return -1;
587            }
588        }
589        internal bool Exists(int Row,int Column)
590        {
591            return GetPointer(Row, Column)>=0;
592        }
593        internal bool Exists(int Row, int Column, ref T value)
594        {
595            var p=GetPointer(Row, Column);
596            if (p >= 0)
597            {
598                value = _values[p];
599                return true;
600            }
601            else
602            {               
603                return false;
604            }
605        }
606        internal void SetValue(int Row, int Column, T Value)
607        {
608            lock (_columnIndex)
609            {
610                var col = Array.BinarySearch(_columnIndex, 0, ColumnCount, new IndexBase() { Index = (short)(Column) });
611                var page = (short)(Row >> pageBits);
612                if (col >= 0)
613                {
614                    //var pos = Array.BinarySearch(_columnIndex[col].Pages, 0, _columnIndex[col].Count, new IndexBase() { Index = page });
615                    var pos = _columnIndex[col].GetPosition(Row);
616                    if (pos < 0)
617                    {
618                        pos = ~pos;
619                        if (pos - 1 < 0 || _columnIndex[col]._pages[pos - 1].IndexOffset + PageSize - 1 < Row)
620                        {
621                            AddPage(_columnIndex[col], pos, page);
622                        }
623                        else
624                        {
625                            pos--;
626                        }
627                    }
628                    if (pos >= _columnIndex[col].PageCount)
629                    {
630                        AddPage(_columnIndex[col], pos, page);
631                    }
632                    var pageItem = _columnIndex[col]._pages[pos];
633                    if (pageItem.IndexOffset > Row)
634                    {
635                        pos--;
636                        page--;
637                        if (pos < 0)
638                        {
639                            throw (new Exception("Unexpected error when setting value"));
640                        }
641                        pageItem = _columnIndex[col]._pages[pos];
642                    }
643
644                    short ix = (short)(Row - ((pageItem.Index << pageBits) + pageItem.Offset));
645                    _searchIx.Index = ix;
646                    var cellPos = Array.BinarySearch(pageItem.Rows, 0, pageItem.RowCount, _searchIx);
647                    if (cellPos < 0)
648                    {
649                        cellPos = ~cellPos;
650                        AddCell(_columnIndex[col], pos, cellPos, ix, Value);
651                    }
652                    else
653                    {
654                        _values[pageItem.Rows[cellPos].IndexPointer] = Value;
655                    }
656                }
657                else //Column does not exist
658                {
659                    col = ~col;
660                    AddColumn(col, Column);
661                    AddPage(_columnIndex[col], 0, page);
662                    short ix = (short)(Row - (page << pageBits));
663                    AddCell(_columnIndex[col], 0, 0, ix, Value);
664                }
665            }
666        }
667
668        internal void Insert(int fromRow, int fromCol, int rows, int columns)
669        {
670            lock (_columnIndex)
671            {
672
673                if (columns > 0)
674                {
675                    var col = GetPosition(fromCol);
676                    if (col < 0)
677                    {
678                        col = ~col;
679                    }
680                    for (var c = col; c < ColumnCount; c++)
681                    {
682                        _columnIndex[c].Index += (short)columns;
683                    }
684                }
685                else
686                {
687                    var page = fromRow >> pageBits;
688                    for (int c = 0; c < ColumnCount; c++)
689                    {
690                        var column = _columnIndex[c];
691                        var pagePos = column.GetPosition(fromRow);
692                        if (pagePos >= 0)
693                        {
694                            if (fromRow >= column._pages[pagePos].MinIndex && fromRow <= column._pages[pagePos].MaxIndex) //The row is inside the page
695                            {
696                                int offset = fromRow - column._pages[pagePos].IndexOffset;
697                                var rowPos = column._pages[pagePos].GetPosition(offset);
698                                if (rowPos < 0)
699                                {
700                                    rowPos = ~rowPos;
701                                }
702                                UpdateIndexOffset(column, pagePos, rowPos, fromRow, rows);
703                            }
704                            else if (column._pages[pagePos].MinIndex > fromRow - 1 && pagePos > 0) //The row is on the page before.
705                            {
706                                int offset = fromRow - ((page - 1) << pageBits);
707                                var rowPos = column._pages[pagePos - 1].GetPosition(offset);
708                                if (rowPos > 0 && pagePos > 0)
709                                {
710                                    UpdateIndexOffset(column, pagePos - 1, rowPos, fromRow, rows);
711                                }
712                            }
713                            else if (column.PageCount >= pagePos + 1)
714                            {
715                                int offset = fromRow - column._pages[pagePos].IndexOffset;
716                                var rowPos = column._pages[pagePos].GetPosition(offset);
717                                if (rowPos < 0)
718                                {
719                                    rowPos = ~rowPos;
720                                }
721                                if (column._pages[pagePos].RowCount > rowPos)
722                                {
723                                    UpdateIndexOffset(column, pagePos, rowPos, fromRow, rows);
724                                }
725                                else
726                                {
727                                    UpdateIndexOffset(column, pagePos + 1, 0, fromRow, rows);
728                                }
729                            }
730                        }
731                        else
732                        {
733                            UpdateIndexOffset(column, ~pagePos, 0, fromRow, rows);
734                        }
735                    }
736                }
737            }
738        }
739        internal void Clear(int fromRow, int fromCol, int rows, int columns)
740        {
741            Delete(fromRow, fromCol, rows, columns, false);
742        }
743        internal void Delete(int fromRow, int fromCol, int rows, int columns)
744        {
745            Delete(fromRow, fromCol, rows, columns, true);
746        }
747        internal void Delete(int fromRow, int fromCol, int rows, int columns, bool shift)
748        {
749            lock (_columnIndex)
750            {
751                if (columns > 0 && fromRow == 1 && rows >= ExcelPackage.MaxRows)
752                {
753                    DeleteColumns(fromCol, columns, shift);
754                }
755                else
756                {
757                    var toCol = fromCol + columns - 1;
758                    var pageFromRow = fromRow >> pageBits;
759                    for (int c = 0; c < ColumnCount; c++)
760                    {
761                        var column = _columnIndex[c];
762                        if (column.Index >= fromCol)
763                        {
764                            if (column.Index > toCol) break;
765                            var pagePos = column.GetPosition(fromRow);
766                            if (pagePos < 0) pagePos = ~pagePos;
767                            if (pagePos < column.PageCount)
768                            {
769                                var page = column._pages[pagePos];
770                                if (shift && page.RowCount > 0 && page.MinIndex > fromRow && page.MaxIndex >= fromRow + rows)
771                                {
772                                    var o=page.MinIndex - fromRow;
773                                    if (o < rows)
774                                    {
775                                        rows -= o;
776                                        page.Offset -= o;
777                                        UpdatePageOffset(column, pagePos, o);
778                                    }
779                                    else
780                                    {
781                                        page.Offset -= rows;
782                                        UpdatePageOffset(column, pagePos, rows);
783                                        continue;
784                                    }
785                                }
786                                if (page.RowCount > 0 && page.MinIndex <= fromRow+rows-1 && page.MaxIndex >= fromRow) //The row is inside the page
787                                {
788                                    var endRow = fromRow + rows;
789                                    var delEndRow = DeleteCells(column._pages[pagePos], fromRow, endRow, shift);
790                                    if (shift && delEndRow != fromRow) UpdatePageOffset(column, pagePos, delEndRow - fromRow);
791                                    if (endRow > delEndRow && pagePos < column.PageCount && column._pages[pagePos].MinIndex < endRow)
792                                    {
793                                        pagePos = (delEndRow == fromRow ? pagePos : pagePos + 1);
794                                        var rowsLeft = DeletePage(fromRow, endRow - delEndRow, column, pagePos);
795                                        //if (shift) UpdatePageOffset(column, pagePos, endRow - fromRow - rowsLeft);
796                                        if (rowsLeft > 0)
797                                        {
798                                            pagePos = column.GetPosition(fromRow);
799                                            delEndRow = DeleteCells(column._pages[pagePos], fromRow, fromRow + rowsLeft, shift);
800                                            if (shift) UpdatePageOffset(column, pagePos, rowsLeft);
801                                        }
802                                    }
803                                }
804                                else if (pagePos > 0 && column._pages[pagePos].IndexOffset > fromRow) //The row is on the page before.
805                                {
806                                    int offset = fromRow + rows - 1 - ((pageFromRow - 1) << pageBits);
807                                    var rowPos = column._pages[pagePos - 1].GetPosition(offset);
808                                    if (rowPos > 0 && pagePos > 0)
809                                    {
810                                        if (shift) UpdateIndexOffset(column, pagePos - 1, rowPos, fromRow + rows - 1, -rows);
811                                    }
812                                }
813                                else
814                                {
815                                    if (shift && pagePos + 1 < column.PageCount) UpdateIndexOffset(column, pagePos + 1, 0, column._pages[pagePos + 1].MinIndex, -rows);
816                                }
817                            }
818                        }
819                    }
820                }
821            }
822        }
823        private void UpdatePageOffset(ColumnIndex column, int pagePos, int rows)
824        {
825            //Update Pageoffset
826           
827            if (++pagePos < column.PageCount)
828            {
829                for (int p = pagePos; p < column.PageCount; p++)
830                {
831                    if (column._pages[p].Offset - rows <= -PageSize)
832                    {
833                        column._pages[p].Index--;
834                        column._pages[p].Offset -= rows-PageSize;
835                    }
836                    else
837                    {
838                        column._pages[p].Offset -= rows;
839                    }
840                }
841
842                if (Math.Abs(column._pages[pagePos].Offset) > PageSize ||
843                    Math.Abs(column._pages[pagePos].Rows[column._pages[pagePos].RowCount-1].Index) > PageSizeMax) //Split or Merge???
844                {
845                    rows=ResetPageOffset(column, pagePos, rows);
846                    ////MergePages
847                    //if (column.Pages[pagePos - 1].Index + 1 == column.Pages[pagePos].Index)
848                    //{
849                    //    if (column.Pages[pagePos].IndexOffset + column.Pages[pagePos].Rows[column.Pages[pagePos].RowCount - 1].Index + rows -
850                    //        column.Pages[pagePos - 1].IndexOffset + column.Pages[pagePos - 1].Rows[0].Index <= PageSize)
851                    //    {
852                    //        //Merge
853                    //        MergePage(column, pagePos - 1, -rows);
854                    //    }
855                    //    else
856                    //    {
857                    //        //Split
858                    //    }
859                    //}
860                    //rows -= PageSize;
861                    //for (int p = pagePos; p < column.PageCount; p++)
862                    //{                           
863                    //    column.Pages[p].Index -= 1;
864                    //}
865                    return;
866                }
867            }
868        }
869
870        private int ResetPageOffset(ColumnIndex column, int pagePos, int rows)
871        {
872            PageIndex fromPage=column._pages[pagePos];
873            PageIndex toPage;
874            short pageAdd = 0;
875            if (fromPage.Offset < -PageSize)
876            {
877                toPage=column._pages[pagePos-1];
878                pageAdd = -1;
879                if (fromPage.Index - 1 == toPage.Index)
880                {
881                    if (fromPage.IndexOffset + fromPage.Rows[fromPage.RowCount - 1].Index -
882                        toPage.IndexOffset + toPage.Rows[0].Index <= PageSizeMax)
883                    {
884                        MergePage(column, pagePos - 1);
885                        //var newPage = new PageIndex(toPage, 0, GetSize(fromPage.RowCount + toPage.RowCount));
886                        //newPage.RowCount = fromPage.RowCount + fromPage.RowCount;
887                        //Array.Copy(toPage.Rows, 0, newPage.Rows, 0, toPage.RowCount);
888                        //Array.Copy(fromPage.Rows, 0, newPage.Rows, toPage.RowCount, fromPage.RowCount);
889                        //for (int r = toPage.RowCount; r < newPage.RowCount; r++)
890                        //{
891                        //    newPage.Rows[r].Index += (short)(fromPage.IndexOffset - toPage.IndexOffset);
892                        //}
893                       
894                    }
895                }
896                else //No page after
897                {
898                    fromPage.Index -= pageAdd;
899                    fromPage.Offset += PageSize;
900                }
901            }
902            else if (fromPage.Offset > PageSize)
903            {
904                toPage = column._pages[pagePos + 1];
905                pageAdd = 1;
906                if (fromPage.Index + 1 == toPage.Index)
907                {
908
909                }
910                else
911                {
912                    fromPage.Index += pageAdd;
913                    fromPage.Offset += PageSize;
914                }
915            }
916            return rows;
917        }
918
919        private int DeletePage(int fromRow, int rows, ColumnIndex column, int pagePos)
920        {
921            PageIndex page = column._pages[pagePos];
922            while (page != null && page.MinIndex >= fromRow && page.MaxIndex < fromRow + rows)
923            {
924                //Delete entire page.
925                var delSize=page.MaxIndex - page.MinIndex+1;
926                rows -= delSize;
927                var prevOffset = page.Offset;
928                Array.Copy(column._pages, pagePos + 1, column._pages, pagePos, column.PageCount - pagePos + 1);
929                column.PageCount--;
930                if (column.PageCount == 0)
931                {
932                    return 0;
933                }
934                else
935                {
936                    for (int i = pagePos; i < column.PageCount; i++)
937                    {
938                        column._pages[i].Offset -= delSize;
939                        if (column._pages[i].Offset <= -PageSize)
940                        {
941                            column._pages[i].Index--;
942                            column._pages[i].Offset += PageSize;
943                        }
944                    }
945                }               
946                if (column.PageCount > pagePos)
947                {
948                    page = column._pages[pagePos];
949                    //page.Offset = pagePos == 0 ? 1 : prevOffset;  //First page can only reference to rows starting from Index == 1
950                }
951                else
952                {
953                    //No more pages, return 0
954                    return 0;
955                }
956            }
957            return rows;
958        }
959        ///
960        private int DeleteCells(PageIndex page,  int fromRow, int toRow, bool shift)
961        {
962            var fromPos = page.GetPosition(fromRow - (page.IndexOffset));
963            if (fromPos < 0)
964            {
965                fromPos = ~fromPos;
966            }
967            var maxRow = page.MaxIndex;
968            var offset = toRow - page.IndexOffset;
969            if (offset > PageSizeMax) offset = PageSizeMax;
970            var toPos = page.GetPosition(offset);
971            if (toPos < 0)
972            {
973                toPos = ~toPos;
974            }
975
976            if (fromPos <= toPos && fromPos < page.RowCount && page.GetIndex(fromPos) < toRow)
977            {
978                if (toRow > page.MaxIndex)
979                {
980                    if (fromRow == page.MinIndex) //Delete entire page, late in the page delete method
981                    {
982                        return fromRow;
983                    }
984                    var r = page.MaxIndex;
985                    var deletedRow = page.RowCount - fromPos;
986                    page.RowCount -= deletedRow;
987                    return r+1;
988                }
989                else
990                {
991                    var rows = toRow - fromRow;
992                    if(shift) UpdateRowIndex(page, toPos, rows);
993                    Array.Copy(page.Rows, toPos, page.Rows, fromPos, page.RowCount - toPos);
994                    page.RowCount -= toPos-fromPos;
995
996                    return toRow;
997                }
998            }
999            else if(shift)
1000            {
1001                UpdateRowIndex(page, toPos, toRow - fromRow);
1002            }
1003            return toRow < maxRow ? toRow : maxRow;
1004        }
1005
1006        private static void UpdateRowIndex(PageIndex page, int toPos, int rows)
1007        {
1008            for (int r = toPos; r < page.RowCount; r++)
1009            {
1010                page.Rows[r].Index -= (short) rows;
1011            }
1012        }
1013
1014        private void DeleteColumns(int fromCol, int columns, bool shift)
1015        {
1016            var fPos = GetPosition(fromCol);
1017            if (fPos < 0)
1018            {
1019                fPos = ~fPos;
1020            }
1021            int tPos = fPos;
1022            for (var c = fPos; c <= ColumnCount; c++)
1023            {
1024                tPos = c;
1025                if (tPos==ColumnCount || _columnIndex[c].Index >= fromCol + columns)
1026                {
1027                    break;
1028                }
1029            }
1030
1031            if (ColumnCount <= fPos)
1032            {
1033                return;
1034            }
1035
1036            if (_columnIndex[fPos].Index >= fromCol && _columnIndex[fPos].Index <= fromCol + columns)
1037            {
1038                //if (_columnIndex[fPos].Index < ColumnCount)
1039                //{
1040                    if (tPos < ColumnCount)
1041                    {
1042                        Array.Copy(_columnIndex, tPos, _columnIndex, fPos, ColumnCount - tPos);
1043                    }
1044                    ColumnCount -= (tPos - fPos);
1045                //}
1046            }
1047            if (shift)
1048            {
1049                for (var c = fPos; c < ColumnCount; c++)
1050                {
1051                    _columnIndex[c].Index -= (short)columns;
1052                }
1053            }
1054        }
1055
1056        private void UpdateIndexOffset(ColumnIndex column, int pagePos, int rowPos, int row, int rows)
1057        {
1058            if (pagePos >= column.PageCount) return;    //A page after last cell.
1059            var page = column._pages[pagePos];
1060            if (rows > PageSize)
1061            {
1062                short addPages = (short)(rows >> pageBits);
1063                int offset = +(int)(rows - (PageSize*addPages));
1064                for (int p = pagePos + 1; p < column.PageCount; p++)
1065                {
1066                    if (column._pages[p].Offset + offset > PageSize)
1067                    {
1068                        column._pages[p].Index += (short)(addPages + 1);
1069                        column._pages[p].Offset += offset - PageSize;
1070                    }
1071                    else
1072                    {
1073                        column._pages[p].Index += addPages;
1074                        column._pages[p].Offset += offset;
1075                    }
1076                   
1077                }
1078
1079                var size = page.RowCount - rowPos;
1080                if (page.RowCount > rowPos)
1081                {
1082                    if (column.PageCount-1 == pagePos) //No page after, create a new one.
1083                    {
1084                        //Copy rows to next page.
1085                        var newPage = CopyNew(page, rowPos, size);
1086                        newPage.Index = (short)((row + rows) >> pageBits);
1087                        newPage.Offset = row + rows - (newPage.Index * PageSize) - newPage.Rows[0].Index;
1088                        if (newPage.Offset > PageSize)
1089                        {
1090                            newPage.Index++;
1091                            newPage.Offset -= PageSize;
1092                        }
1093                        AddPage(column, pagePos + 1, newPage);
1094                        page.RowCount = rowPos;
1095                    }
1096                    else
1097                    {
1098                        if (column._pages[pagePos + 1].RowCount + size > PageSizeMax) //Split Page
1099                        {
1100                            SplitPageInsert(column,pagePos, rowPos, rows, size, addPages);
1101                        }
1102                        else //Copy Page.
1103                        {
1104                            CopyMergePage(page, rowPos, rows, size, column._pages[pagePos + 1]);                           
1105                        }
1106                    }
1107                }
1108            }
1109            else
1110            {
1111                //Add to Pages.
1112                for (int r = rowPos; r < page.RowCount; r++)
1113                {
1114                    page.Rows[r].Index += (short)rows;
1115                }
1116                if (page.Offset + page.Rows[page.RowCount-1].Index >= PageSizeMax)   //Can not be larger than the max size of the page.
1117                {
1118                    AdjustIndex(column, pagePos);
1119                    if (page.Offset + page.Rows[page.RowCount - 1].Index >= PageSizeMax)
1120                    {
1121                        pagePos=SplitPage(column, pagePos);
1122                    }
1123                    //IndexItem[] newRows = new IndexItem[GetSize(page.RowCount - page.Rows[r].Index)];
1124                    //var newPage = new PageIndex(newRows, r);
1125                    //newPage.Index = (short)(pagePos + 1);
1126                    //TODO: MoveRows to next page.
1127                }
1128
1129                for (int p = pagePos + 1; p < column.PageCount; p++)
1130                {
1131                    if (column._pages[p].Offset + rows < PageSize)
1132                    {
1133                        column._pages[p].Offset += rows;
1134                    }
1135                    else
1136                    {
1137                        column._pages[p].Index++;
1138                        column._pages[p].Offset = (column._pages[p].Offset+rows) % PageSize;
1139                    }
1140                }
1141            }
1142        }
1143
1144        private void SplitPageInsert(ColumnIndex column,int pagePos, int rowPos, int rows, int size, int addPages)
1145        {
1146            var newRows = new IndexItem[GetSize(size)];
1147            var page=column._pages[pagePos];
1148
1149            var rStart=-1;
1150            for (int r = rowPos; r < page.RowCount; r++)
1151            {
1152                if (page.IndexExpanded - (page.Rows[r].Index + rows) > PageSize)
1153                {
1154                    rStart = r;
1155                    break;
1156                }
1157                else
1158                {
1159                    page.Rows[r].Index += (short)rows;
1160                }
1161            }
1162            var rc = page.RowCount - rStart;
1163            page.RowCount=rStart;
1164            if(rc>0)
1165            {
1166                //Copy to a new page
1167                var row = page.IndexOffset;
1168                var newPage=CopyNew(page,rStart,rc);
1169                var ix = (short)(page.Index + addPages);
1170                var offset = page.IndexOffset + rows - (ix * PageSize);
1171                if (offset > PageSize)
1172                {
1173                    ix += (short)(offset / PageSize);
1174                    offset %= PageSize;
1175                }
1176                newPage.Index = ix;
1177                newPage.Offset = offset;
1178                AddPage(column, pagePos + 1, newPage);
1179            }
1180
1181            //Copy from next Row
1182        }
1183
1184        private void CopyMergePage(PageIndex page, int rowPos, int rows, int size, PageIndex ToPage)
1185        {
1186            var startRow = page.IndexOffset + page.Rows[rowPos].Index + rows;
1187            var newRows = new IndexItem[GetSize(ToPage.RowCount + size)];
1188            page.RowCount -= size;
1189            Array.Copy(page.Rows, rowPos, newRows, 0, size);
1190            for (int r = 0; r < size; r++)
1191            {
1192                newRows[r].Index += (short)(page.IndexOffset + rows - ToPage.IndexOffset);
1193            }
1194
1195            Array.Copy(ToPage.Rows, 0, newRows, size, ToPage.RowCount);
1196            ToPage.Rows = newRows;
1197            ToPage.RowCount += size;
1198        }
1199        private void MergePage(ColumnIndex column, int pagePos)
1200        {
1201            PageIndex Page1=column._pages[pagePos];
1202            PageIndex Page2 = column._pages[pagePos + 1];
1203
1204            var newPage = new PageIndex(Page1, 0, Page1.RowCount + Page2.RowCount);
1205            newPage.RowCount = Page1.RowCount + Page2.RowCount;
1206            Array.Copy(Page1.Rows, 0, newPage.Rows, 0, Page1.RowCount);
1207            Array.Copy(Page2.Rows, 0, newPage.Rows, Page1.RowCount, Page2.RowCount);
1208            for (int r = Page1.RowCount; r < newPage.RowCount; r++)
1209            {
1210                newPage.Rows[r].Index += (short)(Page2.IndexOffset - Page1.IndexOffset);
1211            }
1212
1213            column._pages[pagePos] = newPage;
1214            column.PageCount--;
1215
1216            if (column.PageCount > (pagePos + 1))
1217            {
1218                Array.Copy(column._pages, pagePos+2, column._pages,pagePos+1,column.PageCount-(pagePos+1));
1219                for (int p = pagePos + 1; p < column.PageCount; p++)
1220                {
1221                    column._pages[p].Index--;
1222                    column._pages[p].Offset += PageSize;
1223                }
1224            }
1225        }
1226
1227        private PageIndex CopyNew(PageIndex pageFrom, int rowPos, int size)
1228        {
1229            IndexItem[] newRows = new IndexItem[GetSize(size)];
1230            Array.Copy(pageFrom.Rows, rowPos, newRows, 0, size);
1231            return new PageIndex(newRows, size);
1232        }
1233
1234        internal static int GetSize(int size)
1235        {
1236            var newSize=256;
1237            while (newSize < size)
1238            {
1239                newSize <<= 1;
1240            }
1241            return newSize;
1242        }
1243        private void AddCell(ColumnIndex columnIndex, int pagePos, int pos, short ix, T value)
1244        {
1245            PageIndex pageItem = columnIndex._pages[pagePos];
1246            if (pageItem.RowCount == pageItem.Rows.Length)
1247            {
1248                if (pageItem.RowCount == PageSizeMax) //Max size-->Split
1249                {
1250                    pagePos=SplitPage(columnIndex, pagePos);
1251                    if (columnIndex._pages[pagePos - 1].RowCount > pos)
1252                    {
1253                        pagePos--;                       
1254                    }
1255                    else
1256                    {
1257                        pos -= columnIndex._pages[pagePos - 1].RowCount;
1258                    }
1259                    pageItem = columnIndex._pages[pagePos];
1260                }
1261                else //Expand to double size.
1262                {
1263                    var rowsTmp = new IndexItem[pageItem.Rows.Length << 1];
1264                    Array.Copy(pageItem.Rows, 0, rowsTmp, 0, pageItem.RowCount);
1265                    pageItem.Rows = rowsTmp;
1266                }
1267            }
1268            if (pos < pageItem.RowCount)
1269            {
1270                Array.Copy(pageItem.Rows, pos, pageItem.Rows, pos + 1, pageItem.RowCount - pos);
1271            }
1272            pageItem.Rows[pos] = new IndexItem() { Index = ix,IndexPointer=_values.Count };
1273            _values.Add(value);
1274            pageItem.RowCount++;
1275        }
1276
1277        private int SplitPage(ColumnIndex columnIndex, int pagePos)
1278        {
1279            var page = columnIndex._pages[pagePos];
1280            if (page.Offset != 0)
1281            {
1282                var offset = page.Offset;
1283                page.Offset = 0;
1284                for (int r = 0; r < page.RowCount; r++)
1285                {
1286                    page.Rows[r].Index -= (short)offset;
1287                }
1288            }
1289            //Find Split pos
1290            int splitPos=0;           
1291            for (int r = 0; r < page.RowCount; r++)
1292            {
1293                if (page.Rows[r].Index > PageSize)
1294                {
1295                    splitPos=r;
1296                    break;
1297                }
1298            }
1299            var newPage = new PageIndex(page, 0, splitPos);
1300            var nextPage = new PageIndex(page, splitPos, page.RowCount - splitPos, (short)(page.Index + 1), page.Offset);
1301
1302            for (int r = 0; r < nextPage.RowCount; r++)
1303            {
1304                nextPage.Rows[r].Index = (short)(nextPage.Rows[r].Index - PageSize);
1305            }
1306           
1307            columnIndex._pages[pagePos] = newPage;
1308            if (columnIndex.PageCount + 1 > columnIndex._pages.Length)
1309            {
1310                var pageTmp = new PageIndex[columnIndex._pages.Length << 1];
1311                Array.Copy(columnIndex._pages, 0, pageTmp, 0, columnIndex.PageCount);
1312                columnIndex._pages = pageTmp;
1313            }
1314            Array.Copy(columnIndex._pages, pagePos + 1, columnIndex._pages, pagePos + 2, columnIndex.PageCount - pagePos - 1);
1315            columnIndex._pages[pagePos + 1] = nextPage;
1316            page = nextPage;
1317            //pos -= PageSize;
1318            columnIndex.PageCount++;
1319            return pagePos+1;
1320        }
1321
1322        private PageIndex AdjustIndex(ColumnIndex columnIndex, int pagePos)
1323        {
1324            PageIndex page = columnIndex._pages[pagePos];
1325            //First Adjust indexes
1326            if (page.Offset + page.Rows[0].Index >= PageSize ||
1327                page.Offset >= PageSize ||
1328                page.Rows[0].Index >= PageSize)
1329            {
1330                page.Index++;
1331                page.Offset -= PageSize;
1332            }
1333            else if (page.Offset + page.Rows[0].Index  <= -PageSize ||
1334                     page.Offset <= -PageSize ||
1335                     page.Rows[0].Index <= -PageSize)
1336            {
1337                page.Index--;
1338                page.Offset += PageSize;
1339            }
1340            //else if (page.Rows[0].Index >= PageSize) //Delete
1341            //{
1342            //    page.Index++;
1343            //    AddPageRowOffset(page, -PageSize);
1344            //}
1345            //else if (page.Rows[0].Index <= -PageSize)   //Delete
1346            //{
1347            //    page.Index--;
1348            //    AddPageRowOffset(page, PageSize);
1349            //}
1350            return page;
1351        }
1352
1353        private void AddPageRowOffset(PageIndex page, short offset)
1354        {
1355            for (int r = 0; r < page.RowCount; r++)
1356            {
1357                page.Rows[r].Index += offset;
1358            }
1359        }
1360        private void AddPage(ColumnIndex column, int pos, short index)
1361        {
1362            AddPage(column, pos);
1363            column._pages[pos] = new PageIndex() { Index = index };
1364            if (pos > 0)
1365            {
1366                var pp=column._pages[pos-1];
1367                if(pp.RowCount>0 && pp.Rows[pp.RowCount-1].Index > PageSize)
1368                {
1369                    column._pages[pos].Offset = pp.Rows[pp.RowCount-1].Index-PageSize;
1370                }
1371            }
1372        }
1373        /// <summary>
1374        /// Add a new page to the collection
1375        /// </summary>
1376        /// <param name="column">The column</param>
1377        /// <param name="pos">Position</param>
1378        /// <param name="page">The new page object to add</param>
1379        private void AddPage(ColumnIndex column, int pos, PageIndex page)
1380        {
1381            AddPage(column, pos);
1382            column._pages[pos] = page ;
1383        }
1384        /// <summary>
1385        /// Add a new page to the collection
1386        /// </summary>
1387        /// <param name="column">The column</param>
1388        /// <param name="pos">Position</param>
1389        private void AddPage(ColumnIndex column, int pos)
1390        {
1391            if (column.PageCount ==column._pages.Length)
1392            {
1393                var pageTmp = new PageIndex[column._pages.Length * 2];
1394                Array.Copy(column._pages, 0, pageTmp, 0, column.PageCount);
1395                column._pages = pageTmp;
1396            }
1397            if (pos < column.PageCount)
1398            {
1399                Array.Copy(column._pages, pos, column._pages, pos + 1, column.PageCount - pos);
1400            }
1401            column.PageCount++;
1402        }
1403        private void AddColumn(int pos, int Column)
1404        {
1405            if (ColumnCount == _columnIndex.Length)
1406            {
1407                var colTmp = new ColumnIndex[_columnIndex.Length*2];
1408                Array.Copy(_columnIndex, 0, colTmp, 0, ColumnCount);
1409                _columnIndex = colTmp;
1410            }
1411            if (pos < ColumnCount)
1412            {
1413                Array.Copy(_columnIndex, pos, _columnIndex, pos + 1, ColumnCount - pos);
1414            }
1415            _columnIndex[pos] = new ColumnIndex() { Index = (short)(Column) };
1416            ColumnCount++;
1417        }       
1418        int _colPos = -1, _row;
1419        public ulong Current
1420        {
1421            get
1422            {
1423                return ((ulong)_row << 32) | (uint)(_columnIndex[_colPos].Index);
1424            }
1425        }
1426
1427        public void Dispose()
1428        {
1429            if(_values!=null) _values.Clear();
1430            for(var c=0;c<ColumnCount;c++)
1431            {
1432                if (_columnIndex[c] != null)
1433                {
1434                    ((IDisposable)_columnIndex[c]).Dispose();
1435                }
1436            }
1437            _values = null;
1438            _columnIndex = null;
1439        }
1440
1441        //object IEnumerator.Current
1442        //{
1443        //    get
1444        //    {
1445        //        return GetValue(_row+1, _columnIndex[_colPos].Index);
1446        //    }
1447        //}
1448        public bool MoveNext()
1449        {
1450            return GetNextCell(ref _row, ref _colPos, 0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
1451        }
1452        internal bool NextCell(ref int row, ref int col)
1453        {
1454           
1455            return NextCell(ref row, ref col, 0,0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
1456        }
1457        internal bool NextCell(ref int row, ref int col, int minRow, int minColPos,int maxRow, int maxColPos)
1458        {
1459            if (minColPos >= ColumnCount)
1460            {
1461                return false;
1462            }
1463            if (maxColPos >= ColumnCount)
1464            {
1465                maxColPos = ColumnCount-1;
1466            }
1467            var c=GetPosition(col);
1468            if(c>=0)
1469            {
1470                if (c > maxColPos)
1471                {
1472                    if (col <= minColPos)
1473                    {
1474                        return false;
1475                    }
1476                    col = minColPos;
1477                    return NextCell(ref row, ref col);
1478                }
1479                else
1480                {
1481                    var r=GetNextCell(ref row, ref c, minColPos, maxRow, maxColPos);
1482                    col = _columnIndex[c].Index;
1483                    return r;
1484                }
1485            }
1486            else
1487            {
1488                c=~c;
1489                if (c > _columnIndex[c].Index)
1490                {
1491                    if (col <= minColPos)
1492                    {
1493                        return false;
1494                    }
1495                    col = minColPos;
1496                    return NextCell(ref row, ref col, minRow, minColPos, maxRow, maxColPos);
1497                }
1498                else
1499                {                   
1500                    var r=GetNextCell(ref c, ref row, minColPos, maxRow, maxColPos);
1501                    col = _columnIndex[c].Index;
1502                    return r;
1503                }
1504            }
1505        }
1506        internal bool GetNextCell(ref int row, ref int colPos, int startColPos, int endRow, int endColPos)
1507        {
1508            if (ColumnCount == 0)
1509            {
1510                return false;
1511            }
1512            else
1513            {
1514                if (++colPos < ColumnCount && colPos <=endColPos)
1515                {
1516                    var r = _columnIndex[colPos].GetNextRow(row);
1517                    if (r == row) //Exists next Row
1518                    {
1519                        return true;
1520                    }
1521                    else
1522                    {
1523                        int minRow, minCol;
1524                        if (r > row)
1525                        {
1526                            minRow = r;
1527                            minCol = colPos;
1528                        }
1529                        else
1530                        {
1531                            minRow = int.MaxValue;
1532                            minCol = 0;
1533                        }
1534
1535                        var c = colPos + 1;
1536                        while (c < ColumnCount && c <= endColPos)
1537                        {
1538                            r = _columnIndex[c].GetNextRow(row);
1539                            if (r == row) //Exists next Row
1540                            {
1541                                colPos = c;
1542                                return true;
1543                            }
1544                            if (r > row && r < minRow)
1545                            {
1546                                minRow = r;
1547                                minCol = c;
1548                            }
1549                            c++;
1550                        }
1551                        c = startColPos;
1552                        if (row < endRow)
1553                        {
1554                            row++;
1555                            while (c < colPos)
1556                            {
1557                                r = _columnIndex[c].GetNextRow(row);
1558                                if (r == row) //Exists next Row
1559                                {
1560                                    colPos = c;
1561                                    return true;
1562                                }
1563                                if (r > row && (r < minRow || (r==minRow && c<minCol)) && r <= endRow)
1564                                {
1565                                    minRow = r;
1566                                    minCol = c;
1567                                }
1568                                c++;
1569                            }
1570                        }
1571
1572                        if (minRow == int.MaxValue || minRow > endRow)
1573                        {
1574                            return false;
1575                        }
1576                        else
1577                        {
1578                            row = minRow;
1579                            colPos = minCol;
1580                            return true;
1581                        }
1582                    }
1583                }
1584                else
1585                {
1586                    if (colPos <= startColPos || row>=endRow)
1587                    {
1588                        return false;
1589                    }
1590                    colPos = startColPos - 1;
1591                    row++;
1592                    return GetNextCell(ref row, ref colPos, startColPos, endRow, endColPos);
1593                }
1594            }
1595        }
1596        internal bool GetNextCell(ref int row, ref int colPos, int startColPos, int endRow, int endColPos, ref int[] pagePos, ref int[] cellPos)
1597        {
1598            if (colPos == endColPos)
1599            {
1600                colPos = startColPos;
1601                row++;
1602            }
1603            else
1604            {
1605                colPos++;
1606            }
1607
1608            if (pagePos[colPos] < 0)
1609            {
1610                if(pagePos[colPos]==-1)
1611                {
1612                    pagePos[colPos] = _columnIndex[colPos].GetPosition(row);
1613                }
1614            }
1615            else if (_columnIndex[colPos]._pages[pagePos[colPos]].RowCount <= row)
1616            {
1617                if (_columnIndex[colPos].PageCount > pagePos[colPos])
1618                    pagePos[colPos]++;
1619                else
1620                {
1621                    pagePos[colPos]=-2;
1622                }
1623            }
1624           
1625            var r = _columnIndex[colPos]._pages[pagePos[colPos]].IndexOffset + _columnIndex[colPos]._pages[pagePos[colPos]].Rows[cellPos[colPos]].Index;
1626            if (r == row)
1627            {
1628                row = r;
1629            }
1630            else
1631            {
1632            }
1633            return true;
1634        }
1635        internal bool PrevCell(ref int row, ref int col)
1636        {
1637            return PrevCell(ref row, ref col, 0, 0, ExcelPackage.MaxRows, ExcelPackage.MaxColumns);
1638        }
1639        internal bool PrevCell(ref int row, ref int col, int minRow, int minColPos, int maxRow, int maxColPos)
1640        {
1641            if (minColPos >= ColumnCount)
1642            {
1643                return false;
1644            }
1645            if (maxColPos >= ColumnCount)
1646            {
1647                maxColPos = ColumnCount - 1;
1648            }
1649            var c = GetPosition(col);
1650            if(c>=0)
1651            {
1652                if (c == 0)
1653                {
1654                    if (col >= maxColPos)
1655                    {
1656                        return false;
1657                    }
1658                    if (row == minRow)
1659                    {
1660                        return false;
1661                    }
1662                    row--;
1663                    col = maxColPos;                   
1664                    return PrevCell(ref row, ref col, minRow, minColPos, maxRow, maxColPos);
1665                }
1666                else
1667                {
1668                    var ret=GetPrevCell(ref row, ref c, minRow, minColPos, maxColPos);
1669                    if (ret)
1670                    {
1671                        col = _columnIndex[c].Index;
1672                    }
1673                    return ret;
1674                }
1675            }
1676            else
1677            {
1678                c=~c;
1679                if (c == 0)
1680                {
1681                    if (col >= maxColPos || row<=0)
1682                    {
1683                        return false;
1684                    }
1685                    col = maxColPos;
1686                    row--;
1687                    return PrevCell(ref row, ref col, minRow, minColPos, maxRow, maxColPos);
1688                }
1689                else
1690                {
1691                    var ret = GetPrevCell(ref row, ref c, minRow, minColPos, maxColPos);
1692                    if (ret)
1693                    {
1694                        col = _columnIndex[c].Index;
1695                    }
1696                    return ret;
1697                }
1698            }
1699        }
1700        internal bool GetPrevCell(ref int row, ref int colPos, int startRow, int startColPos, int endColPos)
1701        {
1702            if (ColumnCount == 0)
1703            {
1704                return false;
1705            }
1706            else
1707            {
1708                if (--colPos >= startColPos)
1709//                if (++colPos < ColumnCount && colPos <= endColPos)
1710                {
1711                    var r = _columnIndex[colPos].GetNextRow(row);
1712                    if (r == row) //Exists next Row
1713                    {
1714                        return true;
1715                    }
1716                    else
1717                    {
1718                        int minRow, minCol;
1719                        if (r > row && r >= startRow)
1720                        {
1721                            minRow = r;
1722                            minCol = colPos;
1723                        }
1724                        else
1725                        {
1726                            minRow = int.MaxValue;
1727                            minCol = 0;
1728                        }
1729
1730                        var c = colPos - 1;
1731                        if (c >= startColPos)
1732                        {
1733                            while (c >= startColPos)
1734                            {
1735                                r = _columnIndex[c].GetNextRow(row);
1736                                if (r == row) //Exists next Row
1737                                {
1738                                    colPos = c;
1739                                    return true;
1740                                }
1741                                if (r > row && r < minRow && r >= startRow)
1742                                {
1743                                    minRow = r;
1744                                    minCol = c;
1745                                }
1746                                c--;
1747                            }
1748                        }
1749                        if (row > startRow)
1750                        {
1751                            c = endColPos;
1752                            row--;
1753                            while (c > colPos)
1754                            {
1755                                r = _columnIndex[c].GetNextRow(row);
1756                                if (r == row) //Exists next Row
1757                                {
1758                                    colPos = c;
1759                                    return true;
1760                                }
1761                                if (r > row && r < minRow && r >= startRow)
1762                                {
1763                                    minRow = r;
1764                                    minCol = c;
1765                                }
1766                                c--;
1767                            }
1768                        }
1769                        if (minRow == int.MaxValue || startRow < minRow)
1770                        {
1771                            return false;
1772                        }
1773                        else
1774                        {
1775                            row = minRow;
1776                            colPos = minCol;
1777                            return true;
1778                        }
1779                    }
1780                }
1781                else
1782                {
1783                    colPos = ColumnCount;
1784                    row--;
1785                    if (row < startRow)
1786                    {
1787                        Reset();
1788                        return false;
1789                    }
1790                    else
1791                    {
1792                        return GetPrevCell(ref colPos, ref row, startRow, startColPos, endColPos);
1793                    }
1794                }
1795            }
1796        }
1797        public void Reset()
1798        {
1799            _colPos = -1;           
1800            _row= 0;
1801        }
1802
1803        //public IEnumerator<ulong> GetEnumerator()
1804        //{
1805        //    this.Reset();
1806        //    return this;
1807        //}
1808
1809        //IEnumerator IEnumerable.GetEnumerator()
1810        //{
1811        //    this.Reset();
1812        //    return this;
1813        //}
1814
1815    }
1816    internal class CellsStoreEnumerator<T> : IEnumerable<T>, IEnumerator<T>
1817    {
1818        CellStore<T> _cellStore;
1819        int row, colPos;
1820        int[] pagePos, cellPos;
1821        int _startRow, _startCol, _endRow, _endCol;
1822        int minRow, minColPos, maxRow, maxColPos;
1823        public CellsStoreEnumerator(CellStore<T> cellStore) :
1824            this(cellStore, 0,0,ExcelPackage.MaxRows, ExcelPackage.MaxColumns)       
1825        {
1826        }
1827        public CellsStoreEnumerator(CellStore<T> cellStore, int StartRow, int StartCol, int EndRow, int EndCol)
1828        {
1829            _cellStore = cellStore;
1830           
1831            _startRow=StartRow;
1832            _startCol=StartCol;
1833            _endRow=EndRow;
1834            _endCol=EndCol;
1835
1836            Init();
1837
1838        }
1839
1840        internal void Init()
1841        {
1842            minRow = _startRow;
1843            maxRow = _endRow;
1844
1845            minColPos = _cellStore.GetPosition(_startCol);
1846            if (minColPos < 0) minColPos = ~minColPos;
1847            maxColPos = _cellStore.GetPosition(_endCol);
1848            if (maxColPos < 0) maxColPos = ~maxColPos-1;
1849            row = minRow;
1850            colPos = minColPos - 1;
1851
1852            var cols = maxColPos - minColPos + 1;
1853            pagePos = new int[cols];
1854            cellPos = new int[cols];
1855            for (int i = 0; i < cols; i++)
1856            {
1857                pagePos[i] = -1;
1858                cellPos[i] = -1;
1859            }
1860        }
1861        internal int Row
1862        {
1863            get
1864            {
1865                return row;
1866            }
1867        }
1868        internal int Column
1869        {
1870            get
1871            {
1872                if (colPos == -1) MoveNext();
1873                if (colPos == -1) return 0;
1874                return _cellStore._columnIndex[colPos].Index;
1875            }
1876        }
1877        internal T Value
1878        {
1879            get
1880            {
1881                lock (_cellStore)
1882                {
1883                    return _cellStore.GetValue(row, Column);
1884                }
1885            }
1886            set
1887            {
1888                lock (_cellStore)
1889                {
1890                    _cellStore.SetValue(row, Column, value);
1891                }
1892            }
1893        }
1894        internal bool Next()
1895        {
1896            //return _cellStore.GetNextCell(ref row, ref colPos, minColPos, maxRow, maxColPos);
1897            return _cellStore.GetNextCell(ref row, ref colPos, minColPos, maxRow, maxColPos);
1898        }
1899        internal bool Previous()
1900        {
1901            lock (_cellStore)
1902            {
1903                return _cellStore.GetPrevCell(ref row, ref colPos, minRow, minColPos, maxColPos);
1904            }
1905        }
1906
1907        public string CellAddress
1908        {
1909            get
1910            {
1911                return ExcelAddressBase.GetAddress(Row, Column);
1912            }
1913        }
1914
1915        public IEnumerator<T> GetEnumerator()
1916        {
1917            Reset();
1918            return this;
1919        }
1920
1921        IEnumerator IEnumerable.GetEnumerator()
1922        {
1923            Reset();
1924            return this;
1925        }
1926
1927        public T Current
1928        {
1929            get
1930            {
1931                return Value;
1932            }
1933        }
1934
1935        public void Dispose()
1936        {
1937            //_cellStore=null;
1938        }
1939
1940        object IEnumerator.Current
1941        {
1942            get
1943            {
1944                Reset();
1945                return this;
1946            }
1947        }
1948
1949        public bool MoveNext()
1950        {
1951            return Next();
1952        }
1953
1954        public void Reset()
1955        {
1956            Init();
1957        }
1958    }
1959    internal class FlagCellStore : CellStore<byte>
1960    {
1961        internal void SetFlagValue(int Row, int Col, bool value, CellFlags cellFlags)
1962        {
1963            CellFlags currentValue = (CellFlags) GetValue(Row, Col);
1964            if (value)
1965            {
1966                SetValue(Row, Col, (byte)(currentValue | cellFlags)); // add the CellFlag bit
1967            }
1968            else
1969            {
1970                SetValue(Row, Col, (byte)(currentValue & ~cellFlags)); // remove the CellFlag bit
1971            }
1972        }
1973        internal bool GetFlagValue(int Row, int Col, CellFlags cellFlags)
1974        {
1975            return !(((byte)cellFlags & GetValue(Row, Col)) == 0);
1976        }
1977    }
Note: See TracBrowser for help on using the repository browser.