Expression
class from the previous assignment will be used to represent the formulas in the spreadsheet cells. (Formulas that refer to other spreadsheet cells will contain variables corresponding to those cells!) A given cell's value can be calculated via its formula's evaluate
method, assuming the values of all referenced cells are already known. The tricky part has to do with recalculating values in the spreadsheet after updating or adding a formula, but more about that in a moment...
Expression
class, or my solution, as you work on this final assignment.
Ethan Spence and Lucas Takiff
Gabriel Guinn and Stephen Rice
Grey Roppolo and Bonacic
Ella Slattery and Noah Zimmer
Noah Sprenger and Jacob Endrina
Rohan Crossland and Brett Garon
Devan Meyer and Alex Lopez
Cian Monaghan and Asa Bonner
Noah McCullough and Jinwoo Choi
Brendan Bell and Lucas Calaff
Mackenzie Leibee and Spencer Racca-Gwozdzik
The GUI just displays information though — it doesn't store values or evaluate formulas. When the window is drawn, it interacts with a spreadsheet implementation via the set of methods in the Sheetable
interface. (See the documentation for Sheetable
and the GUI.) The GUI uses a getValue
method (that you'll need to impleent) to request the value of a cell during the display process, setFormula
to update spreadsheet formulas when the user enters or modifies formulas. Thus, the GUI can be combined with any object that implements the Sheetable
interface.
To get you started, and to illustrate the use of the GUI, I'm providing a "fake" spreadsheet that implements the Sheetable
interface. It doesn't do anything very interesting, but it does implement all of the required methods in a naive way. I'm also giving you the Demo class. It contains a main method that ties all of the pieces together — it creates a FakeSpreadsheet object and a GUI that interacts with it. If you download and compile all of this code (or the zipped version),
you'll have a working demonstration. (It doesn't actually store any
formulas — that part is up to you!) The class diagram below illustrates the relationships between the classes I'm providing:
Expression
class
allows variables in expressions or this would be a lot harder!
(The column identifier always comes first, and we will assume that
it will consist of a single upper-case character. The row number
may be more than a single digit, however.)
We won't use an "=" to differentiate between simple values and formulas like Excel does — each of our cells will hold a formula (possibly a formula consisting of a single value), so we won't need the "=". Initially, though, all cells in the spreadsheet should be empty. They should only take on values once the user has clicked on a cell and entered a formula. People make mistakes though, so there's no guarantee that an input formula will be syntactically correct. If it's not, catch any resulting exceptions and leave the cell's contents unchanged.
2.0
, C2 holds the formula B2 * 2.0
, and D2 holds C2 * 2.0
. E2's formula is shown in the editing window. Since none of the cells contain formulas that reference E2, only cell E2 would need to be updated if the user modified its formula. If the user were to edit B2 and change the 2.0 to a 3.0, however, all four cells shown would have to be updated. Note also that the order in which they're evaluated is important: A good spreadsheet would evaluate the cells from left to right in this particular case, so that C2's new value is available when we update D2, and D2's new value is ready for E2 when it's recalculated. The most efficient order in which to visit and re-evaluate cells depends upon the relationship between their formulas, so you can't just build in a particular ordering if you want to be efficient.
For this assignment, you can select from one of the three possible approaches to the recalculation problem described below. Your grade will be influenced by the approach you take, since the difficulty of implementing them differs. Regardless of the approach you choose, you must detect cycles among formulas (e.g. B1 refers to B2, and B2 refers to B1). The three algorithms reveal cycles in different ways, but if you detect one you should stop the recalculation process and report an error. You need not describe the cycle to the user — just tell them that one exists and leave it up to them to find and fix it.
Cell | Formula | Current Value |
---|---|---|
B2 | 2 | 2 |
C2 | B2 * 2 | 4 |
D2 | C2 * 2 | 8 |
E2 | ( D2 * 2 ) + B2 | 18 |
In terms of the example above, our list would contain [B2, D2, C2, E2], in that order. (C2 and D2 have the same number of variables and so could appear in either order, but I'm listing them this way because it's more interesting that way.) Thus we'd start by evaluating B2. Its new value of 3 wouldn't change, but we'd then go through the rest of the list and remove B2 from the variable sets of the remaining formulas. That would leave D2 with one variable, C2 with 0 variables, and E2 with one. If we re-sort the list based on the size of these variable sets we'd get [C2, D2, E2]. That tells us that C2 is the one to evaluate next. Removing C2 from the rest of the variable sets would leave D2 with none and E2 with one, so we'd have [D2, E2]. Repeat until they're all evaluated.
The algorithm in this case is to start at the node that's been updated and visit the "downstream" nodes that use its value. (You'll want to be a little clever about the order in which you visit these nodes if you want the best efficiency, otherwise you might visit E2 and recompute its value before you visit C2. The algorithm will work even if you don't worry about the order though.) Keep going until you reach a node with no outgoing arrows — E2 in this case. That is, updating B2 would cause you to visit and evaluate C2 and (eventually) E2. Updating C2 causes you to visit and update D2, which causes you to visit and update E2. Eventually, when there are no more arrows to follow, you're done. This approach can potentially get by without recalculating all of the cells in the spreadsheet. If we changed the formula in D2, for example, we'd recompute E2 but wouldn't have to consider B2 or C2.
spreadsheet
.
arithmeticExpression
package code — and submit the .zip archive via Canvas. I want to make sure I've got all of the code necessary to compile and run your projects. (I'd appreciate it if you'd make sure there's nothing but .java files in the folder.) Additionally, each group member should email me a sentence or two, individually, describing how the work was divided, what your role was in the design and implementation, and your experiences during the group design and programming sessions.
System.out.println
.