Home | Libraries | People | FAQ | More |
The tutorial aims to present some basic ideas and usage of the library and would end with real life examples so that the use of the library is apparent. It is hopeful that the followed style is easy to follow. The term document refers to spreadsheet documents in general unless explicitly defined.
Firstly, to use the library in your C++ code, one would need to add the following header in your code.
#include <boost/document.hpp>
One can also include the different headers separately, in <boost/document/*.hpp>
, the above header merely includes
all the headers. All the types and classes fall in the namespace boost and
using namespace aliases might be useful for clean coding.
Firstly, we would need to declare a variable for the document by specifying the file path, specifically as boost::filesystem::path type. So, we can write,
boost::document d("/foo/bar/file.ods");
Or use a path variable to achieve the same thing,
boost::filesystem::path p("/foo/bar/file.ods"); boost::document d(p);
We would like to do something interesting with our document variable now. So, let's open it and export it as a CSV file.
Tip | |
---|---|
To Perform virtually nearly anything with the document, you would need to open it first and then close it. Closing however happens automatically when the variable goes out of scope, during the destruction sequence of the object and hence need not be explicitly carried out. |
#include <boost/document.hpp> int main(int argc, char **argv) { boost::document doc("/foo/bar/file.ods"); doc.open_document(); doc.export_document(boost::document_file_format::CSV); return 0; }
Important thing to note here is the enum
document_file_format which has three values, PDF, CSV and XML which it can
accept. The exported file would reside in the same folder as the original file.
Also, note the ommision of the doc.close_document()
which would happen automatically.
We would also like to make some changes to our sheets in the document and get some information about them. There are various methods provided in the document class for the same. For example, the following examples prints out the names of all the sheets, after getting an instance by their indices. The sheet class is a wrapper over the actual sheet of the document and acts like a reference to the same.
Warning | |
---|---|
Sheets are zero indexed irrespective of implementation details. Same goes for cells, rows and columns. |
#include <boost/document.hpp> int main(int argc, char **argv) { boost::document doc("/foo/bar/file.ods"); doc.open_document(); std::size_t count = doc.sheet_count(); for(int i = 0 ; i < count; i++) { boost::sheet s = doc.get_sheet(i); std::cout << "#" << i << "\t" << s.sheet_name() << std::endl; } return 0; }
sheet_count()
method provides the number of sheets present in the document. Sheet instances
can be obtained by their names or indices (using the get_sheet
methods), and also through the []
operator, however the []
operator
provides no exception handling unlike the get_sheet
methods.
Moving on, we would like to save our files after we have edited them programmatically.
The user can call the save_document()
or the save_as_document(const boost::filesystem::path&)
methods to save their document after they have been edited. The following example
renames a sheet and then saves the document.
#include <boost/document.hpp> int main(int argc, char **argv) { boost::document doc("/foo/bar/file.ods"); doc.open_document(); boost::sheet s = doc["Anurag"]; s.rename_sheet("Vatika"); doc.save_document(); return 0; }
Point to note here is that, the program would crash if there is no sheet "Anurag"
present. We can also use doc.get_sheet("Anurag")
for an exception being raised.
There are other sheet methods which can be used, checking the reference would be a good idea.
Now, to use the cells there are multiple ways, all of which come with their
own advantages and disadvantages. One could use the get_cell(std::size_t row,std::size_t column)
method, or the []
operators. The following example would illustrate effectively. We would also
understand the various intricacies of cell usage. The example is a mix of many
styles and must not be used as a good coding example, it is only to illustrate
the capabilities of the library.
Warning | |
---|---|
Cells are zero indexed irrespective of implementation details. |
#include <boost/document.hpp> int main(int argc, char **argv) { boost::document doc("/foo/bar/file.ods"); doc.open_document(); boost::sheet s = doc.get_sheet("Anurag"); boost::cell c = s.get_cell(4,5); // row = 4, column = 5 c.set_string("Boost"); if(c.get_content_type() == boost::cell_content_type::STRING) { std::cout << c.get_string() << std::endl; } if(s["B2"].empty()) { s["B2"] = 2.56; } doc["Vatika"][7][2] = "Anurag"; boost::sheet new = doc["Vatika"]; new["C3"] = 0.5; // row = 4, column = 2 new["C4"] = 0.5; new["C5"].set_formula("=C3+C4"); std::cout << doc["Vatika"]["C5"].get_value() << std::endl; new["D8"] = c; // Assignment if(new["D8"].get_string() == "Boost") { std::cout << "Yay!" << std::endl; } doc.save_document(); return 0; }
The get_cell()
method expects the row number and the column number of the cell, in zero indexed
format. A lot of people are more accustomed with the alphanumeric index (Eg.
"A2" or "F5") which have been provided too as []
operators.
Method like empty()
returns a bool
telling whether
the cell is empty or not. get_content_type()
returns an enum value which can be either
EMPTY,STRING,VALUE,FORMULA or ERROR.
The user can use set_formula()
or set_string()
or set_value()
methods, or can use the =
operators which sets a value for doubles passed and sets a string for std::string
passed. Likewise, get_value()
, get_formula()
and get_string()
are also provided.
The explicit function calls instead of the []
operator provide the safety of exceptions. Having a look at the cell class
reference document would help in aligning your coding style with the library
usage.
Warning | |
---|---|
The cells are a reference to the actual cells in the spreadsheet. Assignment operator must be carefully used. |
Assignment of a cell with another cell holding some instance would result in copying of the contents of the cell to the former. This should be used very carefully.
Documents thus act like a 3D matrix, the first dimension being the sheet name/sheet index, the second and third being the column and row index of the cell respectively.
Now that we can access cells, it would be great if we could iterate over them
too! The library provides access to two classes and associated const
and non-const
iterators, namely a class row
and a class column
.
There are get_column(std::size_t)
and get_row(std::size_t)
methods
in the sheet
class and the
[]
operator returns a column instance.
A small example for illustration is as follows,
#include <boost/document.hpp> int main(int argc, char **argv) { boost::document doc("/foo/bar/file.ods"); doc.open_document(); boost::sheet s1 = doc["Anurag"]; boost::row r = s1.get_row(3); std::fill(r.begin(), r.begin() + 50, 1); double sum = 0; const boost::row_iterator end(r.begin() + 50); for (auto it = r.begin(); it != end; ++it) { sum += (*it).get_value(); } std::cout << "#sum " << sum << std::endl; return 0; }
Tip | |
---|---|
One should use the STL functionality over the iterators carefully as the copy constructors and the assignment operators do not behave as we expect at times. |
The iterators themselves are random-access iterators in nature. We can similarly work with columns also. The tutorial now ends having covered the basic ideas to be presented in the Library. If you have any suggestions to the interface or the tutorial, do not hesistate to contact the authors.