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
|
#include "TableTemplate.hpp"
#include <xlsxwriter.h>
bool TableCell::IsPrimaryCell() const
{
return PrimaryCellLocation == Location;
}
bool TableCell::IsMergedCell() const
{
return PrimaryCellLocation.x == -1 || PrimaryCellLocation.y == -1;
}
int TableTemplate::GetTableWidth() const
{
return mTableWidth;
}
int TableTemplate::GetTableHeight() const
{
return mTableHeight;
}
void TableTemplate::Resize(int newWidth, int newHeight)
{
// TODO this doesn't gracefully handle resizing to a smaller size which trims some merged cells
std::vector<TableCell> cells;
cells.reserve(newWidth * newHeight);
int yEnd = std::min(mTableHeight, newHeight);
int xEnd = std::min(mTableWidth, newWidth);
for (int y = 0; y < yEnd; ++y) {
if (y >= mTableHeight) {
for (int x = 0; x < xEnd; ++x) {
cells.push_back(TableCell{});
}
continue;
}
for (int x = 0; x < xEnd; ++x) {
if (x >= mTableWidth) {
cells.push_back(TableCell{});
} else {
auto& cell = GetCell({ x, y });
cells.push_back(std::move(cell));
}
}
}
mCells = std::move(cells);
}
const TableCell& TableTemplate::GetCell(Vec2i pos) const
{
return mCells[pos.y * mTableWidth + pos.x];
}
TableCell& TableTemplate::GetCell(Vec2i pos)
{
return const_cast<TableCell&>(const_cast<const TableTemplate*>(this)->GetCell(pos));
}
TableTemplate::MergeCellsResult TableTemplate::MergeCells(Vec2i topLeft, Vec2i bottomRight)
{
auto SortTwo = [](int& a, int& b) {
if (a > b) {
std::swap(a, b);
}
};
SortTwo(topLeft.x, bottomRight.x);
SortTwo(topLeft.y, bottomRight.y);
auto ResetProgress = [&]() {
for (int y = topLeft.y; y < bottomRight.y; ++y) {
for (int x = topLeft.x; x < bottomRight.x; ++x) {
auto& cell = GetCell({ x, y });
cell.PrimaryCellLocation = { -1, -1 };
}
}
};
for (int y = topLeft.y; y < bottomRight.y; ++y) {
for (int x = topLeft.x; x < bottomRight.x; ++x) {
auto& cell = GetCell({ x, y });
if (cell.IsMergedCell()) {
ResetProgress();
return MCR_CellAlreadyMerged;
}
cell.PrimaryCellLocation = topLeft;
}
}
auto& primaryCell = GetCell(topLeft);
primaryCell.SpanX = bottomRight.x - topLeft.x;
primaryCell.SpanY = bottomRight.y - topLeft.y;
return MCR_Success;
}
TableTemplate::BreakCellsResult TableTemplate::BreakCells(Vec2i topLeft)
{
auto& primaryCell = GetCell(topLeft);
if (!primaryCell.IsMergedCell()) {
return BCR_CellNotMerged;
}
for (int dy = 0; dy < primaryCell.SpanY; ++dy) {
for (int dx = 0; dx < primaryCell.SpanX; ++dx) {
auto& cell = GetCell({ topLeft.x + dx, topLeft.y + dy });
cell.PrimaryCellLocation = { -1, -1 };
}
}
primaryCell.SpanX = 1;
primaryCell.SpanY = 1;
return BCR_Success;
}
lxw_workbook* TableTemplate::InstanciateToExcelWorkbook(const TableInstanciationParameters& params) const
{
auto workbook = workbook_new("Table.xlsx");
InstanciateToExcelWorksheet(workbook, params);
return workbook;
}
lxw_worksheet* TableTemplate::InstanciateToExcelWorksheet(lxw_workbook* workbook, const TableInstanciationParameters& params) const
{
auto worksheet = workbook_add_worksheet(workbook, "Cplt Export");
for (int y = 0; y < mTableHeight; ++y) {
for (int x = 0; x < mTableWidth; ++x) {
auto& cell = GetCell({ x, y });
switch (cell.Type) {
case TableCell::ConstantCell: {
worksheet_write_string(worksheet, y, x, cell.Content.c_str(), nullptr);
} break;
case TableCell::ParametricCell: {
// TODO
} break;
}
}
}
return worksheet;
}
|