react-native-nitro-xlsx 0.1.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NitroXlsx.podspec +1 -0
- package/Package.swift +6 -2
- package/README.md +219 -57
- package/android/CMakeLists.txt +4 -0
- package/android/cpp-adapter.cpp +12 -0
- package/android/src/main/java/com/margelo/nitro/xlsx/NitroXlsxPackage.kt +9 -0
- package/cpp/HybridNitroXlsx.cpp +25 -179
- package/cpp/HybridNitroXlsx.hpp +2 -2
- package/cpp/HybridXlsxConditionalFormat.cpp +252 -0
- package/cpp/HybridXlsxConditionalFormat.hpp +62 -0
- package/cpp/HybridXlsxConditionalFormats.cpp +46 -0
- package/cpp/HybridXlsxConditionalFormats.hpp +28 -0
- package/cpp/HybridXlsxWorkbook.cpp +159 -196
- package/cpp/HybridXlsxWorkbook.hpp +7 -2
- package/cpp/HybridXlsxWorksheet.cpp +433 -62
- package/cpp/HybridXlsxWorksheet.hpp +73 -26
- package/cpp/XlsxCacheDir.cpp +76 -0
- package/cpp/XlsxCacheDir.hpp +27 -0
- package/cpp/XlsxError.hpp +68 -0
- package/cpp/XlsxJson.cpp +185 -0
- package/cpp/XlsxJson.hpp +36 -0
- package/ios/XlsxCacheDir.mm +60 -0
- package/nitrogen/generated/android/NitroXlsx+autolinking.cmake +2 -0
- package/nitrogen/generated/shared/c++/HybridNitroXlsxSpec.hpp +5 -3
- package/nitrogen/generated/shared/c++/HybridXlsxConditionalFormatSpec.cpp +54 -0
- package/nitrogen/generated/shared/c++/HybridXlsxConditionalFormatSpec.hpp +95 -0
- package/nitrogen/generated/shared/c++/HybridXlsxConditionalFormatsSpec.cpp +24 -0
- package/nitrogen/generated/shared/c++/HybridXlsxConditionalFormatsSpec.hpp +68 -0
- package/nitrogen/generated/shared/c++/HybridXlsxWorkbookSpec.cpp +3 -0
- package/nitrogen/generated/shared/c++/HybridXlsxWorkbookSpec.hpp +6 -1
- package/nitrogen/generated/shared/c++/HybridXlsxWorksheetSpec.cpp +47 -19
- package/nitrogen/generated/shared/c++/HybridXlsxWorksheetSpec.hpp +52 -20
- package/package.json +2 -2
- package/scripts/prepare-openxlsx.js +23 -6
- package/scripts/run-cpp-tests.sh +14 -0
- package/src/__mocks__/react-native-nitro-modules.ts +1 -0
- package/src/__tests__/index.test.ts +76 -7
- package/src/index.ts +107 -18
- package/src/specs/NitroXlsx.nitro.ts +141 -44
- package/ios/dummy.swift +0 -2
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
#include "HybridXlsxWorksheet.hpp"
|
|
2
|
+
#include "XlsxError.hpp"
|
|
3
|
+
#include "XlsxJson.hpp"
|
|
4
|
+
#include <OpenXLSX/XLCellReference.hpp>
|
|
2
5
|
#include <cstring>
|
|
6
|
+
#include <cmath>
|
|
3
7
|
#include <fstream>
|
|
4
8
|
#include <chrono>
|
|
5
9
|
|
|
@@ -23,71 +27,93 @@ void HybridXlsxWorksheet::applyFormat(OpenXLSX::XLCell& cell, const std::optiona
|
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
void HybridXlsxWorksheet::writeString(double row, double col, const std::string& value, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
31
|
+
OpenXLSX::XLCell cell = _worksheet.cell(static_cast<unsigned int>(row), static_cast<unsigned int>(col));
|
|
32
|
+
cell.value() = value;
|
|
33
|
+
applyFormat(cell, format);
|
|
34
|
+
});
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
void HybridXlsxWorksheet::writeNumber(double row, double col, double value, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
39
|
+
OpenXLSX::XLCell cell = _worksheet.cell(static_cast<unsigned int>(row), static_cast<unsigned int>(col));
|
|
40
|
+
cell.value() = value;
|
|
41
|
+
applyFormat(cell, format);
|
|
42
|
+
});
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
void HybridXlsxWorksheet::writeBoolean(double row, double col, bool value, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
47
|
+
OpenXLSX::XLCell cell = _worksheet.cell(static_cast<unsigned int>(row), static_cast<unsigned int>(col));
|
|
48
|
+
cell.value() = value;
|
|
49
|
+
applyFormat(cell, format);
|
|
50
|
+
});
|
|
41
51
|
}
|
|
42
52
|
|
|
43
53
|
void HybridXlsxWorksheet::writeBlank(double row, double col, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
55
|
+
OpenXLSX::XLCell cell = _worksheet.cell(static_cast<unsigned int>(row), static_cast<unsigned int>(col));
|
|
56
|
+
applyFormat(cell, format);
|
|
57
|
+
});
|
|
46
58
|
}
|
|
47
59
|
|
|
48
60
|
void HybridXlsxWorksheet::writeFormula(double row, double col, const std::string& formula, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
61
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
62
|
+
OpenXLSX::XLCell cell = _worksheet.cell(static_cast<unsigned int>(row), static_cast<unsigned int>(col));
|
|
63
|
+
cell.formula() = formula;
|
|
64
|
+
applyFormat(cell, format);
|
|
65
|
+
});
|
|
52
66
|
}
|
|
53
67
|
|
|
54
68
|
void HybridXlsxWorksheet::writeFormulaNum(double row, double col, const std::string& formula, double number, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
69
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
70
|
+
OpenXLSX::XLCell cell = _worksheet.cell(static_cast<unsigned int>(row), static_cast<unsigned int>(col));
|
|
71
|
+
cell.formula() = formula;
|
|
72
|
+
cell.value() = number;
|
|
73
|
+
applyFormat(cell, format);
|
|
74
|
+
});
|
|
59
75
|
}
|
|
60
76
|
|
|
61
77
|
void HybridXlsxWorksheet::writeFormulaString(double row, double col, const std::string& formula, const std::string& str, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
78
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
79
|
+
OpenXLSX::XLCell cell = _worksheet.cell(static_cast<unsigned int>(row), static_cast<unsigned int>(col));
|
|
80
|
+
cell.formula() = formula;
|
|
81
|
+
cell.value() = str;
|
|
82
|
+
applyFormat(cell, format);
|
|
83
|
+
});
|
|
66
84
|
}
|
|
67
85
|
|
|
68
86
|
void HybridXlsxWorksheet::writeFormulaBoolean(double row, double col, const std::string& formula, bool boolVal, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
87
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
88
|
+
OpenXLSX::XLCell cell = _worksheet.cell(static_cast<unsigned int>(row), static_cast<unsigned int>(col));
|
|
89
|
+
cell.formula() = formula;
|
|
90
|
+
cell.value() = boolVal;
|
|
91
|
+
applyFormat(cell, format);
|
|
92
|
+
});
|
|
73
93
|
}
|
|
74
94
|
|
|
75
95
|
void HybridXlsxWorksheet::writeArrayFormula(double firstRow, double firstCol, double lastRow, double lastCol, const std::string& formula, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
96
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
97
|
+
OpenXLSX::XLCell cell = _worksheet.cell(static_cast<unsigned int>(firstRow), static_cast<unsigned int>(firstCol));
|
|
98
|
+
cell.formula() = formula;
|
|
99
|
+
applyFormat(cell, format);
|
|
100
|
+
});
|
|
79
101
|
}
|
|
80
102
|
|
|
81
103
|
void HybridXlsxWorksheet::writeDatetime(double row, double col, double datetime, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
104
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
105
|
+
OpenXLSX::XLCell cell = _worksheet.cell(static_cast<unsigned int>(row), static_cast<unsigned int>(col));
|
|
106
|
+
cell.value() = datetime;
|
|
107
|
+
applyFormat(cell, format);
|
|
108
|
+
});
|
|
85
109
|
}
|
|
86
110
|
|
|
87
111
|
void HybridXlsxWorksheet::writeURL(double row, double col, const std::string& url, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
112
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
113
|
+
OpenXLSX::XLCell cell = _worksheet.cell(static_cast<unsigned int>(row), static_cast<unsigned int>(col));
|
|
114
|
+
cell.value() = url;
|
|
115
|
+
applyFormat(cell, format);
|
|
116
|
+
});
|
|
91
117
|
}
|
|
92
118
|
|
|
93
119
|
void HybridXlsxWorksheet::setColumn(double firstCol, double lastCol, double width, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
@@ -123,6 +149,54 @@ void HybridXlsxWorksheet::setRow(double row, double height, const std::optional<
|
|
|
123
149
|
}
|
|
124
150
|
}
|
|
125
151
|
|
|
152
|
+
bool HybridXlsxWorksheet::deleteRow(double row) {
|
|
153
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
154
|
+
return _worksheet.deleteRow(static_cast<uint32_t>(row));
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
bool HybridXlsxWorksheet::deleteColumn(double col) {
|
|
159
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
160
|
+
unsigned int targetCol = static_cast<unsigned int>(col);
|
|
161
|
+
if (targetCol < 1) {
|
|
162
|
+
throw XlsxError(xlsx_error::INVALID_ARGUMENT, "Column index must be >= 1");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
unsigned int lastCol = _worksheet.columnCount();
|
|
166
|
+
unsigned int lastRow = _worksheet.rowCount();
|
|
167
|
+
if (targetCol > lastCol) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Shift cell contents left for every row
|
|
172
|
+
for (unsigned int r = 1; r <= lastRow; ++r) {
|
|
173
|
+
for (unsigned int c = targetCol + 1; c <= lastCol; ++c) {
|
|
174
|
+
OpenXLSX::XLCell src = _worksheet.cell(r, c);
|
|
175
|
+
OpenXLSX::XLCell dst = _worksheet.cell(r, c - 1);
|
|
176
|
+
if (!src.empty()) {
|
|
177
|
+
dst.copyFrom(src);
|
|
178
|
+
dst.setCellFormat(src.cellFormat());
|
|
179
|
+
} else {
|
|
180
|
+
dst.clear(0);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Clear the trailing column
|
|
184
|
+
OpenXLSX::XLCell trailing = _worksheet.cell(r, lastCol);
|
|
185
|
+
trailing.clear(0);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Shift column widths / hidden state left
|
|
189
|
+
for (unsigned int c = targetCol + 1; c <= lastCol; ++c) {
|
|
190
|
+
OpenXLSX::XLColumn srcCol = _worksheet.column(c);
|
|
191
|
+
OpenXLSX::XLColumn dstCol = _worksheet.column(c - 1);
|
|
192
|
+
dstCol.setWidth(srcCol.width());
|
|
193
|
+
dstCol.setHidden(srcCol.isHidden());
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return true;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
126
200
|
void HybridXlsxWorksheet::mergeRange(double firstRow, double firstCol, double lastRow, double lastCol, const std::string& value, const std::optional<std::shared_ptr<HybridXlsxCellFormatSpec>>& format) {
|
|
127
201
|
OpenXLSX::XLCellReference topLeft(static_cast<unsigned int>(firstRow), static_cast<unsigned int>(firstCol));
|
|
128
202
|
OpenXLSX::XLCellReference bottomRight(static_cast<unsigned int>(lastRow), static_cast<unsigned int>(lastCol));
|
|
@@ -143,75 +217,251 @@ void HybridXlsxWorksheet::mergeRangeNum(double firstRow, double firstCol, double
|
|
|
143
217
|
applyFormat(cell, format);
|
|
144
218
|
}
|
|
145
219
|
|
|
146
|
-
void HybridXlsxWorksheet::
|
|
220
|
+
void HybridXlsxWorksheet::unmergeCells(double firstRow, double firstCol, double lastRow, double lastCol) {
|
|
221
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
222
|
+
OpenXLSX::XLCellReference topLeft(static_cast<unsigned int>(firstRow), static_cast<unsigned int>(firstCol));
|
|
223
|
+
OpenXLSX::XLCellReference bottomRight(static_cast<unsigned int>(lastRow), static_cast<unsigned int>(lastCol));
|
|
224
|
+
std::string rangeRef = topLeft.address() + ":" + bottomRight.address();
|
|
225
|
+
_worksheet.unmergeCells(rangeRef);
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
void HybridXlsxWorksheet::hide() {
|
|
230
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
231
|
+
_worksheet.setVisibility(OpenXLSX::XLSheetState::Hidden);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
void HybridXlsxWorksheet::activate() {
|
|
236
|
+
_worksheet.setActive();
|
|
147
237
|
}
|
|
148
238
|
|
|
149
|
-
|
|
239
|
+
// ========== Sheet protection ==========
|
|
240
|
+
|
|
241
|
+
namespace {
|
|
242
|
+
// OpenXLSX defaults `set` to true when the argument is omitted
|
|
243
|
+
bool resolveSet(const std::optional<bool>& set) {
|
|
244
|
+
return set.value_or(true);
|
|
245
|
+
}
|
|
150
246
|
}
|
|
151
247
|
|
|
152
|
-
void HybridXlsxWorksheet::
|
|
248
|
+
void HybridXlsxWorksheet::protect(const std::optional<std::string>& password) {
|
|
249
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
250
|
+
if (password.has_value() && !password->empty()) {
|
|
251
|
+
if (!_worksheet.setPassword(*password)) {
|
|
252
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set sheet password");
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (!_worksheet.protectSheet()) {
|
|
256
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to protect sheet");
|
|
257
|
+
}
|
|
258
|
+
});
|
|
153
259
|
}
|
|
154
260
|
|
|
155
|
-
void HybridXlsxWorksheet::
|
|
261
|
+
void HybridXlsxWorksheet::protectSheet(std::optional<bool> set) {
|
|
262
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
263
|
+
if (!_worksheet.protectSheet(resolveSet(set))) {
|
|
264
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set protectSheet");
|
|
265
|
+
}
|
|
266
|
+
});
|
|
156
267
|
}
|
|
157
268
|
|
|
158
|
-
void HybridXlsxWorksheet::
|
|
269
|
+
void HybridXlsxWorksheet::protectObjects(std::optional<bool> set) {
|
|
270
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
271
|
+
if (!_worksheet.protectObjects(resolveSet(set))) {
|
|
272
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set protectObjects");
|
|
273
|
+
}
|
|
274
|
+
});
|
|
159
275
|
}
|
|
160
276
|
|
|
161
|
-
void HybridXlsxWorksheet::
|
|
277
|
+
void HybridXlsxWorksheet::protectScenarios(std::optional<bool> set) {
|
|
278
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
279
|
+
if (!_worksheet.protectScenarios(resolveSet(set))) {
|
|
280
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set protectScenarios");
|
|
281
|
+
}
|
|
282
|
+
});
|
|
162
283
|
}
|
|
163
284
|
|
|
164
|
-
|
|
285
|
+
// ========== Password ==========
|
|
286
|
+
|
|
287
|
+
void HybridXlsxWorksheet::setPassword(const std::string& password) {
|
|
288
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
289
|
+
if (!_worksheet.setPassword(password)) {
|
|
290
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set password");
|
|
291
|
+
}
|
|
292
|
+
});
|
|
165
293
|
}
|
|
166
294
|
|
|
167
|
-
void HybridXlsxWorksheet::
|
|
168
|
-
|
|
295
|
+
void HybridXlsxWorksheet::setPasswordHash(const std::string& hash) {
|
|
296
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
297
|
+
if (!_worksheet.setPasswordHash(hash)) {
|
|
298
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set password hash");
|
|
299
|
+
}
|
|
300
|
+
});
|
|
169
301
|
}
|
|
170
302
|
|
|
171
|
-
void HybridXlsxWorksheet::
|
|
303
|
+
void HybridXlsxWorksheet::clearPassword() {
|
|
304
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
305
|
+
if (!_worksheet.clearPassword()) {
|
|
306
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to clear password");
|
|
307
|
+
}
|
|
308
|
+
});
|
|
172
309
|
}
|
|
173
310
|
|
|
174
|
-
void HybridXlsxWorksheet::
|
|
175
|
-
|
|
176
|
-
_worksheet.
|
|
177
|
-
|
|
178
|
-
|
|
311
|
+
void HybridXlsxWorksheet::clearSheetProtection() {
|
|
312
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
313
|
+
if (!_worksheet.clearSheetProtection()) {
|
|
314
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to clear sheet protection");
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// ========== Fine-grained permissions ==========
|
|
320
|
+
|
|
321
|
+
void HybridXlsxWorksheet::allowInsertColumns(std::optional<bool> set) {
|
|
322
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
323
|
+
if (!_worksheet.allowInsertColumns(resolveSet(set))) {
|
|
324
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set allowInsertColumns");
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
void HybridXlsxWorksheet::allowInsertRows(std::optional<bool> set) {
|
|
330
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
331
|
+
if (!_worksheet.allowInsertRows(resolveSet(set))) {
|
|
332
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set allowInsertRows");
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
void HybridXlsxWorksheet::allowDeleteColumns(std::optional<bool> set) {
|
|
338
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
339
|
+
if (!_worksheet.allowDeleteColumns(resolveSet(set))) {
|
|
340
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set allowDeleteColumns");
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
void HybridXlsxWorksheet::allowDeleteRows(std::optional<bool> set) {
|
|
346
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
347
|
+
if (!_worksheet.allowDeleteRows(resolveSet(set))) {
|
|
348
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set allowDeleteRows");
|
|
349
|
+
}
|
|
350
|
+
});
|
|
179
351
|
}
|
|
180
352
|
|
|
181
|
-
void HybridXlsxWorksheet::
|
|
353
|
+
void HybridXlsxWorksheet::allowSelectLockedCells(std::optional<bool> set) {
|
|
354
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
355
|
+
if (!_worksheet.allowSelectLockedCells(resolveSet(set))) {
|
|
356
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set allowSelectLockedCells");
|
|
357
|
+
}
|
|
358
|
+
});
|
|
182
359
|
}
|
|
183
360
|
|
|
184
|
-
void HybridXlsxWorksheet::
|
|
361
|
+
void HybridXlsxWorksheet::allowSelectUnlockedCells(std::optional<bool> set) {
|
|
362
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
363
|
+
if (!_worksheet.allowSelectUnlockedCells(resolveSet(set))) {
|
|
364
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set allowSelectUnlockedCells");
|
|
365
|
+
}
|
|
366
|
+
});
|
|
185
367
|
}
|
|
186
368
|
|
|
187
|
-
void HybridXlsxWorksheet::
|
|
369
|
+
void HybridXlsxWorksheet::denyInsertColumns() {
|
|
370
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
371
|
+
if (!_worksheet.denyInsertColumns()) {
|
|
372
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to denyInsertColumns");
|
|
373
|
+
}
|
|
374
|
+
});
|
|
188
375
|
}
|
|
189
376
|
|
|
190
|
-
void HybridXlsxWorksheet::
|
|
377
|
+
void HybridXlsxWorksheet::denyInsertRows() {
|
|
378
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
379
|
+
if (!_worksheet.denyInsertRows()) {
|
|
380
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to denyInsertRows");
|
|
381
|
+
}
|
|
382
|
+
});
|
|
191
383
|
}
|
|
192
384
|
|
|
193
|
-
void HybridXlsxWorksheet::
|
|
385
|
+
void HybridXlsxWorksheet::denyDeleteColumns() {
|
|
386
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
387
|
+
if (!_worksheet.denyDeleteColumns()) {
|
|
388
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to denyDeleteColumns");
|
|
389
|
+
}
|
|
390
|
+
});
|
|
194
391
|
}
|
|
195
392
|
|
|
196
|
-
void HybridXlsxWorksheet::
|
|
393
|
+
void HybridXlsxWorksheet::denyDeleteRows() {
|
|
394
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
395
|
+
if (!_worksheet.denyDeleteRows()) {
|
|
396
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to denyDeleteRows");
|
|
397
|
+
}
|
|
398
|
+
});
|
|
197
399
|
}
|
|
198
400
|
|
|
199
|
-
void HybridXlsxWorksheet::
|
|
401
|
+
void HybridXlsxWorksheet::denySelectLockedCells() {
|
|
402
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
403
|
+
if (!_worksheet.denySelectLockedCells()) {
|
|
404
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to denySelectLockedCells");
|
|
405
|
+
}
|
|
406
|
+
});
|
|
200
407
|
}
|
|
201
408
|
|
|
202
|
-
void HybridXlsxWorksheet::
|
|
409
|
+
void HybridXlsxWorksheet::denySelectUnlockedCells() {
|
|
410
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
411
|
+
if (!_worksheet.denySelectUnlockedCells()) {
|
|
412
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to denySelectUnlockedCells");
|
|
413
|
+
}
|
|
414
|
+
});
|
|
203
415
|
}
|
|
204
416
|
|
|
205
|
-
|
|
417
|
+
// ========== Protection state ==========
|
|
418
|
+
|
|
419
|
+
bool HybridXlsxWorksheet::sheetProtected() {
|
|
420
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] { return _worksheet.sheetProtected(); });
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
bool HybridXlsxWorksheet::objectsProtected() {
|
|
424
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] { return _worksheet.objectsProtected(); });
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
bool HybridXlsxWorksheet::scenariosProtected() {
|
|
428
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] { return _worksheet.scenariosProtected(); });
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
bool HybridXlsxWorksheet::insertColumnsAllowed() {
|
|
432
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] { return _worksheet.insertColumnsAllowed(); });
|
|
206
433
|
}
|
|
207
434
|
|
|
208
|
-
|
|
435
|
+
bool HybridXlsxWorksheet::insertRowsAllowed() {
|
|
436
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] { return _worksheet.insertRowsAllowed(); });
|
|
209
437
|
}
|
|
210
438
|
|
|
211
|
-
|
|
439
|
+
bool HybridXlsxWorksheet::deleteColumnsAllowed() {
|
|
440
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] { return _worksheet.deleteColumnsAllowed(); });
|
|
212
441
|
}
|
|
213
442
|
|
|
214
|
-
|
|
443
|
+
bool HybridXlsxWorksheet::deleteRowsAllowed() {
|
|
444
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] { return _worksheet.deleteRowsAllowed(); });
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
bool HybridXlsxWorksheet::selectLockedCellsAllowed() {
|
|
448
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] { return _worksheet.selectLockedCellsAllowed(); });
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
bool HybridXlsxWorksheet::selectUnlockedCellsAllowed() {
|
|
452
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] { return _worksheet.selectUnlockedCellsAllowed(); });
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
bool HybridXlsxWorksheet::passwordIsSet() {
|
|
456
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] { return _worksheet.passwordIsSet(); });
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
std::string HybridXlsxWorksheet::passwordHash() {
|
|
460
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] { return _worksheet.passwordHash(); });
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
std::string HybridXlsxWorksheet::sheetProtectionSummary() {
|
|
464
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] { return _worksheet.sheetProtectionSummary(); });
|
|
215
465
|
}
|
|
216
466
|
|
|
217
467
|
void HybridXlsxWorksheet::setColumnHidden(double firstCol, double lastCol, bool hidden) {
|
|
@@ -341,4 +591,125 @@ std::string HybridXlsxWorksheet::getName() {
|
|
|
341
591
|
return _worksheet.name();
|
|
342
592
|
}
|
|
343
593
|
|
|
594
|
+
void HybridXlsxWorksheet::applyRename(const std::string& oldName, const std::string& newName) {
|
|
595
|
+
_worksheet.setName(newName);
|
|
596
|
+
_worksheet.updateSheetName(oldName, newName);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
void HybridXlsxWorksheet::rewriteSheetNameRef(const std::string& oldName, const std::string& newName) {
|
|
600
|
+
_worksheet.updateSheetName(oldName, newName);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// ========== JSON import / export (this worksheet) ==========
|
|
604
|
+
|
|
605
|
+
std::vector<std::shared_ptr<AnyMap>> HybridXlsxWorksheet::toJSON(const std::optional<std::vector<std::string>>& keys) {
|
|
606
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
607
|
+
return worksheetToRecords(_worksheet, keys);
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
void HybridXlsxWorksheet::fromJSON(const std::vector<std::shared_ptr<AnyMap>>& data) {
|
|
612
|
+
withXlsxError(xlsx_error::INVALID_ARGUMENT, [&] {
|
|
613
|
+
recordsToWorksheet(_worksheet, data);
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
std::string HybridXlsxWorksheet::cellAddress(double row, double col) {
|
|
618
|
+
return OpenXLSX::XLCellReference(static_cast<uint32_t>(row), static_cast<uint16_t>(col)).address();
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// ========== Comments ==========
|
|
622
|
+
|
|
623
|
+
void HybridXlsxWorksheet::setComment(double row, double col, const std::string& text, std::optional<double> authorId) {
|
|
624
|
+
withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
625
|
+
std::string ref = cellAddress(row, col);
|
|
626
|
+
auto& comments = _worksheet.comments();
|
|
627
|
+
// Excel requires every comment's authorId to reference a real <author> entry.
|
|
628
|
+
// OpenXLSX does not auto-register authors, so ensure at least one exists here;
|
|
629
|
+
// otherwise the generated comments.xml has an empty <authors> + a dangling authorId,
|
|
630
|
+
// which Excel flags as "We found a problem with some content".
|
|
631
|
+
if (comments.authorCount() == 0) {
|
|
632
|
+
comments.addAuthor("Author"); // becomes index 0
|
|
633
|
+
}
|
|
634
|
+
uint16_t author = authorId.has_value() ? static_cast<uint16_t>(*authorId) : 0;
|
|
635
|
+
if (author >= comments.authorCount()) {
|
|
636
|
+
author = 0; // fall back to a valid author
|
|
637
|
+
}
|
|
638
|
+
if (!comments.set(ref, text, author)) {
|
|
639
|
+
throw XlsxError(xlsx_error::XLSX_ERROR, "Failed to set comment for cell " + ref);
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
std::string HybridXlsxWorksheet::getComment(double row, double col) {
|
|
645
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
646
|
+
return _worksheet.comments().get(cellAddress(row, col));
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
bool HybridXlsxWorksheet::hasComment(double row, double col) {
|
|
651
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
652
|
+
std::string text = _worksheet.comments().get(cellAddress(row, col));
|
|
653
|
+
return !text.empty();
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
bool HybridXlsxWorksheet::deleteComment(double row, double col) {
|
|
658
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
659
|
+
return _worksheet.comments().deleteComment(cellAddress(row, col));
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
double HybridXlsxWorksheet::getCommentCount() {
|
|
664
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
665
|
+
return static_cast<double>(_worksheet.comments().count());
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
double HybridXlsxWorksheet::addCommentAuthor(const std::string& author) {
|
|
670
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
671
|
+
return static_cast<double>(_worksheet.comments().addAuthor(author));
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
std::string HybridXlsxWorksheet::getCommentAuthor(double authorId) {
|
|
676
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
677
|
+
return _worksheet.comments().author(static_cast<uint16_t>(authorId));
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// ========== Conditional formatting ==========
|
|
682
|
+
|
|
683
|
+
std::shared_ptr<HybridXlsxConditionalFormatsSpec> HybridXlsxWorksheet::getConditionalFormats() {
|
|
684
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
685
|
+
return std::static_pointer_cast<HybridXlsxConditionalFormatsSpec>(
|
|
686
|
+
std::make_shared<HybridXlsxConditionalFormats>(_worksheet.conditionalFormats()));
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// ========== Formula / findCell ==========
|
|
691
|
+
|
|
692
|
+
bool HybridXlsxWorksheet::hasFormula(double row, double col) {
|
|
693
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
694
|
+
OpenXLSX::XLCellAssignable cell = _worksheet.findCell(static_cast<uint32_t>(row), static_cast<uint16_t>(col));
|
|
695
|
+
if (cell.empty()) return false;
|
|
696
|
+
return cell.hasFormula();
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
std::string HybridXlsxWorksheet::formula(double row, double col) {
|
|
701
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
702
|
+
OpenXLSX::XLCellAssignable cell = _worksheet.findCell(static_cast<uint32_t>(row), static_cast<uint16_t>(col));
|
|
703
|
+
if (cell.empty() || !cell.hasFormula()) return std::string();
|
|
704
|
+
return cell.formula().get();
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
bool HybridXlsxWorksheet::findCell(double row, double col) {
|
|
709
|
+
return withXlsxError(xlsx_error::XLSX_ERROR, [&] {
|
|
710
|
+
OpenXLSX::XLCellAssignable cell = _worksheet.findCell(static_cast<uint32_t>(row), static_cast<uint16_t>(col));
|
|
711
|
+
return !cell.empty();
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
|
|
344
715
|
}
|