diff --git a/cmake/xlnt.cmake b/cmake/xlnt.cmake index 3886c250..b13982b2 100644 --- a/cmake/xlnt.cmake +++ b/cmake/xlnt.cmake @@ -10,7 +10,7 @@ FILE(GLOB CELL_HEADERS ../include/xlnt/cell/*.hpp) FILE(GLOB CHARTS_HEADERS ../include/xlnt/charts/*.hpp) FILE(GLOB CHARTSHEET_HEADERS ../include/xlnt/chartsheet/*.hpp) FILE(GLOB DRAWING_HEADERS ../include/xlnt/drawing/*.hpp) -FILE(GLOB FORUMULA_HEADERS ../include/xlnt/formula/*.hpp) +FILE(GLOB FORMULA_HEADERS ../include/xlnt/formula/*.hpp) FILE(GLOB PACKAGING_HEADERS ../include/xlnt/packaging/*.hpp) FILE(GLOB SERIALIZATION_HEADERS ../include/xlnt/serialization/*.hpp) FILE(GLOB STYLES_HEADERS ../include/xlnt/styles/*.hpp) @@ -25,7 +25,7 @@ FILE(GLOB CELL_SOURCES ../source/cell/*.cpp) FILE(GLOB CHARTS_SOURCES ../source/charts/*.cpp) FILE(GLOB CHARTSHEET_SOURCES ../source/chartsheet/*.cpp) FILE(GLOB DRAWING_SOURCES ../source/drawing/*.cpp) -FILE(GLOB FORUMULA_SOURCES ../source/formula/*.cpp) +FILE(GLOB FORMULA_SOURCES ../source/formula/*.cpp) FILE(GLOB PACKAGING_SOURCES ../source/packaging/*.cpp) FILE(GLOB SERIALIZATION_SOURCES ../source/serialization/*.cpp) FILE(GLOB STYLES_SOURCES ../source/styles/*.cpp) @@ -48,7 +48,7 @@ source_group(cell FILES ${CELL_HEADERS} ${CELL_SOURCES}) source_group(charts FILES ${CHARTS_HEADERS} ${CHARTS_SOURCES}) source_group(chartsheet FILES ${CHARTSHEET_HEADERS} ${CHARTSHEET_SOURCES}) source_group(drawing FILES ${DRAWING_HEADERS} ${DRAWING_SOURCES}) -source_group(formula FILES ${FORUMULA_HEADERS} ${FORUMULA_SOURCES}) +source_group(formula FILES ${FORMULA_HEADERS} ${FORMULA_SOURCES}) source_group(packaging FILES ${PACKAGING_HEADERS} ${PACKAGING_SOURCES}) source_group(serialization FILES ${SERIALIZATION_HEADERS} ${SERIALIZATION_SOURCES}) source_group(styles FILES ${STYLES_HEADERS} ${STYLES_SOURCES}) diff --git a/docs/api/xlnt.cell.rst b/docs/api/xlnt.cell.rst new file mode 100644 index 00000000..01b87a8c --- /dev/null +++ b/docs/api/xlnt.cell.rst @@ -0,0 +1,23 @@ +Cell Module +=========== + +.. doxygenstruct:: xlnt::cell_reference_hash + :members: + +.. doxygenclass:: xlnt::cell_reference + :members: + +.. doxygenclass:: xlnt::cell + :members: + +.. doxygenclass:: xlnt::comment + :members: + +.. doxygentypedef:: xlnt::row_t + +.. doxygenclass:: xlnt::column_t + :members: + +.. doxygenstruct:: xlnt::column_hash + :members: + diff --git a/docs/api/xlnt.charts.rst b/docs/api/xlnt.charts.rst new file mode 100644 index 00000000..29eae9a6 --- /dev/null +++ b/docs/api/xlnt.charts.rst @@ -0,0 +1,2 @@ +Charts Module +============= diff --git a/docs/api/xlnt.chartsheet.rst b/docs/api/xlnt.chartsheet.rst new file mode 100644 index 00000000..c5b621dc --- /dev/null +++ b/docs/api/xlnt.chartsheet.rst @@ -0,0 +1,2 @@ +Charsheet Module +================ diff --git a/docs/api/xlnt.drawing.rst b/docs/api/xlnt.drawing.rst new file mode 100644 index 00000000..2886e537 --- /dev/null +++ b/docs/api/xlnt.drawing.rst @@ -0,0 +1,5 @@ +Drawing Module +============== + +.. doxygenclass:: xlnt::drawing + :members: diff --git a/docs/api/xlnt.formula.rst b/docs/api/xlnt.formula.rst new file mode 100644 index 00000000..774be7df --- /dev/null +++ b/docs/api/xlnt.formula.rst @@ -0,0 +1,8 @@ +Formula Module +============== + +.. doxygenclass:: xlnt::tokenizer + :members: + +.. doxygenclass:: xlnt::translator + :members: diff --git a/docs/api/xlnt.packaging.rst b/docs/api/xlnt.packaging.rst new file mode 100644 index 00000000..eb21f7ef --- /dev/null +++ b/docs/api/xlnt.packaging.rst @@ -0,0 +1,24 @@ +Packaging Module +================ + +.. doxygenclass:: xlnt::document_properties + :members: + +.. doxygenclass:: xlnt::default_type + :members: + +.. doxygenclass:: xlnt::override_type + :members: + +.. doxygenclass:: xlnt::manifest + :members: + +.. doxygenclass:: xlnt::relationship + :members: + +.. doxygenstruct:: xlnt::zip_info + :members: + +.. doxygenclass:: xlnt::zip_file + :members: + diff --git a/docs/api/xlnt.rst b/docs/api/xlnt.rst index c862399d..b1c13061 100644 --- a/docs/api/xlnt.rst +++ b/docs/api/xlnt.rst @@ -1,183 +1,22 @@ -xlnt library +xlnt Library ============ -.. doxygenstruct:: xlnt::cell_reference_hash - :members: +.. doxygenenum:: xlnt::limit_style +.. doxygenvariable:: xlnt::LimitStyle -.. doxygenclass:: xlnt::cell_reference - :members: - -.. doxygenclass:: xlnt::cell - :members: - -.. doxygenclass:: xlnt::comment - :members: - -.. doxygenstruct:: xlnt::date - :members: - -.. doxygenstruct:: xlnt::time - :members: - -.. doxygenstruct:: xlnt::datetime - :members: - -.. doxygenstruct:: xlnt::timedelta - :members: - -.. doxygenclass:: xlnt::relationship - :members: - -.. doxygenstruct:: xlnt::zip_info - :members: - -.. doxygenclass:: xlnt::zip_file - :members: - -.. doxygenclass:: xlnt::drawing - :members: - -.. doxygenclass:: xlnt::tokenizer - :members: - -.. doxygenclass:: xlnt::translator - :members: - -.. doxygenclass:: xlnt::alignment - :members: - -.. doxygenclass:: xlnt::border - :members: - -.. doxygenclass:: xlnt::color - :members: - -.. doxygenclass:: xlnt::fill - :members: - -.. doxygenclass:: xlnt::font - :members: - -.. doxygenclass:: xlnt::named_style - :members: - -.. doxygenclass:: xlnt::number_format - :members: - -.. doxygenclass:: xlnt::protection - :members: - -.. doxygenclass:: xlnt::side - :members: - -.. doxygenclass:: xlnt::style - :members: - -.. doxygenclass:: xlnt::document_properties - :members: - -.. doxygenclass:: xlnt::document_security - :members: - -.. doxygenclass:: xlnt::manifest - :members: - -.. doxygenclass:: xlnt::named_range - :members: - -.. doxygenclass:: xlnt::theme - :members: - -.. doxygenclass:: xlnt::workbook - :members: - -.. doxygenclass:: xlnt::cell_vector - :members: - -.. doxygenclass:: xlnt::column_properties - :members: - -.. doxygenstruct:: xlnt::major_order - :members: - -.. doxygenclass:: xlnt::page_margins - :members: - -.. doxygenstruct:: xlnt::page_setup - :members: - -.. doxygenclass:: xlnt::pane - :members: - -.. doxygenclass:: xlnt::range_reference - :members: - -.. doxygenclass:: xlnt::range - :members: - -.. doxygenclass:: xlnt::row_properties - :members: - -.. doxygenclass:: xlnt::sheet_protection - :members: - -.. doxygenclass:: xlnt::sheet_view - :members: - -.. doxygenclass:: xlnt::header - :members: - -.. doxygenclass:: xlnt::footer - :members: - -.. doxygenclass:: xlnt::header_footer - :members: - -.. doxygenstruct:: xlnt::margins - :members: - -.. doxygenclass:: xlnt::worksheet - :members: - -.. doxygenclass:: xlnt::comment_serializer - :members: - -.. doxygenclass:: xlnt::excel_serializer - :members: - -.. doxygenclass:: xlnt::manifest_serializer - :members: - -.. doxygenclass:: xlnt::relationship_serializer - :members: - -.. doxygenclass:: xlnt::shared_strings_serializer - :members: - -.. doxygenclass:: xlnt::style_serializer - :members: - -.. doxygenclass:: xlnt::theme_serializer - :members: - -.. doxygenclass:: xlnt::workbook_serializer - :members: - -.. doxygenclass:: xlnt::worksheet_serializer - :members: - -.. doxygenclass:: xlnt::xml_document - :members: - -.. doxygenclass:: xlnt::xml_node - :members: - -.. doxygenclass:: xlnt::xml_serializer - :members: - -library modules +Library Modules =============== .. toctree:: - xlnt.s11n + xlnt.cell + xlnt.chart + xlnt.chartsheet + xlnt.drawing + xlnt.formula + xlnt.packaging + xlnt.serialization + xlnt.styles + xlnt.utils + xlnt.workbook + xlnt.worksheet diff --git a/docs/api/xlnt.s11n.rst b/docs/api/xlnt.serialization.rst similarity index 91% rename from docs/api/xlnt.s11n.rst rename to docs/api/xlnt.serialization.rst index 4197cf5e..e65b405b 100644 --- a/docs/api/xlnt.s11n.rst +++ b/docs/api/xlnt.serialization.rst @@ -1,9 +1,12 @@ -serialization module +Serialization Module ==================== .. doxygenclass:: xlnt::comment_serializer :members: +.. doxygenenum:: xlnt::encoding + :members: + .. doxygenclass:: xlnt::excel_serializer :members: diff --git a/docs/api/xlnt.styles.rst b/docs/api/xlnt.styles.rst new file mode 100644 index 00000000..bdfe2f66 --- /dev/null +++ b/docs/api/xlnt.styles.rst @@ -0,0 +1,38 @@ +Styles Module +============= + +.. doxygenclass:: xlnt::alignment + :members: + +.. doxygenenum:: xlnt::border + :members: + +.. doxygenclass:: xlnt::border + :members: + +.. doxygenclass:: xlnt::color + :members: + +.. doxygenclass:: xlnt::fill + :members: + +.. doxygenclass:: xlnt::font + :members: + +.. doxygenclass:: xlnt::named_style + :members: + +.. doxygenclass:: xlnt::number_format + :members: + +.. doxygenclass:: xlnt::protection + :members: + +.. doxygenenum:: xlnt::border_style + :members: + +.. doxygenclass:: xlnt::side + :members: + +.. doxygenclass:: xlnt::style + :members: diff --git a/docs/api/xlnt.utils.rst b/docs/api/xlnt.utils.rst new file mode 100644 index 00000000..516bec35 --- /dev/null +++ b/docs/api/xlnt.utils.rst @@ -0,0 +1,47 @@ +Utilities Module +================ + +.. doxygenstruct:: xlnt::date + :members: + +.. doxygenstruct:: xlnt::time + :members: + +.. doxygenstruct:: xlnt::datetime + :members: + +.. doxygenstruct:: xlnt::timedelta + :members: + +.. doxygenclass:: xlnt::cell_coordinates_exception + :members: + +.. doxygenclass:: xlnt::illegal_character_error + :members: + +.. doxygenclass:: xlnt::column_string_index_exception + :members: + +.. doxygenclass:: xlnt::data_type_exception + :members: + +.. doxygenclass:: xlnt::named_range_exception + :members: + +.. doxygenclass:: xlnt::sheet_title_exception + :members: + +.. doxygenclass:: xlnt::invalid_file_exception + :members: + +.. doxygenclass:: xlnt::read_only_workbook_exception + :members: + +.. doxygenclass:: xlnt::missing_number_format + :members: + +.. doxygenclass:: xlnt::attribute_error + :members: + +.. doxygenclass:: xlnt::value_error + :members: diff --git a/docs/api/xlnt.workbook.rst b/docs/api/xlnt.workbook.rst new file mode 100644 index 00000000..2c88ea5c --- /dev/null +++ b/docs/api/xlnt.workbook.rst @@ -0,0 +1,17 @@ +Workbook Module +=============== + +.. doxygenclass:: xlnt::document_security + :members: + +.. doxygenclass:: xlnt::external_book + :members: + +.. doxygenclass:: xlnt::named_range + :members: + +.. doxygenclass:: xlnt::theme + :members: + +.. doxygenclass:: xlnt::workbook + :members: diff --git a/docs/api/xlnt.worksheet.rst b/docs/api/xlnt.worksheet.rst new file mode 100644 index 00000000..afaf7ceb --- /dev/null +++ b/docs/api/xlnt.worksheet.rst @@ -0,0 +1,56 @@ +Worksheet Module +================ + +.. doxygenclass:: xlnt::cell_vector + :members: + +.. doxygenclass:: xlnt::column_properties + :members: + +.. doxygenenum:: xlnt::major_order + :members: + +.. doxygenclass:: xlnt::page_margins + :members: + +.. doxygenstruct:: xlnt::page_setup + :members: + +.. doxygenclass:: xlnt::pane + :members: + +.. doxygenclass:: xlnt::range_reference + :members: + +.. doxygenclass:: xlnt::range + :members: + +.. doxygenclass:: xlnt::row_properties + :members: + +.. doxygenclass:: xlnt::selection + :members: + +.. doxygenclass:: xlnt::sheet_protection + :members: + +.. doxygenclass:: xlnt::sheet_view + :members: + +.. doxygenclass:: xlnt::worksheet_properties + :members: + +.. doxygenclass:: xlnt::header + :members: + +.. doxygenclass:: xlnt::footer + :members: + +.. doxygenclass:: xlnt::header_footer + :members: + +.. doxygenstruct:: xlnt::margins + :members: + +.. doxygenclass:: xlnt::worksheet + :members: diff --git a/docs/changes.rst b/docs/changes.rst new file mode 100644 index 00000000..ac7f2c81 --- /dev/null +++ b/docs/changes.rst @@ -0,0 +1,4 @@ +0.9.0 (unreleased) +================== + +Beta release diff --git a/docs/charts/introduction.rst b/docs/charts/introduction.rst new file mode 100644 index 00000000..34a91646 --- /dev/null +++ b/docs/charts/introduction.rst @@ -0,0 +1,4 @@ +Charts +====== + +Charts aren't supported yet. diff --git a/docs/comments.rst b/docs/comments.rst new file mode 100644 index 00000000..4564f2b0 --- /dev/null +++ b/docs/comments.rst @@ -0,0 +1,36 @@ +Comments +======== + +Adding a comment to a cell +-------------------------- + +Comments have a text attribute and an author attribute, which must both be set. + +.. code-block:: cpp + + xlnt::workbook workbook; + auto worksheet = workbook.get_active_sheet(); + auto comment = worksheet.get_cell("A1").get_comment(); + comment = xlnt::comment("This is the comment text", "Comment Author"); + std::cout << comment.get_text() << std::endl; + std::cout << comment.get_author() << std::endl; + +You cannot assign the same Comment object to two different cells. Doing so +raises an xlnt::attribute_error. + +.. code-block:: cpp + + xlnt::workbook workbook; + auto worksheet = workbook.get_active_sheet(); + xlnt::comment comment("Text", "Author"); + worksheet.get_cell("A1").set_comment(comment); + worksheet.get_cell("B1").set_comment(comment); + + // prints: terminate called after throwing an instance of 'xlnt::attribute_error' + +Loading and saving comments +---------------------------- + +Comments present in a workbook when loaded are stored in the comment +attribute of their respective cells automatically. Comments remaining in a workbook when it is saved are automatically saved to +the workbook file. diff --git a/docs/cookbook.rst b/docs/cookbook.rst new file mode 100644 index 00000000..37861d7e --- /dev/null +++ b/docs/cookbook.rst @@ -0,0 +1,204 @@ +Simple usage +============ + +Write a workbook +---------------- +.. code-block:: cpp + + #include + + int main() + { + xlnt::workbook wb; + + std::string dest_filename = "empty_book.xlsx"; + + auto ws1 = wb.get_active_sheet(); + ws1.set_title("range names"); + + for(xlnt::row_t row = 1; row < 40; row++) + { + std::vector to_append(600, 0); + std::iota(std::begin(to_append), std::end(to_append), 0); + ws1.append(to_append); + } + + auto ws2 = wb.create_sheet("Pi"); + + ws2.get_cell("F5").set_value(3.14); + + for(xlnt::row_t row = 10; row < 20; row++) + { + for(xlnt::column_t column = 27; column < 54; column++) + { + ws3.get_cell(column, row).set_value(column.column_string()); + } + } + + std::cout << ws3.get_cell("AA10") << std::endl; + + wb.save(dest_filename); + + return 0; + } + +Read an existing workbook +------------------------- +.. code-block:: cpp + + #include + + int main() + { + xlnt::workbook wb; + wb.load("empty_book.xlsx"); + auto sheet_ranges = wb.get_range("range names"); + + std::cout << sheet_ranges["D18"] << std::endl; + // prints: 3 + + return 0; + } + +.. note :: + + There are several optional parameters that can be used in xlnt::workbook::load (in order): + + - `guess_types` will enable or disable (default) type inference when + reading cells. + + - `data_only` controls whether cells with formulae have either the + formula (default) or the value stored the last time Excel read the sheet. + + - `keep_vba` controls whether any Visual Basic elements are preserved or + not (default). If they are preserved they are still not editable. + + +.. warning :: + + xlnt does currently not read all possible items in an Excel file so + images and charts will be lost from existing files if they are opened and + saved with the same name. + + +Using number formats +-------------------- +.. code-block:: cpp + + #include + + int main() + { + xlnt::workbook wb; + wb.guess_types(true); + + auto ws = wb.get_active_sheet(); + ws.get_cell("A1").set_value(xlnt::datetime(2010, 7, 21)); + std::cout << ws.get_cell("A1").get_number_format().get_format_string() << std::endl + // prints: yyyy-mm-dd h:mm:ss + + // set percentage using a string followed by the percent sign + ws.get_cell("B1").set_value("3.14%"); + std::cout << cell.get_value() << std::endl; + // prints: 0.031400000000000004 + std::cout << cell << std::endl; + // prints: 3.14% + std::cout << cell.get_number_format().get_format_string() << std::endl; + // prints: 0% + + return 0; + } + +Using formulae +-------------- +.. code-block:: cpp + + #include + + int main() + { + xlnt::workbook wb; + auto ws = wb.get_active_sheet(); + ws.get_cell("A1").set_formula("=SUM(1, 1)"); + wb.save("formula.xlsx"); + } + +.. warning:: + NB you must use the English name for a function and function arguments *must* be separated by commas and not other punctuation such as semi-colons. + +xlsx never evaluates formula but it is possible to check the name of a formula: + +.. code-block:: cpp + + #include + + int main() + { + bool found = xlnt::formulae::exists("HEX2DEC"); + std::cout << (found ? "True" : "False") << std::endl; + // prints: True + + return 0; + } + +If you're trying to use a formula that isn't known this could be because you're using a formula that was not included in the initial specification. Such formulae must be prefixed with `xlfn.` to work. + +Merge / Unmerge cells +--------------------- +.. code-block:: cpp + + #include + + int main() + { + xlnt::workbook wb; + auto ws = wb.get_active_sheet(); + + ws.merge_cells("A1:B1"); + ws.unmerge_cells("A1:B1"); + + // or + + ws.merge_cells(1, 2, 4, 2) + ws.unmerge_cells(1, 2, 4, 2); + + return 0; + } + + +Inserting an image +------------------- +.. code-block:: cpp + + #include + + int main() + { + xlnt::workbook wb; + auto ws = wb.get_active_sheet(); + ws.get_cell("A1").set_value("You should see three logos below"); + + // create an image + auto img = xlnt::image("logo.png"); + + // add to worksheet and anchor next to cells + ws.add_image(img, "A1"); + wb.save("logo.xlsx"); + + return 0; + } + +Fold columns (outline) +---------------------- +.. code-block:: cpp + + int main() + { + xlnt::workbook wb; + auto ws = wb.create_sheet(); + bool hidden = true; + ws.group_columns("A", "D", hidden); + wb.save("group.xlsx"); + + return 0; + } diff --git a/docs/development.rst b/docs/development.rst new file mode 100644 index 00000000..17761e48 --- /dev/null +++ b/docs/development.rst @@ -0,0 +1,50 @@ +Development +=========== + +What is suppoprted +------------------ + +Supporting different platforms +------------------------------ + +Coding style +------------ + +Testing +------- + +Coverage +++++++++ + +Organisation +++++++++++++ + +Checking XML +++++++++++++ + +Schema validation ++++++++++++++++++ + +Microsoft Tools ++++++++++++++++ + +Contributing +------------ + +Contributions in the form of pull requests are always welcome. Don't forget +to add yourself to the list of authors! + +Branch naming convention +------------------------ + +Pull Requests +------------- + +Documentation ++++++++++++++ + +Benchmarking +------------ + +Memory Use +++++++++++ diff --git a/docs/formatting.rst b/docs/formatting.rst new file mode 100644 index 00000000..b408e696 --- /dev/null +++ b/docs/formatting.rst @@ -0,0 +1,4 @@ +Conditional Formatting +====================== + +Not supported yet. diff --git a/docs/formula.rst b/docs/formula.rst new file mode 100644 index 00000000..1c8564f1 --- /dev/null +++ b/docs/formula.rst @@ -0,0 +1,106 @@ +Parsing Formulas +================ + +`xlnt` supports limited parsing of formulas embedded in cells. The +`xlnt/formula` module contains a `tokenizer` class to break +formulas into their consitutuent tokens. Usage is as follows: + +.. code-block:: cpp + + #include + + int main() + { + std::string formula = R"(=IF($A$1,"then True",MAX(DEFAULT_VAL,'Sheet 2'!B1)))"; + xlnt::tokenizer tok(formula); + tok.parse(); + + for(auto &t : tok.get_items()) + { + std::cout << t.get_value() << "\t" << t.get_type() << "\t" << t.get_subtype() << std::endl; + } + + // prints: + // + // IF( FUNC OPEN + // $A$1 OPERAND RANGE + // , SEP ARG + // "then True" OPERAND TEXT + // , SEP ARG + // MAX( FUNC OPEN + // DEFAULT_VAL OPERAND RANGE + // , SEP ARG + // 'Sheet 2'!B1 OPERAND RANGE + // ) FUNC CLOSE + // ) FUNC CLOSE + + return 0; + } + +As shown above, tokens have three attributes of interest: + +* ``.value``: The substring of the formula that produced this token + +* ``.type``: The type of token this represents. Can be one of + + - ``token::literal``: If the cell does not contain a formula, its + value is represented by a single ``LITERAL`` token. + + - ``token::operand``: A generic term for any value in the Excel + formula. (See ``.subtype`` below for more details). + + - ``token::func``: Function calls are broken up into tokens for the + opener (e.g., ``SUM(``), followed by the arguments, followed by + the closer (i.e., ``)``). The function name and opening + parenthesis together form one ``FUNC`` token, and the matching + parenthesis forms another ``FUNC`` token. + + - ``token::array``: Array literals (enclosed between curly braces) + get two ``ARRAY`` tokens each, one for the opening ``{`` and one + for the closing ``}``. + + - ``token::paren``: When used for grouping subexpressions (and not to + denote function calls), parentheses are tokenized as ``paren`` + tokens (one per character). + + - ``token::sep``: These tokens are created from either commas (``,``) + or semicolons (``;``). Commas create ``sep`` tokens when they are + used to separate function arguments (e.g., ``SUM(a,b)``) or when + they are used to separate array elements (e.g., ``{a,b}``). (They + have another use as an infix operator for joining + ranges). Semicolons are always used to separate rows in an array + literal, so always create ``sep`` tokens. + + - ``token::op_pre``: Designates a prefix unary operator. Its value is + always ``+`` or ``-`` + + - ``token::op_in``: Designates an infix binary operator. Possible + values are ``>=``, ``<=``, ``<>``, ``=``, ``>``, ``<``, ``*``, + ``/``, ``+``, ``-``, ``^``, or ``&``. + + - ``token::op_post``: Designates a postfix unary operator. Its value + is always ``%``. + + - ``token::wspace``: Created for any whitespace encountered. Its + value is always a single space, regardless of how much whitespace + is found. + +* ``.subtype``: Some of the token types above use the subtype to + provide additional information about the token. Possible subtypes + are: + + + ``token::text``, ``token::number``, ``token::logical``, + ``token::error``, ``token::range``: these subtypes describe the + various forms of ``operand`` found in formulae. ``logical`` is + either ``true`` or ``false``, ``range`` is either a named range or + a direct reference to another range. ``text``, ``number``, and + ``error`` all refer to literal values in the formula + + + ``token::open`` and ``token::close``: these two subtypes are used by + ``paren``, ``func``, and ``array``, to describe whether the token + is opening a new subexpression or closing it. + + + ``token::arg`` and ``token::row``: are used by the ``sep`` tokens, + to distinguish between the comma and semicolon. Commas produce + tokens of subtype ``arg`` whereas semicolons produce tokens of + subtype ``row`` diff --git a/docs/styles.rst b/docs/styles.rst new file mode 100644 index 00000000..838a4b6e --- /dev/null +++ b/docs/styles.rst @@ -0,0 +1,17 @@ +Working with styles +=================== + +Introduction +------------ + +Styles are used to change the look of your data while displayed on screen. +They are also used to determine the number format being used for a given cell +or range of cells. + +Styles can be applied to the following aspects: + + * font to set font size, color, underlining, etc. + * fill to set a pattern or color gradient + * border to set borders on a cell + * cell alignment + * protection diff --git a/docs/tutorial.rst b/docs/tutorial.rst new file mode 100644 index 00000000..d4c235ad --- /dev/null +++ b/docs/tutorial.rst @@ -0,0 +1,5 @@ +Manipulating a workbook in memory +================================= + +Create a workbook +----------------- diff --git a/docs/validation.rst b/docs/validation.rst new file mode 100644 index 00000000..72615271 --- /dev/null +++ b/docs/validation.rst @@ -0,0 +1,2 @@ +Validating cells +================ diff --git a/docs/windows-development.rst b/docs/windows-development.rst new file mode 100644 index 00000000..45f690a7 --- /dev/null +++ b/docs/windows-development.rst @@ -0,0 +1,2 @@ +Testing on Windows +================== diff --git a/include/xlnt/cell/cell.hpp b/include/xlnt/cell/cell.hpp index 9944bac9..ab4db322 100644 --- a/include/xlnt/cell/cell.hpp +++ b/include/xlnt/cell/cell.hpp @@ -49,11 +49,7 @@ struct datetime; struct time; struct timedelta; -namespace detail { - -struct cell_impl; - -} // namespace detail +namespace detail { struct cell_impl; } /// /// Describes cell associated properties. @@ -66,22 +62,28 @@ struct cell_impl; /// class cell { - public: +public: /// /// Enumerates the possible types a cell can be determined by it's current value. /// enum class type { + /// no value. note: this is different from an empty string value or 0 numeric value null, + /// number numeric, + /// string string, + /// value is a formula formula, + /// value is a known error code such as \#VALUE! error, + /// value is TRUE or FALSE boolean }; /// - /// Return a map of error strings such as #DIV/0! and their associated indices. + /// Return a map of error strings such as \#DIV/0! and their associated indices. /// static const std::unordered_map &error_codes(); @@ -114,15 +116,35 @@ class cell /// bool has_value() const; + /// + /// Return the value of this cell as an instance of type T. + /// Overloads exist for most C++ fundamental types like bool, int, etc. as well + /// as for std::string and xlnt datetime types: date, time, datetime, and timedelta. + /// template T get_value() const; + /// + /// Make this cell have a value of type null. + /// All other cell attributes are retained. + /// void clear_value(); + /// + /// Set the value of this cell to the given value. + /// Overloads exist for most C++ fundamental types like bool, int, etc. as well + /// as for std::string and xlnt datetime types: date, time, datetime, and timedelta. template void set_value(T value); + /// + /// Return the type of this cell. + /// type get_data_type() const; + + /// + /// Set the type of this cell. + /// void set_data_type(type t); // properties @@ -139,39 +161,130 @@ class cell bool is_date() const; // position + + /// + /// Return a cell_reference that points to the location of this cell. + /// cell_reference get_reference() const; + + /// + /// Return the column of this cell. + /// column_t get_column() const; + + /// + /// Return the row of this cell. + /// row_t get_row() const; + + /// + /// Return the location of this cell as an ordered pair. + /// std::pair get_anchor() const; // hyperlink + + /// + /// Return a relationship representing this cell's hyperlink. + /// relationship get_hyperlink() const; + + /// + /// Add a hyperlink to this cell pointing to the URI of the given value. + /// void set_hyperlink(const std::string &value); + + /// + /// Return true if this cell has a hyperlink set. + /// bool has_hyperlink() const; // style + + /// + /// Return true if this cell has had a style applied to it. + /// bool has_style() const; + + /// + /// Return the index of this cell's style in its parent workbook. + /// This is also the index of the style in the stylesheet XML, xl/styles.xml. + /// std::size_t get_style_id() const; + + /// + /// Set the style index of this cell. This should be an existing style in + /// the parent workbook. + /// void set_style_id(std::size_t style_id); + + /// + /// Return the number format of this cell. + /// const number_format &get_number_format() const; void set_number_format(const number_format &format); + + /// + /// Return the font applied to the text in this cell. + /// const font &get_font() const; + void set_font(const font &font_); + + /// + /// Return the fill applied to this cell. + /// const fill &get_fill() const; + void set_fill(const fill &fill_); + + /// + /// Return the border of this cell. + /// const border &get_border() const; + void set_border(const border &border_); + + /// + /// Return the alignment of the text in this cell. + /// const alignment &get_alignment() const; + void set_alignment(const alignment &alignment_); + + /// + /// Return the protection of this cell. + /// const protection &get_protection() const; + void set_protection(const protection &protection_); + void set_pivot_button(bool b); + + /// + /// Return true iff pivot button? + /// bool pivot_button() const; + void set_quote_prefix(bool b); + + /// + /// Return true iff quote prefix? + /// bool quote_prefix() const; // comment + + /// + /// Return the comment of this cell. + /// comment get_comment(); + + /// + /// Return the comment of this cell. + /// + const comment get_comment() const; + void set_comment(const comment &comment); void clear_comment(); bool has_comment() const; @@ -196,35 +309,97 @@ class cell std::string to_string() const; // merging + + /// + /// Return true iff this cell has been merged with one or more + /// surrounding cells. + /// bool is_merged() const; + + /// + /// Make this a merged cell iff merged is true. + /// Generally, this shouldn't be called directly. Instead, + /// use worksheet::merge_cells on its parent worksheet. + /// void set_merged(bool merged); + /// + /// Return the error string that is stored in this cell. + /// std::string get_error() const; + + /// + /// Directly assign the value of this cell to be the given error. + /// void set_error(const std::string &error); + /// + /// Return a cell from this cell's parent workbook at + /// a relative offset given by the parameters. + /// cell offset(int column, int row); - + + /// + /// Return the worksheet that owns this cell. + /// worksheet get_parent(); + + /// + /// Return the worksheet that owns this cell. + /// const worksheet get_parent() const; + /// + /// Shortcut to return the base date of the parent workbook. + /// Equivalent to get_parent().get_parent().get_properties().excel_base_date + /// calendar get_base_date() const; // operators + + /// + /// Make this cell point to rhs. + /// The cell originally pointed to by this cell will be unchanged. + /// cell &operator=(const cell &rhs); + /// + /// Return true if this cell the same cell as comparand (compare by reference). + /// bool operator==(const cell &comparand) const; + + /// + /// Return true if this cell is uninitialized. + /// bool operator==(std::nullptr_t) const; // friend operators, so we can put cell on either side of comparisons with other types + + /// + /// Return true if this cell is uninitialized. + /// friend bool operator==(std::nullptr_t, const cell &cell); + + /// + /// Return the result of left.get_reference() < right.get_reference(). + /// What's the point of this? + /// friend bool operator<(cell left, cell right); - private: +private: + // make these friends so they can use the private constructor friend class worksheet; friend struct detail::cell_impl; friend class style; + /// + /// Private constructor to create a cell from its implementation. + /// cell(detail::cell_impl *d); + + /// + /// A pointer to this cell's implementation. + /// detail::cell_impl *d_; }; diff --git a/include/xlnt/cell/types.hpp b/include/xlnt/cell/types.hpp index d81fe775..77f8d2a7 100644 --- a/include/xlnt/cell/types.hpp +++ b/include/xlnt/cell/types.hpp @@ -312,8 +312,8 @@ public: }; /// -/// Functor for hashing a cell reference. -/// Allows for use of std::unordered_set and similar. +/// Functor for hashing a column. +/// Allows for use of std::unordered_set and similar. /// struct column_hash { diff --git a/include/xlnt/config.hpp b/include/xlnt/config.hpp index 49cc709a..54771b73 100644 --- a/include/xlnt/config.hpp +++ b/include/xlnt/config.hpp @@ -34,9 +34,18 @@ namespace xlnt { /// enum class limit_style { - openpyxl, /// limit style using in openpyxl - excel, /// limits according to Excel - maximum /// limits based on system + /// + /// limits used in openpyxl + /// + openpyxl, + /// + /// limits as determined by Excel + /// + excel, + /// + /// limits as high as possible based on system (i.e. 32-bit or 64-bit) + /// + maximum }; /// diff --git a/include/xlnt/packaging/zip_file.hpp b/include/xlnt/packaging/zip_file.hpp index a5301438..91117062 100644 --- a/include/xlnt/packaging/zip_file.hpp +++ b/include/xlnt/packaging/zip_file.hpp @@ -13,8 +13,14 @@ struct mz_zip_archive_tag; namespace xlnt { +/// +/// Information about a specific file in zip_file. +/// struct zip_info { + /// + /// A struct representing a particular date and time. + /// struct date_time_t { int year; @@ -25,6 +31,9 @@ struct zip_info int seconds; }; + /// + /// Default constructor for zip_info. + /// zip_info(); date_time_t date_time; @@ -44,6 +53,10 @@ struct zip_info std::size_t file_size; }; +/// +/// A compressed archive file that exists in memory which can read +/// or write to and from the filesystem, std::iostreams, and byte vectors. +/// class zip_file { public: diff --git a/include/xlnt/serialization/relationship_serializer.hpp b/include/xlnt/serialization/relationship_serializer.hpp index 011fcf85..3d8195f6 100644 --- a/include/xlnt/serialization/relationship_serializer.hpp +++ b/include/xlnt/serialization/relationship_serializer.hpp @@ -8,12 +8,32 @@ namespace xlnt { class relationship; class zip_file; +/// +/// Reads and writes collections of relationshps for a particular file. +/// class relationship_serializer { - public: - static std::vector read_relationships(zip_file &archive, const std::string &target); - static bool write_relationships(const std::vector &relationships, const std::string &target, - zip_file &archive); +public: + /// + /// Construct a serializer which operates on archive. + /// + relationship_serializer(zip_file &archive); + + /// + /// Return a vector of relationships corresponding to target. + /// + std::vector read_relationships(const std::string &target); + + /// + /// Write relationships to archive for the given target. + /// + bool write_relationships(const std::vector &relationships, const std::string &target); + +private: + /// + /// Internal archive which is used for reading and writing. + /// + zip_file &archive_; }; } // namespace xlnt diff --git a/include/xlnt/worksheet/worksheet.hpp b/include/xlnt/worksheet/worksheet.hpp index a5c0e9a5..1f29e8c9 100644 --- a/include/xlnt/worksheet/worksheet.hpp +++ b/include/xlnt/worksheet/worksheet.hpp @@ -51,6 +51,9 @@ namespace detail { struct worksheet_impl; } // namespace detail +/// +/// Worksheet header +/// class header { public: @@ -88,6 +91,9 @@ class header std::string font_color_; }; +/// +/// Worksheet footer +/// class footer { public: @@ -125,6 +131,9 @@ class footer std::string font_color_; }; +/// +/// Worksheet header and footer +/// class header_footer { public: @@ -173,6 +182,9 @@ class header_footer footer left_footer_, right_footer_, center_footer_; }; +/// +/// Worksheet margins +/// struct margins { public: @@ -249,6 +261,9 @@ struct margins double footer_; }; +/// +/// A worksheet is a 2D array of cells. +/// class worksheet { public: diff --git a/include/xlnt/xlnt.hpp b/include/xlnt/xlnt.hpp index 51552df0..3c717456 100644 --- a/include/xlnt/xlnt.hpp +++ b/include/xlnt/xlnt.hpp @@ -25,14 +25,6 @@ #include -const std::string xlnt_version = "0.1.0"; - -const std::string author = "Thomas Fussell"; -const std::string license = "MIT"; -const std::string author_email = "thomas.fussell@gmail.com"; -const std::string url = "https://github.com/tfussell/xlnt"; -const std::string download_url = "https://github.com/tfussell/xlnt/archive/master.zip"; - #include #include diff --git a/source/serialization/excel_serializer.cpp b/source/serialization/excel_serializer.cpp index d3bad4f0..f9efe52b 100644 --- a/source/serialization/excel_serializer.cpp +++ b/source/serialization/excel_serializer.cpp @@ -68,9 +68,9 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl core_properties_xml.from_string(archive.read(xlnt::constants::ArcCore())); workbook_serializer_.read_properties_core(core_properties_xml); } - - auto workbook_relationships = - xlnt::relationship_serializer::read_relationships(archive, xlnt::constants::ArcWorkbook()); + + xlnt::relationship_serializer relationship_serializer_(archive); + auto workbook_relationships = relationship_serializer_.read_relationships(xlnt::constants::ArcWorkbook()); for (const auto &relationship : workbook_relationships) { @@ -193,8 +193,9 @@ excel_serializer::excel_serializer(workbook &wb) : workbook_(wb) void excel_serializer::write_data(bool /*as_template*/) { - relationship_serializer::write_relationships(workbook_.get_root_relationships(), "", archive_); - relationship_serializer::write_relationships(workbook_.get_relationships(), constants::ArcWorkbook(), archive_); + relationship_serializer relationship_serializer_(archive_); + relationship_serializer_.write_relationships(workbook_.get_root_relationships(), ""); + relationship_serializer_.write_relationships(workbook_.get_relationships(), constants::ArcWorkbook()); xml_document properties_app_xml; workbook_serializer workbook_serializer_(workbook_); diff --git a/source/serialization/relationship_serializer.cpp b/source/serialization/relationship_serializer.cpp index 8b1e77e1..b548d9f6 100644 --- a/source/serialization/relationship_serializer.cpp +++ b/source/serialization/relationship_serializer.cpp @@ -28,10 +28,14 @@ std::string make_rels_name(const std::string &target) namespace xlnt { -std::vector relationship_serializer::read_relationships(zip_file &archive, const std::string &target) +relationship_serializer::relationship_serializer(zip_file &archive) : archive_(archive) +{ +} + +std::vector relationship_serializer::read_relationships(const std::string &target) { xml_document xml; - xml.from_string(archive.read(make_rels_name(target))); + xml.from_string(archive_.read(make_rels_name(target))); auto root_node = xml.get_child("Relationships"); @@ -55,7 +59,7 @@ std::vector relationship_serializer::read_relationships(zip_file & } bool relationship_serializer::write_relationships(const std::vector &relationships, - const std::string &target, zip_file &archive) + const std::string &target) { xml_document xml; @@ -77,7 +81,7 @@ bool relationship_serializer::write_relationships(const std::vector