| using System.Collections; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| namespace AppsheetEpplus; | |
| public class EpplusExcelDataProvider : ExcelDataProvider { | |
| public class RangeInfo : IRangeInfo { | |
| internal ExcelWorksheet _ws; | |
| private readonly CellsStoreEnumerator<object> _values; | |
| private readonly int _fromRow; | |
| private readonly int _toRow; | |
| private readonly int _fromCol; | |
| private readonly int _toCol; | |
| private int _cellCount; | |
| private readonly ExcelAddressBase _address; | |
| private readonly 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(_fromRow, _fromCol, _toRow, _toCol); | |
| _address._ws = ws.Name; | |
| _values = new(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; | |
| } | |
| if (_values.Next()) { | |
| _values.Reset(); | |
| return false; | |
| } | |
| return true; | |
| } | |
| } | |
| public bool IsMulti { | |
| get { | |
| if (_cellCount == 0) { | |
| if (_values.Next() && _values.Next()) { | |
| _values.Reset(); | |
| return true; | |
| } | |
| _values.Reset(); | |
| return false; | |
| } | |
| if (_cellCount > 1) { | |
| return true; | |
| } | |
| return false; | |
| } | |
| } | |
| public ICellInfo Current => _cell; | |
| public ExcelWorksheet Worksheet => _ws; | |
| public void Dispose() {} | |
| object IEnumerator.Current => 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; | |
| } | |
| IEnumerator IEnumerable.GetEnumerator() { | |
| return this; | |
| } | |
| public ExcelAddressBase Address => _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(_fromRow + rowOffset, _fromCol + colOffset); | |
| } | |
| return _ws.GetValue(_values.Row + rowOffset, _values.Column + colOffset); | |
| } | |
| } | |
| public class CellInfo : ICellInfo { | |
| private readonly ExcelWorksheet _ws; | |
| private readonly CellsStoreEnumerator<object> _values; | |
| internal CellInfo(ExcelWorksheet ws, CellsStoreEnumerator<object> values) { | |
| _ws = ws; | |
| _values = values; | |
| } | |
| public string Address => _values.CellAddress; | |
| public int Row => _values.Row; | |
| public int Column => _values.Column; | |
| public string Formula => _ws.GetFormula(_values.Row, _values.Column); | |
| public object Value => _values.Value; | |
| public double ValueDouble => ConvertUtil.GetValueDouble(_values.Value, true); | |
| public double ValueDoubleLogical => ConvertUtil.GetValueDouble(_values.Value); | |
| public bool IsHiddenRow { | |
| get { | |
| var row = _ws._values.GetValue(_values.Row, 0) as RowInternal; | |
| if (row != null) { | |
| return row.Hidden || row.Height == 0; | |
| } | |
| return false; | |
| } | |
| } | |
| public bool IsExcelError => ExcelErrorValue.Values.IsErrorValue(_values.Value); | |
| public IList<Token> Tokens => _ws._formulaTokens.GetValue(_values.Row, _values.Column); | |
| } | |
| public class NameInfo : 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 ExcelWorkbook _workbook; | |
| private ExcelWorksheet _currentWorksheet; | |
| private Dictionary<ulong, INameInfo> _names = new(); | |
| public EpplusExcelDataProvider(ExcelWorkbook workbook) { | |
| _workbook = workbook; | |
| } | |
| public override ExcelNamedRangeCollection GetWorksheetNames(string worksheet) { | |
| var ws = _workbook.Worksheets[worksheet]; | |
| if (ws != null) { | |
| return ws.Names; | |
| } | |
| return null; | |
| } | |
| public override ExcelNamedRangeCollection GetWorkbookNameValues() { | |
| return _workbook.Names; | |
| } | |
| public override IRangeInfo GetRange( | |
| string worksheet, | |
| int fromRow, | |
| int fromCol, | |
| int toRow, | |
| int toCol) { | |
| SetCurrentWorksheet(worksheet); | |
| var wsName = string.IsNullOrEmpty(worksheet) ? _currentWorksheet.Name : worksheet; | |
| var ws = _workbook.Worksheets[wsName]; | |
| return new RangeInfo(ws, fromRow, fromCol, toRow, toCol); | |
| } | |
| public override IRangeInfo GetRange(string worksheet, int row, int column, string address) { | |
| var addr = new ExcelAddress(worksheet, address); | |
| if (addr.Table != null) { | |
| addr.SetRcFromTable(_workbook, new(row, column, row, column)); | |
| } | |
| //SetCurrentWorksheet(addr.WorkSheet); | |
| var wsName = string.IsNullOrEmpty(addr.WorkSheet) ? _currentWorksheet.Name : addr.WorkSheet; | |
| var ws = _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 (_workbook.Names.ContainsKey(name)) { | |
| nameItem = _workbook.Names[name]; | |
| } else { | |
| return null; | |
| } | |
| ws = null; | |
| } else { | |
| ws = _workbook.Worksheets[worksheet]; | |
| if (ws != null && ws.Names.ContainsKey(name)) { | |
| nameItem = ws.Names[name]; | |
| } else if (_workbook.Names.ContainsKey(name)) { | |
| nameItem = _workbook.Names[name]; | |
| } else { | |
| return null; | |
| } | |
| } | |
| id = ExcelCellBase.GetCellId(nameItem.LocalSheetId, nameItem.Index, 0); | |
| if (_names.ContainsKey(id)) { | |
| return _names[id]; | |
| } | |
| 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 = _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); | |
| return _currentWorksheet.MergedCells[row, column] != null; | |
| } | |
| 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); | |
| } | |
| public override ExcelCellAddress GetDimensionEnd(string worksheet) { | |
| ExcelCellAddress address = null; | |
| try { | |
| address = _workbook.Worksheets[worksheet].Dimension.End; | |
| } catch {} | |
| return address; | |
| } | |
| private void SetCurrentWorksheet(ExcelAddressInfo addressInfo) { | |
| if (addressInfo.WorksheetIsSpecified) { | |
| _currentWorksheet = _workbook.Worksheets[addressInfo.Worksheet]; | |
| } else if (_currentWorksheet == null) { | |
| _currentWorksheet = _workbook.Worksheets.First(); | |
| } | |
| } | |
| private void SetCurrentWorksheet(string worksheetName) { | |
| if (!string.IsNullOrEmpty(worksheetName)) { | |
| _currentWorksheet = _workbook.Worksheets[worksheetName]; | |
| } else { | |
| _currentWorksheet = _workbook.Worksheets.First(); | |
| } | |
| } | |
| public override int ExcelMaxColumns => ExcelPackage.MaxColumns; | |
| public override int ExcelMaxRows => 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 = _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(format, -1); | |
| } | |
| return ExcelRangeBase.FormatValue(value, ft, format, ft.NetFormat); | |
| } | |
| public override List<Token> GetRangeFormulaTokens(string worksheetName, int row, int column) { | |
| return _workbook.Worksheets[worksheetName]._formulaTokens.GetValue(row, column); | |
| } | |
| public override bool IsRowHidden(string worksheetName, int row) { | |
| var b = | |
| _workbook.Worksheets[worksheetName].Row(row).Height == 0 | |
| || _workbook.Worksheets[worksheetName].Row(row).Hidden; | |
| return b; | |
| } | |
| public override void Reset() { | |
| _names = new(); //Reset name cache. | |
| } | |
| } |