public void Menu() { int flag = 0; string expressionString = "(A1-12-C1)"; //now having error in parentheses string varName; string varValue; double numValue; newExpressionTree = new ExpTree(expressionString); while (flag != 1) //1 causes problems { Console.WriteLine("_________________MENU_________________"); Console.WriteLine("The expression entered is: " + expressionString); /*Console.WriteLine("Would you like to update this expression? Enter y for yes and n for no \n"); * char userInput = Console.ReadKey().KeyChar; //this can cause errors in program testing, just for my own testing purposes * if (userInput == 'y') * { * Console.WriteLine("Please input your new expression with NO whitespaces: \n"); * expressionString = Console.ReadLine(); * * }*/ Console.WriteLine("(1): Update Expression"); Console.WriteLine("(2): Update the value"); Console.WriteLine("(3): Evaluate the tree"); Console.WriteLine("(4): GoodBye"); string userInput = Console.ReadLine().ToString(); Console.WriteLine("You entered option {0}", userInput); switch (userInput) { case "1": Console.WriteLine("Please enter a new expression: "); expressionString = Console.ReadLine(); newExpressionTree = new ExpTree(expressionString); break; case "2": Console.WriteLine("Enter a variable name: "); varName = Console.ReadLine(); Console.WriteLine("Now please enter a value of that variable: "); varValue = Console.ReadLine(); numValue = Convert.ToDouble(varValue); //need to make the value a double Console.WriteLine("Variable Name: {0}\nVariable Value: {1}", varName, numValue); //updated by SHW for readability newExpressionTree.SetVar(varName, numValue); //takes string and double, makes brand new exp tree break; case "3": Console.WriteLine("The result is: {0}", newExpressionTree.Eval()); break; case "4": flag = 1; //exit flag break; } } }
/************************************************************* * Function: setExp(createACell m_Cell, Cell cell) * Date Created: Feb 8, 2017 * Date Last Modified: Feb 9, 2017 * Description: set value to exp * Return: void *************************************************************/ private void setExp(createACell m_Cell, Cell cell) { ExpTree exptree = new ExpTree(m_Cell.Text.Substring(1)); string[] variables = exptree.GetAllVariables(); foreach (string variableName in variables) { Cell variableCell = GetCell(variableName); double value; if (string.IsNullOrEmpty(variableCell.Value)) { exptree.SetVar(variableCell.Name, 0); } else if (!double.TryParse(variableCell.Value, out value)) { exptree.SetVar(variableName, 0); } else { exptree.SetVar(variableName, value); } } //old code from hw4 //string letter = m_Cell.Text.Substring(1); //string number = letter.Substring(1); //string lettersAZ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //int col = 0, row = int.Parse(number) - 1; //for (int i = 0; i < 26; i++) //{ // if (lettersAZ[i] == letter[0]) // { // col = i; // break; // } //} //m_Cell.SetValue(GetCell(row, col).Value.ToString()); m_Cell.SetValue(exptree.Eval().ToString()); CellPropertyChanged(cell, new PropertyChangedEventArgs("Value")); }
// sets a cell's value in the ExpTree's variable dictionary private void SetCellVariable(ExpTree userExpTree, string varName) { // get the cell based on the varName Cell relevantCell = GetCell(varName); double value; // check if the cell's value is a double if (double.TryParse(relevantCell.Value, out value)) { // if it's a double, set its variable to that double value userExpTree.SetVar(varName, value); } else { // otherwise set its variable to 0.0 userExpTree.SetVar(varName, 0.0); } }
private void DefineVars(ExpTree newTree) { foreach (var name in newTree.varNameList) { var col = name[0] - 'A'; var row = Convert.ToInt32(name.Substring(1)) - 1; var tempCell = GetCell(col, row); try { newTree.SetVar(name, Convert.ToDouble(tempCell.Value)); } catch (FormatException) { } } }
private void getCellValue(Cell c) { //c = (cell)sender if (c.setText.Length == 0) { c.Value = ""; } else if (!c.setText.StartsWith("=")) //no formula { c.Value = c.setText; } else // formula { if (c.setText.Length > 1) { try { string equation = c.setText.Substring(1); ExpTree xp = new ExpTree(equation); string[] cref = xp.getVariables(); foreach (string name in cref) { double val = getCorrCellVal(name); xp.SetVar(name, val); Cell key = getCorrCell(name); if (!dep.ContainsKey(key)) //add dependency { dep.Add(key, new HashSet <Cell>()); } dep[key].Add(c); } c.Value = xp.Eval().ToString(); } catch { c.Value = "#REF!"; throw; } } } }
// overloaded UpdateCell, takes a cell as the parameter private void UpdateCell(Cell cellToUpdate) { // remove old dependencies RemoveDependencies(cellToUpdate); // first check if the cell is empty // i.e. the user deleted the text from the cell if (string.IsNullOrEmpty(cellToUpdate.Text)) { cellToUpdate.Value = ""; } // if the text doesn't begin with an = else if (cellToUpdate.Text[0] != '=') { double cellValue; // if the cell contains a double if (double.TryParse(cellToUpdate.Text, out cellValue)) { // build the ExpTree to set the cell's variable ExpTree userExpTree = new ExpTree(cellToUpdate.Text); cellValue = userExpTree.Eval(); userExpTree.SetVar(cellToUpdate.Name, cellValue); // update the value to the double cellToUpdate.Value = cellValue.ToString(); } else { // otherwise the value is just set to the text cellToUpdate.Value = cellToUpdate.Text; } } // need to evaluate an expression here else { // parse the text to get the expression string exp = cellToUpdate.Text.Substring(1); // build an ExpTree, eval to add variables ExpTree userExpTree = new ExpTree(exp); userExpTree.Eval(); // get the variable names string[] varNames = userExpTree.GetVarNames(); // loop through each variable name in the array foreach (string variable in varNames) { // get the cell and add its value to the dictionary double value = 0.0; Cell relevantCell = GetCell(variable); // try to parse out the double double.TryParse(relevantCell.Value, out value); // set the variable userExpTree.SetVar(variable, value); } // set the value to the computed value of the ExpTree cellToUpdate.Value = userExpTree.Eval().ToString(); // add the dependencies AddDependencies(cellToUpdate, varNames); } // if there are cells that depend on the one we just updated if (m_dependencies.ContainsKey(cellToUpdate)) { // update all dependent cells UpdateDependencies(cellToUpdate); } // and notify subscribers that the cell property changed // need to pass the sender which is the cell // passing the this reference would pass the spreadsheet CellPropertyChanged(cellToUpdate, new PropertyChangedEventArgs("CellChanged")); }
private void Spreadsheet_PropertyChanged(object sender, PropertyChangedEventArgs e) { if ("Text" == e.PropertyName) //checks if Cell.Text property was changed { string oldValue = ((Cell)sender).Value; //make a copy of the value of the old string for undo methods ICmd temp = new RestoreText((Cell)sender, oldValue); AddUndo(temp); if (((Cell)sender).Text.IndexOf('=') == 0) //must evaluate if it's a formula { //remove cell from every hashset in dependency table to update the dependency table after formula evaluation foreach (KeyValuePair <Cell, HashSet <Cell> > p in dependencies) { dependencies[p.Key].Remove((Cell)sender); } string formula = ((Cell)sender).Text.Replace("=", ""); var tree = new ExpTree(formula); //put the formula in tree for evaluation string[] variables = tree.GetVars(); //get the variables from the tree if (checkValidFormulaVariables(variables) && !checkSelfReference(((Cell)sender), variables)) //check if variables are in valid format { foreach (string s in variables) { double value = getCorrespondingCellValue(s); //get the individual variable value tree.SetVar(s, value); //set the variable so the tree can evaluate the expression updateDependencyTable((Cell)sender, s); } double finalValue = tree.Eval(); //returns the final result of formula evaluation ((Cell)sender).Value = finalValue.ToString(); } else if (!checkValidFormulaVariables(variables)) //variables not in valid format { tree.ClearVariables(); //delete bad variables ((Cell)sender).Text = "!(invalid entry)"; } else { tree.ClearVariables(); ((Cell)sender).Text = "!(self reference)"; } } else //just a constant value or some string was entered { //check if any cells depend on the cell where value was changed and update them if (dependencies.ContainsKey((Cell)sender) && dependencies[(Cell)sender].Count > 0) { foreach (Cell cell in dependencies[(Cell)sender]) { //Re-evaluate the formulas of each cell depending on the changed cell string formula = cell.Text.Replace("=", ""); var tree = new ExpTree(formula); string[] vars = tree.GetVars(); if (checkValidFormulaVariables(vars)) //check if variables are in valid format { foreach (string v in vars) { Cell check = getCorrespondingCell(v); double varValue = 0.0; if (check == ((Cell)sender)) //check if the variable is the cell being changed { double.TryParse(((Cell)sender).Text, out varValue); //set value of that variable to the newly changed value } else { varValue = getCorrespondingCellValue(v); } tree.SetVar(v, varValue); } double finalValue = tree.Eval(); //returns the final result of formula evaluation cell.Value = finalValue.ToString(); } else { cell.Text = "!(invalid entry)"; } } } ((Cell)sender).Value = ((Cell)sender).Text; //set the value of the cell } } if (CellPropertyChanged != null) //does the event have subscribers? { CellPropertyChanged(sender, e); } }
// overloaded UpdateCell, takes a cell as the parameter private void UpdateCell(Cell cellToUpdate) { // remove old dependencies RemoveDependencies(cellToUpdate); // first check if the cell is empty // i.e. the user deleted the text from the cell if (string.IsNullOrEmpty(cellToUpdate.Text)) { cellToUpdate.Value = ""; } // if the text doesn't begin with an = else if (cellToUpdate.Text[0] != '=') { double cellValue; // if the cell contains a double if (double.TryParse(cellToUpdate.Text, out cellValue)) { // build the ExpTree to set the cell's variable ExpTree userExpTree = new ExpTree(cellToUpdate.Text); cellValue = userExpTree.Eval(); userExpTree.SetVar(cellToUpdate.Name, cellValue); // update the value to the double cellToUpdate.Value = cellValue.ToString(); } else { // otherwise the value is just set to the text cellToUpdate.Value = cellToUpdate.Text; } } // need to evaluate an expression here else { // flag to check for errors bool errors = false; // parse the text to get the expression string exp = cellToUpdate.Text.Substring(1); // build an ExpTree, eval to add variables ExpTree userExpTree = new ExpTree(exp); userExpTree.Eval(); // get the variable names string[] varNames = userExpTree.GetVarNames(); // loop through each variable name in the array foreach (string variable in varNames) { // get the cell and add its value to the dictionary double value = 0.0; Cell relevantCell = GetCell(variable); // check for valid cells // CASE ONE: BAD REFERENCE if (relevantCell == null) { // display that the cell has a bad reference and notify subscribers cellToUpdate.Value = "!(bad reference)"; CellPropertyChanged(cellToUpdate, new PropertyChangedEventArgs("CellChanged")); // set the error flag to true errors = true; } // CASE TWO: SELF-REFERENCE else if (cellToUpdate.Name == variable) { // display that the cell has a self-reference and notify subscribers cellToUpdate.Value = "!(self reference)"; CellPropertyChanged(cellToUpdate, new PropertyChangedEventArgs("CellChanged")); // set the error flag to true errors = true; } // if there's an error, get out of the function if (errors == true) { // if there are cells that depend on the one we just updated if (m_dependencies.ContainsKey(cellToUpdate)) { // update all dependent cells UpdateDependencies(cellToUpdate); } return; } // try to parse out the double double.TryParse(relevantCell.Value, out value); // set the variable userExpTree.SetVar(variable, value); // add the cell to the HashSet to check for circular references this.visitedCells.Add(relevantCell); } // set the value to the computed value of the ExpTree cellToUpdate.Value = userExpTree.Eval().ToString(); // add the dependencies AddDependencies(cellToUpdate, varNames); // check for circular references if (CheckForCircularReferences(cellToUpdate)) { // display that the cell has a circular-reference and notify subscribers cellToUpdate.Value = "!(circular reference)"; CellPropertyChanged(cellToUpdate, new PropertyChangedEventArgs("CellChanged")); // set the error flag to true errors = true; } // if there's an error, get out of the function if (errors == true) { return; } } // if there are cells that depend on the one we just updated if (m_dependencies.ContainsKey(cellToUpdate)) { // update all dependent cells UpdateDependencies(cellToUpdate); } // and notify subscribers that the cell property changed // need to pass the sender which is the cell // passing the this reference would pass the spreadsheet CellPropertyChanged(cellToUpdate, new PropertyChangedEventArgs("CellChanged")); // clear the visited cells HashSet at a successful cell change this.visitedCells.Clear(); }