diff options
Diffstat (limited to 'doc/cpp/quickstart/using_document.rst')
-rw-r--r-- | doc/cpp/quickstart/using_document.rst | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/doc/cpp/quickstart/using_document.rst b/doc/cpp/quickstart/using_document.rst new file mode 100644 index 0000000..8c6b779 --- /dev/null +++ b/doc/cpp/quickstart/using_document.rst @@ -0,0 +1,143 @@ + +.. highlight:: cpp + +.. _quickstart-document: + +Using document class +==================== + +In the :ref:`quickstart-model-context` section, we saw an example of how to +set up a cell value store and run some simple calculations using the +:cpp:class:`~ixion::model_context` class. While that approach certainly works +fine, one large drawback is that you do need to manually handle formula tokenization, +formula cell registration (and un-registration), as well as to trace which cells +have their values changed and which formula cells have been created or modified. +This is because the :cpp:class:`~ixion::model_context` class is designed to only +handle cell value storage, and all other operations related to formula expressions +and formula cell (re-)calculations have to be done outside of it. + +Luckily, Ixion also provides a higher level document class called +:cpp:class:`~ixion::document` which internally uses :cpp:class:`~ixion::model_context` +and handles all the formula cell related operations internally. This section +provides an overview of how to use the :cpp:class:`~ixion::document` class to +do more or less similar things we did in the :ref:`quickstart-model-context` +section. + +First, we need to instantiate the :cpp:class:`~ixion::document` instance and +insert a sheet named ``MySheet``. + +:: + + ixion::document doc; + doc.append_sheet("MySheet"); + +Next, like we did in the previous section, we will insert numbers 1 through 10 +in cells A1 through A10:: + + for (ixion::abs_address_t pos(0, 0, 0); pos.row <= 9; ++pos.row) + { + double value = pos.row + 1.0; // Set the row position + 1 as the cell value. + doc.set_numeric_cell(pos, value); + } + +So far we don't see much of a difference from model_context. Let's now insert +string values into cells B2 and B3:: + + // Insert string values. + std::string s = "This cell contains a string value."; + doc.set_string_cell("B2", s); + doc.set_string_cell("B3", "This too contains a string value."); + +Here we see the first difference. When using :cpp:class:`~ixion::document`, +You can specify the cell position either by :cpp:struct:`~ixion::abs_address_t` +as with :cpp:class:`~ixion::model_context`, or by a string whose value is the +name of the cell address. The default address syntax for the string cell address +is "Excel A1" syntax. You can pick a different syntax by passing a value of type +:cpp:enum:`~ixion::formula_name_resolver_t` to the constructor. + +It's worth noting that, when specifying the cell position as a string value and +the sheet name is omitted, the first sheet is implied. You can also specify +the sheet name explicitly as in the following:: + + doc.set_string_cell("MySheet!B4", "Yet another string value."); + +For a document with only one sheet, it makes no difference whether to include +the sheet name or leave it out, but if you have more than one sheet, you need to +specify the sheet name when specifying a cell position on sheets other than the +first one. + +Now, let's insert a a formula into A11 to sum up values in A1:A10, and calculate +it afterward:: + + doc.set_formula_cell("A11", "SUM(A1:A10)"); + doc.calculate(0); + +And fetch the calculated value in A11 and see what the result is:: + + double value = doc.get_numeric_value("A11"); + cout << "value of A11: " << value << endl; + +You should see the following output: + +.. code-block:: text + + value of A11: 55 + +It looks about right. The :cpp:func:`~ixion::document::calculate` method takes one +argument that is the number of threads to use for the calculation. We pass 0 here to +run the calculation using only the main thread. + +Now, let's re-write the formula in cell A11 to take the average of A1:A10 instead, +run the calculation again, and check the value of A11:: + + // Insert a new formula to A11. + doc.set_formula_cell("A11", "AVERAGE(A1:A10)"); + doc.calculate(0); + + value = doc.get_numeric_value("A11"); + cout << "value of A11: " << value << endl; + +The output says: + +.. code-block:: text + + value of A11: 5.5 + +which looks right. Note that, unlike the previous example, there is no need to un-register +and register cell A11 before and after the edit. + +Lastly, let's insert into cell A10 a new formula that contains no references to other cells. +As this will trigger a re-calculation of cell A11, we will check the values of both A10 +and A11:: + + // Overwrite A10 with a formula cell with no references. + doc.set_formula_cell("A10", "(100+50)/2"); + doc.calculate(0); + + value = doc.get_numeric_value("A10"); + cout << "value of A10: " << value << endl; + + value = doc.get_numeric_value("A11"); + cout << "value of A11: " << value << endl; + +The output will be: + +.. code-block:: text + + value of A10: 75 + value of A11: 12 + +Notice once again that there is no need to do formula cell registration nor manual tracking +of dirty formula cells. + + +Conclusion +---------- + +In this section, we have performed the same thing we did in the :ref:`quickstart-model-context` +section, but with much less code, and without the complexity of low-level formula expression +tokenization, formula cell registration, or manual tracking of modified cells. If you are +looking to leverage the functionality of Ixion but don't want to deal with lower-level formula +API, using the :cpp:class:`~ixion::document` class may be just the ticket. + +The complete source code of this example is avaiable `here <https://gitlab.com/ixion/ixion/-/blob/master/doc_example/document_simple.cpp>`_. |