Ejemplo n.º 1
0
        /// <summary>
        /// If the formula parameter is null, throws an ArgumentNullException.
        /// 
        /// Otherwise, 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.  (No change is made to the spreadsheet.)
        /// 
        /// 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"></param>
        /// <param name="formula"></param>
        /// <returns></returns>
        protected override ISet<string> SetCellContents(string name, SpreadsheetUtilities.Formula formula)
        {
            //first of all normalize name
            name = Normalize(name);

            if (formula == null)
                throw new ArgumentNullException();

            if (name == null || !Name_Verify(name))
                throw new InvalidNameException();

            //HadAdd is used to monitoring which dependent is added in DependGraph, if circularexception occur, delete all the
            //dependent which is been add in the DependGraph
            List<string> HadAdd = new List<string>();
            //check if the new formula contain a circulardepent
            foreach (string s in formula.GetVariables())
            {
                //make sure that dependent(s,name) is not in the graph_dependent then we add them into the graph_dependent
                if (!new HashSet<string>(Spreadsheet_DependGraph.GetDependents(s)).Contains(name))
                {
                    HadAdd.Add(s);
                    Spreadsheet_DependGraph.AddDependency(s, name);
                }

                try
                {
                    //use getCellTorecalcualte function to test if the circular dependency exist
                    GetCellsToRecalculate(name);
                }
                catch (CircularException ce)
                {
                    //if the circular dependency exist remove the dependency which you have add and throw an exception
                    foreach (string s1 in HadAdd)
                    {
                        Spreadsheet_DependGraph.RemoveDependency(s1, name);
                    }
                    throw ce;
                }

            }

            //set the named cell's value to the value.
            cell A_cell;
            Spreadsheet_cells.TryGetValue(name, out A_cell);
            if (A_cell == null)
            {
                A_cell = new cell();
                A_cell.name = name;
                A_cell.content = (object)formula;
                A_cell.value = formula.Evaluate(lookup);
                Spreadsheet_cells.Add(A_cell.name, A_cell);
            }
            else
            {
                A_cell.content = (object)formula;
                A_cell.value = formula.Evaluate(lookup);
                Spreadsheet_cells.Remove(A_cell.name);
                Spreadsheet_cells.Add(A_cell.name, A_cell);
            }

            //recalculate all the direct and indirect cells' value

            foreach (string s in GetCellsToRecalculate(name))
            {
                if (s == name)
                    continue;

                cell cell1;
                Spreadsheet_cells.TryGetValue(s, out cell1);
                cell1.value = ((Formula)cell1.content).Evaluate(lookup);
                Spreadsheet_cells.Remove(s);
                Spreadsheet_cells.Add(s, cell1);
            }

            //define that the spreadsheet is changed
            Changed = true;
            return new HashSet<string>(GetCellsToRecalculate(name));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// If text is null, throws an ArgumentNullException.
        /// 
        /// Otherwise, if name is null or invalid, throws an InvalidNameException.
        /// 
        /// Otherwise, the contents of the named cell becomes text.  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"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        protected override ISet<string> SetCellContents(string name, string text)
        {
            //first of all normalize name
            name = Normalize(name);

            if (text == null)
                throw new ArgumentNullException();

            if (name == null || !Name_Verify(name))
                throw new InvalidNameException();

            //set the named cell's value to the value.
            cell A_cell;
            Spreadsheet_cells.TryGetValue(name, out A_cell);

            if (A_cell == null)
            {
                A_cell = new cell();
                A_cell.name = name;
                A_cell.content = (object)text;
                A_cell.value = (object)text;
                Spreadsheet_cells.Add(A_cell.name, A_cell);
            }
            else
            {
                A_cell.content = (object)text;
                A_cell.value = (object)text;
                Spreadsheet_cells.Remove(A_cell.name);
                Spreadsheet_cells.Add(A_cell.name, A_cell);
            }
            //remove all the dependee it has
            foreach (string s in Spreadsheet_DependGraph.GetDependees(name))
            {
                Spreadsheet_DependGraph.RemoveDependency(s, name);
            }

            //recalculate all the direct and indirect cells' value
            foreach (string s in GetCellsToRecalculate(name))
            {
                if (s == name)
                    continue;

                cell cell1;
                Spreadsheet_cells.TryGetValue(s, out cell1);
                cell1.value = ((Formula)cell1.content).Evaluate(lookup);
                Spreadsheet_cells.Remove(s);
                Spreadsheet_cells.Add(s, cell1);
            }
            //define that the spreadsheet is changed
            Changed = true;

            //get all the value dependent on named cell using helper method Visit
            return new HashSet<string>(GetCellsToRecalculate(name));
        }