Exemplo n.º 1
0
        protected override ISet <String> SetCellContents(String name, Formula formula)
        {
            //EXCEPTION HANDELING\\
            if (System.String.IsNullOrWhiteSpace(name))
            {
                throw new InvalidNameException();
            }
            if (!isValid(name))
            {
                throw new InvalidNameException();
            }
            if (formula == null)
            {
                throw new ArgumentNullException();
            }

            this.temp = new HashSet <string>();
            foreach (string s in formula.GetVariables())        //GET ALL THE VARIABLES FROM THE FORMULA AND ADD THEM TO A SET
            {
                if (!isValid(s))
                {
                    throw new FormulaFormatException("One or more variables names do not follow the proper syntax expected");
                }
                this.temp.Add(s);
            }

            foreach (string s in this.temp)                     //TRACK DEPENDENCIES
            {
                if (ssDep.HasDependents(s))
                {
                    foreach (string ss in ssDep.GetDependents(s))
                    {
                        if (ss == s || ss == name)
                        {
                            throw new CircularException();
                        }
                    }
                }
                ssDep.AddDependency(name, s);
            }
            Cell v;

            if (Cells.TryGetValue(name, out v))                 //Get the right cell
            {
                if (v.Content is Formula)
                {
                    Formula check = (Formula)v.Content;
                    foreach (string s in check.GetVariables())
                    {
                        ssDep.RemoveDependency(name, s);        //Remove old dependencies
                    }
                }
            }
            ISet <string> set = Set(name, formula);

            foreach (string s in set)                           //Recalculate Cells that depend on new cells content
            {
                calculateV(s);
            }
            return(set);
        }
Exemplo n.º 2
0
        /// <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)
        {
            if (!IsValidCellName(name, IsValid))
            {
                throw new InvalidNameException();
            }

            if (!Cells.ContainsKey(name))
            {
                Cells.Add(name, new Cell());
            }

            // Set consisting of variables in formula
            ISet <string> variables = formula.GetVariables();


            object oldVal     = Cells[name.ToUpper()].GetContent();
            bool   hadFormula = Cells[name.ToUpper()].hasFormula;

            Cells[name.ToUpper()].SetContent(formula);

            // Remove dependess that aren't there in the formula
            if (Graph.HasDependees(name))
            {
                foreach (string dependee in Graph.GetDependees(name).ToList())
                {
                    if (!variables.Contains(dependee))
                    {
                        Graph.RemoveDependency(dependee, name);
                    }
                }
            }

            // Add dependees that don't already exist
            foreach (string variable in variables)
            {
                Graph.AddDependency(variable, name);
            }


            ISet <string> changedSet = new HashSet <string>();

            changedSet = GetAllRelatedDependents(name);
            //            changedSet.Add(name);
            //            if (Graph.HasDependents(name))
            //            {
            //                foreach (string dependent in Graph.GetDependents(name))
            //                {
            //                    changedSet.Add(dependent);
            //                }
            //            }

            // To check for Circular Dependency
            try
            {
                GetCellsToRecalculate(changedSet);
            }
            catch (CircularException e)
            {
                Cells[name.ToUpper()].SetContent(oldVal);
                Cells[name.ToUpper()].hasFormula = hadFormula;
                throw e;
            }

            return(changedSet);
        }
        protected override ISet <string> SetCellContents(string name, Formula formula)
        {
            // Parse the formula to get the variables
            IEnumerable variables = formula.GetVariables();

            // Get features of cell prior to removing it in case there is a circular dependency
            Cell   beforeCircleCheck = new Cell();
            Object contents          = new Object();

            if (spreadsheetCells.TryGetValue(name, out beforeCircleCheck))
            {
                contents = beforeCircleCheck.cellContents;
            }

            // If the cell already exists, remove it
            if (spreadsheetCells.ContainsKey(name))
            {
                spreadsheetCells.Remove(name);
                foreach (String variable in variables)
                {
                    dependencies.RemoveDependency(name, variable);
                }
            }

            // Create new cell object
            Cell toBeAdded = new Cell();

            // Set cellName equal to name
            toBeAdded.cellName = name;
            // Set cellContents eequal to formula
            toBeAdded.cellContents = "=" + formula;
            // Set cellContentsType equal to formula
            toBeAdded.cellContentsType = "formula";

            // Add (name, cell) to spreadsheetCells dictionary
            spreadsheetCells.Add(name, toBeAdded);

            // Add to dependency Graph
            foreach (String variable in variables)
            {
                dependencies.AddDependency(name, variable);
            }

            // Check for circular dependencies. If one is found, restore origional cell
            try
            {
                GetCellsToRecalculate(name);
            }
            catch (CircularException e)
            {
                // Restore origional cell
                if (!(beforeCircleCheck == null))
                {
                    spreadsheetCells.Remove(name);
                    foreach (String var in variables)
                    {
                        dependencies.AddDependency(name, var);
                    }
                    toBeAdded.cellContents = beforeCircleCheck.cellContents;
                    spreadsheetCells.Add(name, toBeAdded);
                }
                throw e;
            }

            // Set value of cell
            try
            {
                toBeAdded.cellValue = formula.Evaluate((x) => (double)GetCellValue(x));
            }
            catch (InvalidCastException)
            {
                toBeAdded.cellValue = new FormulaError();
            }
            catch (FormulaEvaluationException)
            {
                toBeAdded.cellValue = new FormulaError();
            }

            // Get dependencies for return method call
            HashSet <String> returnValues = new HashSet <String>();
            // Call GetCellsToRecalculate for direct dependents
            IEnumerable dependents = GetCellsToRecalculate(name);

            foreach (String temp in dependents)
            {
                // Add direct dependents to returnValues
                returnValues.Add(temp);
            }

            // Call GetDependees on dependencies to get indirect dependents
            IEnumerable dependees = dependencies.GetDependees(name);

            foreach (String temp in dependees)
            {
                // Add indriect dependents to returnValues
                returnValues.Add(temp);
            }

            // Recalculate
            Cell recalculation;

            foreach (String depend in dependents)
            {
                if (spreadsheetCells.TryGetValue(depend, out recalculation))
                {
                    // Set value of cell
                    try
                    {
                        recalculation.cellValue = formula.Evaluate((x) => (double)GetCellValue(x));
                    }
                    catch (InvalidCastException)
                    {
                        recalculation.cellValue = new FormulaError();
                    }
                    catch (FormulaEvaluationException)
                    {
                        recalculation.cellValue = new FormulaError();
                    }
                }
            }

            // Change changed to true since we made a change to the spreadsheet
            Changed = true;

            // return
            return(returnValues);
        }