Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Async/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/EPPlus-4.0.3/RangeCollection.cs @ 13329

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

#2341: Added EPPlus-4.0.3 to ExtLibs

File size: 10.7 KB
Line 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/*******************************************************************************
23 * You may amend and distribute as you like, but don't remove this header!
24 *
25 * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
26 * See http://www.codeplex.com/EPPlus for details.
27 *
28 * Copyright (C) 2011  Jan Källman
29 *
30 * This library is free software; you can redistribute it and/or
31 * modify it under the terms of the GNU Lesser General Public
32 * License as published by the Free Software Foundation; either
33 * version 2.1 of the License, or (at your option) any later version.
34
35 * This library is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
38 * See the GNU Lesser General Public License for more details.
39 *
40 * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
41 * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
42 *
43 * All code and executables are provided "as is" with no warranty either express or implied.
44 * The author accepts no liability for any damage or loss of business that this product may cause.
45 *
46 * Code change notes:
47 *
48 * Author             Change            Date
49 * ******************************************************************************
50 * Jan Källman        Added                   2010-02-04
51 * Jan Källman        License changed GPL-->LGPL  2011-12-27
52 *******************************************************************************/
53using System;
54using System.Collections.Generic;
55using System.Text;
56using System.Collections;
57using OfficeOpenXml.Drawing.Vml;namespace OfficeOpenXml
58{
59    /// <summary>
60    /// This is the store for all Rows, Columns and Cells.
61    /// It is a Dictionary implementation that allows you to change the Key (the RowID, ColumnID or CellID )
62    /// </summary>
63    internal class RangeCollection : IEnumerator<IRangeID>, IEnumerable, IDisposable
64    {
65        private class IndexItem
66        {
67            internal IndexItem(ulong cellId)
68            {
69                RangeID = cellId;
70            }
71            internal IndexItem(ulong cellId, int listPointer)
72          {
73                RangeID = cellId;
74                ListPointer=listPointer;
75          }
76            internal ulong RangeID;
77            internal int ListPointer;
78        }
79        /// <summary>
80        /// Compares an IndexItem
81        /// </summary>
82        internal class Compare : IComparer<IndexItem>
83        {
84            #region IComparer<IndexItem> Members
85            int IComparer<IndexItem>.Compare(IndexItem x, IndexItem y)
86            {
87                return x.RangeID < y.RangeID ? -1 : x.RangeID > y.RangeID ? 1 : 0;
88            }
89
90            #endregion
91        }
92        IndexItem[] _cellIndex;
93        List<IRangeID> _cells;
94        static readonly Compare _comparer=new Compare();
95        /// <summary>
96        /// Creates a new collection
97        /// </summary>
98        /// <param name="cells">The Cells. This list must be sorted</param>
99        internal RangeCollection(List<IRangeID> cells)
100        {   
101            _cells = cells;
102            InitSize(_cells);
103            for (int i = 0; i < _cells.Count; i++)
104            {
105                _cellIndex[i] = new IndexItem(cells[i].RangeID, i);
106            }
107        }
108        ~RangeCollection()
109        {
110            _cells = null;
111            _cellIndex = null;
112        }
113        /// <summary>
114        /// Return the item with the RangeID
115        /// </summary>
116        /// <param name="RangeID"></param>
117        /// <returns></returns>
118        internal IRangeID this[ulong RangeID]
119        {
120            get
121            {
122                return _cells[_cellIndex[IndexOf(RangeID)].ListPointer];
123            }
124        }
125        /// <summary>
126        /// Return specified index from the sorted list
127        /// </summary>
128        /// <param name="Index"></param>
129        /// <returns></returns>
130        internal IRangeID this[int Index]
131        {
132            get
133            {
134                return _cells[_cellIndex[Index].ListPointer];
135            }
136        }
137        internal int Count
138        {
139            get
140            {
141                return _cells.Count;
142            }
143        }
144        internal void Add(IRangeID cell)
145        {
146            var ix = IndexOf(cell.RangeID);
147            if (ix >= 0)
148            {
149                throw (new Exception("Item already exists"));
150            }
151            Insert(~ix, cell);
152        }
153        internal void Delete(ulong key)
154        {
155            var ix = IndexOf(key);
156            if (ix < 0)
157            {
158                throw (new Exception("Key does not exists"));
159            }
160            int listPointer = _cellIndex[ix].ListPointer;
161            Array.Copy(_cellIndex, ix + 1, _cellIndex, ix, _cells.Count - ix - 1);
162            _cells.RemoveAt(listPointer);
163
164            //Item is removed subtract one from all items with greater ListPointer
165            for (int i = 0; i < _cells.Count; i++)
166            {
167                if (_cellIndex[i].ListPointer >= listPointer)
168                {
169                    _cellIndex[i].ListPointer--;
170                }
171
172            }
173        }
174        internal int IndexOf(ulong key)
175        {
176            return Array.BinarySearch<IndexItem>(_cellIndex, 0, _cells.Count, new IndexItem(key), _comparer);
177        }
178        internal bool ContainsKey(ulong key)
179        {
180            return IndexOf(key) < 0 ? false : true;
181        }
182        int _size { get; set; }
183        #region "RangeID manipulation methods"
184        /// <summary>
185        /// Insert a number of rows in the collecion but dont update the cell only the index
186        /// </summary>
187        /// <param name="rowID"></param>
188        /// <param name="rows"></param>
189        /// <returns>Index of first rangeItem</returns>
190        internal int InsertRowsUpdateIndex(ulong rowID, int rows)
191        {
192            int index = IndexOf(rowID);
193            if (index < 0) index = ~index; //No match found invert to get start cell
194            ulong rowAdd = (((ulong)rows) << 29);
195            for (int i = index; i < _cells.Count; i++)
196            {
197                _cellIndex[i].RangeID += rowAdd;
198            }
199            return index;
200        }
201        /// <summary>
202        /// Insert a number of rows in the collecion
203        /// </summary>
204        /// <param name="rowID"></param>
205        /// <param name="rows"></param>
206        /// <returns>Index of first rangeItem</returns>
207        internal int InsertRows(ulong rowID, int rows)
208        {
209            int index = IndexOf(rowID);
210            if (index < 0) index = ~index; //No match found invert to get start cell
211            ulong rowAdd=(((ulong)rows) << 29);
212            for (int i = index; i < _cells.Count; i++)
213            {
214                _cellIndex[i].RangeID += rowAdd;
215                _cells[_cellIndex[i].ListPointer].RangeID += rowAdd;
216            }
217            return index;
218        }
219        /// <summary>
220        /// Delete rows from the collecion
221        /// </summary>
222        /// <param name="rowID"></param>
223        /// <param name="rows"></param>
224        /// <param name="updateCells">Update range id's on cells</param>
225        internal int DeleteRows(ulong rowID, int rows, bool updateCells)
226        {
227            ulong rowAdd = (((ulong)rows) << 29);
228            var index = IndexOf(rowID);
229            if (index < 0) index = ~index; //No match found invert to get start cell
230
231            if (index >= _cells.Count || _cellIndex[index] == null) return -1;   //No row above this row
232            while (index < _cells.Count && _cellIndex[index].RangeID < rowID + rowAdd)
233            {
234                Delete(_cellIndex[index].RangeID);
235            }
236
237            int updIndex = IndexOf(rowID + rowAdd);
238            if (updIndex < 0) updIndex = ~updIndex; //No match found invert to get start cell
239
240            for (int i = updIndex; i < _cells.Count; i++)
241            {
242                _cellIndex[i].RangeID -= rowAdd;                        //Change the index
243                if (updateCells) _cells[_cellIndex[i].ListPointer].RangeID -= rowAdd;    //Change the cell/row or column object
244            }
245            return index;
246        }
247        internal void InsertColumn(ulong ColumnID, int columns)
248        {
249            throw (new Exception("Working on it..."));
250        }
251        internal void DeleteColumn(ulong ColumnID,int columns)
252        {
253            throw (new Exception("Working on it..."));
254        }
255        #endregion
256        #region "Private Methods"
257        /// <summary>
258        /// Init the size starting from 128 items. Double the size until the list fits.
259        /// </summary>
260        /// <param name="_cells"></param>
261        private void InitSize(List<IRangeID> _cells)
262        {
263            _size = 128;
264            while (_cells.Count > _size) _size <<= 1;
265            _cellIndex = new IndexItem[_size];
266        }
267        /// <summary>
268        /// Check the size and double the size if out of bound
269        /// </summary>
270        private void CheckSize()
271        {
272            if (_cells.Count >= _size)
273            {
274                _size <<= 1;
275                Array.Resize(ref _cellIndex, _size);
276            }
277        }
278        private void Insert(int ix, IRangeID cell)
279        {
280            CheckSize();
281            Array.Copy(_cellIndex, ix, _cellIndex, ix + 1, _cells.Count - ix);
282            _cellIndex[ix] = new IndexItem(cell.RangeID, _cells.Count);
283            _cells.Add(cell);
284        }
285        #endregion
286
287        #region IEnumerator<IRangeID> Members
288
289        IRangeID IEnumerator<IRangeID>.Current
290        {
291            get { throw new NotImplementedException(); }
292        }
293
294        #endregion
295
296        #region IDisposable for the enumerator Members
297
298        void IDisposable.Dispose()
299        {
300            _ix = -1;
301        }
302
303        #endregion
304
305        #region IEnumerator Members
306        int _ix = -1;
307        object IEnumerator.Current
308        {
309            get
310            {
311                return _cells[_cellIndex[_ix].ListPointer];
312            }
313        }
314
315        bool IEnumerator.MoveNext()
316        {
317           _ix++;
318           return _ix < _cells.Count;
319        }
320
321        void IEnumerator.Reset()
322        {
323            _ix = -1;
324        }
325
326        #endregion
327
328        #region IEnumerable Members
329
330        IEnumerator IEnumerable.GetEnumerator()
331        {
332            return this.MemberwiseClone() as IEnumerator;
333        }
334
335        #endregion
336    }
337}
Note: See TracBrowser for help on using the repository browser.