/* global Currency,OpenDocument,Node */ /** * * @constructor * @param {OpenDocument.XmlWriter} xmlWriter */ OpenDocument.OdsConverter = function (xmlWriter) { this.xmlWriter = xmlWriter; this.sheetName = ""; this.nameMap = {}; this.flatOds = true; this.styleManager = new OpenDocument.StyleManager(); this.cellStyleNumber = 1; this.currencyMap = {}; this.fixedRows = 0; this.fixedColumns = 0; }; OpenDocument.OdsConverter.convertToBlob = function (table, options) { var xml = OpenDocument.OdsConverter.convertToXml(table, options); return new Blob([xml], {type: OpenDocument.SPREADSHEET_MIMETYPE }); }; OpenDocument.OdsConverter.convertToXml = function (table, options) { var xmlWriter = new OpenDocument.XmlWriter({prettyXml: true}); var odsConverter = new OpenDocument.OdsConverter(xmlWriter); odsConverter.convert(table, options); return xmlWriter.xml; }; OpenDocument.OdsConverter.prototype.convert = function (table, options) { if (typeof table === "string") { table = document.getElementById(table); } var converter = this; var styleManager = this.styleManager; var _getRowStyleName = OpenDocument.OdsConverter.default_getRowStyleName; var _getCellStyleName = OpenDocument.OdsConverter.default_getCellStyleName; var textDataAttribute = "text"; var defaultCurrencyCode = ""; _checkArguments(); var columnArray = OpenDocument.OdsConverter.readTableColumns(table, styleManager); var xw = new OpenDocument.XmlWriter({indentLength: 3}); xw .openTable(converter.sheetName); for(let tableColumn of columnArray) { xw .addTableColumn(tableColumn); } for(let row of table.rows) { xw .openTableRow(_getRowStyleName(row, styleManager)); for(let cell of row.cells) { _addCell(cell); } xw .closeTableRow(); } xw .closeTable(xw); this.ods(xw.xml); function _checkArguments() { if (options) { if (options.rowStyleName) { _getRowStyleName = options.rowStyleName; } if (options.cellStyleName) { _getCellStyleName = options.cellStyleName; } if (options.textDataAttribute) { textDataAttribute = options.textDataAttribute; } } defaultCurrencyCode = table.dataset["odCurrency"]; let sheetName = table.dataset["odSheetname"]; if (sheetName) { converter.sheetName = sheetName; } let fixedRows = table.dataset["odFixedRows"]; if (fixedRows) { converter.fixedRows = fixedRows; } let fixedColumns = table.dataset["odFixedColumns"]; if (fixedColumns) { converter.fixedColumns = fixedColumns; } } function _addCell(cell) { let text = _getCellText(cell); let odCell = new OpenDocument.Elements.Cell(text, _getCellStyleName(cell, styleManager), cell.rowSpan, cell.colSpan); if (!text) { xw .addEmptyTableCell(odCell); return; } let type = cell.dataset["odType"]; switch(type) { case "number": xw .addNumberTableCell(odCell); break; case "date": odCell.styleName = styleManager.getAutomaticCellStyleName("date", odCell.styleName); xw .addDateTableCell(odCell); break; case "currency": let currencyCode = cell.dataset["odCurrency"]; if (!currencyCode) { currencyCode = defaultCurrencyCode; } odCell.styleName = styleManager.getAutomaticCellStyleName("currency", odCell.styleName, currencyCode); xw .addCurrencyTableCell(odCell, currencyCode); break; default: xw .addStringTableCell(odCell); } } function _getCellText(cellElement) { let cellText = cellElement.dataset["odText"]; if (cellText) { return cellText; } cellText = cellElement.dataset[textDataAttribute]; if (cellText) { return cellText; } cellText = ""; let previousBlock = false; for(let node of cellElement.childNodes) { if (node.nodeType === Node.ELEMENT_NODE) { let display = window.getComputedStyle(node).display; let odHidden = node.dataset["odHidden"]; switch(display) { case "none": break; case "block": if (!odHidden) { __addText(node.innerText, true); } previousBlock = true; break; default: if (!odHidden) { __addText(node.innerText, false); } } } else { if (node.textContent) { let text = node.textContent; text = text.replace(/[\s\uFEFF\xA0]/g, ' '); __addText(text, false); } } } return cellText.trim().replace(/ +/g, ' '); function __addText(text, isBlock) { if (!text) { return false; } if ((previousBlock) || (isBlock)) { cellText = cellText.trimEnd() + "\n"; previousBlock = false; text = text.trimStart(); } cellText += text; return true; } } }; OpenDocument.OdsConverter.prototype.ods = function (tableXml) { var xw = this.xmlWriter; xw.appendXMLDeclaration(); if (this.flatOds) { xw .openDocument(OpenDocument.SPREADSHEET_MIMETYPE); } else { xw .openDocumentContent(); } if ((this.fixedColumns > 0) || (this.fixedRows > 0)) { xw .openSettings() .openConfigItemSet("ooo:view-settings") .openConfigItemMapIndexed("Views") .openConfigItemMapEntry( "") .addConfigItem("ViewId", "string", "view1") .openConfigItemMapNamed("Tables") .openConfigItemMapEntry(this.sheetName); if (this.fixedColumns > 0) { xw .addConfigItem("HorizontalSplitMode", "short", "2") .addConfigItem("HorizontalSplitPosition", "int", this.fixedColumns) .addConfigItem("PositionLeft", "int", "0") .addConfigItem("PositionRight", "int", this.fixedColumns); } if (this.fixedRows > 0) { xw .addConfigItem("VerticalSplitMode", "short", "2") .addConfigItem("VerticalSplitPosition", "int", this.fixedRows) .addConfigItem("PositionTop", "int", "0") .addConfigItem("PositionBottom", "int", this.fixedRows); } xw .closeConfigItemMapEntry() .closeConfigItemMapNamed() .closeConfigItemMapEntry() .closeConfigItemMapIndexed() .closeConfigItemSet() .closeSettings(); } xw .openStyles() this.styleManager.writeStyles("cell-named", xw); xw .closeStyles(); xw .openAutomaticStyles(); this.styleManager.writeStyles("row-named", xw); this.styleManager.writeStyles("column-automatic", xw); this.styleManager.writeDataStyles(xw); this.styleManager.writeStyles("cell-automatic", xw); xw .closeAutomaticStyles() .openBody() .openSpreadsheet(xw) .write(tableXml) .closeSpreadsheet() .closeBody(); if (this.flatOds) { xw .closeDocument(); } else { xw .closeDocumentContent(); } }; OpenDocument.OdsConverter.prototype.checkSheetName = function (name) { if (!name) { name = "sheet"; } name = OpenDocument.checkSheetName(name); if (!this.nameMap.hasOwnProperty(name)) { this.nameMap[name] = true; return name; } else { var p = 2; while (true) { var newName = name + " (" + p + ")"; if (!this.nameMap.hasOwnProperty(newName)) { this.nameMap[newName] = true; return newName; } p++; } } }; OpenDocument.OdsConverter.readTableColumns = function(table, styleManager) { let colElementArray = new Array(); let result = new Array(); let colgroupList = table.getElementsByTagName("colgroup"); for(let colgroup of colgroupList) { let colList = colgroup.getElementsByTagName("col"); if (colList.length > 0) { for(let col of colList) { colElementArray.push(col); } } else { colElementArray.push(colgroup); } } let columnNumber = 1; for(let col of colElementArray) { let columnName = OpenDocument.COLUMNSTYLE_PREFIX + columnNumber; columnNumber++; let columnStyle = new OpenDocument.Style("column", columnName); let originalStyleName = _getColumnStyleName(col); if (originalStyleName) { let originalStyle = styleManager.getStyle("column-named", originalStyleName); if (originalStyle) { columnStyle.copyProperties(originalStyle); } } let customWidth = col.dataset["odWidth"]; if (customWidth) { columnStyle.putStyleProperty(OpenDocument.Style.STYLEPROPERTYDEFS["column-width"], customWidth); } styleManager.putStyle("column-automatic", columnStyle); result.push(new OpenDocument.Elements.TableColumn(columnName, col.span, "Standard")); } return result; function _getColumnStyleName(col) { let styleName = col.dataset["odStyle"];; if (styleName) { return styleName; } styleName = styleManager.getMatchingStyleName("column", col); if (styleName) { return styleName; } return ""; } }; OpenDocument.OdsConverter.default_getRowStyleName = function (row, styleManager) { let styleName = row.dataset["odStyle"]; if (styleName) { return styleName; } styleName = styleManager.getMatchingStyleName("row", row); if (styleName) { return styleName; } return ""; }; OpenDocument.OdsConverter.default_getCellStyleName = function (cell, styleManager) { let styleName = cell.dataset["odStyle"]; if (styleName) { return styleName; } styleName = styleManager.getMatchingStyleName("cell", cell); if (styleName) { return styleName; } if (cell.tagName.toLowerCase() === "th") { return "Header"; } else { return "Standard"; } };