| using System; |
| using System.Collections.Generic; |
| using System.Linq; |
| using System.Text; |
| using OfficeOpenXml.FormulaParsing; |
| using OfficeOpenXml.FormulaParsing.ExcelUtilities; |
| using OfficeOpenXml.FormulaParsing.Excel.Functions; |
| using OfficeOpenXml.FormulaParsing.LexicalAnalysis; |
| using OfficeOpenXml.Utils; |
| using OfficeOpenXml.Style.XmlAccess; |
| |
| namespace OfficeOpenXml.FormulaParsing |
| { |
| public class EpplusExcelDataProvider : ExcelDataProvider |
| { |
| public class RangeInfo : IRangeInfo |
| { |
| internal ExcelWorksheet _ws; |
| CellsStoreEnumerator<object> _values = null; |
| int _fromRow, _toRow, _fromCol, _toCol; |
| int _cellCount = 0; |
| ExcelAddressBase _address; |
| ICellInfo _cell; |
| |
| public RangeInfo(ExcelWorksheet ws, int fromRow, int fromCol, int toRow, int toCol) |
| { |
| _ws = ws; |
| _fromRow = fromRow; |
| _fromCol = fromCol; |
| _toRow = toRow; |
| _toCol = toCol; |
| _address = new ExcelAddressBase(_fromRow, _fromCol, _toRow, _toCol); |
| _values = new CellsStoreEnumerator<object>(ws._values, _fromRow, _fromCol, _toRow, _toCol); |
| _cell = new CellInfo(_ws, _values); |
| } |
| |
| public int GetNCells() |
| { |
| return ((_toRow - _fromRow) + 1) * ((_toCol - _fromCol) + 1); |
| } |
| |
| public bool IsEmpty |
| { |
| get |
| { |
| if (_cellCount > 0) |
| { |
| return false; |
| } |
| else if (_values.Next()) |
| { |
| _values.Reset(); |
| return false; |
| } |
| else |
| { |
| return true; |
| } |
| } |
| } |
| public bool IsMulti |
| { |
| get |
| { |
| if (_cellCount == 0) |
| { |
| if (_values.Next() && _values.Next()) |
| { |
| _values.Reset(); |
| return true; |
| } |
| else |
| { |
| _values.Reset(); |
| return false; |
| } |
| } |
| else if (_cellCount > 1) |
| { |
| return true; |
| } |
| return false; |
| } |
| } |
| |
| public ICellInfo Current |
| { |
| get { return _cell; } |
| } |
| |
| public void Dispose() |
| { |
| //_values = null; |
| //_ws = null; |
| //_cell = null; |
| } |
| |
| object System.Collections.IEnumerator.Current |
| { |
| get |
| { |
| return this; |
| } |
| } |
| |
| public bool MoveNext() |
| { |
| _cellCount++; |
| return _values.MoveNext(); |
| } |
| |
| public void Reset() |
| { |
| _values.Init(); |
| } |
| |
| |
| public bool NextCell() |
| { |
| _cellCount++; |
| return _values.MoveNext(); |
| } |
| |
| public IEnumerator<ICellInfo> GetEnumerator() |
| { |
| Reset(); |
| return this; |
| } |
| |
| System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() |
| { |
| return this; |
| } |
| |
| |
| public ExcelAddressBase Address |
| { |
| get { return _address; } |
| } |
| |
| public object GetValue(int row, int col) |
| { |
| return _ws.GetValue(row, col); |
| } |
| |
| public object GetOffset(int rowOffset, int colOffset) |
| { |
| if (_values.Row < _fromRow || _values.Column < _fromCol) |
| { |
| return _ws.GetValue(_fromCol + rowOffset, _fromCol + colOffset); |
| } |
| else |
| { |
| return _ws.GetValue(_values.Row + rowOffset, _values.Column + colOffset); |
| } |
| } |
| } |
| public class CellInfo : ICellInfo |
| { |
| ExcelWorksheet _ws; |
| CellsStoreEnumerator<object> _values; |
| internal CellInfo(ExcelWorksheet ws, CellsStoreEnumerator<object> values) |
| { |
| _ws = ws; |
| _values = values; |
| } |
| public string Address |
| { |
| get { return _values.CellAddress; } |
| } |
| |
| public int Row |
| { |
| get { return _values.Row; } |
| } |
| |
| public int Column |
| { |
| get { return _values.Column; } |
| } |
| |
| public string Formula |
| { |
| get |
| { |
| return _ws.GetFormula(_values.Row, _values.Column); |
| } |
| } |
| |
| public object Value |
| { |
| get { return _values.Value; } |
| } |
| |
| public double ValueDouble |
| { |
| get { return ConvertUtil.GetValueDouble(_values.Value, true); } |
| } |
| public double ValueDoubleLogical |
| { |
| get { return ConvertUtil.GetValueDouble(_values.Value, false); } |
| } |
| public bool IsHiddenRow |
| { |
| get |
| { |
| var row=_ws._values.GetValue(_values.Row, 0) as RowInternal; |
| if(row != null) |
| { |
| return row.Hidden || row.Height==0; |
| } |
| else |
| { |
| return false; |
| } |
| } |
| } |
| |
| public bool IsExcelError |
| { |
| get { return ExcelErrorValue.Values.IsErrorValue(_values.Value); } |
| } |
| |
| public IList<Token> Tokens |
| { |
| get |
| { |
| return _ws._formulaTokens.GetValue(_values.Row, _values.Column); |
| } |
| } |
| |
| } |
| public class NameInfo : ExcelDataProvider.INameInfo |
| { |
| public ulong Id { get; set; } |
| public string Worksheet { get; set; } |
| public string Name { get; set; } |
| public string Formula { get; set; } |
| public IList<Token> Tokens { get; internal set; } |
| public object Value { get; set; } |
| } |
| |
| private readonly ExcelPackage _package; |
| private ExcelWorksheet _currentWorksheet; |
| private RangeAddressFactory _rangeAddressFactory; |
| private Dictionary<ulong, INameInfo> _names=new Dictionary<ulong,INameInfo>(); |
| |
| public EpplusExcelDataProvider(ExcelPackage package) |
| { |
| _package = package; |
| |
| _rangeAddressFactory = new RangeAddressFactory(this); |
| } |
| |
| public override ExcelNamedRangeCollection GetWorksheetNames() |
| { |
| return _package.Workbook.Worksheets.First().Names; |
| } |
| |
| public override ExcelNamedRangeCollection GetWorkbookNameValues() |
| { |
| return _package.Workbook.Names; |
| } |
| public override IRangeInfo GetRange(string worksheet, int row, int column, string address) |
| { |
| var addr = new ExcelAddress(worksheet, address); |
| if (addr.Table != null) |
| { |
| addr.SetRCFromTable(_package, new ExcelAddressBase(row, column, row, column)); |
| } |
| //SetCurrentWorksheet(addr.WorkSheet); |
| var wsName = string.IsNullOrEmpty(addr.WorkSheet) ? _currentWorksheet.Name : addr.WorkSheet; |
| var ws = _package.Workbook.Worksheets[wsName]; |
| //return new CellsStoreEnumerator<object>(ws._values, addr._fromRow, addr._fromCol, addr._toRow, addr._toCol); |
| return new RangeInfo(ws, addr._fromRow, addr._fromCol, addr._toRow, addr._toCol); |
| } |
| public override INameInfo GetName(string worksheet, string name) |
| { |
| ExcelNamedRange nameItem; |
| ulong id; |
| ExcelWorksheet ws; |
| if (string.IsNullOrEmpty(worksheet)) |
| { |
| if(_package._workbook.Names.ContainsKey(name)) |
| { |
| nameItem = _package._workbook.Names[name]; |
| } |
| else |
| { |
| return null; |
| } |
| ws = null; |
| } |
| else |
| { |
| ws = _package._workbook.Worksheets[worksheet]; |
| if (ws !=null && ws.Names.ContainsKey(name)) |
| { |
| nameItem = _package._workbook.Names[name]; |
| } |
| else if (_package._workbook.Names.ContainsKey(name)) |
| { |
| nameItem = _package._workbook.Names[name]; |
| } |
| else |
| { |
| return null; |
| } |
| } |
| id = ExcelAddressBase.GetCellID(nameItem.LocalSheetId, nameItem.Index, 0); |
| |
| if (_names.ContainsKey(id)) |
| { |
| return _names[id]; |
| } |
| else |
| { |
| var ni = new NameInfo() |
| { |
| Id = id, |
| Name = name, |
| Worksheet = nameItem.Worksheet==null ? nameItem._ws : nameItem.Worksheet.Name, |
| Formula = nameItem.Formula |
| }; |
| if (nameItem._fromRow > 0) |
| { |
| ni.Value = new RangeInfo(nameItem.Worksheet ?? ws, nameItem._fromRow, nameItem._fromCol, nameItem._toRow, nameItem._toCol); |
| } |
| else |
| { |
| ni.Value = nameItem.Value; |
| } |
| _names.Add(id, ni); |
| return ni; |
| } |
| } |
| public override IEnumerable<object> GetRangeValues(string address) |
| { |
| SetCurrentWorksheet(ExcelAddressInfo.Parse(address)); |
| var addr = new ExcelAddress(address); |
| var wsName = string.IsNullOrEmpty(addr.WorkSheet) ? _currentWorksheet.Name : addr.WorkSheet; |
| var ws = _package.Workbook.Worksheets[wsName]; |
| return (new CellsStoreEnumerator<object>(ws._values, addr._fromRow, addr._fromCol, addr._toRow, addr._toCol)); |
| } |
| |
| |
| public object GetValue(int row, int column) |
| { |
| return _currentWorksheet._values.GetValue(row, column); |
| } |
| |
| public bool IsMerged(int row, int column) |
| { |
| return _currentWorksheet._flags.GetFlagValue(row, column, CellFlags.Merged); |
| } |
| |
| public bool IsHidden(int row, int column) |
| { |
| return _currentWorksheet.Column(column).Hidden || _currentWorksheet.Column(column).Width == 0 || |
| _currentWorksheet.Row(row).Hidden || _currentWorksheet.Row(column).Height == 0; |
| } |
| |
| public override object GetCellValue(string sheetName, int row, int col) |
| { |
| SetCurrentWorksheet(sheetName); |
| return _currentWorksheet._values.GetValue(row, col); |
| } |
| |
| private void SetCurrentWorksheet(ExcelAddressInfo addressInfo) |
| { |
| if (addressInfo.WorksheetIsSpecified) |
| { |
| _currentWorksheet = _package.Workbook.Worksheets[addressInfo.Worksheet]; |
| } |
| else if (_currentWorksheet == null) |
| { |
| _currentWorksheet = _package.Workbook.Worksheets.First(); |
| } |
| } |
| |
| private void SetCurrentWorksheet(string worksheetName) |
| { |
| if (!string.IsNullOrEmpty(worksheetName)) |
| { |
| _currentWorksheet = _package.Workbook.Worksheets[worksheetName]; |
| } |
| else |
| { |
| _currentWorksheet = _package.Workbook.Worksheets.First(); |
| } |
| |
| } |
| |
| //public override void SetCellValue(string address, object value) |
| //{ |
| // var addressInfo = ExcelAddressInfo.Parse(address); |
| // var ra = _rangeAddressFactory.Create(address); |
| // SetCurrentWorksheet(addressInfo); |
| // //var valueInfo = (ICalcEngineValueInfo)_currentWorksheet; |
| // //valueInfo.SetFormulaValue(ra.FromRow + 1, ra.FromCol + 1, value); |
| // _currentWorksheet.Cells[ra.FromRow + 1, ra.FromCol + 1].Value = value; |
| //} |
| |
| public override void Dispose() |
| { |
| _package.Dispose(); |
| } |
| |
| public override int ExcelMaxColumns |
| { |
| get { return ExcelPackage.MaxColumns; } |
| } |
| |
| public override int ExcelMaxRows |
| { |
| get { return ExcelPackage.MaxRows; } |
| } |
| |
| public override string GetRangeFormula(string worksheetName, int row, int column) |
| { |
| SetCurrentWorksheet(worksheetName); |
| return _currentWorksheet.GetFormula(row, column); |
| } |
| |
| public override object GetRangeValue(string worksheetName, int row, int column) |
| { |
| SetCurrentWorksheet(worksheetName); |
| return _currentWorksheet.GetValue(row, column); |
| } |
| public override string GetFormat(object value, string format) |
| { |
| var styles = _package.Workbook.Styles; |
| ExcelNumberFormatXml.ExcelFormatTranslator ft=null; |
| foreach(var f in styles.NumberFormats) |
| { |
| if(f.Format==format) |
| { |
| ft=f.FormatTranslator; |
| break; |
| } |
| } |
| if(ft==null) |
| { |
| ft=new ExcelNumberFormatXml.ExcelFormatTranslator(format, -1); |
| } |
| return ExcelRangeBase.FormatValue(value, ft,format, ft.NetFormat); |
| } |
| public override List<LexicalAnalysis.Token> GetRangeFormulaTokens(string worksheetName, int row, int column) |
| { |
| return _package.Workbook.Worksheets[worksheetName]._formulaTokens.GetValue(row, column); |
| } |
| |
| public override bool IsRowHidden(string worksheetName, int row) |
| { |
| var b = _package.Workbook.Worksheets[worksheetName].Row(row).Height == 0 || |
| _package.Workbook.Worksheets[worksheetName].Row(row).Hidden; |
| |
| return b; |
| } |
| } |
| } |
| |