summaryrefslogtreecommitdiffstats
path: root/doc/cpp/quickstart/using_document.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/cpp/quickstart/using_document.rst')
-rw-r--r--doc/cpp/quickstart/using_document.rst143
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>`_.