/// <summary> /// Used to set the contents of a given cell to a formula /// </summary> /// <param name="name">Cell's name</param> /// <param name="formula">Cell's contents</param> /// <returns>a set of all cells affected by the given cell</returns> protected override ISet <string> SetCellContents(string name, string text) { if (name == null || !couldBeAVariable(name)) { throw new InvalidNameException(); } if (text == null) { throw new ArgumentNullException(); } if (cells.ContainsKey(name))//check to see if the cell used to have some other data in it { removeDependencies(name); } if (text != "") //we don't want blank cells in the dictionary { cells[name] = text; } valueDictionary[name] = new FormulaError("Can not evaluate a string"); return(new HashSet <string>(GetCellsToRecalculate(name))); }
/// <summary> /// Requires that all of the variables in formula are valid cell names. /// /// If name is null or invalid, throws an InvalidNameException. /// /// Otherwise, if changing the contents of the named cell to be the formula would cause a /// circular dependency, throws a CircularException. /// /// Otherwise, the contents of the named cell becomes formula. The method returns a Set /// consisting of name plus the names of all other cells whose value depends, directly or /// indirectly, on the named cell. /// /// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the set {A1, B1, C1} /// is returned. /// </summary> /// <param name="name">The name of the cell whose contents will be set.</param> /// <param name="formula">The desired contents for the cell.</param> /// <returns>Returns a set of all cells that now depend on the provided cell.</returns> protected override ISet <string> SetCellContents(string name, Formula formula) { // Add in all of our new dependencies. foreach (string s in formula.GetVariables()) { dependencies.AddDependency(name, s); } // Try and evaluate the formula. object value; try { value = formula.Evaluate(EvalLookup); } // The value will simply be a FormulaError if the formula can't be evaluated. catch (FormulaEvaluationException e) { value = new FormulaError(e.Message); } // Set the cell contents. try { return(SetCellContentsGeneric(name, new Cell(formula, value))); } catch (CircularException e) { foreach (string s in formula.GetVariables()) { dependencies.RemoveDependency(name, s); } throw e; } }
/// <summary> /// Requires that all of the variables in formula are valid cell names. /// /// If name is null or invalid, throws an InvalidNameException. /// /// Otherwise, if changing the contents of the named cell to be the formula would cause a /// circular dependency, throws a CircularException. /// /// Otherwise, the contents of the named cell becomes formula. The method returns a /// Set consisting of name plus the names of all other cells whose value depends, /// directly or indirectly, on the named cell. /// /// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the /// set {A1, B1, C1} is returned. /// </summary> protected override ISet <string> SetCellContents(string name, Formula formula) { //Stores dependents incase it is circular IEnumerable <string> backup = dg.GetDependents(name); //Resets dependency dg.ReplaceDependents(name, new HashSet <string>()); foreach (string itr in formula.GetVariables()) { dg.AddDependency(name, itr); } HashSet <string> rtn = new HashSet <string>(); if (sheet.ContainsKey(name)) { object value; try { value = formula.Evaluate(LookUpDub); } catch { value = new FormulaError(); } sheet[name] = new Cell(formula, value); } else { object value; try { value = formula.Evaluate(LookUpDub); } catch { value = new FormulaError(); } sheet.Add(name, new Cell(formula, value)); } //Check for circular dependency try { foreach (string itr in GetCellsToRecalculate(name)) { sheet[itr].cellContents = sheet[itr].cellContents; } } catch (CircularException) { //Revert back if circular dg.ReplaceDependents(name, backup); throw new CircularException(); } rtn = new HashSet <string>(GetCellsToRecalculate(name)); Changed = true; return(rtn); }
/// <summary> /// If name is null or invalid, throws an InvalidNameException. /// /// Otherwise, returns the value (as opposed to the contents) of the named cell. The return /// value should be either a string, a double, or a FormulaError. /// </summary> public override object GetCellValue(string name) { if (name == null || !isValid.IsMatch(name) || !CellNamePattern.IsMatch(name)) { throw new InvalidNameException(); } name = name.ToUpper(); if (!Cells.ContainsKey(name)) { return(""); } if (Cells[name].Value != null) { return(Cells[name].Value); } object result = GetCellContents(name); if (result.GetType().Equals(typeof(double))) { Cells[name].Value = result; return(result); } if (result.GetType().Equals(new Formula().GetType())) { try { result = ((Formula)result).Evaluate(s => double.Parse(GetCellValue(s).ToString())); Cells[name].Value = result; return(result); } catch (FormulaEvaluationException) { result = new FormulaError("The formula could not be evaluated"); } catch (FormatException) { result = new FormulaError("The formula could not be evaluated"); } } if (result.Equals("")) { result = new FormulaError("The formula is referencing an empty cell"); } Cells[name].Value = result; return(result); }
protected override IList <string> SetCellContents(string name, Formula formula) { foreach (string var in formula.GetVariables()) { if (!IsValid(var)) { throw new FormulaFormatException("invalid variable " + var); } } // Try Catch in case of Circular Exception try { // Adding dependencies for the variables within formula to name foreach (string var in formula.GetVariables()) { depGraph.AddDependency(var, name); } // Our list to return as well as check for CircularException List <string> toReturn = GetCellsToRecalculate(name).ToList(); // Adding as a new Cell and grabbing it's value. object value; try { value = formula.Evaluate(lookup); } catch (ArgumentException) { value = new FormulaError(); } if (!(Cells.ContainsKey(name))) { Cells.Add(name, new Cell(name, formula, value)); } // Overwriting the Cell to a formula else { Cells[name] = new Cell(name, formula, value); } // Recalculate dependents RecalculateDependents(name); Changed = true; return(toReturn); } // Resetting dependencies SS is unchanged. catch (CircularException) { foreach (string var in formula.GetVariables()) { depGraph.RemoveDependency(var, name); } // Then we throw the Exception. throw new CircularException(); } }
/// <summary> /// Sets the value of the cell /// </summary> public void SetValue(FormulaError e) { Value = new object(); Value = e; }