예제 #1
0
        public void MergeDTfromFiles(IProgress <SpreadsheetCollectionProgressModel> progress, CancellationToken cancellationToken)
        {
            SpreadsheetCollectionProgressModel report = new SpreadsheetCollectionProgressModel(ProcessState.IsRunning);
            List <FileInfo> files = StringToFileInfo(Options.Files);
            string          dir   = files[0].DirectoryName;

            List <string> sheets = GenerateSheets();

            List <DataTable> tables     = new List <DataTable>();
            DataTable        errorTable = new DataTable();

            foreach (FileInfo file in files)
            {
                report.steps.Add($"Loading {file.Name}...");
                progress.Report(report);

                var package = SpreadsheetUtilities.GetDTfromExcel(file, Convert.ToInt32(Options.StartRow), sheets, Options.Passwords);
                tables.AddRange(package.data);
                errorTable.Merge(package.errors);
                cancellationToken.ThrowIfCancellationRequested();
            }

            //Combine all tables into first table in list
            for (int i = 1; i < tables.Count; i++)
            {
                report.steps.Add($"Merging {tables[i].TableName}...");
                progress.Report(report);
                tables[0].Merge(tables[i], false, MissingSchemaAction.Add);
                tables[i] = null;
                cancellationToken.ThrowIfCancellationRequested();
            }

            report.IsCancellable = false;
            report.steps.Add("Sending to Excel...");
            progress.Report(report);

            try
            {
                cancellationToken.ThrowIfCancellationRequested();
                SpreadsheetUtilities.DTtoExcel(tables[0], dir, errorTable);
            }
            catch (ArgumentOutOfRangeException e)
            {
                throw new ArgumentOutOfRangeException("Sheet(s) not found in any files!", e);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            finally
            {
                report.State = ProcessState.Completed;
                report.steps.Add("Process Completed!");
                progress.Report(report);
            }
        }
        public void GetDTFromExcel_HeaderPatterns_ReturnTables(string file)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            var mockFile  = new FileInfo($"resources/{file}.xlsx");
            var headerRow = 1;
            var sheets    = new List <string>()
            {
                "Sheet1"
            };
            var passwords = new List <string>();

            var(data, err) = SpreadsheetUtilities.GetDTfromExcel(mockFile, headerRow, sheets, passwords);

            Assert.Equal(0, err.Rows.Count);
            Assert.Single(data);
            Assert.Equal(8, data[0].Columns.Count);
            Assert.Equal(10, data[0].Rows.Count);
        }
예제 #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 cell_name, SpreadsheetUtilities.Formula formula)
 {
     IEnumerable<string> backup_variables = null;
     object backup_contents = null;
     bool had_name = false;
     string name = Normalize(cell_name);
     //if the formula passed in is null this throws an ArgumentNullException();
     if (formula == null)
     {
         throw new ArgumentNullException("Formula cannot be null");
     }
     //checks if the name is null or invalid if so throws a new InvalidNameException();
     if (name == null || IsValid(name) == false)
     {
         throw new InvalidNameException();
     }
     //checks if the cell with the name has been set up, if so this sets the contents of the cell to the formula passed in.
     if (spreadsheet.ContainsKey(name))
     {
         backup_variables = dependency_graph.GetDependees(name);
         backup_contents = spreadsheet[name].get_contents();
         spreadsheet[name].set_contents(formula);
         had_name = true;
     }
     //if the cell hasn't been set up this creates a new cell and sets its contents to the text passed in.
     else
     {
         backup_contents = " ";
         backup_variables = new HashSet<string> { };
         spreadsheet.Add(name, new Cell(name, formula));
     }
     IEnumerable<string> variables = formula.GetVariables(); //Gets all the variables
     dependency_graph.ReplaceDependees(name, variables); //Replace the dependees of the name with all the variables in the formula passed in.
     //creates a hash set for the return ISet.
     ISet<string> depends = new HashSet<string> { };
     //looks through each item in the dependency graph and add them to the hash set to return.
     try
     {
         IEnumerable<string> recalculate_cells = GetCellsToRecalculate(name);
         foreach (string item in recalculate_cells)
         {
             depends.Add(item);
         }
     }
     catch (CircularException)
     {
         spreadsheet[name].set_contents(backup_contents);
         dependency_graph.ReplaceDependees(name, backup_variables);
         throw new CircularException();
     }
     //sets the value of the cell
     IEnumerable<string> evaluate_cells = GetCellsToRecalculate(name);
     foreach (string cell in evaluate_cells)
     {
         Formula value_of_formula = (Formula)GetCellContents(cell);
         try
         {
             spreadsheet[cell].set_value(value_of_formula.Evaluate(Lookup));
         }
         catch(ArgumentException)
         {
         }
     }
     //returns the hash set with all the dependents of name.
     return depends;
 }
예제 #4
0
 /// <summary>
 /// Creates a cell with a name and contents.
 /// </summary>
 /// <param name="name"></param>
 /// <param name="formula">formula</param>
 public Cell(String name, SpreadsheetUtilities.Formula formula)
 {
     cell_name = name;
     contents = formula;
 }
예제 #5
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));
        }
예제 #6
0
        // MODIFIED PROTECTION FOR PS5
        /// <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, SpreadsheetUtilities.Formula formula)
        {
            if (formula == null)
                throw new ArgumentNullException("Error: Formula paramter was null.");

            // Checks if cell name is valid and not null
            if (name == null || !ValidName(name))
                throw new InvalidNameException();

            List<string> cellNames = new List<string>();
            Cell cellValue;

            // Holds the cell names that will be returned
            HashSet<string> result = new HashSet<string>();

            // Holds the contents of the original cell
            object o = null;

            if (cells.ContainsKey(name)) {
                o = cells[name].Content;
                RemoveDependency(name);
            }

            // Save the content of the cell to store in the dictionary
            cellValue = new Cell(formula, GetCell);
            cells.Add(name, cellValue);

            // cellNames gets a list of all of the cell names in the formula and creates a list
            // to add to the dependency graph
            cellNames = formula.GetVariables().ToList();

            // Add the values associated to name to the dependency graph
            foreach (string n in cellNames) {
                dg.AddDependency(name, n);
            }

            try {
                //saves the direct and indirect values into tempI and then put them into my returnSet
                //also checks for circular dependency and recalculates the values in the cells associate with the name
                IEnumerable<string> tempI = GetCellsToRecalculate(name);//recalculates the values and checks for circular dependency
                foreach (string n in tempI)
                    result.Add(n);
            }
            catch (CircularException c) {

                //method comes here if a circularexeption is found when calling the GetCellsToRecalculate method
                //originalCellContent is saved earlier in the code to allow us to go back to the original values to get
                //rid of the circular dependency
                if (o != null) {
                    if (o is Formula) {
                        Formula originalFormula = new Formula(o.ToString());

                        SetCellContents(name, originalFormula);
                    }
                    else if (o is String) {
                        SetCellContents(name, o.ToString());
                    }
                    else if (o is double) {
                        SetCellContents(name, Convert.ToDouble(o));
                    }
                }
                else
                    SetCellContents(name, "");
                throw c;
            }
            return result;
        }
        /// <summary>
        /// Sets the contents of the specified cell to the Formula specified
        /// </summary>
        /// <param name="name">The cell we want to set the contents of</param>
        /// <param name="formula">The contents we want the cell to hold</param>
        /// <returns>The other cells whose value depends on this cell</returns>
        protected override ISet<string> SetCellContents(string name, SpreadsheetUtilities.Formula formula)
        {
            if (formula == null)
                throw new ArgumentNullException();
            if (name == null || !isValidName(name))
                throw new InvalidNameException();

            object oldContents = formula;
            bool isDouble = false;
            bool isString = false;

            if (cells.ContainsKey(name))
            {
                oldContents = cells[name].CellContents;
                if (cells[name].CellContents is double)
                    isDouble = true;
                if (cells[name].CellContents is string)
                    isString = true;

                try
                {
                    //if (!(cells[name].CellContents is double) && !(cells[name].CellContents is string))
                    //{
                        Formula oldValue = (Formula)cells[name].CellContents;
                        foreach (string s in oldValue.GetVariables())
                        {
                            dependencyGraph.RemoveDependency(s, name);
                        }
                    //  }
                    cells[name].CellContents = formula;
                }
                catch {
                    cells[name].CellContents = oldContents;
                }
            }

            foreach (string v in formula.GetVariables())
            {
                dependencyGraph.AddDependency(v, name);
            }

            HashSet<string> dependentCells = new HashSet<string>();

            try
            {
                dependentCells = new HashSet<string>(GetCellsToRecalculate(name));
                cells.Remove(name);
                cells.Add(name, new Cell(formula, lookup));
            }
            catch
            {
                cells.Remove(name);
                if (isDouble)
                    cells.Add(name, new Cell((double)oldContents));
                else if (isString)
                    cells.Add(name, new Cell((string)oldContents));
                else
                    cells.Add(name, new Cell((Formula)oldContents, lookup));
                throw new CircularException();
                //cells[name].CellContents = oldContents;
            }
            foreach (string s in dependentCells)
            {
                if (cells.ContainsKey(s))
                {
                    if (cells[s].CellContents is Formula)
                    {
                        Formula oldValue = (Formula)cells[s].CellContents;
                        cells.Remove(s);
                        cells.Add(s, new Cell(oldValue, lookup));
                    }
                }
            }
            hasChanged = true;
            return dependentCells;
        }
예제 #8
0
        protected override ISet<string> SetCellContents(string name, SpreadsheetUtilities.Formula formula)
        {
            if (name==null)                                             //if the name is null, throw ArgumentNullException.
            {
                throw new ArgumentNullException();
            }
            if (!IsValid(name))                                        //if name is invalid, throw InvalidNameException.
            {
                throw new InvalidNameException();
            }
            String cellName = Normalize(name);
            HashSet<string> dependents = new HashSet<string>();     //A SortedSet to hold the dependents.
            foreach (Cell cell in cells)                                //for each cell in the hashset.
            {
                if (cell.getName().Equals(cellName))                        //if the cell name equals the parameter name.
                {
                    cell.setFormula(formula);                           //set the cell formula to the parameter.
                    dg.ReplaceDependees(cellName, formula.GetVariables());  //replace the dependees.

                        foreach (String s in GetCellsToRecalculate(cellName))   //for each string in getcellstorecalculate.
                        {
                            dependents.Add(s);                          //add string to the sorted set.
                        }

                    return (dependents);                                //return the sorted set.

                }

            }
            Formula cellForm = new Formula("="+formula.ToString(), s=>true);
            cells.Add(new Cell(cellName, cellForm));                         //otherwise, create a new cell using the parameters.
            foreach (string s in formula.GetVariables())                //for each string in getvariables.
            {
                dg.AddDependency(s, cellName);                              //add a new dependency.
            }
            foreach (String s in GetCellsToRecalculate(cellName))           //for each string in getcellstorecalculate.
            {
                dependents.Add(s);                                      //add the string to the sorted set.

            }
            return (dependents);                                        //return the sorted set.
        }