diff options
author | rtk0c <[email protected]> | 2021-05-29 13:01:01 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2021-05-29 13:34:43 -0700 |
commit | 088da97531935a61870ecada10f06b9b9a8255d1 (patch) | |
tree | 04ad2015d8af3555353c6ea84a1c312fa67c8600 /core | |
parent | f957f4094a8d98ad0de294c3e6325ce9a860994e (diff) |
Table instaciation to xlsx complete
Diffstat (limited to 'core')
-rw-r--r-- | core/src/Model/Template/TableTemplate.cpp | 130 | ||||
-rw-r--r-- | core/src/Model/Template/TableTemplate.hpp | 66 | ||||
-rw-r--r-- | core/src/Model/Template/fwd.hpp | 2 |
3 files changed, 171 insertions, 27 deletions
diff --git a/core/src/Model/Template/TableTemplate.cpp b/core/src/Model/Template/TableTemplate.cpp index 0684c77..258bb37 100644 --- a/core/src/Model/Template/TableTemplate.cpp +++ b/core/src/Model/Template/TableTemplate.cpp @@ -1,6 +1,11 @@ #include "TableTemplate.hpp" #include <xlsxwriter.h> +#include <map> + +bool TableCell::IsDataHoldingCell() const +{ +} bool TableCell::IsPrimaryCell() const { @@ -12,6 +17,45 @@ bool TableCell::IsMergedCell() const return PrimaryCellLocation.x == -1 || PrimaryCellLocation.y == -1; } +Vec2i TableCellArrayGroup::GetLeftCell() const +{ + return { Row, LeftCell }; +} + +Vec2i TableCellArrayGroup::GetRightCell() const +{ + return { Row, RightCell }; +} + +int TableCellArrayGroup::GetCount() const +{ + return RightCell - LeftCell + 1; +} + +TableInstanciationParameters::TableInstanciationParameters(const TableTemplate& table) + : mTable{ &table } +{ +} + +TableInstanciationParameters& TableInstanciationParameters::ResetTable(const TableTemplate& newTable) +{ + mTable = &newTable; + return *this; +} + +TableInstanciationParameters TableInstanciationParameters::RebindTable(const TableTemplate& newTable) const +{ + TableInstanciationParameters result(newTable); + result.SingularCells = this->SingularCells; + result.ArrayGroups = this->ArrayGroups; + return result; +} + +const TableTemplate& TableInstanciationParameters::GetTable() const +{ + return *mTable; +} + int TableTemplate::GetTableWidth() const { return mTableWidth; @@ -129,19 +173,97 @@ lxw_workbook* TableTemplate::InstanciateToExcelWorkbook(const TableInstanciation lxw_worksheet* TableTemplate::InstanciateToExcelWorksheet(lxw_workbook* workbook, const TableInstanciationParameters& params) const { - auto worksheet = workbook_add_worksheet(workbook, "Cplt Export"); + auto worksheet = workbook_add_worksheet(workbook, "CpltExport.xlsx"); + + // Map: row number -> length of generated ranges + std::map<int, int> generatedRanges; + for (size_t i = 0; i < mArrayGroups.size(); ++i) { + auto& info = mArrayGroups[i]; + auto& param = params.ArrayGroups[i]; + + auto iter = generatedRanges.find(i); + if (iter != generatedRanges.end()) { + int available = iter->second; + if (available >= param.size()) { + // Current space is enough to fit in this array group, skip + continue; + } + } + + // Not enough space to fit in this array group, update (or insert) the appropriate amount of generated rows + int row = i; + int count = param.size(); + generatedRanges.insert(row, count); + } + + auto GetOffset = [&](int y) -> int { + // std::find_if <values less than y> + int verticalOffset = 0; + for (auto it = generatedRanges.begin(); it != generatedRanges.end() && it->first < y; ++it) { + verticalOffset += it->second; + } + return verticalOffset; + }; + + auto WriteCell = [&](int row, int col, const TableCell& cell, const char* text) -> void { + if (cell.IsPrimaryCell()) { + int lastRow = row + cell.SpanY - 1; + int lastCol = col + cell.SpanX - 1; + // When both `string` and `format` are null, the top-left cell contents are untouched (what we just wrote in the above switch) + worksheet_merge_range(worksheet, row, col, lastRow, lastCol, text, nullptr); + } else { + worksheet_write_string(worksheet, row, col, text, nullptr); + } + }; + + // Write/instanciate all array groups + for (size_t i = 0; i < mArrayGroups.size(); ++i) { + auto& groupInfo = mArrayGroups[i]; + auto& groupParams = params.ArrayGroups[i]; + + int rowCellCount = groupInfo.GetCount(); + int row = groupInfo.Row + GetOffset(groupInfo.Row); + + // For each row that would be generated + for (auto& rowCells : groupParams) { + // For each cell in the row + for (int i = 0; i < rowCellCount; ++i) { + // TODO spport merged cells in array groups + worksheet_write_string(worksheet, row + i, col, rowCells[i].c_str(), nullptr); + } + } + } + + // Write all regular and singular parameter cells for (int y = 0; y < mTableHeight; ++y) { for (int x = 0; x < mTableWidth; ++x) { auto& cell = GetCell({ x, y }); + + if (!cell.IsDataHoldingCell()) { + continue; + } + switch (cell.Type) { case TableCell::ConstantCell: { - worksheet_write_string(worksheet, y, x, cell.Content.c_str(), nullptr); + int row = y + GetOffset(y); + int col = x; + + WriteCell(row, col, cell, cell.Content.c_str()); } break; - case TableCell::ParametricCell: { - // TODO + case TableCell::SingularParametricCell: { + int row = y + GetOffset(y); + int col = x; + + auto iter = params.SingularCells.find({ x, y }); + if (iter != params.SingularCells.end()) { + WriteCell(row, col, cell, iter.value().c_str()); + } } break; + + // See loop above that processes whole array groups at the same time + case TableCell::ArrayParametricCell: break; } } } diff --git a/core/src/Model/Template/TableTemplate.hpp b/core/src/Model/Template/TableTemplate.hpp index 6454ccd..be043a9 100644 --- a/core/src/Model/Template/TableTemplate.hpp +++ b/core/src/Model/Template/TableTemplate.hpp @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "Utils/Vector.hpp" #include "Utils/VectorHash.hpp" @@ -24,7 +24,8 @@ public: enum CellType { ConstantCell, - ParametricCell, + SingularParametricCell, + ArrayParametricCell, }; public: @@ -38,15 +39,23 @@ public: TextAlignment HorizontalAlignment = AlignAxisMin; TextAlignment VerticalAlignment = AlignAxisMin; CellType Type; + /// The id of the group description object, if this cell isn't a constant or singluar parameter cell. Otherwise, this value is -1. + int DataId = -1; public: + /// Return whether this cell holds meaningful data, i.e. true when this cell is either unmerged or the primary cell of a merged range. + bool IsDataHoldingCell() const; + /// Return whether this cell is the primary (i.e. top left) cell of a merged range or not. bool IsPrimaryCell() const; + /// Return whether this cell is a part of a merged range or not. Includes the primary cell. bool IsMergedCell() const; }; -/// Parameter group information for a grouped array of cells, either horizontal or vertical. -/// These cells can have "expansion behavior", i.e. when instanciating, a list of cell values would be provided by -/// the caller: +// TODO support reverse (bottom to top) filling order +// TODO support horizontal filling order +/// Parameter group information for a grouped array of cells. When instanciated, an array of 0 or more +/// elements shall be provided by the user, which will replace the group of templated cells with a list +/// of rows, each instanciated with the n-th element in the provided array. /// \code /// [["foo", "bar", "foobar"], /// ["a", "b", c"], @@ -54,11 +63,9 @@ public: /// ["x", "y", "z"]] /// // ... may be more /// \endcode +/// This would create 4 rows of data in the place of the original parameter group. /// -/// For a array parameter group that vertically expands, this would create 4 rows of data in the place of the -/// original parameter group. If more than one array parameter groups are on the same row, they would share space -/// between each other : -/// +/// If more than one array parameter groups are on the same row, they would share space between each other: /// \code /// | 2 elements was fed to it /// | | 1 element was fed to it @@ -70,19 +77,23 @@ public: /// | Cool | Example | | /// +------+---------+---------------+ /// \endcode -class TableArrayParameterGroup +/// +/// \see TableCell +/// \see TableInstanciationParameters +/// \see TableTemplate +class TableCellArrayGroup { public: - enum ExpansionDirection - { - ExpandUp, - ExpandDown, - ExpandLeft, - ExpandRight, - }; + int Row; + /// Leftmost cell in this group + int LeftCell; + /// Rightmost cell in this group + int RightCell; public: - ExpansionDirection ExpandDirection; + Vec2i GetLeftCell() const; + Vec2i GetRightCell() const; + int GetCount() const; }; // Forward declaration of libxlsxwriter structs @@ -94,11 +105,22 @@ struct lxw_worksheet; class TableInstanciationParameters { private: - TableTemplate* mTemplate; - tsl::robin_map<Vec2i, std::string> ParametricCells; + const TableTemplate* mTable; public: - // TODO + tsl::robin_map<Vec2i, std::string> SingularCells; + + using ArrayGroupRow = std::vector<std::string>; + using ArrayGroupData = std::vector<ArrayGroupRow>; + std::vector<ArrayGroupData> ArrayGroups; + +public: + TableInstanciationParameters(const TableTemplate& table); + + TableInstanciationParameters& ResetTable(const TableTemplate& newTable); + TableInstanciationParameters RebindTable(const TableTemplate& newTable) const; + + const TableTemplate& GetTable() const; }; /// A table template, where individual cells can be filled by workflows instanciating this template. Merged cells, @@ -109,7 +131,7 @@ class TableTemplate { private: std::vector<TableCell> mCells; - std::vector<TableArrayParameterGroup> mArrayGroups; + std::vector<TableCellArrayGroup> mArrayGroups; int mTableWidth; int mTableHeight; diff --git a/core/src/Model/Template/fwd.hpp b/core/src/Model/Template/fwd.hpp index d62552f..2f41f22 100644 --- a/core/src/Model/Template/fwd.hpp +++ b/core/src/Model/Template/fwd.hpp @@ -2,6 +2,6 @@ // TableTemplate.hpp class TableCell; -class TableArrayParameterGroup; +class TableCellArrayGroup; class TableInstanciationParameters; class TableTemplate; |