namespace com.azkoss.excellite { using System; using System.Collections; using System.Drawing; using System.Reflection; using System.Runtime.InteropServices; /// ///Cell range is a rectangular group of worksheet cells. /// /// ///

Cell range is determined by its top (FirstRowIndex), ///left (FirstColumnIndex), ///bottom (LastRowIndex) and ///right (LastColumnIndex) borders. This properties ///are read-only, so if you require different cell range use one of GetSubrange methods ///(GetSubrangeAbsolute, ///GetSubrangeRelative or ///GetSubrange). Specific cell can be accessed in a few ///ways, depending on IndexingMode. Cells in the ///range can be merged / unmerged by the use of Merged ///property.

///

Value property set will set value of multiple cells ///or of a merged range. Value property get has meaning ///only if range is merged; otherwise, exception is thrown.

///

Style property set will set style of multiple cells ///or of a merged range. Style property get has meaning ///only if range is merged; otherwise, exception is thrown.

///

Note that for Style property set on a cell range that ///is not merged, you can't use the following format: /// ///Dim cr As CellRange = excelFile.Worksheets(0).Rows(1).Cells ///cr.Style.Rotation = 30 /// /// ///CellRange cr = excelFile.Worksheets[0].Rows[1].Cells; ///cr.Style.Rotation = 30; /// ///because that would first call Style property get method and that ///will certainly fail because Style property get is defined only ///for a merged cell range.

Instead you can use two different code patterns, depending on whether you want to replace or combine the existing ///cell range styles with the new style.

///If you want to replace cell style on every cell in a cell range use the following code: /// ///Dim cr As CellRange = excelFile.Worksheets(0).Rows(1).Cells ///Dim style As CellStyle = New CellStyle() ///style.Rotation = 30 ///cr.Style = style /// /// ///CellRange cr = excelFile.Worksheets[0].Rows[1].Cells; ///CellStyle style = new CellStyle(); ///style.Rotation = 30; ///cr.Style = style; /// ///

///If you want to set cell style property on every cell in a cell range (other cell style property values will ///remain unchanged) use the following code: /// ///Dim cell As ExcelCell ///For Each cell In excelFile.Worksheets(0).Rows(1).Cells ///cell.Style.Rotation = 30 ///Next /// /// ///foreach(ExcelCell cell in excelFile.Worksheets[0].Rows[1].Cells) ///cell.Style.Rotation = 30; /// ///

///
/// Following code creates horizontal, vertical and rectangular cell ranges and demonstrates how ///indexing works different in different context. SetBorders ///method is used to mark outside borders of the rectangular range. /// ///Dim cr As CellRange = excelFile.Worksheets(0).Rows(1).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(3).Value = "D2" ///cr("B").Value = "B2" /// ///cr = excelFile.Worksheets(0).Columns(4).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(2).Value = "E3" ///cr("5").Value = "E5" /// ///cr = excelFile.Worksheets(0).Cells.GetSubrange("F2", "J8") ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed) /// ///cr("I7").Value = cr.IndexingMode ///cr(0, 0).Value = "F2" ///cr("G3").Value = "G3" ///cr(5).Value = "F3" ' Cell range width is 5 (F G H I J). /// /// ///CellRange cr = excelFile.Worksheets[0].Rows[1].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[3].Value = "D2"; ///cr["B"].Value = "B2"; /// ///cr = excelFile.Worksheets[0].Columns[4].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[2].Value = "E3"; ///cr["5"].Value = "E5"; /// ///cr = excelFile.Worksheets[0].Cells.GetSubrange("F2", "J8"); ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed); /// ///cr["I7"].Value = cr.IndexingMode; ///cr[0,0].Value = "F2"; ///cr["G3"].Value = "G3"; ///cr[5].Value = "F3"; // Cell range width is 5 (F G H I J). /// /// public class CellRange : AbstractRange, IEnumerable { // Methods internal CellRange(ExcelWorksheet parent) : base(parent) { this.lastRow = 0xffff; this.lastColumn = 0xff; } internal CellRange(ExcelWorksheet parent, int firstRow, int firstColumn, int lastRow, int lastColumn) : base(parent) { ExcelRowCollection.ExceptionIfRowOutOfRange(firstRow); ExcelColumnCollection.ExceptionIfColumnOutOfRange(firstColumn); ExcelRowCollection.ExceptionIfRowOutOfRange(lastRow); ExcelColumnCollection.ExceptionIfColumnOutOfRange(lastColumn); if (lastRow < firstRow) { throw new ArgumentOutOfRangeException("", lastRow, "Argument lastRow can't be smaller than firstRow."); } if (lastColumn < firstColumn) { throw new ArgumentOutOfRangeException("", lastColumn, "Argument lastColumn can't be smaller than firstColumn."); } this.firstRow = firstRow; this.firstColumn = firstColumn; this.lastRow = lastRow; this.lastColumn = lastColumn; } /// ///Copies this cell range to another position in the same worksheet. /// ///Full name of the top-left cell of the destination range. /// ///

topLeftCell specifies position of the top-left cell of ///the destination cell range.

///

Destination cell range has the same width and height as this cell range.

///

is thrown if destination range: /// ///breaks Excel worksheet row or column limit, ///overlaps with source range, or ///overlaps with existing merged range. ///

///
///Thrown if destination range is invalid. public void CopyTo(string topLeftCell) { this.CopyTo(base.Parent, topLeftCell); } /// ///Copies this cell range to another worksheet. /// ///Destination worksheet. ///Full name of the top-left cell of the destination range. /// ///

topLeftCell specifies position of the top-left cell of ///the destination cell range.

///

Destination cell range has the same width and height as this cell range.

///

is thrown if destination range: /// ///breaks Excel worksheet row or column limit, ///overlaps with source range, or ///overlaps with existing merged range. ///

///
///Thrown if destination range is invalid. public void CopyTo(ExcelWorksheet destinationWorksheet, string topLeftCell) { int num1; int num2; CellRange.PositionToRowColumn(topLeftCell, out num1, out num2); this.CopyTo(destinationWorksheet, num1, num2); } ///Copies this cell range to the specified position. /// ///Copies this cell range to another position in the same worksheet. /// ///Absolute index of the destination row. ///Absolute index of the destination column. /// ///

absoluteRow and absoluteColumn specify position of the top-left cell of ///the destination cell range.

///

Destination cell range has the same width and height as this cell range.

///

is thrown if destination range: /// ///breaks Excel worksheet row or column limit, ///overlaps with source range, or ///overlaps with existing merged range. ///

///
///Thrown if destination range is invalid. public void CopyTo(int absoluteRow, int absoluteColumn) { this.CopyTo(base.Parent, absoluteRow, absoluteColumn); } /// ///Copies this cell range to another worksheet. /// ///Destination worksheet. ///Absolute index of the destination row. ///Absolute index of the destination column. /// ///

absoluteRow and absoluteColumn specify position of the top-left cell of ///the destination cell range.

///

Destination cell range has the same width and height as this cell range.

///

is thrown if destination range: /// ///breaks Excel worksheet row or column limit, ///overlaps with source range, or ///overlaps with existing merged range. ///

///
///Thrown if destination range is invalid. public void CopyTo(ExcelWorksheet destinationWorksheet, int absoluteRow, int absoluteColumn) { CellRange range1; try { range1 = destinationWorksheet.Cells.GetSubrangeAbsolute(absoluteRow, absoluteColumn, absoluteRow + this.Height, absoluteColumn + this.Width); } catch (Exception) { throw new ArgumentException("Destination range is incorrectly specified."); } if (this.Overlaps(range1)) { throw new ArgumentException("Destination range can't overlap with source range."); } if (range1.IsAnyCellMerged) { throw new ArgumentException("Destination range can't overlap with existing merged range."); } int num1 = absoluteRow - this.firstRow; int num2 = absoluteColumn - this.firstColumn; Hashtable hashtable1 = new Hashtable(); CellRangeEnumerator enumerator1 = this.GetReadEnumerator(); while (enumerator1.MoveNext()) { ExcelCell cell1 = enumerator1.CurrentCell; ExcelCell cell2 = destinationWorksheet.Rows[enumerator1.CurrentRow + num1].AllocatedCells[enumerator1.CurrentColumn + num2]; cell2.Value = cell1.Value; cell2.Style = cell1.Style; CellRange range2 = cell1.MergedRange; if (range2 != null) { hashtable1[range2] = range2; } } foreach (MergedCellRange range3 in hashtable1.Values) { destinationWorksheet.Cells.GetSubrangeAbsolute(range3.firstRow + num1, range3.firstColumn + num2, range3.lastRow + num1, range3.lastColumn + num2).Merged = true; } } /// ///Determines whether the specified CellRange is equal ///to the current CellRange. /// ///Object of CellRange type. ///true if the specified CellRange is equal ///to the current CellRange; otherwise, false. public override bool Equals(object obj) { CellRange range1 = (CellRange) obj; if (((this.firstRow == range1.firstRow) && (this.firstColumn == range1.firstColumn)) && (this.lastRow == range1.lastRow)) { return (this.lastColumn == range1.lastColumn); } return false; } internal void ExceptionIfRowColumnOutOfRange(int row, int column) { if (this.IsRowColumnOutOfRange(row, column)) { throw new ArgumentException("Row or column index is invalid or out of required range."); } } internal void FixFirstRowIndex(int rowIndex, int offset) { this.firstRow = Math.Min(Math.Max((int) (this.firstRow + offset), rowIndex), 0xffff); } internal void FixLastRowIndex(int rowIndex, int offset) { this.lastRow = Math.Min(Math.Max((int) (this.lastRow + offset), (int) (rowIndex - 1)), 0xffff); } /// ///Returns an enumerator for the CellRange (all cells). /// /// ///Returns default enumerator that iterates all cells in the range. If you are only reading existing ///cells (values or formatting), use more appropriate . /// public IEnumerator GetEnumerator() { return new CellRangeEnumerator(this, false); } /// ///Returns the hash code of this object. /// ///Hash code. public override int GetHashCode() { return (((this.firstRow ^ this.firstColumn) ^ this.lastRow) ^ this.lastColumn); } /// ///Returns enumerator for the CellRange (only allocated cells). /// /// ///Returns enumerator that iterates only already allocated cells in the range. If you are only reading existing ///cells (values or formatting), use this enumerator as it is faster and doesn't allocate unnecessary cells. /// public CellRangeEnumerator GetReadEnumerator() { return new CellRangeEnumerator(this, true); } /// ///Returns new cell range using start and end position. /// ///Name of first (top-left) cell. ///Name of last (bottom-right) cell. /// ///New cell range must be within this cell range. /// /// Following code creates horizontal, vertical and rectangular cell ranges and demonstrates how ///indexing works different in different context. SetBorders ///method is used to mark outside borders of the rectangular range. /// ///Dim cr As CellRange = excelFile.Worksheets(0).Rows(1).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(3).Value = "D2" ///cr("B").Value = "B2" /// ///cr = excelFile.Worksheets(0).Columns(4).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(2).Value = "E3" ///cr("5").Value = "E5" /// ///cr = excelFile.Worksheets(0).Cells.GetSubrange("F2", "J8") ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed) /// ///cr("I7").Value = cr.IndexingMode ///cr(0, 0).Value = "F2" ///cr("G3").Value = "G3" ///cr(5).Value = "F3" ' Cell range width is 5 (F G H I J). /// /// ///CellRange cr = excelFile.Worksheets[0].Rows[1].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[3].Value = "D2"; ///cr["B"].Value = "B2"; /// ///cr = excelFile.Worksheets[0].Columns[4].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[2].Value = "E3"; ///cr["5"].Value = "E5"; /// ///cr = excelFile.Worksheets[0].Cells.GetSubrange("F2", "J8"); ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed); /// ///cr["I7"].Value = cr.IndexingMode; ///cr[0,0].Value = "F2"; ///cr["G3"].Value = "G3"; ///cr[5].Value = "F3"; // Cell range width is 5 (F G H I J). /// /// ///Thrown if arguments are out of range. /// /// /// /// public CellRange GetSubrange(string firstCell, string lastCell) { int num1; int num2; int num3; int num4; CellRange.PositionToRowColumn(firstCell, out num1, out num2); CellRange.PositionToRowColumn(lastCell, out num3, out num4); return this.GetSubrangeAbsolute(num1, num2, num3, num4); } /// ///Returns new cell range using absolute indexing. /// ///Absolute index of the first row. ///Absolute index of the first column. ///Absolute index of the last row. ///Absolute index of the last column. /// ///New cell range must be within this cell range. /// ///Thrown if arguments are out of range. /// /// /// /// /// /// public CellRange GetSubrangeAbsolute(int firstRow, int firstColumn, int lastRow, int lastColumn) { if (((firstRow < this.firstRow) || (firstRow > this.lastRow)) || ((firstColumn < this.firstColumn) || (lastColumn > this.lastColumn))) { throw new ArgumentException("Specified subrange must be within this cell range."); } return new CellRange(base.Parent, firstRow, firstColumn, lastRow, lastColumn); } /// ///Returns new cell range using relative indexing. /// ///Relative index of the first row. ///Relative index of the first column. ///Width of new cell range in columns. ///Height of new cell range in rows. /// ///New cell range must be within this cell range. /// ///Thrown if arguments are out of range. /// /// /// /// public CellRange GetSubrangeRelative(int relativeRow, int relativeColumn, int width, int height) { int num1 = this.firstRow + relativeRow; int num2 = this.firstColumn + relativeColumn; return this.GetSubrangeAbsolute(num1, num2, (num1 + height) - 1, (num2 + width) - 1); } internal bool IsRowColumnOutOfRange(int row, int column) { if (((row >= this.firstRow) && (row <= this.lastRow)) && ((column >= this.firstColumn) && (column <= this.lastColumn))) { return false; } return true; } /// ///Checks if this cell range overlaps with another cell range. /// ///Cell range. ///true if cell ranges overlap; otherwise, false. public bool Overlaps(CellRange range) { if ((base.Parent == range.Parent) && this.SectionsOverlap(this.firstColumn, this.lastColumn, range.firstColumn, range.lastColumn)) { return this.SectionsOverlap(this.firstRow, this.lastRow, range.firstRow, range.lastRow); } return false; } /// ///Converts position string ("A1", "BN27", etc.) to row and column index. /// ///Position string. ///Row index. ///Column index. public static void PositionToRowColumn(string position, out int row, out int column) { bool flag1; CellRange.PositionToRowColumn(position, out row, out column, out flag1); if (flag1) { throw new ArgumentException("Position is not in format RowNameColumnName."); } } internal static void PositionToRowColumn(string position, out int row, out int column, out bool wrongFormat) { string text1 = position.Split(new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9' } , 2)[0]; if ((text1.Length == 0) || (text1.Length == position.Length)) { int num1; column = num1 = -1; row = num1; wrongFormat = true; } else { string text2 = position.Remove(0, text1.Length); row = ExcelRowCollection.RowNameToIndex(text2); column = ExcelColumnCollection.ColumnNameToIndex(text1); wrongFormat = false; } } /// ///Converts row and column index to position string ("A1", "BN27", etc.). /// ///Row index. ///Column index. ///Position string. public static string RowColumnToPosition(int row, int column) { return (ExcelColumnCollection.ColumnIndexToName(column) + ExcelRowCollection.RowIndexToName(row)); } private bool SectionsOverlap(int sectionAStart, int sectionAEnd, int sectionBStart, int sectionBEnd) { if (sectionAEnd >= sectionBStart) { return (sectionBEnd >= sectionAStart); } return false; } /// ///Sets borders on one or more excel cells, taking cell position into account. /// ///Borders to set. ///Line color. ///Line style. /// Following code creates horizontal, vertical and rectangular cell ranges and demonstrates how ///indexing works different in different context. SetBorders ///method is used to mark outside borders of the rectangular range. /// ///Dim cr As CellRange = excelFile.Worksheets(0).Rows(1).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(3).Value = "D2" ///cr("B").Value = "B2" /// ///cr = excelFile.Worksheets(0).Columns(4).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(2).Value = "E3" ///cr("5").Value = "E5" /// ///cr = excelFile.Worksheets(0).Cells.GetSubrange("F2", "J8") ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed) /// ///cr("I7").Value = cr.IndexingMode ///cr(0, 0).Value = "F2" ///cr("G3").Value = "G3" ///cr(5).Value = "F3" ' Cell range width is 5 (F G H I J). /// /// ///CellRange cr = excelFile.Worksheets[0].Rows[1].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[3].Value = "D2"; ///cr["B"].Value = "B2"; /// ///cr = excelFile.Worksheets[0].Columns[4].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[2].Value = "E3"; ///cr["5"].Value = "E5"; /// ///cr = excelFile.Worksheets[0].Cells.GetSubrange("F2", "J8"); ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed); /// ///cr["I7"].Value = cr.IndexingMode; ///cr[0,0].Value = "F2"; ///cr["G3"].Value = "G3"; ///cr[5].Value = "F3"; // Cell range width is 5 (F G H I J). /// /// public override void SetBorders(MultipleBorders multipleBorders, Color lineColor, LineStyle lineStyle) { MergedCellRange range1 = this.MergedRange; if (range1 != null) { range1.SetBorders(multipleBorders, lineColor, lineStyle); } else { for (int num1 = this.firstRow; num1 <= this.lastRow; num1++) { for (int num2 = this.firstColumn; num2 <= this.lastColumn; num2++) { MultipleBorders borders1 = multipleBorders; if (num1 < this.lastRow) { borders1 &= ((MultipleBorders) (-3)); } if (num1 > this.firstRow) { borders1 &= ((MultipleBorders) (-2)); } if (num2 < this.lastColumn) { borders1 &= ((MultipleBorders) (-9)); } if (num2 > this.firstColumn) { borders1 &= ((MultipleBorders) (-5)); } base.Parent.Rows[num1].AllocatedCells[num2].SetBorders(borders1, lineColor, lineStyle); } } } } /// ///Returns a that represents the current CellRange. /// /// ///A that represents the current CellRange. /// public override string ToString() { if ((this.Width <= 1) && (this.Height <= 1)) { return (ExcelColumnCollection.ColumnIndexToName(this.firstColumn) + ExcelRowCollection.RowIndexToName(this.firstRow)); } string[] textArray1 = new string[] { ExcelColumnCollection.ColumnIndexToName(this.firstColumn), ExcelRowCollection.RowIndexToName(this.firstRow), ":", ExcelColumnCollection.ColumnIndexToName(this.lastColumn), ExcelRowCollection.RowIndexToName(this.lastRow) } ; return string.Concat(textArray1); } // Properties /// ///Gets name of the last (bottom-right) cell in this cell range. /// public string EndPosition { get { return CellRange.RowColumnToPosition(this.lastRow, this.lastColumn); } } /// ///Gets index of the first (leftmost) column. /// public int FirstColumnIndex { get { return this.firstColumn; } } /// ///Gets index of the first (topmost) row. /// public int FirstRowIndex { get { return this.firstRow; } } /// ///Gets or sets formula string. /// /// ///

ExcelLite can read and write formulas, but can not calculate formula results. When you open a XLS file in ///MS Excel, formula results will be calculated automaticaly.

///

During setting formula string ExcelLite formula parser will use English culture to parse numbers.

///

Currently supported formula features are: /// ///Named cell ///Named range ///Absolute cell/range ///Relative cell/range ///Functions( partly, see the list of supported functions below ) ///Missed argument ///Unary operator ///Binary operator ///Parentheses ///3d cell reference ///3d cell range reference ///Boolean ///Integer ///Float ///String ///Error /// ///

///

///Currently unsupported formula features are: /// ///Const array ///Array formula ///R1C1 reference /// ///

///

///Currently supported functions are: /// ///NOW ///SECOND ///MINUTE ///HOUR ///WEEKDAY ///YEAR ///MONTH ///DAY ///TIME ///DATE ///RAND ///TEXT ///VAR ///MOD ///NOT ///OR ///AND ///FALSE ///TRUE ///VALUE ///LEN ///MID ///ROUND ///SIGN ///INT ///ABS ///LN ///EXP ///SQRT ///PI ///COS ///SIN ///COLUMN ///ROW ///MAX ///MIN ///AVERAGE ///SUM ///IF ///COUNT /// ///

///

///For more information on formulas, consult Microsoft Excel documentation. ///

///
///Thrown if property get is attempted on a cell range ///which is not merged. ///Following code demonstrates how to use formulas and named ranges. It shows next features: ///cell references (both absolute and relative), unary and binary operators, constand operands (integer and floating point), ///functions and named cell ranges. /// ///ws.Cells("A1").Value = 5 ///ws.Cells("A2").Value = 6 ///ws.Cells("A3").Value = 10 /// ///ws.Cells("C1").Formula = "=A1+A2" ///ws.Cells("C2").Formula = "=$A$1-A3" ///ws.Cells("C3").Formula = "=COUNT(A1:A3)" ///ws.Cells("C4").Formula = "=AVERAGE($A$1:$A$3)" ///ws.Cells("C5").Formula = "=SUM(A1:A3,2,3)" ///ws.Cells("C7").Formula = "= 123 - (-(-(23.5)))" /// ///ws.NamedRanges.Add("DataRange", ws.Cells.GetSubrange("A1", "A3")) ///ws.Cells("C8").Formula = "=MAX(DataRange)" /// ///Dim cr As CellRange = ws.Cells.GetSubrange("B9","C10") ///cr.Merged = True ///cr.Formula = "=A1*25" /// /// ///ws.Cells["A1"].Value = 5; ///ws.Cells["A2"].Value = 6; ///ws.Cells["A3"].Value = 10; /// ///ws.Cells["C1"].Formula = "=A1+A2"; ///ws.Cells["C2"].Formula = "=$A$1-A3"; ///ws.Cells["C3"].Formula = "=COUNT(A1:A3)"; ///ws.Cells["C4"].Formula = "=AVERAGE($A$1:$A$3)"; ///ws.Cells["C5"].Formula = "=SUM(A1:A3,2,3)"; ///ws.Cells["C7"].Formula = "= 123 - (-(-(23.5)))"; /// ///ws.NamedRanges.Add("DataRange", ws.Cells.GetSubrange("A1", "A3")); ///ws.Cells["C8"].Formula = "=MAX(DataRange)"; /// ///CellRange cr = ws.Cells.GetSubrange("B9", "C10"); ///cr.Merged = true; ///cr.Formula = "=A1*25"; /// /// ///NamedRangeCollection.Add public override string Formula { get { MergedCellRange range1 = this.MergedRange; if (range1 == null) { throw new InvalidOperationException("Cell range has defined formula only if it is merged."); } return range1.Formula; } set { MergedCellRange range1 = this.MergedRange; if (range1 != null) { range1.Formula = value; } else { base.Parent.ParentExcelFile.ExceptionIfOverAffectedCellsLimit(this.Height * this.Width); foreach (ExcelCell cell1 in this) { cell1.Formula = value; } } } } /// ///Gets height of this cell range, in rows. /// public int Height { get { return ((this.lastRow - this.firstRow) + 1); } } /// ///Gets indexing mode used for cell range. /// /// ///

If Height is 1, indexing mode ///is Horizontal.

///

Otherwise, if Width is 1, indexing mode ///is Vertical.

///

Otherwise, indexing mode is ///Rectangular.

///
/// Following code creates horizontal, vertical and rectangular cell ranges and demonstrates how ///indexing works different in different context. SetBorders ///method is used to mark outside borders of the rectangular range. /// ///Dim cr As CellRange = excelFile.Worksheets(0).Rows(1).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(3).Value = "D2" ///cr("B").Value = "B2" /// ///cr = excelFile.Worksheets(0).Columns(4).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(2).Value = "E3" ///cr("5").Value = "E5" /// ///cr = excelFile.Worksheets(0).Cells.GetSubrange("F2", "J8") ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed) /// ///cr("I7").Value = cr.IndexingMode ///cr(0, 0).Value = "F2" ///cr("G3").Value = "G3" ///cr(5).Value = "F3" ' Cell range width is 5 (F G H I J). /// /// ///CellRange cr = excelFile.Worksheets[0].Rows[1].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[3].Value = "D2"; ///cr["B"].Value = "B2"; /// ///cr = excelFile.Worksheets[0].Columns[4].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[2].Value = "E3"; ///cr["5"].Value = "E5"; /// ///cr = excelFile.Worksheets[0].Cells.GetSubrange("F2", "J8"); ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed); /// ///cr["I7"].Value = cr.IndexingMode; ///cr[0,0].Value = "F2"; ///cr["G3"].Value = "G3"; ///cr[5].Value = "F3"; // Cell range width is 5 (F G H I J). /// /// public RangeIndexingMode IndexingMode { get { if (this.Height == 1) { return RangeIndexingMode.Horizontal; } if (this.Width == 1) { return RangeIndexingMode.Vertical; } return RangeIndexingMode.Rectangular; } } /// ///Returns true is any cell in this cell range is merged; otherwise, false. /// public bool IsAnyCellMerged { get { IEnumerator enumerator1 = this.GetReadEnumerator(); while (enumerator1.MoveNext()) { if (((ExcelCell) enumerator1.Current).MergedRange != null) { return true; } } return false; } } /// ///Returns true if all cells in cell range or merged range have default ///cell style; otherwise, false. /// public override bool IsStyleDefault { get { MergedCellRange range1 = this.MergedRange; if (range1 == null) { throw new InvalidOperationException("Cell range has defined style only if it is merged."); } return range1.IsStyleDefault; } } /// ///Gets excel cell at the specified relative position. /// ///The zero-based relative row position. ///The zero-based relative column position. /// ///Absolute position of excel cell is calculated by adding relativeRow and relativeColumn to ///FirstRowIndex and ///FirstColumnIndex. /// /// Following code creates horizontal, vertical and rectangular cell ranges and demonstrates how ///indexing works different in different context. SetBorders ///method is used to mark outside borders of the rectangular range. /// ///Dim cr As CellRange = excelFile.Worksheets(0).Rows(1).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(3).Value = "D2" ///cr("B").Value = "B2" /// ///cr = excelFile.Worksheets(0).Columns(4).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(2).Value = "E3" ///cr("5").Value = "E5" /// ///cr = excelFile.Worksheets(0).Cells.GetSubrange("F2", "J8") ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed) /// ///cr("I7").Value = cr.IndexingMode ///cr(0, 0).Value = "F2" ///cr("G3").Value = "G3" ///cr(5).Value = "F3" ' Cell range width is 5 (F G H I J). /// /// ///CellRange cr = excelFile.Worksheets[0].Rows[1].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[3].Value = "D2"; ///cr["B"].Value = "B2"; /// ///cr = excelFile.Worksheets[0].Columns[4].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[2].Value = "E3"; ///cr["5"].Value = "E5"; /// ///cr = excelFile.Worksheets[0].Cells.GetSubrange("F2", "J8"); ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed); /// ///cr["I7"].Value = cr.IndexingMode; ///cr[0,0].Value = "F2"; ///cr["G3"].Value = "G3"; ///cr[5].Value = "F3"; // Cell range width is 5 (F G H I J). /// /// public ExcelCell this[int relativeRow, int relativeColumn] { get { int num1 = this.firstRow + relativeRow; int num2 = this.firstColumn + relativeColumn; this.ExceptionIfRowColumnOutOfRange(num1, num2); return base.Parent.Rows[num1].AllocatedCells[num2]; } } /// ///Gets excel cell with the specified full or partial name. /// ///Full or partial name of the cell. /// ///

If IndexingMode is ///RangeIndexingMode.Rectangular full name of ///the cell must be used (for example; "A1", "D7", etc.).

///

If IndexingMode is ///RangeIndexingMode.Horizontal column name ///must be used (for example; "A", "D", etc.).

///

If IndexingMode is ///RangeIndexingMode.Vertical row name ///must be used (for example; "1", "7", etc.).

///
/// Following code creates horizontal, vertical and rectangular cell ranges and demonstrates how ///indexing works different in different context. SetBorders ///method is used to mark outside borders of the rectangular range. /// ///Dim cr As CellRange = excelFile.Worksheets(0).Rows(1).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(3).Value = "D2" ///cr("B").Value = "B2" /// ///cr = excelFile.Worksheets(0).Columns(4).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(2).Value = "E3" ///cr("5").Value = "E5" /// ///cr = excelFile.Worksheets(0).Cells.GetSubrange("F2", "J8") ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed) /// ///cr("I7").Value = cr.IndexingMode ///cr(0, 0).Value = "F2" ///cr("G3").Value = "G3" ///cr(5).Value = "F3" ' Cell range width is 5 (F G H I J). /// /// ///CellRange cr = excelFile.Worksheets[0].Rows[1].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[3].Value = "D2"; ///cr["B"].Value = "B2"; /// ///cr = excelFile.Worksheets[0].Columns[4].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[2].Value = "E3"; ///cr["5"].Value = "E5"; /// ///cr = excelFile.Worksheets[0].Cells.GetSubrange("F2", "J8"); ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed); /// ///cr["I7"].Value = cr.IndexingMode; ///cr[0,0].Value = "F2"; ///cr["G3"].Value = "G3"; ///cr[5].Value = "F3"; // Cell range width is 5 (F G H I J). /// /// /// public ExcelCell this[string contextName] { get { int num1; int num2; switch (this.IndexingMode) { case RangeIndexingMode.Rectangular: { CellRange.PositionToRowColumn(contextName, out num1, out num2); break; } case RangeIndexingMode.Horizontal: { num1 = this.firstRow; num2 = ExcelColumnCollection.ColumnNameToIndex(contextName); break; } case RangeIndexingMode.Vertical: { num1 = ExcelRowCollection.RowNameToIndex(contextName); num2 = this.firstColumn; break; } default: { throw new Exception("Internal: Unknown indexing mode."); } } this.ExceptionIfRowColumnOutOfRange(num1, num2); return base.Parent.Rows[num1].AllocatedCells[num2]; } } ///Gets excel cell with the specified name or at the specified position. /// ///Gets excel cell at the specified index. /// ///The zero-based context index of the cell. /// ///

If IndexingMode is ///RangeIndexingMode.Horizontal context index ///is specifying relative column position.

///

If IndexingMode is ///RangeIndexingMode.Vertical context index ///is specifying relative row position.

///

If IndexingMode is ///RangeIndexingMode.Rectangular context index ///is specifying cell index inside cell range. The cell at ///StartPosition has index 0, and the cell at ///EndPosition has index of ///Width x ///Height - 1.

///
/// Following code creates horizontal, vertical and rectangular cell ranges and demonstrates how ///indexing works different in different context. SetBorders ///method is used to mark outside borders of the rectangular range. /// ///Dim cr As CellRange = excelFile.Worksheets(0).Rows(1).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(3).Value = "D2" ///cr("B").Value = "B2" /// ///cr = excelFile.Worksheets(0).Columns(4).Cells /// ///cr(0).Value = cr.IndexingMode ///cr(2).Value = "E3" ///cr("5").Value = "E5" /// ///cr = excelFile.Worksheets(0).Cells.GetSubrange("F2", "J8") ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed) /// ///cr("I7").Value = cr.IndexingMode ///cr(0, 0).Value = "F2" ///cr("G3").Value = "G3" ///cr(5).Value = "F3" ' Cell range width is 5 (F G H I J). /// /// ///CellRange cr = excelFile.Worksheets[0].Rows[1].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[3].Value = "D2"; ///cr["B"].Value = "B2"; /// ///cr = excelFile.Worksheets[0].Columns[4].Cells; /// ///cr[0].Value = cr.IndexingMode; ///cr[2].Value = "E3"; ///cr["5"].Value = "E5"; /// ///cr = excelFile.Worksheets[0].Cells.GetSubrange("F2", "J8"); ///cr.SetBorders(MultipleBorders.Outside, Color.Navy, LineStyle.Dashed); /// ///cr["I7"].Value = cr.IndexingMode; ///cr[0,0].Value = "F2"; ///cr["G3"].Value = "G3"; ///cr[5].Value = "F3"; // Cell range width is 5 (F G H I J). /// /// /// public ExcelCell this[int contextIndex] { get { switch (this.IndexingMode) { case RangeIndexingMode.Rectangular: { int num1 = this.Width; int num2 = contextIndex / num1; int num3 = contextIndex % num1; return this[num2, num3]; } case RangeIndexingMode.Horizontal: { return this[0, contextIndex]; } case RangeIndexingMode.Vertical: { return this[contextIndex, 0]; } } throw new Exception("Internal: Unknown indexing mode."); } } /// ///Gets index of the last (rightmost) column. /// public int LastColumnIndex { get { return this.lastColumn; } } /// ///Gets index of the last (bottommost) row. /// public int LastRowIndex { get { return this.lastRow; } } /// ///Gets or sets whether cells in this range are merged. /// /// ///

By setting this property to true, you are merging all the cells ///(ExcelCell) in this range. Merging process will fail if any ///of the cells in the range is already merged.

///

When modifying merged cell, whole merged range is modified. For example, if you set ///ExcelCell.Value, value of merged range will be modified. ///You can find out if the cell is merged by checking if ///ExcelCell.MergedRange property is different ///than null.

///
///Thrown when merged range can't be created because some of the cells ///in the range are already merged. public virtual bool Merged { get { return (this.MergedRange != null); } set { if (!this.Merged) { if (!value) { return; } base.Parent.ParentExcelFile.ExceptionIfOverAffectedCellsLimit(this.Height * this.Width); base.Parent.MergedRanges.Add(new MergedCellRange(this)); } else if (!value) { base.Parent.ParentExcelFile.ExceptionIfOverAffectedCellsLimit(this.Height * this.Width); base.Parent.MergedRanges.Remove(this.MergedRange); } } } private MergedCellRange MergedRange { get { MergedCellRange range1 = (MergedCellRange) this[0, 0].MergedRange; if ((range1 == null) || ((range1.Width == this.Width) && (range1.Height == this.Height))) { return range1; } return null; } } /// ///Gets name of the first (top-left) cell in this cell range. /// public string StartPosition { get { return CellRange.RowColumnToPosition(this.firstRow, this.firstColumn); } } /// ///Gets or sets cell style (CellStyle) on one or more excel cells. /// /// ///

Property set will set style of multiple cells or of a merged range.

///

Property get has meaning only if range is Merged; ///otherwise, exception is thrown.

///

Note that for Style property set on a cell range that ///is not merged, you can't use the following format: /// ///Dim cr As CellRange = excelFile.Worksheets(0).Rows(1).Cells ///cr.Style.Rotation = 30 /// /// ///CellRange cr = excelFile.Worksheets[0].Rows[1].Cells; ///cr.Style.Rotation = 30; /// ///because that would first call Style property get method and that ///will certainly fail because Style property get is defined only ///for a merged cell range.

Instead you can use two different code patterns, depending on whether you want to replace or combine the existing ///cell range styles with the new style.

///If you want to replace cell style on every cell in a cell range use the following code: /// ///Dim cr As CellRange = excelFile.Worksheets(0).Rows(1).Cells ///Dim style As CellStyle = New CellStyle() ///style.Rotation = 30 ///cr.Style = style /// /// ///CellRange cr = excelFile.Worksheets[0].Rows[1].Cells; ///CellStyle style = new CellStyle(); ///style.Rotation = 30; ///cr.Style = style; /// ///

///If you want to set cell style property on every cell in a cell range (other cell style property values will ///remain unchanged) use the following code: /// ///Dim cell As ExcelCell ///For Each cell In excelFile.Worksheets(0).Rows(1).Cells ///cell.Style.Rotation = 30 ///Next /// /// ///foreach(ExcelCell cell in excelFile.Worksheets[0].Rows[1].Cells) ///cell.Style.Rotation = 30; /// ///

///
///Thrown if property get is attempted on a cell range ///which is not merged. /// public override CellStyle Style { get { MergedCellRange range1 = this.MergedRange; if (range1 == null) { throw new InvalidOperationException("Cell range has defined style only if it is merged."); } return range1.Style; } set { MergedCellRange range1 = this.MergedRange; if (range1 != null) { range1.Style = value; } else { base.Parent.ParentExcelFile.ExceptionIfOverAffectedCellsLimit(this.Height * this.Width); foreach (ExcelCell cell1 in this) { cell1.Style = value; } } } } /// ///Gets or sets cell value on one or more excel cells. /// /// ///

Property set will set value of multiple cells or of a merged range.

///

Property get has meaning only if range is Merged; ///otherwise, exception is thrown.

///
///Thrown if property get is attempted on a cell range ///which is not merged. /// public override object Value { get { MergedCellRange range1 = this.MergedRange; if (range1 == null) { throw new InvalidOperationException("Cell range has defined value only if it is merged."); } return range1.Value; } set { MergedCellRange range1 = this.MergedRange; if (range1 != null) { range1.Value = value; } else { base.Parent.ParentExcelFile.ExceptionIfOverAffectedCellsLimit(this.Height * this.Width); foreach (ExcelCell cell1 in this) { cell1.Value = value; } } } } /// ///Gets width of this cell range, in columns. /// public int Width { get { return ((this.lastColumn - this.firstColumn) + 1); } } // Fields private int firstColumn; private int firstRow; private int lastColumn; private int lastRow; } }