/******************************************************************************* * You may amend and distribute as you like, but don't remove this header! * * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets. * See http://www.codeplex.com/EPPlus for details. * * Copyright (C) 2011 Jan Källman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html * * All code and executables are provided "as is" with no warranty either express or implied. * The author accepts no liability for any damage or loss of business that this product may cause. * * Code change notes: * * Author Change Date ******************************************************************************* * Jan Källman Added 10-SEP-2009 * Jan Källman License changed GPL-->LGPL 2011-12-16 *******************************************************************************/ using System; using System.Collections.Generic; using System.Text; using System.Globalization; using OfficeOpenXml.Style; using System.Text.RegularExpressions; namespace OfficeOpenXml { internal class ExcelCell : ExcelCellBase, IExcelCell, IRangeID { [Flags] private enum flags { isMerged=1, isRichText=2, } #region Cell Private Properties private ExcelWorksheet _worksheet; private int _row; private int _col; internal string _formula=""; internal string _formulaR1C1 = ""; private Uri _hyperlink = null; string _dataType = ""; #endregion #region ExcelCell Constructor /// /// A cell in the worksheet. /// /// A reference to the worksheet /// The row number /// The column number internal ExcelCell(ExcelWorksheet worksheet, int row, int col) { if (row < 1 || col < 1) throw new ArgumentException("Negative row and column numbers are not allowed"); if (row > ExcelPackage.MaxRows || col > ExcelPackage.MaxColumns) throw new ArgumentException("Row or column numbers are out of range"); if (worksheet == null) throw new ArgumentException("Worksheet must be set to a valid reference"); _row = row; _col = col; _worksheet = worksheet; if (col < worksheet._minCol) worksheet._minCol = col; if (col > worksheet._maxCol) worksheet._maxCol = col; _sharedFormulaID = int.MinValue; IsRichText = false; } internal ExcelCell(ExcelWorksheet worksheet, string cellAddress) { _worksheet = worksheet; GetRowColFromAddress(cellAddress, out _row, out _col); if (_col < worksheet._minCol) worksheet._minCol = _col; if (_col > worksheet._maxCol) worksheet._maxCol = _col; _sharedFormulaID = int.MinValue; IsRichText = false; } #endregion internal ulong CellID { get { return GetCellID(_worksheet.SheetID, Row, Column); } } #region ExcelCell Public Properties /// /// Row number /// internal int Row { get { return _row; } set { _row = value; } } /// /// Column number /// internal int Column { get { return _col; } set { _col = value; } } /// /// The address /// internal string CellAddress { get { return GetAddress(_row, _col); } } /// /// Returns true if the cell's contents are numeric. /// public bool IsNumeric { get { return (Value is decimal || Value.GetType().IsPrimitive ); } } #region ExcelCell Value internal object _value = null; /// /// Gets/sets the value of the cell. /// public object Value { get { return _value; } set { SetValueRichText(value); if (IsRichText) IsRichText = false; } } internal void SetValueRichText(object value) { _value = value; if (value is string) DataType = "s"; else DataType = ""; Formula = ""; } /// /// If cell has inline formatting. /// public bool IsRichText { get; set; } /// /// If the cell is merged with other cells /// public bool Merge { get; internal set; } /// /// Merge Id /// internal int MergeId { get; set; } #endregion #region ExcelCell DataType /// /// Datatype /// TODO: remove /// internal string DataType { get { return (_dataType); } set { _dataType = value; } } #endregion #region ExcelCell Style string _styleName=null; /// /// Optional named style for the cell /// public string StyleName { get { if (_styleName == null) { foreach (var ns in _worksheet.Workbook.Styles.NamedStyles) { if (ns.StyleXfId == StyleID) { _styleName = ns.Name; break; } } if (_styleName == null) { _styleName = "Normal"; } } return _styleName; } set { _styleID = _worksheet.Workbook.Styles.GetStyleIdFromName(value); _styleName = value; } } int _styleID=0; /// /// The style ID for the cell. Reference to the style collection /// public int StyleID { get { if(_styleID>0) return _styleID; else if (_worksheet._rows != null && _worksheet._rows.ContainsKey(ExcelRow.GetRowID(_worksheet.SheetID, Row)) && _worksheet.Row(Row).StyleID>0) { return _worksheet.Row(Row).StyleID; } else { ExcelColumn col = GetColumn(Column); if(col==null) { return 0; } else { return col.StyleID; } } } set { _styleID = value; } } private ExcelColumn GetColumn(int col) { foreach (ExcelColumn column in _worksheet._columns) { if (col >= column.ColumnMin && col <= column.ColumnMax) { return column; } } return null; } internal int GetCellStyleID() { return _styleID; } public ExcelStyle Style { get { return _worksheet.Workbook.Styles.GetStyleObject(StyleID, _worksheet.PositionID, CellAddress); } } internal void SetNewStyleName(string Name, int Id) { _styleID = Id; _styleName = Name; } #endregion #region ExcelCell Hyperlink /// /// The cells cell's Hyperlink /// public Uri Hyperlink { get { return (_hyperlink); } set { _hyperlink = value; if ((Value == null || Value.ToString() == "")) { if (value is ExcelHyperLink) { Value = (value as ExcelHyperLink).Display; } else { Value = _hyperlink.AbsoluteUri; } } } } internal string HyperLinkRId { get; set; } #endregion #region ExcelCell Formula /// /// The cell's formula. /// public string Formula { get { if (SharedFormulaID < 0) { if (_formula == "") { return (TranslateFromR1C1(_formulaR1C1, Row, Column)); } else { return (_formula); } } else { if (_worksheet._sharedFormulas.ContainsKey(SharedFormulaID)) { var f = _worksheet._sharedFormulas[SharedFormulaID]; if (f.StartRow == Row && f.StartCol == Column) { return f.Formula; } else { return TranslateFromR1C1(TranslateToR1C1(f.Formula, f.StartRow, f.StartCol), Row, Column); } } else { throw(new Exception("Shared formula reference (SI) is invalid")); } } } set { _formula = value; _formulaR1C1 = ""; _sharedFormulaID = int.MinValue; if (_formula!="" && !_worksheet._formulaCells.ContainsKey(CellID)) { _worksheet._formulaCells.Add(this); } } } /// /// The cell's formula using R1C1 style. /// public string FormulaR1C1 { get { if (SharedFormulaID < 0) { if (_formulaR1C1 == "") { return TranslateToR1C1(_formula, Row, Column); } else { return (_formulaR1C1); } } else { if (_worksheet._sharedFormulas.ContainsKey(SharedFormulaID)) { var f = _worksheet._sharedFormulas[SharedFormulaID]; return TranslateToR1C1(f.Formula, f.StartRow, f.StartCol); } else { throw (new Exception("Shared formula reference (SI) is invalid")); } } } set { // Example cell content for formulas // RC1 // SUM(RC1:RC3) // R[-1]C[-2]+R[-1]C[-1] _formulaR1C1 = value; _formula = ""; SharedFormulaID = int.MinValue; if (!_worksheet._formulaCells.ContainsKey(CellID)) { _worksheet._formulaCells.Add(this); } } } internal int _sharedFormulaID; /// /// Id for the shared formula /// internal int SharedFormulaID { get { return _sharedFormulaID; } set { _sharedFormulaID = value; if(_worksheet._formulaCells.ContainsKey(CellID)) _worksheet._formulaCells.Delete(CellID); } } public bool IsArrayFormula { get; internal set; } #endregion /// /// Returns the cell's value as a string. /// /// The cell's value public override string ToString() { return Value.ToString(); } #endregion #region ExcelCell Private Methods #endregion #region IRangeID Members ulong IRangeID.RangeID { get { return GetCellID(_worksheet.SheetID, Row, Column); } set { _col = ((int)(value >> 15) & 0x3FF); _row = ((int)(value >> 29)); } } #endregion internal ExcelCell Clone(ExcelWorksheet added) { return Clone(added, _row, _col); } internal ExcelCell Clone(ExcelWorksheet added, int row, int col) { ExcelCell newCell = new ExcelCell(added, row, col); if(_hyperlink!=null) newCell.Hyperlink = Hyperlink; newCell._formula = _formula; newCell._formulaR1C1 = _formulaR1C1; newCell.IsRichText = IsRichText; newCell.Merge = Merge; newCell._sharedFormulaID = _sharedFormulaID; newCell._styleName = _styleName; newCell._styleID = _styleID; newCell._value = _value; return newCell; } } }