Warning, /office/calligra/sheets/doc/Dependencies.dox is written in an unsupported language. File is not indexed.
0001 /** 0002 \page dependencies Dependency Handling 0003 \author Ariya Hidayat (<a href="mailto:ariya@kde.org">ariya@kde.org</a>) 0004 \date 2004 0005 0006 \par Status: 0007 FINISHED; NEEDS UPDATE (RecalcManager) 0008 0009 <p>When a cell holds a formula, then it is likely that it depends on other 0010 cell(s) for calculating the result. For example, if cell A11 has the formula 0011 "=SUM(A1:A10)", this means that values in cells A1, A2, A3, until 0012 A10 must be correctly calculated first before the sum can be obtained for 0013 cell A11. This is called <i>dependency</i>.</p> 0014 0015 <p>As for now, Calligra Sheets tries to manage dependency by storing the dependent 0016 cells or ranges in the cell itself. This is not too efficient. If a cell 0017 is very simple, i.e. stored only value, not formula, such scheme will just 0018 waste a couple of bytes of pointers for the dependency data structure. 0019 It is much more wiser to simply create one <i>dependency manager</i> for each 0020 worksheet; it should be responsible for maintaining and handling cell 0021 dependencies for that sheet. Also Calligra Sheets always stores ranges which depend 0022 on one particular cell and ranges whose one of its dependent is that cell 0023 (and these are all in the cell structure itself). This is not necessary as 0024 that information is redundant. The dependency manager should be able to handle 0025 both cases.</p> 0026 0027 <p>Let us have a look at this simple example:</p> 0028 0029 <table cellspacing="0" cellpadding="3" border="1"> 0030 <tr> 0031 <td align="center"> </td> 0032 <td align="center">A</td> 0033 <td align="center">B</td> 0034 <td align="center">C</td> 0035 <td align="center">D</td> 0036 </tr> 0037 <tr> 0038 <td align="center">1</td> 0039 <td align="right">14</td> 0040 <td align="right">36</td> 0041 <td align="right"> </td> 0042 <td align="right"> </td> 0043 </tr> 0044 <tr> 0045 <td align="center">2</td> 0046 <td align="right">3</td> 0047 <td align="right"> </td> 0048 <td align="right"> </td> 0049 <td align="right"> </td> 0050 </tr> 0051 <tr> 0052 <td align="center">3</td> 0053 <td align="right">77</td> 0054 <td align="right"> </td> 0055 <td align="right"> </td> 0056 <td align="right"> </td> 0057 </tr> 0058 <tr> 0059 <td align="center">4</td> 0060 <td align="right">=SUM(<b>A1:A3</b>)</td> 0061 <td align="right">=A4+SUM(<b>B1:B3</b>)</td> 0062 <td align="right">=100*<b>B4</b></td> 0063 <td align="right"> </td> 0064 </tr> 0065 </table> 0066 0067 <p>Such sheet should produce dependencies like:</p> 0068 0069 <table cellspacing="0" cellpadding="3" border="1"> 0070 <tr> 0071 <td><b>Reference</b></td> 0072 <td><b>Dependent(s)</b></td> 0073 </tr> 0074 <tr> 0075 <td>A4</td> 0076 <td>A1:A3</td> 0077 </tr> 0078 <tr> 0079 <td>B4</td> 0080 <td>A4 and B1:B3</td> 0081 </tr> 0082 <tr> 0083 <td>C4</td> 0084 <td>B4</td> 0085 </tr> 0086 </table> 0087 0088 <p>When we want to recalculate cell B4, from the dependencies shown above we 0089 may know that first we need to know values of cell A4 and range B1:B3. Further on, 0090 cell A4 needs to know values of cells in range A1:A3. Therefore, <i>given one reference 0091 cell</i> (e.g. B4), the dependency manager must be able to <i>return all 0092 dependents, cells and/or ranges</i> (e.g. A4, B1:B3). Do we need to go 0093 recursively when searching for dependencies? That really depends on the 0094 implementation, but it is not a big problem, though.</p> 0095 0096 <p>In another case, say the user has changed cell A3 so we need to update the 0097 calculation. We should not recalculate the whole sheet because it wastes time. 0098 We just need to recalculate cells that depend on A3, in this case A4, B4 and C4. 0099 So the dependency manager has another responsibility: <i>given a cell</i> 0100 it should <i>find all cells and/or ranges which depend on that particular 0101 cell</i>. It is a matter of iterating over all dependencies and checking 0102 whether the cell is within the dependent(s) and returning the reference cell. 0103 In this example, cell A3 is in the range A1:A3, a dependent range of cell A4. 0104 Hence, we just return A4. Recursive or not, we can either continue finding 0105 dependents of A4 or just stop here.</p> 0106 0107 <p>Note also that dependency manager should not store cell pointers, but rather 0108 only the location of the cell (i.e. the sheet that owns the cell, row number and 0109 column number). This is because on some cases the dependent cell may not exist 0110 yet. As illustrated in the example, dependents of cell B4 are A4, B1, B2 and B3 0111 but here cells B2 and B3 are still empty. Of course, when we just want to 0112 know which cells we need to recalculate for one reference cell, the dependency 0113 manager is allowed to return only non-empty cells (e.g. A4 and B1 in our case) 0114 as empty cells have no effect and will not be recalculated anyway.</p> 0115 0116 <p>By the same manner, dependency manager can also held responsible when 0117 chart comes into play. Any charts placed in the sheet (that are actually KChart 0118 parts) depend on some values of the cells. An action by the user to changing 0119 those cells, directly or indirectly, should trigger the update of the respective 0120 charts.</p> 0121 0122 <p>Inter-sheet dependencies can be well handled if we store the owner of 0123 each dependent. This is not shown yet in the explanation above to avoid 0124 unnecessary complication. But let have one example now: if Sheet2!A1 is 0125 "=SUM(Sheet1!A1:A10)" then changing Sheet1!A1 (the dependent) 0126 means updating Sheet2!A1 (the reference). Of course during recalculation we 0127 must take care that all sheets in the document must be processed, even though 0128 only one single cell in one sheet has been changed.</p> 0129 0130 */