2024-12-29 undo XLXmlFile xmlName functionality added on 2024-12-20

This commit is contained in:
Lars Uffmann 2024-12-29 23:29:26 +01:00
parent 99d53b2b09
commit 7fd80dd3d3
20 changed files with 94 additions and 121 deletions

1
.gitignore vendored
View File

@ -30,6 +30,7 @@
!/Benchmarks/2024-08-14-benchmarks_post-default-row-column-style-support
!/Benchmarks/2024-09-02-benchmarks
!/Benchmarks/2024-12-19-benchmarks
!/Benchmarks/2024-12-29-benchmarks
# include Documentation folder
!/Documentation

View File

@ -0,0 +1,46 @@
********************************************************************************
DEMO PROGRAM #05: Ranges and Iterators
********************************************************************************
Generating spreadsheet ...
Saving spreadsheet ...
Re-opening spreadsheet ...
Reading data from spreadsheet ...
Cell count: 8388608
Sum of cell values: 415183689
real 1m16.475s
user 1m14.693s
sys 0m1.548s
********************************************************************************
DEMO PROGRAM #06: Row Handling (using containers)
********************************************************************************
Generating spreadsheet ...
Saving spreadsheet ...
Re-opening spreadsheet ...
Reading data from spreadsheet ...
Cell count: 8388608
Sum of cell values: 415298692
real 1m22.542s
user 1m20.651s
sys 0m1.613s
********************************************************************************
DEMO PROGRAM #07: Row Handling (using iterators)
********************************************************************************
Generating spreadsheet ...
Saving spreadsheet ...
Re-opening spreadsheet ...
Reading data from spreadsheet ...
Cell count: 8388608
Sum of cell values: 415295943
real 1m55.292s
user 1m53.279s
sys 0m1.738s

View File

@ -65,6 +65,7 @@ int main()
cout << "Cell count: " << std::distance(rng.begin(), rng.end()) << endl;
cout << "Sum of cell values: "
<< accumulate(rng.begin(), rng.end(), 0, [](uint64_t a, XLCell& b) { return a + b.value().get<int64_t>(); });
cout << endl;
doc.close();

View File

@ -246,7 +246,6 @@ namespace OpenXLSX
std::vector<XLContentItem> getContentItems();
private: // ---------- Private Member Variables ---------- //
static constexpr const char *m_classFile = "[Content_Types].xml"; // passed to XLXmlFile constructor for underlying m_xmlName
};
} // namespace OpenXLSX

View File

@ -67,8 +67,6 @@ namespace OpenXLSX
class OPENXLSX_EXPORT XLProperties : public XLXmlFile
{
private:
static constexpr const char *m_classFile = "docProps/core.xml"; // passed to XLXmlFile constructor for underlying m_xmlName
/**
* @brief constructor helper function: create core.xml content from template
* @param workbook
@ -83,7 +81,7 @@ namespace OpenXLSX
/**
* @brief
*/
XLProperties();
XLProperties() = default;
/**
* @brief
@ -171,8 +169,6 @@ namespace OpenXLSX
class OPENXLSX_EXPORT XLAppProperties : public XLXmlFile
{
private:
static constexpr const char *m_classFile = "docProps/app.xml"; // passed to XLXmlFile constructor for underlying m_xmlName
/**
* @brief constructor helper function: create app.xml content from template
* @param workbook
@ -187,7 +183,7 @@ namespace OpenXLSX
/**
* @brief
*/
XLAppProperties();
XLAppProperties() = default;
/**
* @brief enable XLAppProperties to re-create a worksheet list in docProps/app.xml <TitlesOfParts> element from workbookXml

View File

@ -80,7 +80,7 @@ namespace OpenXLSX
/**
* @brief
*/
XLSharedStrings();
XLSharedStrings() = default;
/**
* @brief
@ -172,8 +172,6 @@ namespace OpenXLSX
private:
std::deque<std::string>* m_stringCache {}; /** < Each string must have an unchanging memory address; hence the use of std::deque */
static constexpr const char *m_classFile = "xl/sharedStrings.xml"; // passed to XLXmlFile constructor for underlying m_xmlName
};
} // namespace OpenXLSX

View File

@ -95,17 +95,15 @@ namespace OpenXLSX
/**
* @brief Constructor
*/
XLSheetBase() : XLXmlFile(nullptr, m_classFile) {};
XLSheetBase() : XLXmlFile(nullptr) {};
/**
* @brief The constructor. There are no default constructor, so all parameters must be provided for
* constructing an XLAbstractSheet object. Since this is a pure abstract class, instantiation is only
* possible via one of the derived classes.
* @param xmlData
* @param classFile base name of the underlying base class (without sheet numbering)
*/
explicit XLSheetBase(XLXmlData* xmlData) : XLXmlFile(xmlData, m_classFile) {};
explicit XLSheetBase(XLXmlData* xmlData, std::string classFile) : XLXmlFile(xmlData, classFile) {};
explicit XLSheetBase(XLXmlData* xmlData) : XLXmlFile(xmlData) {}
/**
* @brief The copy constructor.
@ -304,11 +302,7 @@ namespace OpenXLSX
.setParam("cloneName", newName));
}
//----------------------------------------------------------------------------------------------------------------------
// Private Member Variables
//----------------------------------------------------------------------------------------------------------------------
private:
static constexpr const char *m_classFile = "(XLSheetBase: uninitialized)"; // passed to XLXmlFile constructor for underlying m_xmlName
private: // ---------- Private Member Variables ---------- //
};
/**
@ -329,7 +323,7 @@ namespace OpenXLSX
/**
* @brief Default constructor
*/
XLWorksheet() : XLSheetBase(nullptr, m_classFile) {};
XLWorksheet() : XLSheetBase(nullptr) {};
/**
* @brief
@ -588,13 +582,9 @@ namespace OpenXLSX
*/
bool setActive_impl();
//----------------------------------------------------------------------------------------------------------------------
// Private Member Variables
//----------------------------------------------------------------------------------------------------------------------
private:
private: // ---------- Private Member Variables ---------- //
XLMergeCells m_merges; /**< class handling the <mergeCells> */
static constexpr const char *m_classFile = "xl/worksheets/sheet#.xml"; // passed to XLXmlFile constructor for underlying m_xmlName
inline static const std::vector< std::string_view > m_nodeOrder = { // worksheet XML root node required child sequence
"sheetPr",
"dimension",
@ -627,7 +617,7 @@ namespace OpenXLSX
/**
* @brief Default constructor
*/
XLChartsheet() : XLSheetBase(nullptr, m_classFile) {};
XLChartsheet() : XLSheetBase(nullptr) {};
/**
* @brief
@ -691,11 +681,7 @@ namespace OpenXLSX
*/
void setSelected_impl(bool selected);
//----------------------------------------------------------------------------------------------------------------------
// Private Member Variables
//----------------------------------------------------------------------------------------------------------------------
private:
static constexpr const char *m_classFile = "XLChartsheet class: refer to ::name() for details"; // passed to XLXmlFile constructor for underlying m_xmlName
private: // ---------- Private Member Variables ---------- //
};
/**
@ -866,13 +852,8 @@ namespace OpenXLSX
*/
void print(std::basic_ostream<char>& ostr) const;
//----------------------------------------------------------------------------------------------------------------------
// Private Member Variables
//----------------------------------------------------------------------------------------------------------------------
private:
private: // ---------- Private Member Variables ---------- //
std::variant<XLWorksheet, XLChartsheet> m_sheet; /**< */
static constexpr const char *m_classFile = "(XLSheet: uninitialized)"; // passed to XLXmlFile constructor for underlying m_xmlName
};
} // namespace OpenXLSX

View File

@ -2205,8 +2205,6 @@ namespace OpenXLSX
std::unique_ptr<XLCellFormats> m_cellStyleFormats; // handle to the underlying cell style formats descriptions
std::unique_ptr<XLCellFormats> m_cellFormats; // handle to the underlying cell formats descriptions
std::unique_ptr<XLCellStyles> m_cellStyles; // handle to the underlying cell styles
static constexpr const char *m_classFile = "xl/styles.xml"; // passed to XLXmlFile constructor for underlying m_xmlName
};
} // namespace OpenXLSX

View File

@ -89,16 +89,14 @@ namespace OpenXLSX
/**
* @brief Default constructor. Creates an empty ('null') XLWorkbook object.
*/
XLWorkbook();
XLWorkbook() = default;
/**
* @brief Constructor. Takes a pointer to an XLXmlData object (stored in the parent XLDocument object).
* @param xmlData A pointer to the underlying XLXmlData object, which holds the XML data.
* @param pathTo the path to the workbook file origin of xmlData, used to initialize m_classFile
* @note Do not create an XLWorkbook object directly. Access via XLDocument::workbook().
*/
explicit XLWorkbook(XLXmlData* xmlData);
explicit XLWorkbook(XLXmlData* xmlData, std::string pathTo);
/**
* @brief Copy Constructor.
@ -396,10 +394,6 @@ namespace OpenXLSX
* @return true if sheetNode can be considered visible (and could be activated)
*/
bool isVisible(XMLNode const& sheetNode) const;
private: // ---------- Private Member Variables ---------- //
static constexpr const char * m_classFileDefault = "xl/workbook.xml";
std::string m_classFile; // passed to XLXmlFile constructor for underlying m_xmlName, defaults to m_classFileDefault
};
} // namespace OpenXLSX

View File

@ -78,10 +78,8 @@ namespace OpenXLSX
/**
* @brief Constructor. Creates an object based on the xmlData input.
* @param xmlData An XLXmlData object with the XML data to be represented by the object.
* @param xmlName optional name of the underlying XML file within the document
*/
explicit XLXmlFile(XLXmlData* xmlData);
explicit XLXmlFile(XLXmlData* xmlData, std::string xmlName);
/**
* @brief Copy constructor. Default implementation used.
@ -108,12 +106,6 @@ namespace OpenXLSX
*/
bool valid() const { return m_xmlData != nullptr; }
/**
* @brief Method to retrieve a descriptive name of the class link to the document XML
* @return A std::string with the document's XML file
*/
std::string const & xmlName() const { return m_xmlName; }
/**
* @brief The copy assignment operator. The default implementation has been used.
* @param other The object to copy.
@ -172,9 +164,8 @@ namespace OpenXLSX
*/
const XMLDocument& xmlDocument() const;
protected: // ===== PRIVATE MEMBER VARIABLES
XLXmlData* m_xmlData { nullptr }; /**< The underlying XML data object. */
std::string m_xmlName { "uninitialized" }; /**< informational: should be initialized with path to the underlying XML file within the document */
protected: // ===== PROTECTED MEMBER VARIABLES
XLXmlData* m_xmlData { nullptr }; /**< The underlying XML data object. */
};
} // namespace OpenXLSX

View File

@ -224,12 +224,12 @@ std::string XLContentItem::path() const { return m_contentNode->attribute("PartN
/**
* @details
*/
XLContentTypes::XLContentTypes() : XLXmlFile(nullptr, m_classFile) {}
XLContentTypes::XLContentTypes() = default;
/**
* @details
*/
XLContentTypes::XLContentTypes(XLXmlData* xmlData) : XLXmlFile(xmlData, m_classFile) {}
XLContentTypes::XLContentTypes(XLXmlData* xmlData) : XLXmlFile(xmlData) {}
/**
* @details

View File

@ -592,7 +592,7 @@ void XLDocument::open(const std::string& fileName)
}
// ===== Open the workbook and document property items
m_workbook = XLWorkbook(getXmlData(workbookPath), workbookPath);
m_workbook = XLWorkbook(getXmlData(workbookPath));
// 2024-05-31: moved XLWorkbook object creation up in code worksheets info can be used for XLAppProperties generation from scratch
// ===== 2024-06-03: creating core and extended properties if they do not exist

View File

@ -246,15 +246,10 @@ void XLProperties::createFromTemplate()
prop.text().set("2019-08-16T00:34:26Z");
}
/**
* @details default constructor
*/
XLProperties::XLProperties() : XLXmlFile(nullptr, m_classFile) {}
/**
* @details
*/
XLProperties::XLProperties(XLXmlData* xmlData) : XLXmlFile(xmlData, m_classFile)
XLProperties::XLProperties(XLXmlData* xmlData) : XLXmlFile(xmlData)
{
XMLNode doc = xmlData->getXmlDocument()->document_element();
XMLNode child = doc.first_child_of_type(pugi::node_element);
@ -387,16 +382,11 @@ void XLAppProperties::createFromTemplate(XMLDocument const & workbookXml)
props.append_child("AppVersion").text().set("16.0300");
}
/**
* @details default constructor
*/
XLAppProperties::XLAppProperties() : XLXmlFile(nullptr, m_classFile) {}
/**
* @details
*/
XLAppProperties::XLAppProperties(XLXmlData* xmlData, XMLDocument const & workbookXml)
: XLXmlFile(xmlData, m_classFile)
: XLXmlFile(xmlData)
{
XMLNode doc = xmlData->getXmlDocument()->document_element();
XMLNode child = doc.first_child_of_type(pugi::node_element);

View File

@ -347,7 +347,7 @@ bool XLRelationshipItem::empty() const { return m_relationshipNode->empty(); }
* used to return all relationship targets as absolute paths within the XLSX archive
*/
XLRelationships::XLRelationships(XLXmlData* xmlData, std::string pathTo)
: XLXmlFile(xmlData, pathTo)
: XLXmlFile(xmlData)
{
constexpr const char *relFolder = "_rels/"; // all relationships are stored in a (sub-)folder named "_rels/"
static const size_t relFolderLen = strlen(relFolder); // 2024-08-23: strlen seems to not be accepted in a constexpr in VS2019 with c++17

View File

@ -55,17 +55,12 @@ YM M9 MM MM MM MM MM d' `MM. MM MM d' `MM.
using namespace OpenXLSX;
/**
* @details Default constructor
*/
XLSharedStrings::XLSharedStrings() : XLXmlFile(nullptr, m_classFile) {}
/**
* @details Constructs a new XLSharedStrings object. Only one (common) object is allowed per XLDocument instance.
* A filepath to the underlying XML file must be provided.
*/
XLSharedStrings::XLSharedStrings(XLXmlData* xmlData, std::deque<std::string>* stringCache)
: XLXmlFile(xmlData, m_classFile),
: XLXmlFile(xmlData),
m_stringCache(stringCache)
{
XMLDocument & doc = xmlDocument();

View File

@ -117,7 +117,7 @@ namespace OpenXLSX
* @details The constructor begins by constructing an instance of its superclass, XLAbstractXMLFile. The default
* sheet type is WorkSheet and the default sheet state is Visible.
*/
XLSheet::XLSheet(XLXmlData* xmlData) : XLXmlFile(xmlData, m_classFile)
XLSheet::XLSheet(XLXmlData* xmlData) : XLXmlFile(xmlData)
{
if (xmlData->getXmlType() == XLContentType::Worksheet)
m_sheet = XLWorksheet(xmlData);
@ -251,7 +251,7 @@ void XLSheet::print(std::basic_ostream<char>& ostr) const { xmlDocument().docume
* For example, columns with identical formatting are by default grouped under the same node. However, this makes it more difficult to
* parse, so the constructor reconfigures it so each column has it's own formatting.
*/
XLWorksheet::XLWorksheet(XLXmlData* xmlData) : XLSheetBase(xmlData, m_classFile)
XLWorksheet::XLWorksheet(XLXmlData* xmlData) : XLSheetBase(xmlData)
{
// ===== Read the dimensions of the Sheet and set data members accordingly.
if (const std::string dimensions = xmlDocument().document_element().child("dimension").attribute("ref").value();
@ -642,21 +642,9 @@ void XLWorksheet::updateSheetName(const std::string& oldName, const std::string&
*/
XLMergeCells & XLWorksheet::merges()
{
// if( m_merges.uninitialized() ) {
// XMLNode mergeCellsNode = xmlDocument().document_element().child("mergeCells");
// if (mergeCellsNode.empty()) {
// // ===== 2024-10-27 BUGFIX: MS Office does not tolerate page formatting nodes before the mergeCells node,
// // therefore, insert the mergeCells node directly after the sheetData node
// XMLNode sheetDataNode = xmlDocument().document_element().child("sheetData");
// if (sheetDataNode.empty())
// throw XLInternalError("XLWorksheet::merges: sheetData XML node is not initialized. Can not proceed.");
// mergeCellsNode = xmlDocument().document_element().insert_child_after("mergeCells", sheetDataNode);
// }
// m_merges = XLMergeCells(mergeCellsNode);
// }
if (m_merges.uninitialized()) {
XMLNode rootNode = xmlDocument().document_element(); // until I learn how to make appendAndGetNode take by reference but not fail on rvalue document_element
m_merges = XLMergeCells(appendAndGetNode(rootNode, "mergeCells", m_nodeOrder ));
m_merges = XLMergeCells(appendAndGetNode(rootNode, "mergeCells", m_nodeOrder));
}
return m_merges;
}
@ -769,7 +757,7 @@ bool XLWorksheet::setRowFormat(uint32_t rowNumber, XLStyleIndex cellFormatIndex)
/**
* @details Constructor
*/
XLChartsheet::XLChartsheet(XLXmlData* xmlData) : XLSheetBase(xmlData, m_classFile) {}
XLChartsheet::XLChartsheet(XLXmlData* xmlData) : XLSheetBase(xmlData) {}
/**
* @details Destructor. Default implementation used.

View File

@ -2281,13 +2281,13 @@ XLStyleIndex XLCellStyles::create(XLCellStyle copyFrom, std::string styleEntries
/**
* @details Default constructor
*/
XLStyles::XLStyles() : XLXmlFile(nullptr, m_classFile) {}
XLStyles::XLStyles() : XLXmlFile(nullptr) {}
/**
* @details Creates an XLStyles object, which will initialize from the given xmlData
*/
XLStyles::XLStyles(XLXmlData* xmlData, bool suppressWarnings, std::string stylesPrefix)
: XLXmlFile(xmlData, m_classFile),
: XLXmlFile(xmlData),
m_suppressWarnings( suppressWarnings )
{
XMLDocument & doc = xmlDocument();

View File

@ -67,17 +67,11 @@ namespace
XMLNode sheetsNode(const XMLDocument& doc) { return doc.document_element().child("sheets"); }
} // namespace
/**
* @details Default constructor
*/
XLWorkbook::XLWorkbook() : XLXmlFile(nullptr, m_classFileDefault), m_classFile(m_classFileDefault) {}
/**
* @details The constructor initializes the member variables and calls the loadXMLData from the
* XLAbstractXMLFile base class.
*/
XLWorkbook::XLWorkbook(XLXmlData* xmlData) : XLXmlFile(xmlData, m_classFileDefault), m_classFile(m_classFileDefault) {}
XLWorkbook::XLWorkbook(XLXmlData* xmlData, std::string pathTo) : XLXmlFile(xmlData, pathTo), m_classFile(pathTo) {}
XLWorkbook::XLWorkbook(XLXmlData* xmlData) : XLXmlFile(xmlData) {}
/**
* @details

View File

@ -59,7 +59,6 @@ using namespace OpenXLSX;
* the data will be read from the .zip file, using the given path.
*/
XLXmlFile::XLXmlFile(XLXmlData* xmlData) : m_xmlData(xmlData) {}
XLXmlFile::XLXmlFile(XLXmlData* xmlData, std::string xmlName) : m_xmlData(xmlData), m_xmlName(xmlName) {}
XLXmlFile::~XLXmlFile() = default;

View File

@ -3,47 +3,49 @@
OpenXLSX is a C++ library for reading, writing, creating and modifying
Microsoft Excel® files, with the .xlsx format.
## (aral-matrix) 25 December 2024 - XLStyles: fixed implementation of ```strike```(through) font property to address issue #314
* XLStyles: if the attribute ```val``` is omitted in the ```<strike>``` XML tag, the value is now interpreted as ```true``` as described in the format specification - previously this was wrongly interpreted as "strikethrough is not set". This addresses issue https://github.com/troldal/OpenXLSX/issues/314
## (aral-matrix) Development note 23 December 2024 - Performance issue: XLSharedStrings is instantiated too much
TODO:
* replace XLSharedStrings instantiations with smart pointers / reference variables
* because of the above, a std::string variable (m_xmlName) in XLSharedStrings is a major performance impact
(3-7 extra seconds on Demo7 runtime - 1m53 vs. 1m56-2m00)
## (aral-matrix) 26 November 2024 - NOTE: "Releases" are severely outdated - do not use them
As the heading says - the latest "Release" that is shown on https://github.com/troldal/OpenXLSX/releases is from 2021-11-06, and severely outdated - please pull / download the latest SW version directly from the repository in its current state. Link for those that do not want to use ```git```: https://github.com/troldal/OpenXLSX/archive/refs/heads/master.zip
## (aral-matrix) 20 December 2024 - XLXmlFile and derived classes (XLWorksheet!) now expose a ::valid() and ::xmlName() method
## TODO: Performance issue: XLSharedStrings is instantiated too much
* replace XLSharedStrings instantiations with smart pointers / reference variables
* since XLSharedStrings is currently instantiated once per row/cell constructor (= very frequently on mass cell operations), adding any new member variables to XLSharedStrings or XLXmlFile would be a significant performance impact (when adding e.g. a std::string to XLXmlFile: 3-7 extra seconds on Demo7 runtime - 1m53 vs. 1m56-2m00)
## Recent changes
### (aral-matrix) 29 December 2024 - XLXmlFile and derived classes: undid 2024-12-20 addition of xmlName() function
* this was a function mainly foreseen for debugging purposes, but not serving any practical purpose, it was removed again
### (aral-matrix) 25 December 2024 - XLStyles: fixed implementation of ```strike```(through) font property to address issue #314
* XLStyles: if the attribute ```val``` is omitted in the ```<strike>``` XML tag, the value is now interpreted as ```true``` as described in the format specification - previously this was wrongly interpreted as "strikethrough is not set". This addresses issue https://github.com/troldal/OpenXLSX/issues/314
### (aral-matrix) 20 December 2024 - XLXmlFile and derived classes (XLWorksheet!) now expose a ::valid() method
* addressed https://github.com/troldal/OpenXLSX/issues/312 on a lower level, all classes derived from XLXmlFile now have a bool valid() method that will return true if a non-nullptr XML data block is linked to the class. For the user, this mostly matters in XLWorksheet, XLWorkbook & XLStyles
* additionally, all these classes now expose a std::string const & xmlName() method which serves mostly debugging purposes and - apart from worksheets / chartsheets - should point to the source XML file within the document archive
* while addressing issue #312, implemented explicit copy/move constructors and assignment operators for XLStyles, which should also address https://github.com/troldal/OpenXLSX/issues/310
## (aral-matrix) 19 December 2024 - XLStyles enhancement to address issues #304 and #305 - artificial ordering of XML elements
### (aral-matrix) 19 December 2024 - XLStyles enhancement to address issues #304 and #305 - artificial ordering of XML elements
* In order to address https://github.com/troldal/OpenXLSX/issues/304 and https://github.com/troldal/OpenXLSX/issues/305, some XLStyles classes now support a strict predefined XML element node order
Note: For now, this only concerns the reported nodes ```XLBorder``` and ```XLCellFormat```. The implementation uses a const class member array ```m_nodeOrder``` of type ```std::string_view```, which will allow relatively easy extension to other classes when discovered that MS Office expects a fixed XML node sequence.
## (aral-matrix) 18 December 2024 - Bugfix for Issue #283 - shared strings cache was not cleared upon XLDocument::Close
### (aral-matrix) 18 December 2024 - Bugfix for Issue #283 - shared strings cache was not cleared upon XLDocument::Close
* BUGFIX XLDocument::close: shared strings cache is now being cleared on doc close, this addresses issue https://github.com/troldal/OpenXLSX/issues/283
* zippy.hpp minor bugfix in ZipArchive::Close: m_IsOpen was not set to false
* Demo10: improved borders demo
* XLStyles: XLDataBarColor::setTheme now supports parameter ```XLDeleteProperty == XLInvalidUInt32 == 0xffffffff``` to delete the theme attribute from XML. This was necessary because even an empty ```theme=""``` attribute affects formatting.
* XLStyles appendAndGetAttribute / appendAndSetAttribute: removed a redundant check for ```not node.empty()```
## (aral-matrix) 17 December 2024 - Added exemplary use of XLBorder to Examples/Demo10.cpp
### (aral-matrix) 17 December 2024 - Added exemplary use of XLBorder to Examples/Demo10.cpp
* in response to https://github.com/troldal/OpenXLSX/issues/309, added use of XLBorder to Demo10
**CAUTION**: Until resolution of https://github.com/troldal/OpenXLSX/issues/304, MS Office may refuse to open a file created with such a formatting due to an unnecessary restriction on the sequence of XML elements (borders).
## (aral-matrix) 15 December 2024 - Bugfix for Issues 306 and #297, default-disable XLDocument & XLStyles warnings about unsupported tags (#296)
### (aral-matrix) 15 December 2024 - Bugfix for Issues 306 and #297, default-disable XLDocument & XLStyles warnings about unsupported tags (#296)
* BUGFIX: document relationships in ```xl/_rels/workbook.xml.rels``` should again open without errors for both relative (to ```xl/``` folder) and absolute archive paths
* warnings about unsupported archive contents and styles elements are now disabled by default and can be enabled using XLDocument::showWarnings() prior to opening an XLSX file
## (aral-matrix) 09 December 2024 - Bugfix for XLDateTime (hopefully final ;)
### (aral-matrix) 09 December 2024 - Bugfix for XLDateTime (hopefully final ;)
Reviewed the XLDateTime code in response to https://github.com/troldal/OpenXLSX/issues/299 and fixed a bug that I think I may have introduced myself. Apologies, dates should now correctly construct from ```double```, ```struct tm``` and ```time_t``` and convert back to ```struct tm```.