Exemple #1
0
 /// <summary>
 /// Creates an empty Spreadsheet whose IsValid regular expression accepts every string.
 /// </summary>
 public Spreadsheet()
 {
     sheet   = new Dictionary <string, Cell>();
     graph   = new Dependencies.DependencyGraph();
     isValid = new Regex("");
     Changed = false;
 }
Exemple #2
0
        /// <summary>
        /// Creates a Spreadsheet that is a duplicate of the spreadsheet saved in source.
        /// See the AbstractSpreadsheet.Save method and Spreadsheet.xsd for the file format
        /// specification.  If there's a problem reading source, throws an IOException
        /// If the contents of source are not consistent with the schema in Spreadsheet.xsd,
        /// throws a SpreadsheetReadException.  If there is an invalid cell name, or a
        /// duplicate cell name, or an invalid formula in the source, throws a SpreadsheetReadException.
        /// If there's a Formula that causes a circular dependency, throws a SpreadsheetReadException.
        /// </summary>
        public Spreadsheet(TextReader source)
        {
            sheet = new Dictionary <string, Cell>();
            graph = new Dependencies.DependencyGraph();

            XmlSchemaSet sc = new XmlSchemaSet();

            sc.Add(null, "Spreadsheet.xsd");

            XmlReaderSettings settings = new XmlReaderSettings();

            settings.ValidationType          = ValidationType.Schema;
            settings.Schemas                 = sc;
            settings.ValidationEventHandler += ValidationCallback;

            using (XmlReader reader = XmlReader.Create(source, settings))
            {
                while (reader.Read())
                {
                    if (reader.IsStartElement())
                    {
                        switch (reader.Name)
                        {
                        case "spreadsheet":
                            isValid = new Regex(reader["IsValid"]);
                            break;

                        case "cell":
                            try
                            {
                                if (sheet.ContainsKey(reader["name"]))
                                {
                                    throw new InvalidDataException();
                                }
                                SetContentsOfCell(reader["name"], reader["contents"]);
                            }
                            catch (InvalidNameException)
                            {
                                throw new SpreadsheetReadException("Invalid name in source file: " + reader["name"]);
                            }
                            catch (CircularException)
                            {
                                throw new SpreadsheetReadException("Formula causes circular dependency: " + reader["contents"]);
                            }
                            catch (FormulaFormatException)
                            {
                                throw new SpreadsheetReadException("Invalid formula in source file: " + reader["contents"]);
                            }
                            catch (InvalidDataException)
                            {
                                throw new SpreadsheetReadException("Source file has duplicate cell name: " + reader["name"]);
                            }
                            break;
                        }
                    }
                }
            }
            Changed = false;
        }
Exemple #3
0
        /// <summary>
        /// If 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.
        ///
        /// 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 (formula.Equals(null))
            {
                throw new ArgumentNullException();
            }
            if (!isValidName(name))
            {
                throw new InvalidNameException();
            }
            name    = name.ToUpper();
            formula = new Formula(formula.ToString().ToUpper());
            if (!sheet.ContainsKey(name))
            {
                sheet.Add(name, new Cell(name, ""));
            }

            Dependencies.DependencyGraph tempGraph = new Dependencies.DependencyGraph(graph);
            Cell             c;
            HashSet <string> set = new HashSet <string>();

            graph.ReplaceDependees(name, formula.GetVariables());

            try
            {
                foreach (string s in GetCellsToRecalculate(name))
                {
                    set.Add(s);
                }
            }
            catch (CircularException)
            {
                graph = tempGraph;
                throw new CircularException();
            }

            if (sheet.TryGetValue(name, out c))
            {
                c.SetContents(formula);
                sheet[name] = c;
            }

            UpdateValue(set);

            return(set);
        }