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;
}
}