public IEnumerable <SpreadSheetCell> GetSheetCells(string input) { var cellVals = input.Split(" "); if (cellVals.Length % 3 != 0) { throw new SpreadSheetException("字符串的格式不正确,插入的值必须为3的备注"); } var result = new List <SpreadSheetCell>(); var cellGroups = cellVals.CutArrayForAppointCount(3); foreach (var group in cellGroups) { if (!int.TryParse(group[0], out int x)) { throw new SpreadSheetException("插入的cell的x坐标必须为整数"); } if (!int.TryParse(group[1], out int y)) { throw new SpreadSheetException("插入的cell的y坐标必须为整数"); } var cell = new SpreadSheetCell(x, y, group[2]); result.Add(cell); } return(result); }
//when new exprssion is inputed into cell all previous connections to cell are terminated using this function private void UnSubscribeFromCells(SpreadSheetCell nCell) { while (nCell._mConnections.Peek() != null) { SpreadSheetCell tempCell = nCell._mConnections.Pop(); tempCell.PropertyChanged -= nCell.connectedCellPropertyChanged; } }
//when new exprssion is inputed into cell a new stack is formed of connections to cells private void SubscribeToCells(string expression, SpreadSheetCell nCell) { List <string> cellList = getCellsFromExp(expression); foreach (string item in cellList) { Tuple <int, int> nCellPos = getCellPosition(item); SpreadSheetCell tempCell = (SpreadSheetCell)getCell(nCellPos.Item1, nCellPos.Item2); tempCell.PropertyChanged += nCell.connectedCellPropertyChanged; nCell._mConnections.Push(tempCell); } }
public SpreadSheet(int width, int height) { Width = width; Height = height; cells = new SpreadSheetCell[width * height]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { cells[width * y + x] = new SpreadSheetCell(); } } }
//Every new action that we dow will be pushed onto the undostack public void addAction(SpreadSheetCell cell, string property) { if (property == "Text") { cell.editType = "t"; undoStack.Push(cell); } else if (property == "Color") { cell.editType = "c"; undoStack.Push(cell); } }
//checks contents content of cell and acts accordingly private void Check(Cell nCell) { SpreadSheetCell tempCell = nCell as SpreadSheetCell; if (tempCell._hasConnections) { UnSubscribeFromCells(tempCell); //since the text within the cell has been changed } //all connections with other cells are broken if (string.IsNullOrEmpty(tempCell.Text)) { tempCell.setValue(""); CellPropChanged(nCell, new PropertyChangedEventArgs("Value")); } else if (tempCell.Text[0] == '=') { if (outOfBounds(tempCell)) { tempCell.setValue("#REF!"); return; } else { tempCell.makeNewExpTree(tempCell.Text.Substring(1)); if (getCellsFromExp(tempCell.Text.Substring(1)) != null) { SubscribeToCells(tempCell.Text.Substring(1), tempCell); } if (tempCell.hasSelfReference()) { tempCell.setValue("#SELFREF!"); UnSubscribeFromCells(tempCell); } else { if (getCellsFromExp(tempCell.Text.Substring(1)).Count <= 1) { tempCell.makeNewExpTree(""); } tempCell.evalTree(); } } CellPropChanged(nCell, new PropertyChangedEventArgs("Value")); } else { tempCell.setValue(tempCell.Text); CellPropChanged(nCell, new PropertyChangedEventArgs("Value")); } }
//Performs the redo action public SpreadSheetCell redoAction(SpreadSheetCell cell) { if (redoStack.Count > 0) { //Pop the previous state off of the stack SpreadSheetCell RevertToThis = redoStack.Pop(); undoStack.Push(cell); cell.editType = RevertToThis.editType; cell = RevertToThis; } return cell; }
public void SignalPropertyChanged(object sender, PropertyChangedEventArgs e) { SpreadSheetCell tempCell = sender as SpreadSheetCell; if (e.PropertyName == "Text") { Check(sender as Cell); CellPropChanged(tempCell, new PropertyChangedEventArgs("Text")); } else { CellPropChanged(tempCell, new PropertyChangedEventArgs("Value")); } }
//makes new SpreadSheet with a specific amount cells public Spreadsheet(int newRows, int newColumns) { _Array = new Cell[newRows, newColumns]; ExpTree newTree = new ExpTree("0"); for (int x = 0; x < newRows; x++) { for (int y = 0; y < newColumns; y++) { string cellName = getCellName(x, y); _Array[x, y] = new SpreadSheetCell(x, y); _Array[x, y].PropertyChanged += SignalPropertyChanged; ExpTree.SetVar(cellName, _Array[x, y]); } } }
//this function makes sure that the refrenced cells dont cause a loop private bool helperHasSelfReference(SpreadSheetCell nCell, HashSet <Tuple <int, int> > nHashSet) { Tuple <int, int> tempCell = new Tuple <int, int>(nCell.Row, nCell.Column); if (nHashSet.Contains(tempCell)) { return(true); } nHashSet.Add(tempCell); foreach (var tCell in nCell._mConnections.Where(a => a != null)) { if (helperHasSelfReference(tCell, nHashSet)) { return(true); } } nHashSet.Remove(tempCell); return(false); }
//Checks if any of the cells refered to by the cell are out of bounds private bool outOfBounds(SpreadSheetCell nCell) { List <string> cellList = getCellsFromExp(nCell.Text.Substring(1)); List <Tuple <int, int> > tempList = new List <Tuple <int, int> >(); if (cellList != null) { foreach (string name in cellList) { tempList.Add(getCellPosition(name)); } foreach (var coord in tempList) { if (coord.Item1 > this.RowCount || coord.Item2 > this.ColumnCount) { return(true); } } } return(false); }
//Checks to see if a cell exists. It will return the cell if it does, otherwise //it will return null. private StandardCell checkReference(string name, SpreadSheetCell[,] sheet) { char p1 = name[0]; string p2 = name.Substring(1); int error = 0; if ((char.IsUpper(p1)) && int.TryParse(p2, out error)) { //Will be used to find the correct column string[] columnIndex = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; //Convert the numerical value of the string to an int for the row number (subtract 1 because rows really start at 0) int row = Convert.ToInt32(p2) - 1; int col = 0; //Checks if the row is within the correct range. If it is execute if (row >= 0 && row <= 50) { //Now we will find the column for (int i = 0; i < columnIndex.Length; i++) { //If the letter in the string matches a corresponding letter in the column index then set the numerical value //of the column to the vlaue if (columnIndex[i].ToString() == (p1.ToString())) { col = i; break; } } } return (StandardCell)sheet[row, col]; } else return null; }
public bool hasSelfReference() { SpreadSheetCell nCell = this; return(helperHasSelfReference(nCell, new HashSet <Tuple <int, int> >())); }
//Performs the undo action public SpreadSheetCell undoAction(SpreadSheetCell cell) { //We must check if there is something to undo if (undoStack.Count > 0) { //Pop the previous state off of the stack SpreadSheetCell RevertToThis = undoStack.Pop(); cell.editType = RevertToThis.editType; redoStack.Push(cell); cell = RevertToThis; if (cell.getColor() == 0) cell.setColor(-1); } return cell; }
public XmlWriter makeTagBlock(SpreadSheetCell sheetCell, XmlWriter xmlWriter) { //The main header for the cell block xmlWriter.WriteStartElement("SheetCell"); //Add in the cell attributes xmlWriter.WriteElementString("Color", sheetCell.getColor().ToString()); xmlWriter.WriteElementString("RowIndex", sheetCell.getRowIndex().ToString()); xmlWriter.WriteElementString("ColumnIndex", sheetCell.getColumnIndex().ToString()); xmlWriter.WriteElementString("Text", sheetCell.getText().ToString()); //The end to the block (aka "</SheetCell>" xmlWriter.WriteEndElement(); return xmlWriter; }
public void setCell(SpreadSheetCell cell) { sheetArray[cell.getRowIndex(), cell.getColumnIndex()] = cell; }
//Suppose to update the text that the cell contains //I completely renovated this function since homework 4 public void updateValue(SpreadSheetCell[,] TwoDArray) { bool updated = false; while (updated == false) { //First we will check if the text is empty of if it hasn't actually been updated if (this._text == null || this._text == this._value) updated = true; //Otherwise we will need to make some updates to the cell else { //If the cell is not an expression or a reference if (this._text[0].ToString() != "=") { this._value = this._text; updated = true; } //My code would always break if I just entered an equals sign... Figured I should fix that else if (this._text == "=") { this._value = this._text; updated = true; } else { /*First we want to make our evaluation tree and get all of the referenced nodes*/ /**/Expression newExp = new Expression(this._text.Substring(1)); /**/ /**/List<string> refList = newExp.getAllNodes(); /**/ /*******************************************************************************/ //If the node isn't a single variable or value (i.e. A1 or 33) we will want to go through all of the //other nodes connected on the expression tree. We will need them for evaulating the expression. if (refList.Count() > 0) { //We will go through each reference in the list we created and filled about for (int i = 0; i < refList.Count(); i++) { //Create a tempory cell for the given index in the list of references StandardCell tempRefCell = checkReference(refList[i], TwoDArray); //If the cell doesn't exist, then we will want to break the loop if (tempRefCell == null) break; //We will use this a few times for checking value is a number int error = 0; //If the tempRefCell doesn't contain the cell we are modifying (this) then we will //want to add it the list of rerferences for the tempRefCell if (tempRefCell.references.Contains(this) != true) tempRefCell.references.Add(this); //We need to parse the refernce in the two parts (column and row) char p1 = refList[i][0]; string p2 = refList[i].Substring(1); //Create our variables for the row and columns int row, col; //If p1 is uppercase and the rest of the string is a number then we know that it's //a cell reference if ((char.IsUpper(p1)) && int.TryParse(p2, out error)) { //Set row to (row - 1) [we start at 0 and not 1] row = Convert.ToInt32(p2) - 1; col = 0; //Will be used to find the correct column string[] columnIndex = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; //Convert the numerical value of the string to an int for the row number (subtract 1 because rows really start at 0) //Checks if the row is within the correct range. If it is execute if (row >= 0 && row <= 50) { //Now we will find the column for (int j = 0; j < columnIndex.Length; j++) { //If the letter in the string matches a corresponding letter in the column index then set the numerical value //of the column to the vlaue if (columnIndex[j].ToString() == (p1.ToString())) { col = j; break; } } } newExp.setDictionaryValue(refList[i], TwoDArray[row, col].getValue()); } } //Evaluate the expression and set it to the cell value. Set updated to true this._value = newExp.eval().ToString(); updated = true; } //If the expression is just a single node else { if (checkReference(newExp.getExpression(), TwoDArray) != null) this._value = checkReference(newExp.getExpression(), TwoDArray).getValue(); else this._value = newExp.eval().ToString(); updated = true; } } } } }