blob: 8dfe6d1247983d25a3018395c65c8a2a2024d9d8 [file] [log] [blame]
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using OfficeOpenXml.FormulaParsing.ExcelUtilities;
using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
using OfficeOpenXml.Style.XmlAccess;
using OfficeOpenXml.Utils;
namespace OfficeOpenXml.FormulaParsing;
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.
}
}