Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Breadcrumbs/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/3.1.3/EPPlus-3.1.3/ExcelAddress.cs @ 10041

Last change on this file since 10041 was 9580, checked in by sforsten, 12 years ago

#1730:

  • added SymbolicDataAnalysisExpressionExcelFormatter
  • changed modifiers in SymbolicExpressionTreeChart of methods SaveImageAsBitmap and SaveImageAsEmf to public
  • added menu item ExportSymbolicSolutionToExcelMenuItem to export a symbolic solution to an excel file
  • added EPPlus-3.1.3 to ExtLibs
File size: 19.7 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   18-MAR-2010
30 * Jan Källman    License changed GPL-->LGPL 2011-12-16
31 *******************************************************************************/
32using System;
33using System.Collections.Generic;
34using System.Text;
35using System.Text.RegularExpressions;
36
37namespace OfficeOpenXml
38{
39    /// <summary>
40    /// A range address
41    /// </summary>
42    /// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
43    public class ExcelAddressBase : ExcelCellBase
44    {
45        internal protected int _fromRow=-1, _toRow, _fromCol, _toCol;
46        internal protected string _wb;
47        internal protected string _ws;
48        internal protected string _address;
49        internal protected event EventHandler AddressChange;
50
51        internal enum eAddressCollition
52        {
53            No,
54            Partly,
55            Inside,
56            Equal
57        }
58        #region "Constructors"
59        internal ExcelAddressBase()
60        {
61        }
62        /// <summary>
63        /// Creates an Address object
64        /// </summary>
65        /// <param name="fromRow">start row</param>
66        /// <param name="fromCol">start column</param>
67        /// <param name="toRow">End row</param>
68        /// <param name="toColumn">End column</param>
69        public ExcelAddressBase(int fromRow, int fromCol, int toRow, int toColumn)
70        {
71            _fromRow = fromRow;
72            _toRow = toRow;
73            _fromCol = fromCol;
74            _toCol = toColumn;
75            Validate();
76
77            _address = GetAddress(_fromRow, _fromCol, _toRow, _toCol);
78        }
79        /// <summary>
80        /// Creates an Address object
81        /// </summary>
82        /// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
83        /// <param name="address">The Excel Address</param>
84        public ExcelAddressBase(string address)
85        {
86            SetAddress(address);
87        }
88
89        /// <summary>
90        /// Address is an defined name
91        /// </summary>
92        /// <param name="address">the name</param>
93        /// <param name="isName">Should always be true</param>
94        internal ExcelAddressBase(string address, bool isName)
95        {
96            if (isName)
97            {
98                _address = address;
99                _fromRow = -1;
100                _fromCol = -1;
101                _toRow = -1;
102                _toCol = -1;
103                _start = null;
104                _end = null;
105            }
106            else
107            {
108                SetAddress(address);
109            }
110        }
111
112        protected internal void SetAddress(string address)
113        {
114            if(address.StartsWith("'"))
115            {
116                int pos = address.IndexOf("'", 1);
117                SetWbWs(address.Substring(1,pos-1).Replace("''","'"));
118                _address = address.Substring(pos + 2);
119            }
120            else if (address.StartsWith("[")) //Remove any external reference
121            {
122                SetWbWs(address);
123            }
124            else
125            {
126                _address = address;
127            }
128            if(_address.IndexOfAny(new char[] {',','!'}) > -1)
129            {
130                //Advanced address. Including Sheet or multi
131                ExtractAddress(_address);
132            }
133            else
134            {
135                //Simple address
136                GetRowColFromAddress(_address, out _fromRow, out _fromCol, out _toRow, out  _toCol);
137                _addresses = null;
138                _start = null;
139                _end = null;
140                _firstAddress = _address;
141            }
142            _address = address;
143            Validate();
144        }
145        internal void ChangeAddress()
146        {
147            if (AddressChange != null)
148            {
149                AddressChange(this, new EventArgs());
150            }
151        }
152        private void SetWbWs(string address)
153        {
154            int pos;
155            if (address[0] == '[')
156            {
157                pos = address.LastIndexOf("]");
158                _wb = address.Substring(1, pos - 1);               
159                _ws = address.Substring(pos + 1);
160            }
161            else
162            {
163                _wb = "";
164                _ws = address;
165            }
166            pos = _ws.IndexOf("!");
167            if (pos > -1)
168            {
169                _address = _ws.Substring(pos + 1);
170                _ws = _ws.Substring(0, pos);
171            }
172        }
173        ExcelCellAddress _start = null;
174        #endregion
175        /// <summary>
176        /// Gets the row and column of the top left cell.
177        /// </summary>
178        /// <value>The start row column.</value>
179        public ExcelCellAddress Start
180        {
181            get
182            {
183                if (_start == null)
184                {
185                    _start = new ExcelCellAddress(_fromRow, _fromCol);
186                }
187                return _start;
188            }
189        }
190        ExcelCellAddress _end = null;
191        /// <summary>
192        /// Gets the row and column of the bottom right cell.
193        /// </summary>
194        /// <value>The end row column.</value>
195        public ExcelCellAddress End
196        {
197            get
198            {
199                if (_end == null)
200                {
201                    _end = new ExcelCellAddress(_toRow, _toCol);
202                }
203                return _end;
204            }
205        }
206        /// <summary>
207        /// The address for the range
208        /// </summary>
209        public virtual string Address
210        {
211            get
212            {
213                return _address;
214            }
215        }       
216        /// <summary>
217        /// If the address is a defined name
218        /// </summary>
219        public bool IsName
220        {
221            get
222            {
223                return _fromRow < 0;
224            }
225        }
226        public override string ToString()
227        {
228            return base.ToString();
229        }
230        string _firstAddress;
231        /// <summary>
232        /// returns the first address if the address is a multi address.
233        /// A1:A2,B1:B2 returns A1:A2
234        /// </summary>
235        internal string FirstAddress
236        {
237            get
238            {
239                if (string.IsNullOrEmpty(_firstAddress))
240                {
241                    return _address;
242                }
243                else
244                {
245                    return _firstAddress;
246                }
247            }
248        }
249        internal string AddressSpaceSeparated
250        {
251            get
252            {
253                return _address.Replace(',', ' '); //Conditional formatting and a few other places use space as separator for mulit addresses.
254            }
255        }
256        /// <summary>
257        /// Validate the address
258        /// </summary>
259        protected void Validate()
260        {
261            if (_fromRow > _toRow || _fromCol > _toCol)
262            {
263                throw new ArgumentOutOfRangeException("Start cell Address must be less or equal to End cell address");
264            }
265        }
266        internal string WorkSheet
267        {
268            get
269            {
270                return _ws;
271            }
272        }
273        List<ExcelAddress> _addresses = null;
274        internal List<ExcelAddress> Addresses
275        {
276            get
277            {
278                return _addresses;
279            }
280        }
281
282        private void ExtractAddress(string fullAddress)
283        {
284            string first="", second="";
285            bool isText=false, hasSheet=false;
286            if (fullAddress == "#REF!")
287            {
288                SetAddress(ref fullAddress, ref second, ref hasSheet );
289                return;
290            }
291            foreach (char c in fullAddress)
292            {
293                if(c=='\'')
294                {
295                    isText=!isText;
296                }
297                else
298                {
299                    if(c=='!' && !isText && !first.EndsWith("#REF") && !second.EndsWith("#REF"))
300                    {
301                        hasSheet=true;
302                    }
303                    else if (c == ',' && !isText)
304                    {
305                        SetAddress(ref first, ref second, ref hasSheet);
306                    }
307                    else
308                    {
309                        if (hasSheet)
310                        {
311                            second += c;
312                        }
313                        else
314                        {
315                            first += c;
316                        }
317                    }
318                }
319            }
320            SetAddress(ref first, ref second, ref hasSheet);
321        }
322        #region Address manipulation methods
323        internal eAddressCollition Collide(ExcelAddressBase address)
324        {
325            if (address.WorkSheet != WorkSheet)
326            {
327                return eAddressCollition.No;
328            }
329
330            if (address._fromRow > _toRow || address._fromCol > _toCol
331                ||
332                _fromRow > address._toRow || _fromCol > address._toCol)
333            {
334                return eAddressCollition.No;
335            }
336            else if (address._fromRow == _fromRow && address._fromCol == _fromCol &&
337                    address._toRow == _toRow && address._toCol == _toCol)
338            {
339                return eAddressCollition.Equal;
340            }
341            else if (address._fromRow >= _fromRow && address._toRow <= _toRow &&
342                     address._fromCol >= _fromCol && address._toCol <= _toCol)
343            {
344                return eAddressCollition.Inside;
345            }
346            else
347                return eAddressCollition.Partly;
348        }       
349        internal ExcelAddressBase AddRow(int row, int rows)
350        {
351            if (row > _toRow)
352            {
353                return this;
354            }
355            else if (row <= _fromRow)
356            {
357                return new ExcelAddressBase(_fromRow + rows, _fromCol, _toRow + rows, _toCol);
358            }
359            else
360            {
361                return new ExcelAddressBase(_fromRow, _fromCol, _toRow + rows, _toCol);
362            }
363        }
364        internal ExcelAddressBase DeleteRow(int row, int rows)
365        {
366            if (row > _toRow) //After
367            {
368                return this;
369            }           
370            else if (row+rows <= _fromRow) //Before
371            {
372                return new ExcelAddressBase(_fromRow - rows, _fromCol, _toRow - rows, _toCol);
373            }
374            else if (row <= _fromRow && row + rows > _toRow) //Inside
375            {
376                return null;
377            }
378            else  //Partly
379            {
380                if (row <= _fromRow)
381                {
382                    return new ExcelAddressBase(row, _fromCol, _toRow - rows, _toCol);
383                }
384                else
385                {
386                    return new ExcelAddressBase(_fromRow, _fromCol, _toRow - rows < row ? row - 1 : _toRow - rows, _toCol);
387                }
388            }
389        }
390        internal ExcelAddressBase AddColumn(int col, int cols)
391        {
392            if (col > _toCol)
393            {
394                return this;
395            }
396            else if (col <= _fromCol)
397            {
398                return new ExcelAddressBase(_fromRow, _fromCol + cols, _toRow, _toCol + cols);
399            }
400            else
401            {
402                return new ExcelAddressBase(_fromRow, _fromCol, _toRow, _toCol + cols);
403            }
404        }
405        internal ExcelAddressBase DeleteColumn(int col, int cols)
406        {
407            if (col > _toCol) //After
408            {
409                return this;
410            }
411            else if (col + cols <= _fromRow) //Before
412            {
413                return new ExcelAddressBase(_fromRow, _fromCol - cols, _toRow, _toCol - cols);
414            }
415            else if (col <= _fromCol && col + cols > _toCol) //Inside
416            {
417                return null;
418            }
419            else  //Partly
420            {
421                if (col <= _fromCol)
422                {
423                    return new ExcelAddressBase(_fromRow, col, _toRow, _toCol - cols);
424                }
425                else
426                {
427                    return new ExcelAddressBase(_fromRow, _fromCol, _toRow, _toCol - cols < col ? col - 1 : _toCol - cols);
428                }
429            }
430        }
431        #endregion
432        private void SetAddress(ref string first, ref string second, ref bool hasSheet)
433        {
434            string ws, address;
435            if (hasSheet)
436            {
437                ws = first;
438                address = second;
439                first = "";
440                second = "";
441            }
442            else
443            {
444                address = first;
445                ws = "";
446                first = "";
447            }
448            hasSheet = false;
449            if (string.IsNullOrEmpty(_firstAddress))
450            {
451                if(string.IsNullOrEmpty(_ws) || !string.IsNullOrEmpty(ws))_ws = ws;
452                _firstAddress = address;
453                GetRowColFromAddress(address, out _fromRow, out _fromCol, out _toRow, out  _toCol);
454            }
455            else
456            {
457                if (_addresses == null) _addresses = new List<ExcelAddress>();
458                _addresses.Add(new ExcelAddress(_ws, address));
459            }
460        }
461        internal enum AddressType
462        {
463            Invalid,
464            InternalAddress,
465            ExternalAddress,
466            InternalName,
467            ExternalName
468        }
469
470        internal static AddressType IsValid(string Address)
471        {
472            string ws="";
473            if (Address.StartsWith("'"))
474            {
475                int ix = Address.IndexOf('\'', 1);
476                if (ix > -1)
477                {
478                    ws = Address.Substring(1, ix-1);
479                    Address = Address.Substring(ix + 2);
480                }
481            }
482            if (Address.IndexOfAny(new char[] { '(', ')', '+', '-', '*', '/', '.', '=','^','&','%','\"' })>-1)
483            {
484                return AddressType.Invalid;
485            }
486            if (Address.IndexOf('!') > 0)
487            {
488                string[] split = Address.Split('!');
489                if (split.Length == 2)
490                {
491                    ws = split[0];
492                    Address = split[1];
493                }
494                else if (split.Length == 3 && split[1] == "#REF" && split[2] == "")
495                {
496                    ws = split[0];
497                    Address = "#REF!";
498                    if (ws.StartsWith("[") && ws.IndexOf("]") > 1)
499                    {
500                        return AddressType.ExternalAddress;
501                    }
502                    else
503                    {
504                        return AddressType.InternalAddress;
505                    }
506                }
507                else
508                {
509                    return AddressType.Invalid;
510                }
511            }
512            int _fromRow, _fromCol, _toRow, _toCol;
513            if (ExcelAddressBase.GetRowColFromAddress(Address, out _fromRow, out _fromCol, out _toRow, out _toCol))
514            {
515                if (_fromRow > 0 && _fromCol > 0 && _toRow <= ExcelPackage.MaxRows && _toCol <= ExcelPackage.MaxColumns)
516                {
517                    if (ws.StartsWith("[") && ws.IndexOf("]") > 1)
518                    {
519                        return AddressType.ExternalAddress;
520                    }
521                    else
522                    {
523                        return AddressType.InternalAddress;
524                    }
525                }
526                else
527                {
528                    return AddressType.Invalid;
529                }
530            }
531            else
532            {
533                if(IsValidName(Address))
534                {
535                    if (ws.StartsWith("[") && ws.IndexOf("]") > 1)
536                    {
537                        return AddressType.ExternalName;
538                    }
539                    else
540                    {
541                        return AddressType.InternalName;
542                    }
543                }
544                else
545                {
546                    return AddressType.Invalid;
547                }
548            }
549
550        }
551
552        private static bool IsValidName(string address)
553        {
554            if (Regex.IsMatch(address, "[^0-9./*-+,½!\"@#£%&/{}()\\[\\]=?`^~':;<>|][^/*-+,½!\"@#£%&/{}()\\[\\]=?`^~':;<>|]*"))
555            {
556                return true;
557            }
558            else
559            {
560                return false;
561            }
562        }
563    }
564    /// <summary>
565    /// Range address with the address property readonly
566    /// </summary>
567    public class ExcelAddress : ExcelAddressBase
568    {
569        internal ExcelAddress()
570            : base()
571        {
572
573        }
574
575        public ExcelAddress(int fromRow, int fromCol, int toRow, int toColumn)
576            : base(fromRow, fromCol, toRow, toColumn)
577        {
578            _ws = "";
579        }
580        public ExcelAddress(string address)
581            : base(address)
582        {
583        }
584       
585        internal ExcelAddress(string ws, string address)
586            : base(address)
587        {
588            if (string.IsNullOrEmpty(_ws)) _ws = ws;
589        }
590        internal ExcelAddress(string ws, string address, bool isName)
591            : base(address, isName)
592        {
593            if (string.IsNullOrEmpty(_ws)) _ws = ws;
594        }
595        /// <summary>
596        /// The address for the range
597        /// </summary>
598        /// <remarks>Examples of addresses are "A1" "B1:C2" "A:A" "1:1" "A1:E2,G3:G5" </remarks>
599        public new string Address
600        {
601            get
602            {
603                if (string.IsNullOrEmpty(_address) && _fromRow>0)
604                {
605                    _address = GetAddress(_fromRow, _fromCol, _toRow, _toCol);
606                }
607                return _address;
608            }
609            set
610            {               
611                SetAddress(value);
612                base.ChangeAddress();
613            }
614        }
615    }
616}
Note: See TracBrowser for help on using the repository browser.