react-native-nitro-xlsx 0.1.1

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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +73 -0
  3. package/NitroXlsx.podspec +110 -0
  4. package/README.md +340 -0
  5. package/android/CMakeLists.txt +52 -0
  6. package/android/build.gradle +49 -0
  7. package/android/cpp-adapter.cpp +9 -0
  8. package/android/src/main/AndroidManifest.xml +2 -0
  9. package/android/src/main/java/com/margelo/nitro/xlsx/NitroXlsxPackage.kt +22 -0
  10. package/cpp/HybridNitroXlsx.cpp +29 -0
  11. package/cpp/HybridNitroXlsx.hpp +19 -0
  12. package/cpp/HybridXlsxCellFormat.cpp +263 -0
  13. package/cpp/HybridXlsxCellFormat.hpp +111 -0
  14. package/cpp/HybridXlsxWorkbook.cpp +184 -0
  15. package/cpp/HybridXlsxWorkbook.hpp +41 -0
  16. package/cpp/HybridXlsxWorksheet.cpp +316 -0
  17. package/cpp/HybridXlsxWorksheet.hpp +86 -0
  18. package/nitro.json +19 -0
  19. package/nitrogen/generated/.gitattributes +1 -0
  20. package/nitrogen/generated/android/NitroXlsx+autolinking.cmake +84 -0
  21. package/nitrogen/generated/android/NitroXlsx+autolinking.gradle +27 -0
  22. package/nitrogen/generated/android/NitroXlsxOnLoad.cpp +49 -0
  23. package/nitrogen/generated/android/NitroXlsxOnLoad.hpp +34 -0
  24. package/nitrogen/generated/android/kotlin/com/margelo/nitro/xlsx/NitroXlsxOnLoad.kt +35 -0
  25. package/nitrogen/generated/ios/NitroXlsx+autolinking.rb +62 -0
  26. package/nitrogen/generated/ios/NitroXlsx-Swift-Cxx-Bridge.cpp +17 -0
  27. package/nitrogen/generated/ios/NitroXlsx-Swift-Cxx-Bridge.hpp +27 -0
  28. package/nitrogen/generated/ios/NitroXlsx-Swift-Cxx-Umbrella.hpp +38 -0
  29. package/nitrogen/generated/ios/NitroXlsxAutolinking.mm +35 -0
  30. package/nitrogen/generated/ios/NitroXlsxAutolinking.swift +16 -0
  31. package/nitrogen/generated/shared/c++/CellType.hpp +100 -0
  32. package/nitrogen/generated/shared/c++/HybridNitroXlsxSpec.cpp +23 -0
  33. package/nitrogen/generated/shared/c++/HybridNitroXlsxSpec.hpp +68 -0
  34. package/nitrogen/generated/shared/c++/HybridXlsxCellFormatSpec.cpp +62 -0
  35. package/nitrogen/generated/shared/c++/HybridXlsxCellFormatSpec.hpp +104 -0
  36. package/nitrogen/generated/shared/c++/HybridXlsxWorkbookSpec.cpp +27 -0
  37. package/nitrogen/generated/shared/c++/HybridXlsxWorkbookSpec.hpp +77 -0
  38. package/nitrogen/generated/shared/c++/HybridXlsxWorksheetSpec.cpp +69 -0
  39. package/nitrogen/generated/shared/c++/HybridXlsxWorksheetSpec.hpp +120 -0
  40. package/package.json +47 -0
  41. package/src/__mocks__/react-native-nitro-modules.ts +28 -0
  42. package/src/__mocks__/react-native.ts +1 -0
  43. package/src/__tests__/index.test.ts +141 -0
  44. package/src/index.ts +195 -0
  45. package/src/specs/NitroXlsx.nitro.ts +154 -0
@@ -0,0 +1,29 @@
1
+ #include "HybridNitroXlsx.hpp"
2
+ #include <fstream>
3
+
4
+ namespace margelo::nitro::xlsx {
5
+
6
+ HybridNitroXlsx::HybridNitroXlsx()
7
+ : HybridObject("NitroXlsx"), HybridNitroXlsxSpec() {
8
+ }
9
+
10
+ HybridNitroXlsx::~HybridNitroXlsx() {
11
+ }
12
+
13
+ std::shared_ptr<HybridXlsxWorkbookSpec> HybridNitroXlsx::createWorkbook() {
14
+ return std::make_shared<HybridXlsxWorkbook>();
15
+ }
16
+
17
+ std::shared_ptr<HybridXlsxWorkbookSpec> HybridNitroXlsx::openWorkbook(const std::string& path) {
18
+ auto workbook = std::make_shared<HybridXlsxWorkbook>();
19
+ workbook->openFromFile(path);
20
+ return workbook;
21
+ }
22
+
23
+ std::shared_ptr<HybridXlsxWorkbookSpec> HybridNitroXlsx::openWorkbookFromBuffer(const std::shared_ptr<ArrayBuffer>& buffer) {
24
+ auto workbook = std::make_shared<HybridXlsxWorkbook>();
25
+ workbook->openFromBuffer(buffer->data(), buffer->size());
26
+ return workbook;
27
+ }
28
+
29
+ }
@@ -0,0 +1,19 @@
1
+ #pragma once
2
+
3
+ #include "HybridNitroXlsxSpec.hpp"
4
+ #include <memory>
5
+ #include "HybridXlsxWorkbook.hpp"
6
+
7
+ namespace margelo::nitro::xlsx {
8
+
9
+ class HybridNitroXlsx : public HybridNitroXlsxSpec {
10
+ public:
11
+ HybridNitroXlsx();
12
+ ~HybridNitroXlsx() override;
13
+
14
+ std::shared_ptr<HybridXlsxWorkbookSpec> createWorkbook() override;
15
+ std::shared_ptr<HybridXlsxWorkbookSpec> openWorkbook(const std::string& path) override;
16
+ std::shared_ptr<HybridXlsxWorkbookSpec> openWorkbookFromBuffer(const std::shared_ptr<ArrayBuffer>& buffer) override;
17
+ };
18
+
19
+ }
@@ -0,0 +1,263 @@
1
+ #include "HybridXlsxCellFormat.hpp"
2
+ #include <sstream>
3
+ #include <iomanip>
4
+
5
+ namespace margelo::nitro::xlsx {
6
+
7
+ static std::string doubleToHexColor(double color) {
8
+ uint32_t c = static_cast<uint32_t>(color);
9
+ // Excel uses ARGB format, prepend alpha channel (FF)
10
+ uint32_t argb = c | 0xFF000000;
11
+ std::stringstream ss;
12
+ ss << std::hex << std::setfill('0') << std::setw(8) << argb;
13
+ return ss.str();
14
+ }
15
+
16
+ HybridXlsxCellFormat::HybridXlsxCellFormat()
17
+ : HybridObject("XlsxCellFormat"), HybridXlsxCellFormatSpec() {
18
+ }
19
+
20
+ HybridXlsxCellFormat::~HybridXlsxCellFormat() {
21
+ }
22
+
23
+ OpenXLSX::XLStyleIndex HybridXlsxCellFormat::applyToDocument(OpenXLSX::XLStyles& styles) {
24
+ OpenXLSX::XLCellFormat cellFormat;
25
+
26
+ // Font
27
+ if (!_fontName.empty() || _fontSize > 0 || _fontColor > 0 || _bold || _italic || _underline > 0 || _strikeout || _fontScript > 0) {
28
+ OpenXLSX::XLFont font;
29
+ if (!_fontName.empty()) font.setFontName(_fontName);
30
+ if (_fontSize > 0) font.setFontSize(static_cast<size_t>(_fontSize));
31
+ if (_fontColor > 0) font.setFontColor(OpenXLSX::XLColor(doubleToHexColor(_fontColor)));
32
+ if (_bold) font.setBold();
33
+ if (_italic) font.setItalic();
34
+ if (_underline > 0) font.setUnderline(static_cast<OpenXLSX::XLUnderlineStyle>(_underline));
35
+ if (_strikeout) font.setStrikethrough();
36
+ if (_fontScript > 0) font.setVertAlign(static_cast<OpenXLSX::XLVerticalAlignRunStyle>(_fontScript));
37
+ cellFormat.setFontIndex(styles.fonts().create(font));
38
+ cellFormat.setApplyFont(true);
39
+ }
40
+
41
+ // Alignment
42
+ if (_textWrap || _rotation != 0 || _indent > 0 || _align > 0 || _verticalAlign > 0 || _shrink) {
43
+ auto alignment = cellFormat.alignment(true);
44
+ if (_align > 0) alignment.setHorizontal(static_cast<OpenXLSX::XLAlignmentStyle>(_align));
45
+ if (_verticalAlign > 0) alignment.setVertical(static_cast<OpenXLSX::XLAlignmentStyle>(_verticalAlign));
46
+ if (_textWrap) alignment.setWrapText();
47
+ if (_rotation != 0) alignment.setTextRotation(static_cast<uint16_t>(_rotation));
48
+ if (_indent > 0) alignment.setIndent(static_cast<uint32_t>(_indent));
49
+ if (_shrink) alignment.setShrinkToFit();
50
+ cellFormat.setApplyAlignment(true);
51
+ }
52
+
53
+ // Number format
54
+ if (!_numFormat.empty()) {
55
+ OpenXLSX::XLNumberFormat numFormat;
56
+ numFormat.setFormatCode(_numFormat);
57
+ OpenXLSX::XLStyleIndex numFmtIndex = styles.numberFormats().create(numFormat);
58
+ uint32_t numFmtId = styles.numberFormats().numberFormatIdFromIndex(numFmtIndex);
59
+ cellFormat.setNumberFormatId(numFmtId);
60
+ cellFormat.setApplyNumberFormat(true);
61
+ }
62
+
63
+ // Fill
64
+ if (_bgColor > 0 || _fgColor > 0 || _pattern > 0) {
65
+ OpenXLSX::XLFill fill;
66
+ fill.setPatternType(_pattern > 0
67
+ ? static_cast<OpenXLSX::XLPatternType>(_pattern)
68
+ : OpenXLSX::XLPatternType::XLPatternSolid);
69
+ if (_bgColor > 0) fill.setBackgroundColor(OpenXLSX::XLColor(doubleToHexColor(_bgColor)));
70
+ if (_fgColor > 0) fill.setColor(OpenXLSX::XLColor(doubleToHexColor(_fgColor)));
71
+ cellFormat.setFillIndex(styles.fills().create(fill));
72
+ cellFormat.setApplyFill(true);
73
+ }
74
+
75
+ // Border
76
+ if (_border > 0 || _bottom > 0 || _top > 0 || _left > 0 || _right > 0 || _diagonal > 0) {
77
+ OpenXLSX::XLBorder border;
78
+ // TODO: Implement border styling with OpenXLSX v0.5.1 API
79
+ cellFormat.setBorderIndex(styles.borders().create(border));
80
+ cellFormat.setApplyBorder(true);
81
+ }
82
+
83
+ // Protection
84
+ if (_locked) {
85
+ cellFormat.setLocked(true);
86
+ cellFormat.setApplyProtection(true);
87
+ }
88
+
89
+ return styles.cellFormats().create(cellFormat);
90
+ }
91
+
92
+ void HybridXlsxCellFormat::applyToCell(OpenXLSX::XLCell& cell, OpenXLSX::XLStyleIndex styleIndex) {
93
+ cell.setCellFormat(styleIndex);
94
+ }
95
+
96
+ void HybridXlsxCellFormat::setFontName(const std::string& name) {
97
+ _fontName = name;
98
+ }
99
+
100
+ void HybridXlsxCellFormat::setFontSize(double size) {
101
+ _fontSize = size;
102
+ }
103
+
104
+ void HybridXlsxCellFormat::setFontColor(double color) {
105
+ _fontColor = color;
106
+ }
107
+
108
+ void HybridXlsxCellFormat::setFontScript(double style) {
109
+ _fontScript = style;
110
+ }
111
+
112
+ void HybridXlsxCellFormat::setBold() {
113
+ _bold = true;
114
+ }
115
+
116
+ void HybridXlsxCellFormat::setItalic() {
117
+ _italic = true;
118
+ }
119
+
120
+ void HybridXlsxCellFormat::setUnderline(std::optional<double> style) {
121
+ _underline = style.has_value() ? *style : 1;
122
+ }
123
+
124
+ void HybridXlsxCellFormat::setStrikeout() {
125
+ _strikeout = true;
126
+ }
127
+
128
+ void HybridXlsxCellFormat::setAlign(double align) {
129
+ _align = align;
130
+ }
131
+
132
+ void HybridXlsxCellFormat::setVerticalAlign(double align) {
133
+ _verticalAlign = align;
134
+ }
135
+
136
+ void HybridXlsxCellFormat::setTextWrap() {
137
+ _textWrap = true;
138
+ }
139
+
140
+ void HybridXlsxCellFormat::setRotation(double angle) {
141
+ _rotation = angle;
142
+ }
143
+
144
+ void HybridXlsxCellFormat::setIndent(double level) {
145
+ _indent = level;
146
+ }
147
+
148
+ void HybridXlsxCellFormat::setShrink() {
149
+ _shrink = true;
150
+ }
151
+
152
+ void HybridXlsxCellFormat::setNumFormat(const std::string& format) {
153
+ _numFormat = format;
154
+ }
155
+
156
+ void HybridXlsxCellFormat::setNumFormatIndex(double index) {
157
+ _numFormatIndex = index;
158
+ }
159
+
160
+ void HybridXlsxCellFormat::setBgColor(double color) {
161
+ _bgColor = color;
162
+ }
163
+
164
+ void HybridXlsxCellFormat::setFgColor(double color) {
165
+ _fgColor = color;
166
+ }
167
+
168
+ void HybridXlsxCellFormat::setPattern(double pattern) {
169
+ _pattern = pattern;
170
+ }
171
+
172
+ void HybridXlsxCellFormat::setBorder(double style) {
173
+ _border = style;
174
+ }
175
+
176
+ void HybridXlsxCellFormat::setBorderColor(double color) {
177
+ _borderColor = color;
178
+ }
179
+
180
+ void HybridXlsxCellFormat::setBottom(double style) {
181
+ _bottom = style;
182
+ }
183
+
184
+ void HybridXlsxCellFormat::setTop(double style) {
185
+ _top = style;
186
+ }
187
+
188
+ void HybridXlsxCellFormat::setLeft(double style) {
189
+ _left = style;
190
+ }
191
+
192
+ void HybridXlsxCellFormat::setRight(double style) {
193
+ _right = style;
194
+ }
195
+
196
+ void HybridXlsxCellFormat::setBottomColor(double color) {
197
+ _bottomColor = color;
198
+ }
199
+
200
+ void HybridXlsxCellFormat::setTopColor(double color) {
201
+ _topColor = color;
202
+ }
203
+
204
+ void HybridXlsxCellFormat::setLeftColor(double color) {
205
+ _leftColor = color;
206
+ }
207
+
208
+ void HybridXlsxCellFormat::setRightColor(double color) {
209
+ _rightColor = color;
210
+ }
211
+
212
+ void HybridXlsxCellFormat::setDiagonal(double style) {
213
+ _diagonal = style;
214
+ }
215
+
216
+ void HybridXlsxCellFormat::setDiagonalColor(double color) {
217
+ _diagonalColor = color;
218
+ }
219
+
220
+ void HybridXlsxCellFormat::setLocked() {
221
+ _locked = true;
222
+ }
223
+
224
+ void HybridXlsxCellFormat::setUnlocked() {
225
+ _locked = false;
226
+ }
227
+
228
+ void HybridXlsxCellFormat::setHyperlink() {
229
+ _hyperlink = true;
230
+ }
231
+
232
+ void HybridXlsxCellFormat::setFontOnly() {
233
+ }
234
+
235
+ std::string HybridXlsxCellFormat::getFontName() {
236
+ return _fontName;
237
+ }
238
+
239
+ double HybridXlsxCellFormat::getFontSize() {
240
+ return _fontSize;
241
+ }
242
+
243
+ double HybridXlsxCellFormat::getFontColor() {
244
+ return _fontColor;
245
+ }
246
+
247
+ bool HybridXlsxCellFormat::getIsBold() {
248
+ return _bold;
249
+ }
250
+
251
+ bool HybridXlsxCellFormat::getIsItalic() {
252
+ return _italic;
253
+ }
254
+
255
+ std::string HybridXlsxCellFormat::getNumFormat() {
256
+ return _numFormat;
257
+ }
258
+
259
+ double HybridXlsxCellFormat::getBgColor() {
260
+ return _bgColor;
261
+ }
262
+
263
+ }
@@ -0,0 +1,111 @@
1
+ #pragma once
2
+
3
+ #include "HybridXlsxCellFormatSpec.hpp"
4
+ #include <OpenXLSX/XLDocument.hpp>
5
+ #include <OpenXLSX/XLSheet.hpp>
6
+ #include <OpenXLSX/XLStyles.hpp>
7
+ #include <string>
8
+ #include <memory>
9
+
10
+ namespace margelo::nitro::xlsx {
11
+
12
+ class HybridXlsxCellFormat : public HybridXlsxCellFormatSpec {
13
+ public:
14
+ HybridXlsxCellFormat();
15
+ ~HybridXlsxCellFormat() override;
16
+
17
+ OpenXLSX::XLStyleIndex applyToDocument(OpenXLSX::XLStyles& styles);
18
+ void applyToCell(OpenXLSX::XLCell& cell, OpenXLSX::XLStyleIndex styleIndex);
19
+
20
+ void setFontName(const std::string& name) override;
21
+ void setFontSize(double size) override;
22
+ void setFontColor(double color) override;
23
+ void setFontScript(double style) override;
24
+ void setBold() override;
25
+ void setItalic() override;
26
+ void setUnderline(std::optional<double> style) override;
27
+ void setStrikeout() override;
28
+
29
+ void setAlign(double align) override;
30
+ void setVerticalAlign(double align) override;
31
+ void setTextWrap() override;
32
+ void setRotation(double angle) override;
33
+ void setIndent(double level) override;
34
+ void setShrink() override;
35
+
36
+ void setNumFormat(const std::string& format) override;
37
+ void setNumFormatIndex(double index) override;
38
+
39
+ void setBgColor(double color) override;
40
+ void setFgColor(double color) override;
41
+ void setPattern(double pattern) override;
42
+
43
+ void setBorder(double style) override;
44
+ void setBorderColor(double color) override;
45
+ void setBottom(double style) override;
46
+ void setTop(double style) override;
47
+ void setLeft(double style) override;
48
+ void setRight(double style) override;
49
+ void setBottomColor(double color) override;
50
+ void setTopColor(double color) override;
51
+ void setLeftColor(double color) override;
52
+ void setRightColor(double color) override;
53
+ void setDiagonal(double style) override;
54
+ void setDiagonalColor(double color) override;
55
+
56
+ void setLocked() override;
57
+ void setUnlocked() override;
58
+
59
+ void setHyperlink() override;
60
+ void setFontOnly() override;
61
+
62
+ std::string getFontName() override;
63
+ double getFontSize() override;
64
+ double getFontColor() override;
65
+ bool getIsBold() override;
66
+ bool getIsItalic() override;
67
+ std::string getNumFormat() override;
68
+ double getBgColor() override;
69
+
70
+ private:
71
+ std::string _fontName;
72
+ double _fontSize = 0;
73
+ double _fontColor = 0;
74
+ double _fontScript = 0;
75
+ bool _bold = false;
76
+ bool _italic = false;
77
+ double _underline = 0;
78
+ bool _strikeout = false;
79
+
80
+ double _align = 0;
81
+ double _verticalAlign = 0;
82
+ bool _textWrap = false;
83
+ double _rotation = 0;
84
+ double _indent = 0;
85
+ bool _shrink = false;
86
+
87
+ std::string _numFormat;
88
+ double _numFormatIndex = 0;
89
+
90
+ double _bgColor = 0;
91
+ double _fgColor = 0;
92
+ double _pattern = 0;
93
+
94
+ double _border = 0;
95
+ double _borderColor = 0;
96
+ double _bottom = 0;
97
+ double _top = 0;
98
+ double _left = 0;
99
+ double _right = 0;
100
+ double _bottomColor = 0;
101
+ double _topColor = 0;
102
+ double _leftColor = 0;
103
+ double _rightColor = 0;
104
+ double _diagonal = 0;
105
+ double _diagonalColor = 0;
106
+
107
+ bool _locked = false;
108
+ bool _hyperlink = false;
109
+ };
110
+
111
+ }
@@ -0,0 +1,184 @@
1
+ #include "HybridXlsxWorkbook.hpp"
2
+ #include <stdexcept>
3
+ #include <fstream>
4
+ #include <sstream>
5
+ #include <cstdlib>
6
+ #include <unistd.h>
7
+
8
+ #ifdef __ANDROID__
9
+ #include <android/api-level.h>
10
+ #include <sys/stat.h>
11
+ #endif
12
+
13
+ namespace margelo::nitro::xlsx {
14
+
15
+ namespace {
16
+ std::string getTempDir() {
17
+ #ifdef __ANDROID__
18
+ // /tmp is typically not available in Android sandbox, use app's cache directory
19
+ const char* cacheDir = std::getenv("TMPDIR");
20
+ if (cacheDir != nullptr && cacheDir[0] != '\0') {
21
+ return std::string(cacheDir);
22
+ }
23
+ // Try common Android cache directories
24
+ const char* candidates[] = {
25
+ "/data/local/tmp",
26
+ "/data/data/tmp",
27
+ "/sdcard/tmp",
28
+ "/tmp"
29
+ };
30
+ for (const char* dir : candidates) {
31
+ struct stat st;
32
+ if (stat(dir, &st) == 0 && S_ISDIR(st.st_mode)) {
33
+ return std::string(dir);
34
+ }
35
+ }
36
+ return "/data/local/tmp";
37
+ #else
38
+ return "/tmp";
39
+ #endif
40
+ }
41
+ }
42
+
43
+ HybridXlsxWorkbook::HybridXlsxWorkbook()
44
+ : HybridObject("XlsxWorkbook"), HybridXlsxWorkbookSpec(), _finalized(false) {
45
+ _workbook = std::make_unique<OpenXLSX::XLDocument>();
46
+ _tempDir = getTempDir();
47
+ }
48
+
49
+ HybridXlsxWorkbook::~HybridXlsxWorkbook() {
50
+ }
51
+
52
+ void HybridXlsxWorkbook::openFromFile(const std::string& path) {
53
+ _workbook->open(path);
54
+ loadWorksheets();
55
+ }
56
+
57
+ void HybridXlsxWorkbook::openFromBuffer(const uint8_t* data, size_t size) {
58
+ std::string tempPath = _tempDir + "/xlsx_open_" + std::to_string(std::chrono::system_clock::now().time_since_epoch().count()) + ".xlsx";
59
+ std::ofstream file(tempPath, std::ios::binary);
60
+ file.write(reinterpret_cast<const char*>(data), size);
61
+ file.close();
62
+
63
+ _workbook->open(tempPath);
64
+ std::remove(tempPath.c_str());
65
+ loadWorksheets();
66
+ }
67
+
68
+ void HybridXlsxWorkbook::loadWorksheets() {
69
+ _worksheets.clear();
70
+ _worksheetNames.clear();
71
+
72
+ auto wb = _workbook->workbook();
73
+ auto count = wb.worksheetCount();
74
+ for (uint16_t i = 1; i <= count; ++i) {
75
+ auto worksheet = wb.worksheet(i);
76
+ std::string sheetName = worksheet.name();
77
+ auto hybridWorksheet = std::make_shared<HybridXlsxWorksheet>(*_workbook, worksheet);
78
+ _worksheets.push_back(hybridWorksheet);
79
+ _worksheetNames[sheetName] = hybridWorksheet;
80
+ }
81
+ }
82
+
83
+ std::shared_ptr<HybridXlsxWorksheetSpec> HybridXlsxWorkbook::addWorksheet(const std::optional<std::string>& name) {
84
+ if (!_workbook->isOpen()) {
85
+ std::string tempPath = _tempDir + "/xlsx_create_" + std::to_string(std::chrono::system_clock::now().time_since_epoch().count()) + ".xlsx";
86
+ _workbook->create(tempPath, OpenXLSX::XLForceOverwrite);
87
+ std::remove(tempPath.c_str());
88
+ loadWorksheets();
89
+ }
90
+
91
+ std::string sheetName;
92
+ if (name.has_value()) {
93
+ sheetName = *name;
94
+ auto it = _worksheetNames.find(sheetName);
95
+ if (it != _worksheetNames.end()) {
96
+ throw std::runtime_error("Sheet named '" + sheetName + "' already exists");
97
+ }
98
+ } else {
99
+ int idx = 1;
100
+ do {
101
+ sheetName = "Sheet" + std::to_string(idx++);
102
+ } while (_worksheetNames.count(sheetName) > 0);
103
+ }
104
+
105
+ _workbook->workbook().addWorksheet(sheetName);
106
+ auto worksheet = _workbook->workbook().worksheet(sheetName);
107
+ auto hybridWorksheet = std::make_shared<HybridXlsxWorksheet>(*_workbook, worksheet);
108
+ _worksheets.push_back(hybridWorksheet);
109
+ _worksheetNames[sheetName] = hybridWorksheet;
110
+ return hybridWorksheet;
111
+ }
112
+
113
+ std::shared_ptr<HybridXlsxWorksheetSpec> HybridXlsxWorkbook::getWorksheet(double index) {
114
+ size_t idx = static_cast<size_t>(index);
115
+ if (idx >= _worksheets.size()) {
116
+ throw std::runtime_error("Worksheet index out of range: " + std::to_string(idx));
117
+ }
118
+ return _worksheets[idx];
119
+ }
120
+
121
+ std::shared_ptr<HybridXlsxWorksheetSpec> HybridXlsxWorkbook::getWorksheetByName(const std::string& name) {
122
+ auto it = _worksheetNames.find(name);
123
+ if (it == _worksheetNames.end()) {
124
+ throw std::runtime_error("Worksheet not found: " + name);
125
+ }
126
+ return it->second;
127
+ }
128
+
129
+ std::shared_ptr<HybridXlsxWorksheetSpec> HybridXlsxWorkbook::getOrAddWorksheet(const std::string& name) {
130
+ auto it = _worksheetNames.find(name);
131
+ if (it != _worksheetNames.end()) {
132
+ return it->second;
133
+ }
134
+ return addWorksheet(name);
135
+ }
136
+
137
+ double HybridXlsxWorkbook::getWorksheetCount() {
138
+ return static_cast<double>(_workbook->workbook().worksheetCount());
139
+ }
140
+
141
+ std::shared_ptr<HybridXlsxCellFormatSpec> HybridXlsxWorkbook::addCellFormat() {
142
+ auto hybridFormat = std::make_shared<HybridXlsxCellFormat>();
143
+ _cellFormats.push_back(hybridFormat);
144
+ return hybridFormat;
145
+ }
146
+
147
+ std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> HybridXlsxWorkbook::getBuffer() {
148
+ auto promise = Promise<std::shared_ptr<ArrayBuffer>>::create();
149
+
150
+ if (_finalized) {
151
+ promise->reject(std::make_exception_ptr(std::runtime_error("Workbook has already been finalized")));
152
+ return promise;
153
+ }
154
+
155
+ try {
156
+ std::string tempPath = _tempDir + "/xlsx_temp_" + std::to_string(std::chrono::system_clock::now().time_since_epoch().count()) + ".xlsx";
157
+ _workbook->saveAs(tempPath, OpenXLSX::XLForceOverwrite);
158
+
159
+ std::ifstream file(tempPath, std::ios::binary | std::ios::ate);
160
+ if (!file.is_open()) {
161
+ promise->reject(std::make_exception_ptr(std::runtime_error("Failed to open temp file")));
162
+ return promise;
163
+ }
164
+
165
+ std::streampos size = file.tellg();
166
+ std::vector<uint8_t> buffer(size);
167
+ file.seekg(0, std::ios::beg);
168
+ file.read(reinterpret_cast<char*>(buffer.data()), size);
169
+ file.close();
170
+
171
+ std::remove(tempPath.c_str());
172
+
173
+ auto arrayBuffer = ArrayBuffer::copy(buffer.data(), buffer.size());
174
+ _finalized = true;
175
+
176
+ promise->resolve(arrayBuffer);
177
+ } catch (const std::exception& e) {
178
+ promise->reject(std::make_exception_ptr(e));
179
+ }
180
+
181
+ return promise;
182
+ }
183
+
184
+ }
@@ -0,0 +1,41 @@
1
+ #pragma once
2
+
3
+ #include "HybridXlsxWorkbookSpec.hpp"
4
+ #include <OpenXLSX/XLDocument.hpp>
5
+ #include <memory>
6
+ #include <string>
7
+ #include <vector>
8
+ #include <unordered_map>
9
+ #include "HybridXlsxWorksheet.hpp"
10
+ #include "HybridXlsxCellFormat.hpp"
11
+
12
+ namespace margelo::nitro::xlsx {
13
+
14
+ class HybridXlsxWorkbook : public HybridXlsxWorkbookSpec {
15
+ public:
16
+ HybridXlsxWorkbook();
17
+ ~HybridXlsxWorkbook() override;
18
+
19
+ void openFromFile(const std::string& path);
20
+ void openFromBuffer(const uint8_t* data, size_t size);
21
+
22
+ std::shared_ptr<HybridXlsxWorksheetSpec> addWorksheet(const std::optional<std::string>& name) override;
23
+ std::shared_ptr<HybridXlsxWorksheetSpec> getWorksheet(double index) override;
24
+ std::shared_ptr<HybridXlsxWorksheetSpec> getWorksheetByName(const std::string& name) override;
25
+ std::shared_ptr<HybridXlsxWorksheetSpec> getOrAddWorksheet(const std::string& name) override;
26
+ double getWorksheetCount() override;
27
+ std::shared_ptr<HybridXlsxCellFormatSpec> addCellFormat() override;
28
+ std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> getBuffer() override;
29
+
30
+ private:
31
+ std::unique_ptr<OpenXLSX::XLDocument> _workbook;
32
+ std::vector<std::shared_ptr<HybridXlsxWorksheet>> _worksheets;
33
+ std::unordered_map<std::string, std::shared_ptr<HybridXlsxWorksheet>> _worksheetNames;
34
+ std::vector<std::shared_ptr<HybridXlsxCellFormat>> _cellFormats;
35
+ bool _finalized;
36
+ std::string _tempDir;
37
+
38
+ void loadWorksheets();
39
+ };
40
+
41
+ }