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 | *******************************************************************************/
|
---|
32 | using System;
|
---|
33 | using System.Collections.Generic;
|
---|
34 | using System.Text;
|
---|
35 | using System.Text.RegularExpressions;
|
---|
36 |
|
---|
37 | namespace 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 | }
|
---|