123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Collections;
- using Biff8Excel.Interfaces;
- using Biff8Excel.Excel;
- namespace Biff8Excel.Formulas
- {
- public class Calculator
- {
- //Calculate
- double[] arrStack = new double[100];
- ushort stackPointer;
- //ExcelCellLink m_cells;
- ExcelCellDictionary m_cells;
- IExternSheet m_externSheet;
- ushort m_thisSheetNumber;
- public Calculator()
- {
- //stackPointer = 0;
- }
- // If there are no sheets in the function string, use
- // this value to make sure we only reference cells from the formulas sheet
- internal ushort ThisSheetNumber
- {
- set { m_thisSheetNumber = value; }
- }
- internal IExternSheet ExternSheet
- {
- set { m_externSheet = value; }
- }
- internal ExcelCellDictionary CellCollection
- //internal ExcelCellLink CellCollection
- {
- set { m_cells = value; }
- }
- /// <summary>
- /// Procedure : Function EvaluteSupportedFunction
- /// </summary>
- /// <param name="funcString"></param>
- /// <returns></returns>
- private double EvaluteSupportedFunction(string funcString)
- {
- switch ( Globals.GetFunctionName(funcString))
- {
- case "SUM":
- return EvaluateSum(funcString);
- case "AVERAGE":
- return EvaluateAverage(funcString);
- case "COUNT":
- return EvaluateCount(funcString);
- default:
- return 0;
- }
- }
- private ushort GetSheetNumberFromName(string sheetName)
- {
- try
- {
- for (ushort i = 0; i < Globals.g_arrSheetNames.Length; i++)
- {
- if (Globals.g_arrSheetNames[i] == sheetName)
- return i;
- }
- throw new Biff8ExcelException("not find sheetName");
- }
- catch
- {
- throw;
- }
- }
- private ushort[] GetSheetRange(string funcString)
- {
- int pos;
- string reference;
- ushort first;
- ushort last;
- ushort[] result;
- string sheets;
- string sheet1;
- string sheet2;
- result = new ushort[2];
- reference = funcString;
- pos = reference.IndexOf("(");
- if (pos > -1)
- {
- //得到括号内的内容
- reference = reference.Substring(pos + 1, reference.Length - pos - 2);
- }
- // check for sheet references
- pos = reference.IndexOf("!");
- if (pos > -1)
- {
- sheets = reference.Substring(0, pos);
- //how many sheets are their
- pos = sheets.IndexOf(":");
- if (pos < 0)
- {
- last = first = GetSheetNumberFromName(sheets);
- }
- else
- {
- sheet1 = sheets.Substring(0, pos);
- if (sheets.Substring(pos + 1) == "$")
- sheet2 = sheets.Substring(pos + 2);
- else
- sheet2 = sheets.Substring(pos + 1);
- first = GetSheetNumberFromName(sheet1);
- last = GetSheetNumberFromName(sheet2);
- }
- result[0] = first;
- result[1] = last;
- }
- else
- {
- result[0] = m_thisSheetNumber;
- result[1] = m_thisSheetNumber;
- }
- // order the sheets 小的数在前
- if (result[0] > result[1])
- result[0] = (ushort)(result[1] + (result[1] = result[0]) * 0);
- return result;
- }
- //private bool IsAlphaNumeric(byte b)
- //{
- // if ((b >= 48 && b <= 57) || (b >= 65 && b <= 90) || (b >= 97 && b <= 123))
- // return true;
- // return false;
- //}
- private string GetAreaRef(string funcString)
- {
- //string area = "";
- StringBuilder area = new StringBuilder();
- int pos;
- //remove any Sheet references
- pos = funcString.IndexOf("!");
- if (pos > -1)
- {
- funcString = funcString.Substring(pos + 1);
- if (funcString.Substring(funcString.Length - 1) == ")")
- {
- funcString = funcString.Substring(0, funcString.Length - 1);
- return funcString;
- }
- }
- // Get the Cell references
- pos = funcString.IndexOf(":");
- if (pos < 0) return "";
- // get the left cell ref
- for (int i = (pos - 1); i >= 0; i--)
- {
- if (char.IsLetterOrDigit(funcString, i) && (funcString.Substring(i, 1) != "!"))
- //if (IsAlphaNumeric((byte)(funcString.Substring(i, 1).ToCharArray()[0])) && (funcString.Substring(i, 1) != "!"))
- area.Append(funcString.Substring(i, 1));
- else
- break;
- }
- string st = Globals.StrReverse(area.ToString()) + ":";
- area = new StringBuilder();
- area.Append(st);
- //area = Globals.StrReverse(area) + ":";
- // get the right cell ref
- for (int i = (pos + 1); i < funcString.Length; i++)
- {
- if (char.IsLetterOrDigit(funcString, i))
- //if (IsAlphaNumeric((byte)(funcString.Substring(i, 1).ToCharArray()[0])))
- area.Append( funcString.Substring(i, 1));
- else
- break;
- }
- return area.ToString() ;
- }
- private string[] GetCellReferences(string area)
- {
- string[] result;
- string first;
- string last;
- int count = 0;
- ushort rowfrom;
- ushort rowto;
- ushort colfrom;
- ushort colto;
- // get the first an last cell in the range
- count = area.IndexOf(":");
- first = area.Substring(0, count);
- last = area.Substring(count + 1);
- rowfrom = (ushort)Globals.ConvertRowStringToNum(first);
- colfrom = (ushort)Globals.ConvertColStringToNum(first);
- rowto = (ushort)Globals.ConvertRowStringToNum(last);
- colto = (ushort)Globals.ConvertColStringToNum(last);
- int num;
- num = (rowto - rowfrom + 1) * (colto - colfrom + 1);
- result = new string[num];
- count = 0;
- for (ushort x = rowfrom; x <= rowto; x++)
- {
- for (ushort y = colfrom; y <= colto; y++)
- {
- result[count] = Globals.CellReferenceFromRowColumn(x, y);
- count++;
- }
- }
- return result;
- }
- private double EvaluateSum(string funcString)
- {
- ushort count = 0 ;
- return EvaluateSum(funcString,ref count);
- }
-
- private double EvaluateSum(string funcString ,ref ushort cellEvaluated)
- {
- string area;
- ushort[] sheets;
- string[] cells;
- double num;
- double result = 0;
- ICell cell = null;
- string key;
- try
- {
- if (funcString.IndexOf("(") < 0) return default(double);
- // returns the Sheet Range (eg =Sum(Sheet1:Sheet3!A1:B1) returns 1, 2 & 3)
- sheets = GetSheetRange(funcString);
- // get the cells contained between the brackets ( format = Sum(A1:A3) returns A1:A3 )
- area = GetAreaRef(funcString);
- // get an array of all the cells in the enclosed area;
- cells = GetCellReferences(area);
- for (ushort y = sheets[0]; y <= sheets[1]; y++)
- {
- for (ushort x = 0; x < cells.Length; x++)
- {
- key = y.ToString("000") + "!" + cells[x];
- cell = m_cells[key];
- if (cell != null)
- {
- if (cell.ResolvedValue == null)
- result += 0;
- // check for a valid value in the cell
- else if (double.TryParse(cell.ResolvedValue.ToString(),out num) == true)
- result += num;
- cellEvaluated++;
- }
- } //end for x
- } // end for y
- return result;
- }
- catch
- {
- return default(double);
- }
- }
- private double EvaluateAverage(string funcString)
- {
- ushort count = 0;
- double sum;
- try
- {
- // count returns the number of cell evaluated
- sum = EvaluateSum(funcString,ref count);
- return sum / count;
- }
- catch
- {
- return default(double);
- }
- }
- private ushort EvaluateCount(string funcString)
- {
- try
- {
- ushort count = 0;
- // count returns the number of cell evaluated
- EvaluateSum(funcString,ref count);
- return count;
- }
- catch
- {
- return default(ushort);
- }
- }
- internal double Calculate(List<string> tokens)
- {
- int y;
- double num;
- ICell cell;
- string token;
- double lOp, rOp;
- string key;
- int pos;
- ushort iSheet;
- string sheets = "";
- string s;
- for (int i = 0; i < tokens.Count; i++)
- {
- token = tokens[i].ToString();
- switch (token)
- {
- case "+":
- rOp = arrStack[stackPointer];
- stackPointer--;
- lOp = arrStack[stackPointer];
- arrStack[stackPointer] = lOp + rOp;
- break;
- case "-":
- rOp = arrStack[stackPointer];
- stackPointer--;
- lOp = arrStack[stackPointer];
- arrStack[stackPointer] = lOp - rOp;
- break;
- case "*":
- rOp = arrStack[stackPointer];
- stackPointer--;
- lOp = arrStack[stackPointer];
- arrStack[stackPointer] = lOp * rOp;
- break;
- case "/":
- rOp = arrStack[stackPointer];
- stackPointer--;
- lOp = arrStack[stackPointer];
- arrStack[stackPointer] = lOp / rOp;
- break;
- case "^":
- rOp = arrStack[stackPointer];
- stackPointer--;
- lOp = arrStack[stackPointer];
- arrStack[stackPointer] = Math.Pow(lOp, rOp);
- break;
- case " ":
- case "":
- break;
- default:
- double tmp;
- if (double.TryParse(token, out tmp))
- {
- stackPointer++;
- arrStack[stackPointer] = tmp;
- }
- else if (Globals.g_sSupported.IndexOf(Globals.GetFunctionName(token)) > -1) //Supported Function
- {
- num = EvaluteSupportedFunction(token);
- if (default(double) != num)
- {
- stackPointer++;
- arrStack[stackPointer] = num;
- }
- else
- {
- return default(double);
- }
- }
- else
- {
- // if there is a sheet reference then get it's number
- // otherwise use m_thisSheetNumber
- pos = token.IndexOf("!");
- if (pos > -1)
- {
- // split out the sheet(s)
- y = pos - 1;
- do
- {
- s = token.Substring(y, 1);
- if ((s == "(") || (s == "$") || (s == ":")) break;
- sheets += s;
- y--;
- } while (y > 0);
- iSheet = GetSheetNumberFromName(Globals.StrReverse(sheets));
- s = token.Substring(pos + 1);
- }
- else
- {
- iSheet = m_thisSheetNumber;
- s = token;
- }
- key = iSheet.ToString("000") + "!" + s;
- cell = m_cells[key];
- if (cell == null)
- {
- stackPointer++;
- arrStack[stackPointer] = 0.00;
- }
- else
- {
- if (double.TryParse( cell.ResolvedValue.ToString(),out num) == true)
- {
- stackPointer++;
- arrStack[stackPointer] = num;
- }
- else
- {
- return default(double);
- }
- }
- }
- break;
- }
- }
- return arrStack[1];
- }
- }
- }
|