CS333 Lab P1-3:
Computer Supported Collaborative Work: Shared Spreadsheet

Goals of this lab:


Computer supported collaborative work is the use of a computer as an intermediary in human interactions. This is different from simple teleconferencing, since there is computation that takes place as part of the interaction.

In this lab, you will design and implement a simple spreadsheet that allows multiple users to enter data and formulae. The results from the spreadsheet calculations will be available for graphical visualization and control. (In a later assignments, you will extend your shared spreadsheet to support the construction of distributed simulations and other kinds of iterative calculations.)


Read over the entire assignment before starting. Then, follow the instructions step by step.

  1. A Spreadsheet Object: Design a C++ class for a spreadsheet object whose internal representation is a two-dimensional array of real numbers. Let the spreadsheet have a fixed number of rows and columns, provided as parameters to the constructor function. Your spreadsheet object should support the following operations:
    setval row col value
    sets the entry in the given row and column to the given value
    getval row col
    returns the value in the given row and column
    prints the contents of the spreadsheet on the standard output, in nicely formatted rows and columns (useful for debugging)
  2. Publish the Spreadsheet: Read about the PGarray data type in the manual. Modify the constructor of your spreadhsheet object to publish the spreadsheet. Now run two instances of your spreadsheet application on different machines and connect them with a bidirectional connection. Make sure that changes in each spreadsheet are visible in the other.

  3. A Formula Object: Spreadsheets are not very interesting unless they can perform calculations. To allow cells of the spreadsheet to have computed values, we need a way to put formulae into the spreadsheet. Design a formula object whose internal representation is a character string of up to 80 characters. The character string will be a formula with a Scheme-like syntax in which the following operators are allowed:

    Any expression may be used as an argument of any other expression, but for simplicity we will assume that the row and column numbers in a spreadsheet access are constants, not other expressions.

    Your formula object should have a constructor (with the associated spreadsheet object provided as a parameter). Other operations should include: print the formula to standard output, replace the contents of the formula by a new string, and evaluate the formula. (A formula with incorrect syntax will evaluate to 0. You may also want to print an error message in this case.)

  4. Formulae in Cells: Add a two-dimensional array of formula objects to the internal representation of your spreadsheet, where each formula computes the value in the corresponding entry of the spreadsheet. You should also keep track, perhaps in another array, of which cells in the spreadsheet are computed by formulae. Extend your driver with three new commands:

    1. enter (or reenter) the formula for a cell,
    2. evaluate the spreadsheet by evaluating all the formulae,
    3. print all formulae.

    Note that you could compute all the formulae left-to-right and top-to-bottom, but what would happen if the value of a cell A depends upon the value of a cell B that is further to the right or further down? Develop a strategy so that you would calculate the value of cell B before completing the calculation for cell A. However, don't compute the value of any cell more than once in a single evaluation of the spreadsheet! If there are cycles among the formula dependencies, you may break the cycles arbitrarily. See the instructor if you have questions about this.

    Test and debug your formula object using your extended driver.

  5. Publishing individual cells: Add another command to your driver that will allow users of the spreadsheet to publish individual cells (and give them external names). Now use EUPHORIA to observe and control the contents of the cells of the spreadsheet. You may want to try writing a reaction function that will reevaluate the spreadsheet whenever a value is changed externally. What will happen if you connect two spreadsheets together that have such a reaction function?
  6. Spreadsheet Front-End: Read about aggregate mappings in the EUPHORIA manual. Then use EUPHORIA to create a graphical user interface to the spreadsheet module. It should allow data values and formulae to be seen and changed by the user. It should also allow you to control the publishing of individual cell values. (Note: EUPHORIA currently does not support user editing of text that is contained within a widget.)

    We prefer that you create a GUI using EUPHORIA, but another possibility is to write a program that tests your spreadsheet object by interactively taking commands to: set the value in a particular cell, get the value of a particular cell, print the spreadsheet, or quit. Use a switch statement in your driver so that you can easily add more commands later. Your driver should print out a list of the possible commands and their arguments whenever an invalid command is entered.

Optional Extension: Iterating Spreadsheet

In this extension, you will construct a general-purpose iterating spreadsheet. Then, you will use your spreadsheet to build the process control application from the process control lab without writing any additional code!


Consider a dependency graph for a spreadsheet, defined as follows. Let there be exactly one vertex in the graph corresponding to each cell of the spreadsheet, and let there be a directed edge from vertex A to vertex B in the graph if and only if the cell corresponding to vertex A is referenced by the formula used to compute the cell corresponding to vertex B.

For most commercial spreadsheet packages, the dependency graph is restricted to be acyclic, so the entire spreadsheet can be made consistent by evaluating each formula at most once. In other words, the view is that the formulae are normally considered to be invariant assertions about the state of the spreadsheet.

However, if we allow cycles in the cell dependency graph, then we can use spreadsheets to specify more complex calculations, provided that we can specify when the calculations should terminate. Your goal is to augment the shared spreadsheet module you have built so that it can iterate until a specified termination condition is reached. This will allow you to construct simulations and other complex computations simply by entering the appropriate formulae, initial values, and termination conditions into your spreadsheet. You will even be able to distribute these computations by publishing the appropriate cells from multiple spreadsheets and forming logical connections among them.

  1. Termination Condition: Add a termination condition formula to the internal representation of your spreadsheet. This will be just another instance of your formula object. Add an option to your driver program that allows the user to enter a termination condition formula. In your prompt message, remind the user that this should be a true/false formula.

  2. Iteration: Add an option to your driver program to "iterate." Provided that a termination condition has been given, this should evaluate the spreadsheet repeatedly until the termination condition evaluates to true:
    While the termination condition is not true,
       evaluate the spreadsheet
       PG::sleep(1,0);   // so you can see what's happening and not hog the CPU
    You may want to allow the user to specify a maximum number of iterations, so that the program will stop eventually, even if the termination condition does not become true.

    Test your iterating spreadsheet thoroughly. A good first test would be to fill cell 0,0 with an initial value of 0 and the formula (+ (s 0 0) 1). Then iterate using a simple termination condition like (> (s 0 0) 10).

  3. Files: Extend your speadsheet to save and load data and formulae in files. (Alternatively, you can just run your driver, directing the input from a file.)

  4. Constructing a simulation: Use the iteration feature of your spreadsheet to construct the process control simulation. One spreadsheet will act as the sensor module, another as the control module from the process control lab. You will need to publish individual cells of the spreadsheet in order to accomplish this. Suggestion: First set up the control module as a spreadsheet and substituting it for the hard-coded control module you wrote previously. Then do the same for the sensor module.

To receive credit for this lab, you should:

  1. Clean up and print out your code. (Don't turn it in, but save it for your code/design review.)

  2. Turn in a Project Evaluation Form near the beginning of class on the day you want to do your demonstration and code/design review. You should be prepared to demonstrate your working application, explain your design and code, and answer questions.