OpenXLSX 1.9.1
Loading...
Searching...
No Matches
XLRowData.hpp
Go to the documentation of this file.
1#ifndef OPENXLSX_XLROWDATA_HPP
2#define OPENXLSX_XLROWDATA_HPP
3
4#ifdef _MSC_VER // conditionally enable MSVC specific pragmas to avoid other compilers warning about unknown pragmas
5# pragma warning(push)
6# pragma warning(disable : 4251)
7# pragma warning(disable : 4275)
8#endif // _MSC_VER
9
10// ===== External Includes ===== //
11#include <deque>
12#include <iterator>
13#include <list>
14#include <memory>
15#include <vector>
16
17// ===== OpenXLSX Includes ===== //
18#include "OpenXLSX-Exports.hpp"
19#include "XLCell.hpp"
20#include "XLConstants.hpp"
21#include "XLException.hpp"
22#include "XLIterator.hpp"
23#include "XLXmlParser.hpp"
24
25namespace OpenXLSX
26{
27 class XLRow;
28 class XLRowDataRange;
29
34 class OPENXLSX_EXPORT XLRowDataIterator
35 {
36 friend class XLRowDataRange;
37
38 public:
39 using iterator_category = std::forward_iterator_tag;
41 using difference_type = int64_t;
42 using pointer = XLCell*;
43 using reference = XLCell&;
44
49
55
61
67 XLRowDataIterator& operator=(const XLRowDataIterator& other);
68
75
80 XLRowDataIterator& operator++();
81
86 XLRowDataIterator operator++(int); // NOLINT
87
92 reference operator*();
93
98 pointer operator->();
99
105 bool operator==(const XLRowDataIterator& rhs) const;
106
112 bool operator!=(const XLRowDataIterator& rhs) const;
113
114 private:
120 XLRowDataIterator(const XLRowDataRange& rowDataRange, XLIteratorLocation loc);
121
122 std::unique_ptr<XLRowDataRange> m_dataRange;
123 XMLNode m_cellNode;
124 XLCell m_currentCell;
125 };
126
130 class OPENXLSX_EXPORT XLRowDataRange
131 {
132 friend class XLRowDataIterator;
133 friend class XLRowDataProxy;
134 friend class XLRow;
135
136 public:
141 XLRowDataRange(const XLRowDataRange& other);
142
148
153
159 XLRowDataRange& operator=(const XLRowDataRange& other);
160
167
172 uint16_t size() const;
173
178 XLRowDataIterator begin();
179
184 XLRowDataIterator end();
185
193 template<typename T,
194 typename = std::enable_if_t<
195 std::is_integral_v<T> or std::is_floating_point_v<T> or std::is_same_v<std::decay_t<T>, std::string> ||
196 std::is_same_v<std::decay_t<T>, std::string_view> or std::is_same_v<std::decay_t<T>, const char*> ||
197 std::is_same_v<std::decay_t<T>, char*> or std::is_same_v<T, XLDateTime>>>
199 {
200 // forward implementation to templated XLCellValue& XLCellValue::operator=(T value)
201 for (auto it = begin(); it != end(); ++it) it->value() = value;
202 return *this;
203 }
204
205 private:
213 explicit XLRowDataRange(const XMLNode& rowNode, uint16_t firstColumn, uint16_t lastColumn, const XLSharedStrings& sharedStrings);
214
218 explicit XLRowDataRange();
219
220 std::unique_ptr<XMLNode> m_rowNode;
221 uint16_t m_firstCol{1};
222 uint16_t m_lastCol{1};
223 XLSharedStringsRef m_sharedStrings;
224 };
225
230 class OPENXLSX_EXPORT XLRowDataProxy
231 {
232 friend class XLRow;
233
234 public:
239
245 XLRowDataProxy& operator=(const XLRowDataProxy& other);
246
252 XLRowDataProxy& operator=(const std::vector<XLCellValue>& values);
253
259 XLRowDataProxy& operator=(const std::vector<bool>& values);
260
268 template<typename T,
269 typename = std::enable_if_t<!std::is_same_v<T, XLRowDataProxy> &&
270 std::is_base_of_v<std::bidirectional_iterator_tag,
271 typename std::iterator_traits<typename T::iterator>::iterator_category>,
272 T>>
273 XLRowDataProxy& operator=(const T& values) // 2024-04-30: whitespace support
274 {
275 if (values.size() > MAX_COLS) throw XLOverflowError("Container size exceeds maximum number of columns.");
276 if (values.size() == 0) return *this;
277
278 // ===== If the container value_type is XLCellValue, the values can be copied directly.
279 if constexpr (std::is_same_v<typename T::value_type, XLCellValue>) {
280 // ===== First, delete the values in the first N columns.
281 deleteCellValues(static_cast<uint16_t>(values.size())); // 2024-04-30: whitespace support
282
283 // ===== Then, prepend new cell nodes to current row node
284 auto colNo = values.size();
285 for (auto value = values.rbegin(); value != values.rend(); ++value) { // NOLINT
286 prependCellValue(*value,
287 static_cast<uint16_t>(colNo)); // 2024-04-30: whitespace support: this is safe because only
288 // prependCellValue (with whitespace support) touches the row data
289 --colNo;
290 }
291 }
292
293 // ===== If the container value_type is a POD type, use the overloaded operator= on each cell.
294 else {
295 auto range = XLRowDataRange(*m_rowNode, 1, static_cast<uint16_t>(values.size()), getSharedStrings());
296 auto dst = range.begin(); // 2024-04-30: whitespace support: safe because XLRowDataRange::begin invokes whitespace-safe
297 // getCellNode for column 1
298 auto src = values.begin();
299
300 while (true) {
301 dst->value() = *src;
302 ++src;
303 if (src == values.end()) break;
304 ++dst; // 2024-04-30: whitespace support: XLRowDataIterator::operator++ is whitespace-safe
305 }
306 }
307
308 return *this;
309 }
310
311 // // BEGIN working template header
312 // template<
313 // typename T,
314 // typename std::enable_if<
315 // !std::is_same_v< T, XLRowDataProxy >
316 // and std::is_base_of_v< XMLNode, T >,
317 // T
318 // >::type* = nullptr
319 // >
320 // // END working template header
321 // XLRowDataProxy& operator=(const T& values)
322 // {
323 // using namespace std::literals::string_literals;
324 // throw XLInternalError( "templated XLRowDataProxy& operator=(const T& values) instantiated for an XMLNode ("s+ typeid(T).name() +
325 // "), this function must be implemented then"s );
326 //
327 // }
328
333 operator std::vector<XLCellValue>() const; // NOLINT
334
339 operator std::deque<XLCellValue>() const; // NOLINT
340
345 operator std::list<XLCellValue>() const; // NOLINT
346
355 template<typename Container,
356 typename =
357 std::enable_if_t<!std::is_same_v<Container, XLRowDataProxy> &&
358 std::is_base_of_v<std::bidirectional_iterator_tag,
359 typename std::iterator_traits<typename Container::iterator>::iterator_category>,
360 Container>>
361 explicit operator Container() const
362 { return convertContainer<Container>(); }
363
367 void clear();
368
369 private:
370 //---------- Private Member Functions ---------- //
371
377 XLRowDataProxy(XLRow* row, XMLNode* rowNode);
378
384 XLRowDataProxy(const XLRowDataProxy& other);
385
391 XLRowDataProxy(XLRowDataProxy&& other) noexcept;
392
399 XLRowDataProxy& operator=(XLRowDataProxy&& other) noexcept;
400
405 std::vector<XLCellValue> getValues() const;
406
412 const XLSharedStrings& getSharedStrings() const;
413
418 void deleteCellValues(uint16_t count);
419
425 void prependCellValue(const XLCellValue& value, uint16_t col);
426
436 template<typename Container,
437 typename =
438 std::enable_if_t<!std::is_same_v<Container, XLRowDataProxy> &&
439 std::is_base_of_v<std::bidirectional_iterator_tag,
440 typename std::iterator_traits<typename Container::iterator>::iterator_category>,
441 Container>>
442 Container convertContainer() const // 2024-04-30: whitespace support
443 {
444 Container c;
445 auto it = std::inserter(c, c.end());
446 for (const auto& v : getValues()) {
447 // ===== If the value_type of the container is XLCellValue, the value can be assigned directly.
448 if constexpr (std::is_same_v<typename Container::value_type, XLCellValue>) *it++ = v;
449
450 // ===== If the value_type is something else, the underlying value has to be extracted from the XLCellValue object.
451 // ===== Note that if the type contained in the XLCellValue object does not match the value_type, a bad_variant_access
452 // ===== exception will be thrown.
453 else
454 *it++ = v.get<typename Container::value_type>();
455 }
456 return c;
457 }
458
459 //---------- Private Member Variables ---------- //
460
461 XLRow* m_row{nullptr};
462 XMLNode* m_rowNode{nullptr};
463 };
464
465} // namespace OpenXLSX
466
467#ifdef _MSC_VER // conditionally enable MSVC specific pragmas to avoid other compilers warning about unknown pragmas
468# pragma warning(pop)
469#endif // _MSC_VER
470
471#endif // OPENXLSX_XLROWDATA_HPP
Definition XLXmlParser.hpp:84
Class encapsulating a cell value.
Definition XLCellValue.hpp:79
An implementation class encapsulating the properties and behaviours of a spreadsheet cell.
Definition XLCell.hpp:41
Definition XLException.hpp:32
This class encapsulates a (non-const) iterator, for iterating over the cells in a row.
Definition XLRowData.hpp:35
std::forward_iterator_tag iterator_category
Definition XLRowData.hpp:39
int64_t difference_type
Definition XLRowData.hpp:41
XLRowDataIterator(XLRowDataIterator &&other) noexcept
Move constructor.
XLRowDataIterator & operator=(XLRowDataIterator &&other) noexcept
Move assignment operator.
The XLRowDataProxy is used as a proxy object when getting or setting row data. The class facilitates ...
Definition XLRowData.hpp:231
~XLRowDataProxy()
Destructor.
XLRowDataProxy & operator=(const T &values)
Templated assignment operator taking any container supporting bidirectional iterators.
Definition XLRowData.hpp:273
This class encapsulates the concept of a contiguous range of cells in a row.
Definition XLRowData.hpp:131
XLRowDataRange(XLRowDataRange &&other) noexcept
Move constructor.
~XLRowDataRange()
Destructor.
XLRowDataRange & operator=(T value)
Templated assignment operator - assign value to all existing cells in the row.
Definition XLRowData.hpp:198
XLRowDataRange & operator=(XLRowDataRange &&other) noexcept
Move assignment operator.
The XLRow class represent a row in an Excel spreadsheet. Using XLRow objects, various row formatting ...
Definition XLRow.hpp:23
This class encapsulate the Excel concept of Shared Strings. In Excel, instead of havig individual str...
Definition XLSharedStrings.hpp:67
Definition IZipArchive.hpp:18
XLIteratorLocation
Definition XLIterator.hpp:7
bool operator==(const XLCell &lhs, const XLCell &rhs)
Definition XLCell.hpp:304
bool operator!=(const XLCell &lhs, const XLCell &rhs)
Definition XLCell.hpp:311
OpenXLSX_xml_node XMLNode
Definition XLXmlParser.hpp:63
constexpr uint16_t MAX_COLS
Definition XLConstants.hpp:8
std::reference_wrapper< const XLSharedStrings > XLSharedStringsRef
Definition XLSharedStrings.hpp:56