1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
#pragma once
#include "Model/Template/Template.hpp"
#include "Utils/Vector.hpp"
#include "Utils/VectorHash.hpp"
#include "cplt_fwd.hpp"
#include <tsl/robin_map.h>
#include <string>
#include <vector>
class TableCell
{
public:
enum TextAlignment
{
/// For horizontal alignment, this means align left. For vertical alignment, this means align top.
AlignAxisMin,
/// Align middle of the text to the middle of the axis.
AlignCenter,
/// For horizontal alignment, this means align right. For vertical alignment, this means align bottom.
AlignAxisMax,
};
enum CellType
{
ConstantCell,
SingularParametricCell,
ArrayParametricCell,
};
public:
std::string Content;
Vec2i Location;
/// Location of the primary (top left) cell, if this cell is a part of a merged group.
/// Otherwise, either component of this field shall be -1.
Vec2i PrimaryCellLocation{ -1, -1 };
int SpanX = 0;
int SpanY = 0;
TextAlignment HorizontalAlignment = AlignCenter;
TextAlignment VerticalAlignment = AlignCenter;
CellType Type = ConstantCell;
/// 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;
};
// 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 instantiated with the n-th element in the provided array.
/// \code
/// [["foo", "bar", "foobar"],
/// ["a", "b", c"],
/// ["1", "2", "3"],
/// ["x", "y", "z"]]
/// // ... may be more
/// \endcode
/// 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:
/// \code
/// | 2 elements was fed to it
/// | | 1 element was fed to it
/// V V
/// {~~~~~~~~~~~~~~~~}{~~~~~~~~~~~~~~}
/// +------+---------+---------------+
/// | Foo | Example | Another group |
/// +------+---------+---------------+
/// | Cool | Example | |
/// +------+---------+---------------+
/// \endcode
///
/// \see TableCell
/// \see TableInstanciationParameters
/// \see TableTemplate
class TableCellArrayGroup
{
public:
int Row;
/// Leftmost cell in this group
int LeftCell;
/// Rightmost cell in this group
int RightCell;
public:
Vec2i GetLeftCell() const;
Vec2i GetRightCell() const;
int GetCount() const;
};
// Forward declaration of libxlsxwriter structs
struct lxw_workbook;
struct lxw_worksheet;
/// An object containing the necessary information to instanciate a table template.
/// \see TableTemplate
class TableInstanciationParameters
{
private:
const TableTemplate* mTable;
public:
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 instantiating this template. Merged cells,
/// parametric rows/columns, and grids are also supported.
///
/// This current supports exporting to xlsx files.
class TableTemplate : public Template
{
private:
std::vector<TableCell> mCells;
std::vector<TableCellArrayGroup> mArrayGroups;
std::vector<int> mRowHeights;
std::vector<int> mColumnWidths;
public:
static bool IsInstance(const Template* tmpl);
TableTemplate();
int GetTableWidth() const;
int GetTableHeight() const;
void Resize(int newWidth, int newHeight);
int GetRowHeight(int row) const;
void SetRowHeight(int row, int height);
int GetColumnWidth(int column) const;
void SetColumnWidth(int column, int width);
const TableCell& GetCell(Vec2i pos) const;
TableCell& GetCell(Vec2i pos);
enum MergeCellsResult
{
MCR_CellAlreadyMerged,
MCR_Success,
};
MergeCellsResult MergeCells(Vec2i topLeft, Vec2i bottomRight);
enum BreakCellsResult
{
BCR_CellNotMerged,
BCR_Success,
};
BreakCellsResult BreakCells(Vec2i topLeft);
lxw_workbook* InstantiateToExcelWorkbook(const TableInstanciationParameters& params) const;
lxw_worksheet* InstantiateToExcelWorksheet(lxw_workbook* workbook, const TableInstanciationParameters& params) const;
virtual ReadResult ReadFrom(std::istream& stream) override;
virtual void WriteTo(std::ostream& stream) const override;
};
|