CPF/CPF.ReoGrid/Formula/ExcelFunctions.cs
2024-06-24 10:15:59 +08:00

977 lines
23 KiB
C#

using System;
using System.Collections.Generic;
using CPF.ReoGrid.Data;
using CPF.ReoGrid.Utility;
namespace CPF.ReoGrid.Formula
{
internal static class ExcelFunctions
{
public static FormulaValue Sum(Cell cell, FormulaValue[] args)
{
double val = 0.0;
Func<int, int, Cell, bool> callFunc = null;
foreach (FormulaValue formulaValue in args)
{
FormulaValueType type = formulaValue.type;
FormulaValueType formulaValueType = type;
if (formulaValueType != FormulaValueType.Number)
{
if (formulaValueType == FormulaValueType.Range)
{
bool flag = cell == null || cell.Worksheet == null;
if (flag)
{
throw new FormulaTypeMismatchException(cell);
}
Worksheet worksheet = cell.Worksheet;
RangePosition range = (RangePosition)formulaValue.value;
Func<int, int, Cell, bool> iterator;
if ((iterator = callFunc) == null)
{
iterator = (callFunc = delegate(int r, int c, Cell inCell)
{
double num;
bool flag2 = CellUtility.TryGetNumberData(inCell.InnerData, out num);
if (flag2)
{
val += num;
}
return true;
});
}
worksheet.IterateCells(range, iterator);
}
}
else
{
val += (double)formulaValue.value;
}
}
return val;
}
public static FormulaValue SumIf(Cell cell, FormulaValue[] args)
{
bool flag = cell == null || cell.Worksheet == null;
FormulaValue result;
if (flag)
{
result = null;
}
else
{
bool flag2 = args[1].type != FormulaValueType.String;
if (flag2)
{
result = null;
}
else
{
double val = 0.0;
RangePosition sumRange = RangePosition.Empty;
bool flag3 = args[0].type == FormulaValueType.Range;
if (!flag3)
{
throw new FormulaTypeMismatchException(cell);
}
RangePosition evalRange = (RangePosition)args[0].value;
bool flag4 = args.Length > 2;
if (flag4)
{
bool flag5 = args[2].type != FormulaValueType.Range;
if (flag5)
{
throw new FormulaTypeMismatchException(cell);
}
sumRange = (RangePosition)args[2].value;
}
string input = (string)args[1].value;
STValueNode leftExp = new STValueNode(null);
STNode compExp = Parser.ParseInterCompareExp(cell, input);
int rows = cell.Worksheet.Rows;
int cols = cell.Worksheet.Columns;
double data = 0;
cell.Worksheet.IterateCells(evalRange, delegate(int r, int c, Cell inCell)
{
leftExp.Value = Evaluator.CreateFormulaValue(inCell);
compExp[0] = leftExp;
FormulaValue formulaValue = Evaluator.Evaluate(cell, compExp);
bool flag6 = formulaValue.type == FormulaValueType.Boolean && (bool)formulaValue.value;
if (flag6)
{
bool isEmpty = sumRange.IsEmpty;
if (isEmpty)
{
bool flag7 = CellUtility.TryGetNumberData(inCell.InnerData, out data);
if (flag7)
{
val += data;
}
}
else
{
int num = sumRange.Row + r - evalRange.Row;
int num2 = sumRange.Col + c - evalRange.Col;
bool flag8 = num < rows && num2 < cols;
if (flag8)
{
Cell cell2 = cell.Worksheet.GetCell(num, num2);
bool flag9 = cell2 != null && cell2.InnerData != null && CellUtility.TryGetNumberData(cell2.InnerData, out data);
if (flag9)
{
val += data;
}
}
}
}
return true;
});
result = val;
}
}
return result;
}
public static FormulaValue Count(Cell cell, FormulaValue[] args, bool includeEmpty = false)
{
double count = 0.0;
double data;
Func<int, int, Cell, bool> callFunc = null;
foreach (FormulaValue formulaValue in args)
{
switch (formulaValue.type)
{
case FormulaValueType.Number:
{
double count3 = count;
count = count3 + 1.0;
break;
}
case FormulaValueType.String:
{
bool flag = includeEmpty && !string.IsNullOrEmpty((string)formulaValue.value);
if (flag)
{
double count3 = count;
count = count3 + 1.0;
}
break;
}
case FormulaValueType.Range:
{
bool flag2 = cell == null || cell.Worksheet == null;
if (flag2)
{
return null;
}
Worksheet worksheet = cell.Worksheet;
RangePosition range = (RangePosition)formulaValue.value;
Func<int, int, Cell, bool> iterator;
if ((iterator = callFunc) == null)
{
iterator = (callFunc = delegate(int r, int c, Cell inCell)
{
bool includeEmpty2 = includeEmpty;
if (includeEmpty2)
{
bool flag3 = inCell.InnerData != null;
if (flag3)
{
double count2 = count;
count = count2 + 1.0;
}
}
else
{
bool flag4 = CellUtility.TryGetNumberData(inCell.InnerData, out data);
if (flag4)
{
double count2 = count;
count = count2 + 1.0;
}
}
return true;
});
}
worksheet.IterateCells(range, iterator);
break;
}
}
}
return count;
}
public static FormulaValue CountIf(Cell cell, FormulaValue[] args)
{
bool flag = cell == null || cell.Worksheet == null;
FormulaValue result;
if (flag)
{
result = null;
}
else
{
double count = 0.0;
bool flag2 = args[0].type == FormulaValueType.Range;
if (!flag2)
{
throw new FormulaTypeMismatchException(cell);
}
RangePosition range = (RangePosition)args[0].value;
STValueNode leftExp = new STValueNode(null);
FormulaValue formulaValue = args[1];
bool flag3 = args[1].type == FormulaValueType.String;
STNode compExp;
if (flag3)
{
compExp = Parser.ParseInterCompareExp(cell, (string)formulaValue.value);
}
else
{
compExp = new STNode(STNodeType.EQUALS, 0, 0, new List<STNode>(2)
{
leftExp,
new STValueNode(args[1])
});
}
cell.Worksheet.IterateCells(range, delegate(int r, int c, Cell inCell)
{
leftExp.Value = Evaluator.CreateFormulaValue(inCell);
compExp[0] = leftExp;
FormulaValue formulaValue2 = Evaluator.Evaluate(cell, compExp);
bool flag4 = formulaValue2.type == FormulaValueType.Boolean && (bool)formulaValue2.value;
if (flag4)
{
//double count = count;
count += 1.0;
}
return true;
});
result = count;
}
return result;
}
public static FormulaValue Average(Cell cell, FormulaValue[] args)
{
double val = 0.0;
double count = 0.0;
Func<int, int, Cell, bool> callFunc = null;
foreach (FormulaValue formulaValue in args)
{
FormulaValueType type = formulaValue.type;
FormulaValueType formulaValueType = type;
if (formulaValueType != FormulaValueType.Nil)
{
if (formulaValueType != FormulaValueType.Number)
{
if (formulaValueType == FormulaValueType.Range)
{
bool flag = cell == null || cell.Worksheet == null;
if (flag)
{
return null;
}
Worksheet worksheet = cell.Worksheet;
RangePosition range = (RangePosition)formulaValue.value;
Func<int, int, Cell, bool> iterator;
if ((iterator = callFunc) == null)
{
iterator = (callFunc = delegate(int r, int c, Cell inCell)
{
double num;
bool flag2 = CellUtility.TryGetNumberData(inCell.InnerData, out num);
if (flag2)
{
val += num;
double count2 = count;
count = count2 + 1.0;
}
return true;
});
}
worksheet.IterateCells(range, iterator);
}
}
else
{
val += (double)formulaValue.value;
double count3 = count;
count = count3 + 1.0;
}
}
}
return (count > 0.0) ? (val / count) : 0.0;
}
public static FormulaValue AverageIf(Cell cell, FormulaValue[] args)
{
bool flag = cell == null || cell.Worksheet == null;
FormulaValue result;
if (flag)
{
result = null;
}
else
{
bool flag2 = args[1].type != FormulaValueType.String;
if (flag2)
{
result = null;
}
else
{
double val = 0.0;
double count = 0.0;
RangePosition sumRange = RangePosition.Empty;
bool flag3 = args[0].type == FormulaValueType.Range;
if (!flag3)
{
throw new FormulaTypeMismatchException(cell);
}
RangePosition evalRange = (RangePosition)args[0].value;
bool flag4 = args.Length > 2;
if (flag4)
{
bool flag5 = args[2].type != FormulaValueType.Range;
if (flag5)
{
throw new FormulaTypeMismatchException(cell);
}
sumRange = (RangePosition)args[2].value;
}
string input = (string)args[1].value;
STValueNode leftExp = new STValueNode(null);
STNode compExp = Parser.ParseInterCompareExp(cell, input);
int rows = cell.Worksheet.Rows;
int cols = cell.Worksheet.Columns;
double data = 0;
cell.Worksheet.IterateCells(evalRange, delegate(int r, int c, Cell inCell)
{
leftExp.Value = Evaluator.CreateFormulaValue(inCell);
compExp[0] = leftExp;
FormulaValue formulaValue = Evaluator.Evaluate(cell, compExp);
bool flag6 = formulaValue.type == FormulaValueType.Boolean && (bool)formulaValue.value;
if (flag6)
{
bool isEmpty = sumRange.IsEmpty;
if (isEmpty)
{
bool flag7 = CellUtility.TryGetNumberData(inCell.InnerData, out data);
if (flag7)
{
val += data;
//double count = count;
count += 1.0;
}
}
else
{
int num = sumRange.Row + r - evalRange.Row;
int num2 = sumRange.Col + c - evalRange.Col;
bool flag8 = num < rows && num2 < cols;
if (flag8)
{
Cell cell2 = cell.Worksheet.GetCell(num, num2);
bool flag9 = cell2 != null && cell2.InnerData != null && CellUtility.TryGetNumberData(cell2.InnerData, out data);
if (flag9)
{
val += data;
//double count = count;
count += 1.0;
}
}
}
}
return true;
});
result = ((count > 0.0) ? (val / count) : FormulaValue.Nil);
}
}
return result;
}
public static FormulaValue Min(Cell cell, FormulaValue[] args)
{
double min = 0.0;
bool first = true;
double data;
Func<int, int, Cell, bool> callFunc = null;
foreach (FormulaValue formulaValue in args)
{
FormulaValueType type = formulaValue.type;
FormulaValueType formulaValueType = type;
if (formulaValueType != FormulaValueType.Number)
{
if (formulaValueType != FormulaValueType.Range)
{
return null;
}
bool flag = cell == null || cell.Worksheet == null;
if (flag)
{
throw new FormulaTypeMismatchException(cell);
}
Worksheet worksheet = cell.Worksheet;
RangePosition range = (RangePosition)formulaValue.value;
Func<int, int, Cell, bool> iterator;
if ((iterator = callFunc) == null)
{
iterator = (callFunc = delegate(int r, int c, Cell inCell)
{
bool flag3 = CellUtility.TryGetNumberData(inCell.InnerData, out data);
if (flag3)
{
bool first2 = first;
if (first2)
{
min = data;
first = false;
}
else
{
bool flag4 = min > data;
if (flag4)
{
min = data;
}
}
}
return true;
});
}
worksheet.IterateCells(range, iterator);
}
else
{
data = (double)formulaValue.value;
bool first3 = first;
if (first3)
{
min = data;
first = false;
}
else
{
bool flag2 = min > data;
if (flag2)
{
min = data;
}
}
}
}
return min;
}
public static FormulaValue Max(Cell cell, FormulaValue[] args)
{
double max = 0.0;
bool first = true;
double data;
Func<int, int, Cell, bool> callFunc = null;
foreach (FormulaValue formulaValue in args)
{
FormulaValueType type = formulaValue.type;
FormulaValueType formulaValueType = type;
if (formulaValueType != FormulaValueType.Number)
{
if (formulaValueType != FormulaValueType.Range)
{
return null;
}
bool flag = cell == null || cell.Worksheet == null;
if (flag)
{
throw new FormulaTypeMismatchException(cell);
}
Worksheet worksheet = cell.Worksheet;
RangePosition range = (RangePosition)formulaValue.value;
Func<int, int, Cell, bool> iterator;
if ((iterator = callFunc) == null)
{
iterator = (callFunc = delegate(int r, int c, Cell inCell)
{
bool flag3 = CellUtility.TryGetNumberData(inCell.InnerData, out data);
if (flag3)
{
bool first2 = first;
if (first2)
{
max = data;
first = false;
}
else
{
bool flag4 = max < data;
if (flag4)
{
max = data;
}
}
}
return true;
});
}
worksheet.IterateCells(range, iterator);
}
else
{
data = (double)formulaValue.value;
bool first3 = first;
if (first3)
{
max = data;
first = false;
}
else
{
bool flag2 = max < data;
if (flag2)
{
max = data;
}
}
}
}
return max;
}
public static FormulaValue VLookup(Cell cell, FormulaValue[] args)
{
FormulaValue formulaValue = args[0];
FormulaValue formulaValue2 = args[1];
FormulaValue formulaValue3 = args[2];
FormulaValue formulaValue4 = (args.Length > 3) ? args[3] : FormulaValue.Nil;
bool flag = false;
double matchValueDouble = 0.0;
string matchValueText = null;
bool matchNumber = true;
bool flag2 = formulaValue2.type != FormulaValueType.Range || formulaValue3.type != FormulaValueType.Number;
FormulaValue result;
if (flag2)
{
result = null;
}
else
{
bool flag3 = formulaValue4.type > FormulaValueType.Nil;
if (flag3)
{
bool flag4 = formulaValue4.type != FormulaValueType.Boolean;
if (flag4)
{
return null;
}
flag = (bool)formulaValue4.value;
}
RangePosition searchRange = (RangePosition)formulaValue2.value;
FormulaValueType type = formulaValue.type;
FormulaValueType formulaValueType = type;
if (formulaValueType != FormulaValueType.Number)
{
if (formulaValueType != FormulaValueType.String)
{
return null;
}
matchValueText = (string)formulaValue.value;
matchNumber = false;
}
else
{
matchValueDouble = (double)formulaValue.value;
}
int num = (int)Math.Ceiling((double)formulaValue3.value);
int row = searchRange.EndRow;
bool flag5 = false;
bool flag6 = flag;
if (flag6)
{
for (int j = searchRange.Row; j <= searchRange.EndRow; j++)
{
Cell cell2 = cell.Worksheet.GetCell(j, searchRange.Col);
bool flag7 = cell2 != null;
if (flag7)
{
bool matchNumber3 = matchNumber;
if (matchNumber3)
{
double num2 = 0.0;
bool flag8 = CellUtility.TryGetNumberData(cell2.Data, out num2);
if (flag8)
{
bool flag9 = matchValueDouble == num2;
if (flag9)
{
row = j;
flag5 = true;
break;
}
}
}
else
{
string displayText = cell2.DisplayText;
bool flag10 = string.Compare(matchValueText, displayText, true) == 0;
if (flag10)
{
row = j;
flag5 = true;
break;
}
}
}
}
bool flag11 = !flag5;
if (flag11)
{
return null;
}
}
else
{
row = ArrayHelper.QuickFind(searchRange.Row, searchRange.EndRow, delegate(int i)
{
Cell cell3 = cell.Worksheet.GetCell(i, searchRange.Col);
bool flag12 = cell3 == null;
int result2;
if (flag12)
{
result2 = 0;
}
else
{
bool matchNumber2 = matchNumber;
if (matchNumber2)
{
double num3 = 0.0;
bool flag13 = CellUtility.TryGetNumberData(cell3.Data, out num3);
if (flag13)
{
bool flag14 = matchValueDouble < num3;
if (flag14)
{
return -1;
}
bool flag15 = matchValueDouble > num3;
if (flag15)
{
return 1;
}
}
result2 = 0;
}
else
{
string displayText2 = cell3.DisplayText;
result2 = string.Compare(matchValueText, displayText2, true);
}
}
return result2;
});
}
result = Evaluator.CreateFormulaValue(cell.Worksheet.GetCellData(row, searchRange.Col + num - 1));
}
return result;
}
public static FormulaValue Round(Cell cell, FormulaValue[] args)
{
bool flag = args[0].type != FormulaValueType.Number;
if (flag)
{
throw new FormulaTypeMismatchException(cell);
}
int digits = 0;
bool flag2 = args.Length > 1;
if (flag2)
{
bool flag3 = args[1].type != FormulaValueType.Number;
if (flag3)
{
throw new FormulaTypeMismatchException(cell);
}
digits = (int)((double)args[1].value);
}
return Math.Round((double)args[0].value, digits);
}
public static FormulaValue Ceiling(Cell cell, FormulaValue[] args)
{
bool flag = args[0].type != FormulaValueType.Number;
if (flag)
{
throw new FormulaTypeMismatchException(cell);
}
double num = (double)args[0].value;
bool flag2 = args.Length < 2;
FormulaValue result;
if (flag2)
{
result = Math.Ceiling(num);
}
else
{
bool flag3 = args[1].type != FormulaValueType.Number;
if (flag3)
{
throw new FormulaTypeMismatchException(cell);
}
double num2 = (double)args[1].value;
bool flag4 = num2 == 0.0;
if (flag4)
{
result = 0.0;
}
else
{
double num3 = num % num2;
bool flag5 = num3 == 0.0;
if (flag5)
{
result = num;
}
else
{
result = num - num3 + num2;
}
}
}
return result;
}
public static FormulaValue Floor(Cell cell, FormulaValue[] args)
{
bool flag = args[0].type != FormulaValueType.Number;
if (flag)
{
throw new FormulaTypeMismatchException(cell);
}
double num = (double)args[0].value;
bool flag2 = args.Length < 2;
FormulaValue result;
if (flag2)
{
result = Math.Floor(num);
}
else
{
bool flag3 = args[1].type != FormulaValueType.Number;
if (flag3)
{
throw new FormulaTypeMismatchException(cell);
}
double num2 = (double)args[1].value;
bool flag4 = num2 == 0.0;
if (flag4)
{
result = 0.0;
}
else
{
result = num - num % num2;
}
}
return result;
}
public static FormulaValue Row(Cell cell, List<STNode> args)
{
bool flag = args == null || args.Count < 1;
FormulaValue result;
if (flag)
{
result = (double)(cell.Row + 1);
}
else
{
bool flag2 = args[0].Type != STNodeType.CELL;
if (flag2)
{
throw new FormulaParameterMismatchException(cell);
}
result = (double)(((STCellNode)args[0]).Position.Row + 1);
}
return result;
}
public static FormulaValue Column(Cell cell, List<STNode> args)
{
bool flag = args == null || args.Count < 1;
FormulaValue result;
if (flag)
{
result = (double)(cell.Column + 1);
}
else
{
bool flag2 = args[0].Type != STNodeType.CELL;
if (flag2)
{
throw new FormulaParameterMismatchException(cell);
}
result = (double)(((STCellNode)args[0]).Position.Col + 1);
}
return result;
}
public static FormulaValue Address(Cell cell, FormulaValue[] args)
{
bool flag = args[0].type != FormulaValueType.Number || args[1].type != FormulaValueType.Number;
if (flag)
{
throw new FormulaTypeMismatchException(cell);
}
return new CellPosition((int)((double)args[0].value) - 1, (int)((double)args[1].value) - 1).ToAbsoluteAddress();
}
public static FormulaValue Indirect(Cell cell, FormulaValue[] args)
{
bool flag = args[0].type != FormulaValueType.String;
if (flag)
{
throw new FormulaTypeMismatchException(cell);
}
string address = (string)args[0].value;
bool flag2 = CellPosition.IsValidAddress(address);
FormulaValue result;
if (flag2)
{
CellPosition pos = new CellPosition(address);
result = ((cell == null || cell.Worksheet == null) ? null : Evaluator.CreateFormulaValue(cell.Worksheet.GetCell(pos)));
}
else
{
bool flag3 = RangePosition.IsValidAddress(address);
if (!flag3)
{
throw new FormulaTypeMismatchException(cell);
}
result = new RangePosition(address);
}
return result;
}
public static FormulaValue If(Cell cell, STNode funNode)
{
bool flag = funNode.Children.Count < 1;
if (flag)
{
throw new FormulaParameterMismatchException(cell);
}
FormulaValue[] array = new FormulaValue[]
{
null,
null,
null
};
array[0] = Evaluator.Evaluate(cell, funNode.Children[0]);
bool flag2 = array[0].type != FormulaValueType.Boolean;
if (flag2)
{
throw new FormulaTypeMismatchException(cell);
}
bool flag3 = (bool)array[0].value;
FormulaValue result;
if (flag3)
{
bool flag4 = funNode.Children.Count > 1;
if (flag4)
{
array[1] = Evaluator.Evaluate(cell, funNode.Children[1]);
}
result = array[1];
}
else
{
bool flag5 = funNode.Children.Count > 2;
if (flag5)
{
array[2] = Evaluator.Evaluate(cell, funNode.Children[2]);
}
result = array[2];
}
return result;
}
public static FormulaValue And(Cell cell, List<STNode> list)
{
foreach (STNode node in list)
{
FormulaValue formulaValue = Evaluator.Evaluate(cell, node);
bool flag = formulaValue.type == FormulaValueType.Boolean;
if (flag)
{
bool flag2 = !(bool)formulaValue.value;
if (flag2)
{
return false;
}
}
else
{
bool flag3 = formulaValue.type == FormulaValueType.Number;
if (!flag3)
{
throw new FormulaTypeMismatchException(cell);
}
bool flag4 = (double)formulaValue.value == 0.0;
if (flag4)
{
return false;
}
}
}
return true;
}
public static FormulaValue Or(Cell cell, List<STNode> list)
{
bool flag = list == null || list.Count <= 0;
if (flag)
{
throw new FormulaParameterMismatchException(cell, "At least one parameter is needed, but nothing specified.");
}
foreach (STNode node in list)
{
FormulaValue formulaValue = Evaluator.Evaluate(cell, node);
bool flag2 = formulaValue.type == FormulaValueType.Boolean;
if (flag2)
{
bool flag3 = (bool)formulaValue.value;
if (flag3)
{
return true;
}
}
else
{
bool flag4 = formulaValue.type == FormulaValueType.Number;
if (!flag4)
{
throw new FormulaTypeMismatchException(cell);
}
bool flag5 = (double)formulaValue.value != 0.0;
if (flag5)
{
return true;
}
}
}
return false;
}
public static FormulaValue Not(Cell cell, STNode arg0)
{
FormulaValue formulaValue = Evaluator.Evaluate(cell, arg0);
bool flag = formulaValue.type != FormulaValueType.Boolean;
if (flag)
{
throw new FormulaTypeMismatchException(cell);
}
return !(bool)formulaValue.value;
}
}
}