Example #1
0
        private ErrType add_remove(SpreadsheetCell toAlter, ExpTree mainTree, bool removing)
        {
            /*Adding to and removing from the reference table occurs in this function*/
            ErrType Error = ErrType.None;

            if (toAlter.VarList != null && toAlter.VarList.Count > 0)
            {
                string referencedBy = CellToString(toAlter);
                if (removing)
                {
                    foreach (string referencedCell in toAlter.VarList) // Removes all variables from the old tree
                    {
                        if (refTable.ContainsKey(referencedCell))
                        {
                            if (refTable[referencedCell].Contains(referencedBy))
                                refTable[referencedCell].Remove(referencedBy); // Removes the current cell from any other cells referencing hash
                            if (refTable[referencedCell].Count < 1) // If an entry in the table has no cells referencing it, then it is removed
                                refTable.Remove(referencedCell);
                        }
                    }

                    toAlter.VarList.Clear(); // Empty that variable list (will be rebuild below)
                }
                else // Adding value to the reference this
                {
                    foreach (string s in toAlter.VarList) // Updates the reference table with all of the referenced cells (variables in the expTree's context)
                    {
                        double CellValue = 0.0;
                        SpreadsheetCell next = StringToCell(s);
                        if (next != null)
                        {
                            if (s == CellToString(toAlter)) // SELF-REFERENCING
                            {
                                Error = ErrType.SelfRef;
                                CheckErr(toAlter, Error, CellToString(toAlter));
                                UpdateErrorReferecedBy(toAlter, ErrType.SelfRef, CellToString(toAlter)); // Updates all cells referencing this cell that there is a value
                                return ErrType.SelfRef;
                            }
                            else if (next.Value.Contains("REF")) // Won't check for already occuring errors (in referenced cell) 
                            {
                                if (next.Value.Contains("=<BAD_REF")) // If this cell REFERENCES a cell that contains a bad_ref error
                                {
                                    CheckErr(toAlter, ErrType.BadRef, s);
                                    UpdateErrorReferecedBy(toAlter, ErrType.BadRef, s);
                                    Error = ErrType.BadRef;
                                }
                                else if (next.Value.Contains("=<SELF_REF")) // If this cell REFERENCES a cell that contains a self_ref error
                                {
                                    CheckErr(toAlter, ErrType.SelfRef, s);
                                    UpdateErrorReferecedBy(toAlter, ErrType.SelfRef, CellToString(toAlter));
                                    Error = ErrType.SelfRef;
                                }
                                else if (next.Value.Contains("=<CIRC_REF"))
                                {
                                    CheckErr(toAlter, ErrType.CircRef, s);
                                    UpdateErrorReferecedBy(toAlter, ErrType.CircRef, CellToString(toAlter));
                                    Error = ErrType.CircRef;
                                }
                            }
                            if (next.Text != "")
                            {
                                Double.TryParse(next.Value, out CellValue); // Gets the cell's value
                                mainTree.SetVar(s, CellValue); // Sets the variable in the expression tree's dictionary (0 if not yet set)
                            }
                            if (refTable.ContainsKey(s)) // If The variable already has references, just add to its hash
                                refTable[s].Add(referencedBy);
                            else // Otherwise create the new variable key with a new list containing the cell that references it
                                refTable.Add(s, new HashSet<string>() { referencedBy });
                        }
                        else // If Cell parsing return null (cell not recovered), the there is a bad reference
                        {
                            Error = ErrType.BadRef;
                            CheckErr(toAlter, Error, CellToString(toAlter));
                            UpdateErrorReferecedBy(toAlter, ErrType.BadRef, CellToString(toAlter));
                            return ErrType.BadRef;
                        }
                    }
                    if (Error == ErrType.CircRef)
                        return Error;

                    if (Error != ErrType.SelfRef && CheckCircularRef(toAlter, CellToString(toAlter))) // Checks for circular references here ***
                    {
                        Error = ErrType.CircRef;
                        CheckErr(toAlter, Error, CellToString(toAlter));
                        UpdateErrorReferecedBy(toAlter, ErrType.CircRef, CellToString(toAlter));
                    }
                }
            }

            return Error;
        }
Example #2
0
        private void UpdateCellValue(ref SpreadsheetCell cell)
        {
            var mainTree = new ExpTree(); // Initializes a new expression tree to build the cell's expression
            ErrType Error = ErrType.None;

            if (cell.Text != "" && cell.Text[0] != '=') // not an expression, simply a text value
            {
                cellArr[cell.RowIndex, cell.ColumnIndex] = new Cell(cell, cell.Text);
                add_remove(cell, mainTree, true);
            }
            else
            {
                if (cell.Text != "")
                    mainTree.Expression = cell.Text.Substring(1).Replace(" ", ""); // Build the expression tree with the cell's text (minus the '=') :: Also ignores whitespaces
                else
                    mainTree.Expression = cell.Text;

                add_remove(cell, mainTree, true); // Removes all variables cooresponding to the old tree

                cell.VarList = GetVarNames(cell.Text); // Will Return all found variables in the new expression

                Error = add_remove(cell, mainTree, false);

                if (Error != ErrType.None) // Notifies the UI that there is an error in one of the cells that the expression references
                {
                    return; // Exits the function before executing anything else, error display has already been taken care of at this point
                }

                try
                {
                    cellArr[cell.RowIndex, cell.ColumnIndex] = new Cell(cell, mainTree.Eval().ToString()); // Attempts to evaluate the expression, placing it into a new cell
                }
                catch (DivideByZeroException) // User tried to divide by zero
                {
                    CheckErr(cell, ErrType.DivZero, CellToString(cell));
                    UpdateErrorReferecedBy(cell, ErrType.DivZero, CellToString(cell));
                    return;
                }
                catch (NullReferenceException) // Input not regonized / invalid expression
                {
                    if (cell.Text == "")
                    {
                        cellArr[cell.RowIndex, cell.ColumnIndex] = new Cell(cell, ""); // if the cell was deleted or reset, this will set the cell to an empty value (caught by expression tree as null)
                    }
                    else
                    {
                        CheckErr(cell, ErrType.InvExp, CellToString(cell));
                        UpdateErrorReferecedBy(cell, ErrType.InvExp, CellToString(cell)); // Notifies UI that an invalid expression has been entered
                        return;
                    }
                }
            }

            cellArr[cell.RowIndex, cell.ColumnIndex].PropertyChanged += detect_PropertyChanged; // Reassigns the the detect_property function to the cell's delegate

            CellPropertyChanged(cellArr[cell.RowIndex, cell.ColumnIndex], new PropertyChangedEventArgs("Value")); // fires the event that notifies the GUI of a change

            UpdateReferencedBy(cell); // Updates all cells that reference this cell
        }