/* version: v1.0.1 */ var Html2Ods = function (output, table, options) { function Currency (code, symbol, fractionDigit, symbolBefore, formatFunction) { this.code = code; this.symbol = symbol; this.fractionDigit = fractionDigit; this.symbolBefore = symbolBefore; var multiplicator = 1; for(var i = 0; i < fractionDigit; i++) { multiplicator = multiplicator * 10; } this.subunitMultiplicator = multiplicator; if (formatFunction) { this.formatFunction = formatFunction; } }; Currency.prototype.formatAmount = function (moneyLong, locale) { var decimalValue = moneyLong / (this.subunitMultiplicator); if (this.formatFunction) { return this.formatFunction(decimalValue, locale); } else { return decimalValue.toLocaleString(locale, { style: "currency", currency: this.code }); } }; Currency.prototype.toDecimalValue = function (moneyLong) { return moneyLong / (this.subunitMultiplicator); }; Currency.MAP = {}; Currency.formatAmount = function (moneyLong, currencyCode, locale) { var currency = Currency.get(currencyCode); return currency.formatAmount(moneyLong, locale); }; Currency.toDecimalValue = function (moneyLong, currencyCode) { var currency = Currency.get(currencyCode); return currency.toDecimalValue(moneyLong); }; Currency.get = function (code) { if (Currency.MAP.hasOwnProperty(code)) { return Currency.MAP[code]; } var currency; var symbolBefore = _isSymbolBefore(code); if (code === 'CFA') { currency = new Currency("CFA", "CFA", 0, symbolBefore, function(decimalValue, locale) { return decimalValue.toLocaleString(locale, { style: "decimal", maximumFractionDigits: 0 }) + " CFA"; }); } else { var numberFormat = new Intl.NumberFormat('en', { style: 'currency', currency: code }); var options = numberFormat.resolvedOptions(); var fractionDigit = options.maximumFractionDigits; var format = numberFormat.format(987); var idx = format.indexOf(9); var symbol = format.substring(0, idx); currency = new Currency(code, symbol, fractionDigit, symbolBefore); } Currency.MAP[code] = currency; return currency; function _isSymbolBefore (code) { switch(code) { case "USD": case "GBP": return true; default: return false; } } }; XmlWriter = function (options) { this.xml = ""; this.indentLength = -999999; if (options) { if (options.indentLength) { this.indentLength = options.indentLength; } else if (options.prettyXml) { this.indentLength = 0; } } }; XmlWriter.prototype.appendXMLDeclaration = function () { this.write(''); if (this.indentLength < 0) { this.write('\n'); } return this; }; XmlWriter.prototype.startOpenTag = function (tagName, indentBefore) { if (indentBefore === undefined) { indentBefore = true; } if (indentBefore) { this.appendIndent(); } this.write('<'); this.write(tagName); return this; }; XmlWriter.prototype.endOpenTag = function () { this.write('>'); this.increaseIndentValue(); return this; }; XmlWriter.prototype.closeEmptyTag = function () { this.write('/'); this.write('>'); return this; }; XmlWriter.prototype.openTag = function (tagName, indentBefore) { if (indentBefore === undefined) { indentBefore = true; } if (indentBefore) { this.appendIndent(); } this.write('<'); this.write(tagName); this.write('>'); this.increaseIndentValue(); return this; }; XmlWriter.prototype.closeTag = function (tagName, indentBefore) { if (indentBefore === undefined) { indentBefore = true; } this.decreaseIndentValue(); if (indentBefore) { this.appendIndent(); } this.write('<'); this.write('/'); this.write(tagName); this.write('>'); return this; }; XmlWriter.prototype.addText = function (text) { if (text) { this.escape(text); } return this; }; XmlWriter.prototype.addCData = function (text) { this.write(""); this.write("]]"); this.write(""); return this; }; XmlWriter.prototype.addAttribute = function (attributeName, value) { if ((value === 0) || (value)) { this.write(' '); this.write(attributeName); this.write('='); this.write('\"'); this.escape(value.toString()); this.write('\"'); } return this; }; XmlWriter.prototype.addSimpleElement = function (tagName, value) { if (value) { this.startOpenTag(tagName); this.endOpenTag(); this.addText(value); this.closeTag(tagName, false); } return this; }; XmlWriter.prototype.addEmptyElement = function (tagName) { this.startOpenTag(tagName); this.closeEmptyTag(); return this; }; XmlWriter.prototype.write = function (text) { this.xml += text; return this; }; XmlWriter.prototype.escape = function (text) { var carac; for(let i = 0, len = text.length; i < len; i++) { carac = text.charAt(i); switch (carac) { case '&': this.write("&"); break; case '"': this.write("""); break; case '<': this.write("<"); break; case '>': this.write(">"); break; case '\'': this.write("'"); break; case '\u00A0': this.write(" "); break; default: this.write(carac); } } return this; }; XmlWriter.prototype.appendIndent = function () { if (this.indentLength > -1) { this.write('\n'); for(let i = 0, len = this.indentLength; i < len; i++) { this.write('\t'); } } return this; }; XmlWriter.prototype.increaseIndentValue = function () { this.indentLength = this.indentLength + 1; return this; }; XmlWriter.prototype.decreaseIndentValue = function () { this.indentLength = this.indentLength - 1; return this; }; var OpenDocument = {}; OpenDocument.DEFAULT_CELLSTYLE_NAME = "Default"; OpenDocument.COLUMNSTYLE_PREFIX = "co"; OpenDocument.CELLSTYLE_PREFIX = "ce"; OpenDocument.DATASTYLE_PREFIX = "N"; OpenDocument.SPREADSHEET_MIMETYPE = "application/vnd.oasis.opendocument.spreadsheet"; OpenDocument.checkSheetName = function (name) { var result = ""; var carac; for (let i = 0, len = name.length; i < len; i++) { carac = name.charAt(i); switch (carac) { case '[': carac = '('; break; case ']': carac = ')'; break; case '*': case ':': case '/': case '?': case '\\': carac = '-'; break; } result += carac; } return result; }; OpenDocument.checkHiddenValue = function (element) { let odHidden = element.dataset["odHidden"]; if (!odHidden) { return 0; } switch(odHidden.toLowerCase()) { case 'true': case '1': case 'yes': return 1; case 'false': case '0': case '-1': case 'no': return -1; default: return 0; } }; OpenDocument.toChar = function (columnNumber) { return (columnNumber + 64); }; OpenDocument.Elements = {}; OpenDocument.Elements.Cell = function (value, styleName, rowSpan, colSpan) { this.value = value; this.styleName = styleName; this.rowSpan = rowSpan; this.colSpan = colSpan; }; OpenDocument.Elements.TableColumn = function (styleName, columnsRepeated, defaultCellStyleName) { this.styleName = styleName; this.columnsRepeated = columnsRepeated; if (defaultCellStyleName) { this.defaultCellStyleName = defaultCellStyleName; } else { this.defaultCellStyleName = "Default"; } }; OpenDocument.CellCounter = function () { this.row = 0; this.column = 0; this.rowMap = new Map(); }; OpenDocument.CellCounter.prototype.reinit = function () { this.row = 0; this.column = 0; this.rowMap.clear(); }; OpenDocument.CellCounter.prototype.newRow = function () { this.row = this.row + 1; this.column = 1; }; OpenDocument.CellCounter.prototype.newCell = function (rowSpan, colSpan) { let currentRow = this.row; let currentColumn = this.column; let jump = 0; let coveredCellArray = this.rowMap.get(currentRow); if (coveredCellArray) { while(true) { if (coveredCellArray.indexOf(currentColumn) !== -1) { currentColumn++; jump++; } else { break; } } } if (rowSpan > 1) { for(let i = 1; i < rowSpan; i++) { for(let j = 0; j < colSpan; j++) { this.putCoveredCell(currentRow + i, currentColumn + j); } } } if (colSpan > 1) { currentColumn += (colSpan - 1); } this.column = currentColumn + 1; return jump; }; OpenDocument.CellCounter.prototype.putCoveredCell = function (row, column) { if (this.rowMap.has(row)) { this.rowMap.get(row).push(column); } else { let array = new Array(); array.push(column); this.rowMap.set(row, array); } }; OpenDocument.XmlWriter = function (options) { XmlWriter.call(this, options); this.cellCounter = new OpenDocument.CellCounter(); }; OpenDocument.XmlWriter.prototype = Object.create(XmlWriter.prototype); OpenDocument.XmlWriter.prototype.constructor = OpenDocument.XmlWriter; OpenDocument.XmlWriter.prototype.openDocument = function (mimetype) { this .startOpenTag("office:document") .addXmlnsAttributes() .addAttribute("office:mimetype", mimetype) .endOpenTag(); return this; }; OpenDocument.XmlWriter.prototype.closeDocument = function () { this .closeTag("office:document"); return this; }; OpenDocument.XmlWriter.prototype.openDocumentContent = function () { this .startOpenTag("office:document-content") .addXmlnsAttributes() .endOpenTag(); return this; }; OpenDocument.XmlWriter.prototype.addXmlnsAttributes = function () { this .addAttribute("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0") .addAttribute("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0") .addAttribute("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0") .addAttribute("xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0") .addAttribute("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0") .addAttribute("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0") .addAttribute("xmlns:config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0") .addAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink") .addAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/") .addAttribute("xmlns:meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0") .addAttribute("xmlns:number", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0") .addAttribute("xmlns:presentation", "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0") .addAttribute("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0") .addAttribute("xmlns:chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0") .addAttribute("xmlns:dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0") .addAttribute("xmlns:math", "http://www.w3.org/1998/Math/MathML") .addAttribute("xmlns:form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0") .addAttribute("xmlns:script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0") .addAttribute("xmlns:ooo", "http://openoffice.org/2004/office") .addAttribute("xmlns:ooow", "http://openoffice.org/2004/writer") .addAttribute("xmlns:oooc", "http://openoffice.org/2004/calc") .addAttribute("xmlns:dom", "http://www.w3.org/2001/xml-events") .addAttribute("xmlns:xforms", "http://www.w3.org/2002/xforms") .addAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema") .addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") .addAttribute("xmlns:rpt", "http://openoffice.org/2005/report") .addAttribute("xmlns:of", "urn:oasis:names:tc:opendocument:xmlns:of:1.2") .addAttribute("xmlns:xhtml", "http://www.w3.org/1999/xhtml") .addAttribute("xmlns:grddl", "http://www.w3.org/2003/g/data-view#") .addAttribute("xmlns:tableooo", "http://openoffice.org/2009/table") .addAttribute("xmlns:vdrawooo", "http://openoffice.org/2010/draw") .addAttribute("xmlns:calcext", "urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0") .addAttribute("xmlns:loext", "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0") .addAttribute("xmlns:field", "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0") .addAttribute("xmlns:formx", "urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0") .addAttribute("xmlns:css3t", "http://www.w3.org/TR/css3-text/") .addAttribute("office:version", "1.2"); return this; }; OpenDocument.XmlWriter.prototype.openDocumentContentVersion1 = function () { this .startOpenTag("office:document-content") .addAttribute("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0") .addAttribute("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0") .addAttribute("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0") .addAttribute("xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0") .addAttribute("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0") .addAttribute("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0") .addAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink") .addAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/") .addAttribute("xmlns:meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0") .addAttribute("xmlns:number", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0") .addAttribute("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0") .addAttribute("xmlns:chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0") .addAttribute("xmlns:dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0") .addAttribute("xmlns:math", "http://www.w3.org/1998/Math/MathML") .addAttribute("xmlns:form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0") .addAttribute("xmlns:script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0") .addAttribute("xmlns:ooo", "http://openoffice.org/2004/office") .addAttribute("xmlns:ooow", "http://openoffice.org/2004/writer") .addAttribute("xmlns:oooc", "http://openoffice.org/2004/calc") .addAttribute("xmlns:dom", "http://www.w3.org/2001/xml-events") .addAttribute("xmlns:xforms", "http://www.w3.org/2002/xforms") .addAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema") .addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") .addAttribute("office:version", "1.0") .endOpenTag(); return this; }; OpenDocument.XmlWriter.prototype.closeDocumentContent = function () { this .closeTag("office:document-content"); return this; }; OpenDocument.XmlWriter.prototype.openStyles = function () { this .openTag("office:styles"); return this; }; OpenDocument.XmlWriter.prototype.closeStyles = function () { this .closeTag("office:styles"); return this; }; OpenDocument.XmlWriter.prototype.openAutomaticStyles = function () { this .openTag("office:automatic-styles"); return this; }; OpenDocument.XmlWriter.prototype.closeAutomaticStyles = function () { this .closeTag("office:automatic-styles"); return this; }; OpenDocument.XmlWriter.prototype.openBody = function () { this .openTag("office:body"); return this; }; OpenDocument.XmlWriter.prototype.closeBody = function () { this .closeTag("office:body"); return this; }; OpenDocument.XmlWriter.prototype.openSpreadsheet = function () { this .openTag("office:spreadsheet"); return this; }; OpenDocument.XmlWriter.prototype.closeSpreadsheet = function () { this .closeTag("office:spreadsheet"); return this; }; OpenDocument.XmlWriter.prototype.openStyle = function (styleName, styleFamily, parentStyleName) { this .startStyleOpenTag(styleName, styleFamily, parentStyleName) .endOpenTag(); return this; }; OpenDocument.XmlWriter.prototype.startStyleOpenTag = function (styleName, styleFamily, parentStyleName) { this .startOpenTag("style:style") .addAttribute("style:name", styleName); if (styleName.indexOf("_20_") > -1) { let displayName = styleName.replace("_20_", " "); this .addAttribute("style:display-name", displayName); } this .addAttribute("style:family", styleFamily) .addAttribute("style:parent-style-name", parentStyleName); return this; }; OpenDocument.XmlWriter.prototype.closeStyle = function () { this .closeTag("style:style"); return this; }; OpenDocument.XmlWriter.prototype.addDateStyle = function (datePattern, dataStyleName) { var xmlWriter = this; var length = datePattern.length; var buffer = ""; xmlWriter .startOpenTag("number:date-style") .addAttribute("style:name", dataStyleName) .endOpenTag(); for(let i = 0; i < length; i++) { let char = datePattern.charAt(i); let jump = 0; switch(char) { case 'M': jump = _parseMonth(i); break; case 'D': jump = _parseDay(i); break; case 'Y': jump = _parseYear(i); if (jump === 0) { _buf(char); } break; default: _buf(char); } i = i + jump; } _flush(); xmlWriter .closeTag("number:date-style"); return this; function _buf(char) { buffer = buffer + char; } function _parseMonth(index) { _flush(); let jump = 0; let next = index + 1; if ((next < length) && (datePattern.charAt(next) === 'M')) { jump = 1; } _addNumberElement("number:month", (jump === 1)); return jump; } function _parseDay(index) { _flush(); let jump = 0; let next = index + 1; if ((next < length) && (datePattern.charAt(next) === 'D')) { jump = 1; } _addNumberElement("number:day", (jump === 1)); return jump; } function _parseYear(index) { let next = index + 1; if ((next === length) || (datePattern.charAt(next) !== 'Y')) { return 0; } _flush(); let jump = 1; if (next < (length -2)) { if ((datePattern.charAt(next + 1) === 'Y') && (datePattern.charAt(next + 2) === 'Y')) { jump = 3; } } _addNumberElement("number:year", (jump === 3)); return jump; } function _flush() { if (buffer) { xmlWriter.addSimpleElement("number:text", buffer); buffer = ""; } } function _addNumberElement(name, isLong) { xmlWriter .startOpenTag(name); if (isLong) { xmlWriter .addAttribute("number:style", "long"); } xmlWriter .closeEmptyTag(); } }; OpenDocument.XmlWriter.prototype.addCurrencyStyle = function (currencyCode, dataStyleName) { var currency = Currency.get(currencyCode); this .startOpenTag("number:currency-style") .addAttribute("style:name", dataStyleName + "P0") .addAttribute("style:volatile", "true") .endOpenTag(); if (currency.symbolBefore) { this .addSimpleElement("number:currency-symbol", currency.symbol); } this .startOpenTag("number:number") .addAttribute("number:decimal-places", currency.fractionDigits) .addAttribute("number:min-integer-digits", "1") .addAttribute("number:grouping", "true") .closeEmptyTag(); if (!currency.symbolBefore) { this .addSimpleElement("number:text", " ") .addSimpleElement("number:currency-symbol", currency.symbol); } this .closeTag("number:currency-style") .startOpenTag("number:currency-style") .addAttribute("style:name", dataStyleName) .endOpenTag() .startOpenTag("style:text-properties") .addAttribute("fo:color", "#ff0000") .closeEmptyTag() .addSimpleElement("number:text", "-"); if (currency.symbolBefore) { this .addSimpleElement("number:currency-symbol", currency.symbol); } this .startOpenTag("number:number") .addAttribute("number:decimal-places", currency.fractionDigits) .addAttribute("number:min-integer-digits", "1") .addAttribute("number:grouping", "true") .closeEmptyTag(); if (!currency.symbolBefore) { this .addSimpleElement("number:text", " ") .addSimpleElement("number:currency-symbol", currency.symbol); } this .startOpenTag("style:map") .addAttribute("style:condition", "value()>=0") .addAttribute("style:apply-style-name", dataStyleName + "P0") .closeEmptyTag() .closeTag("number:currency-style"); return this; }; OpenDocument.XmlWriter.prototype.openNamedExpressions = function () { this .openTag("table:named-expressions"); return this; }; OpenDocument.XmlWriter.prototype.closeNamedExpressions = function () { this .closeTag("table:named-expressions"); return this; }; OpenDocument.XmlWriter.prototype.addNamedRange = function (name, address) { this .startOpenTag("table:named-range") .addAttribute("table:name", name) .addAttribute("table:base-cell-address", address) .addAttribute("table:cell-range-address", address) .closeEmptyTag(); return this; }; OpenDocument.XmlWriter.prototype.openTable = function (name) { this.cellCounter.reinit(); this .startOpenTag("table:table") .addAttribute("table:name", OpenDocument.checkSheetName(name)) .endOpenTag(); return this; }; OpenDocument.XmlWriter.prototype.closeTable = function () { this .closeTag("table:table"); return this; }; OpenDocument.XmlWriter.prototype.addTableColumn = function (tableColumn) { this .startOpenTag("table:table-column") .addAttribute("table:style-name", tableColumn.styleName); if (tableColumn.columnsRepeated > 1) { this .addAttribute("table:number-columns-repeated", tableColumn.columnsRepeated); } this .addAttribute("table:default-cell-style-name", tableColumn.defaultCellStyleName) .closeEmptyTag(); return this; }; OpenDocument.XmlWriter.prototype.openTableRow = function (rowStyleName) { this.cellCounter.newRow(); this .startOpenTag("table:table-row") .addAttribute("table:style-name", rowStyleName) .endOpenTag(); return this; }; OpenDocument.XmlWriter.prototype.closeTableRow = function () { this .closeTag("table:table-row"); return this; }; OpenDocument.XmlWriter.prototype.addEmptyTableCell = function (cell) { this .startCell(cell) .endCell(cell, true); return this; }; OpenDocument.XmlWriter.prototype.addNumberTableCell = function (cell) { this .startCell(cell) .addAttribute("office:value-type", "float") .addAttribute("office:value", cell.value) .endCell(cell, true); return this; }; OpenDocument.XmlWriter.prototype.addPercentageTableCell = function (cell) { this .startCell(cell) .addAttribute("office:value-type", "percentage") .addAttribute("office:value", cell.value) .endCell(cell, true); return this; }; OpenDocument.XmlWriter.prototype.addDateTableCell = function (cell) { this .startCell(cell) .addAttribute("office:value-type", "date") .addAttribute("office:date-value", cell.value) .endCell(cell, true); return this; }; OpenDocument.XmlWriter.prototype.addCurrencyTableCell = function (cell, currency) { this .startCell(cell) .addAttribute("office:value-type", "currency") .addAttribute("office:currency", currency) .addAttribute("office:value", cell.value) .endCell(cell, true); return this; }; OpenDocument.XmlWriter.prototype.addLinkStringTableCell = function (cell, linkString) { this .startCell(cell) .addAttribute("office:value-type", "string") .endOpenTag(); if ((linkString) && (linkString.length > 0)) { this .startOpenTag("text:p") .endOpenTag() .XmlWriter.prototype.addLink(linkString) .closeTag("text:p", false); } this .endCell(cell, false); return this; }; OpenDocument.XmlWriter.prototype.addStringTableCell = function (cell) { this .startCell(cell) .addAttribute("office:value-type", "string") .endOpenTag() .splitText(cell.value) .endCell(cell, false); return this; }; OpenDocument.XmlWriter.prototype.addFormulaTableCell = function (cell, valueType) { this .startCell(cell) .addAttribute("table:formula", cell.value) .addAttribute("office:value-type", valueType) .endCell(cell, true); return this; }; OpenDocument.XmlWriter.prototype.splitText = function (value) { if (value) { var tokens = value.split('\n'); for (let token of tokens) { this .startOpenTag("text:p") .endOpenTag() .addText(token) .closeTag("text:p", false); } } return this; }; OpenDocument.XmlWriter.prototype.addLink = function (link) { this .startOpenTag("text:a", false) .addAttribute("xlink:href", link) .endOpenTag() .addText(link) .closeTag("text:a", false); return this; }; OpenDocument.XmlWriter.prototype.startCell = function (cell) { var jump = this.cellCounter.newCell(cell.rowSpan, cell.colSpan); if (jump > 0) { this .startOpenTag("table:covered-table-cell"); if (jump > 1) { this .addAttribute("table:number-columns-repeated", jump) } this .closeEmptyTag(); } this .startOpenTag("table:table-cell") .addAttribute("table:style-name", cell.styleName); if (cell.rowSpan > 1) { this.addAttribute("table:number-rows-spanned", cell.rowSpan); } if (cell.colSpan > 1) { this .addAttribute("table:number-columns-spanned", cell.colSpan); } return this; }; OpenDocument.XmlWriter.prototype.endCell = function (cell, emptyTag) { if (emptyTag) { this .closeEmptyTag(); } else { this .closeTag("table:table-cell"); } if (cell.colSpan > 1) { this .startOpenTag("table:covered-table-cell"); if (cell.colSpan > 2) { this .addAttribute("table:number-columns-repeated", (cell.colSpan - 1)); } this .closeEmptyTag(); } return this; }; OpenDocument.XmlWriter.prototype.openSettings = function () { this .openTag("office:settings"); return this; }; OpenDocument.XmlWriter.prototype.closeSettings = function () { this .closeTag("office:settings"); return this; }; OpenDocument.XmlWriter.prototype.openConfigItemSet = function (name) { this .startOpenTag("config:config-item-set") .addAttribute("config:name", name) .endOpenTag(); return this; }; OpenDocument.XmlWriter.prototype.closeConfigItemSet = function () { this .closeTag("config:config-item-set"); return this; }; OpenDocument.XmlWriter.prototype.openConfigItemMapIndexed = function (name) { this .startOpenTag("config:config-item-map-indexed") .addAttribute("config:name", name) .endOpenTag(); return this; }; OpenDocument.XmlWriter.prototype.closeConfigItemMapIndexed = function () { this .closeTag("config:config-item-map-indexed"); return this; }; OpenDocument.XmlWriter.prototype.openConfigItemMapNamed = function (name) { this .startOpenTag("config:config-item-map-named") .addAttribute("config:name", name) .endOpenTag(); return this; }; OpenDocument.XmlWriter.prototype.closeConfigItemMapNamed = function () { this .closeTag("config:config-item-map-named"); return this; }; OpenDocument.XmlWriter.prototype.openConfigItemMapEntry = function (name) { this .startOpenTag("config:config-item-map-entry") .addAttribute("config:name", name) .endOpenTag(); return this; }; OpenDocument.XmlWriter.prototype.closeConfigItemMapEntry = function () { this .closeTag("config:config-item-map-entry"); return this; }; OpenDocument.XmlWriter.prototype.addConfigItem = function (name, type, value) { this .startOpenTag("config:config-item", true) .addAttribute("config:name", name) .addAttribute("config:type", type) .endOpenTag() .addText(value) .closeTag("config:config-item", false); return this; }; OpenDocument.Style = function (type, styleName) { this.type = type; this.styleName = styleName; this.styleFamily = OpenDocument.Style.getMatchingStyleFamily(type); this.parentStyleName = ""; this.dataStyleName = ""; this.propertiesMaps = new Map([ ["paragraph", new Map()], ["text", new Map()], ["table-cell", new Map()], ["table-row", new Map()], ["table-column", new Map()] ]); }; OpenDocument.Style.prototype.putStyleProperty = function (stylePropertyDef, value) { var propertyName = stylePropertyDef.name; switch(stylePropertyDef.format) { case "color": value = OpenDocument.Style.formatColor(value); break; case "wrap": value = _convertWrap(); break; } var property = { name: propertyName, value: value }; this.propertiesMaps.get(stylePropertyDef.category).set(propertyName, property); function _convertWrap() { switch(value) { case "anywhere": case "break-word": return "wrap"; default: return "no-wrap"; } } }; OpenDocument.Style.prototype.setParent = function (parentStyleName) { this.parentStyleName = parentStyleName; }; OpenDocument.Style.prototype.setDataStyle = function (dataStyleName) { this.dataStyleName = dataStyleName; }; OpenDocument.Style.prototype.isEmpty = function () { for(let map of this.propertiesMaps.values()) { if (map.size > 0) { return false; } } return true; }; OpenDocument.Style.prototype.copyProperties = function (otherStyle) { if (otherStyle.parentStyleName) { this.setParent(otherStyle.parentStyleName); } for(let entry of otherStyle.propertiesMaps) { let otherMap = entry[1]; let thisMap = this.propertiesMaps.get(entry[0]); for(let entry2 of otherMap) { thisMap.set(entry2[0], entry2[1]); } } }; OpenDocument.Style.prototype.write = function (xmlWriter) { xmlWriter .startStyleOpenTag(this.styleName, this.styleFamily, this.parentStyleName) .addAttribute("style:data-style-name", this.dataStyleName); if (this.isEmpty()) { xmlWriter .closeEmptyTag(); } else { xmlWriter .endOpenTag(); for(let entry of this.propertiesMaps) { let category = entry[0]; let map = entry[1]; if (map.size > 0) { xmlWriter .startOpenTag("style:" + category + "-properties"); for(let property of map.values()) { xmlWriter .addAttribute(property.name, property.value); } xmlWriter .closeEmptyTag(); } } xmlWriter .closeStyle(); } }; OpenDocument.Style.getStylePropertyDef = function (type, name) { name = _checkAlias(); if (OpenDocument.Style.STYLEPROPERTYDEFS.hasOwnProperty(name)) { let propertyDef = OpenDocument.Style.STYLEPROPERTYDEFS[name]; if (propertyDef.categories) { for(let propKey in propertyDef.categories) { if (propKey === type) { return Object.assign({}, propertyDef, {category: propertyDef.categories[propKey]}); } } return null; } else { return propertyDef; } } else { return null; } function _checkAlias() { switch(type) { case "row": switch(name) { case "height": return "row-height"; } break; case "column": switch(name) { case "width": return "column-width"; } break; case "cell": switch(name) { case "overflow-wrap": return "wrap-option"; } break; } return name; } }; OpenDocument.Style.getMatchingStyleFamily = function (type) { switch(type) { case "cell": return "table-cell"; case "row": return "table-row"; case "column": return "table-column"; } }; OpenDocument.Style.STYLEPROPERTYDEFS = { "background-color": { name: "fo:background-color", categories: { "cell": "table-cell", "row": "table-row" }, format: "color" }, "border": { name: "fo:border", category: "table-cell" }, "border-bottom": { name: "fo:border-bottom", category: "table-cell" }, "border-left": { name: "fo:border-left", category: "table-cell" }, "border-right": { name: "fo:border-right", category: "table-cell" }, "border-top": { name: "fo:border-top", category: "table-cell" }, "color": { name: "fo:color", category: "text", format: "color" }, "column-width": { name: "style:column-width", category: "table-column" }, "font-size": { name: "fo:font-size", category: "text" }, "font-style": { name: "fo:font-style", category: "text" }, "font-weight": { name: "fo:font-weight", category: "text" }, "padding": { name: "fo:padding", category: "table-cell" }, "padding-bottom": { name: "fo:padding-bottom", category: "table-cell" }, "padding-left": { name: "fo:padding-left", category: "table-cell" }, "padding-right": { name: "fo:padding-right", category: "table-cell" }, "padding-top": { name: "fo:padding-top", category: "table-cell" }, "row-height": { name: "style:row-height", category: "table-row" }, "text-align": { name: "fo:text-align", category: "paragraph" }, "use-optimal-row-height": { name: "style:use-optimal-row-height", category: "table-row" }, "vertical-align": { name: "style:vertical-align", category: "table-cell" }, "wrap-option": { name: "fo:wrap-option", category: "table-cell", format: "wrap" } }; OpenDocument.Style.formatColor = function (color) { let colorList = color.match(/rgb\((.*)\)/); if (colorList) { let hexresult = "#"; for(let token of colorList[1].split(",")) { let hex = Number.parseInt(token.trim(), 10).toString(16); if (hex.length === 1) { hex = "0" + hex; } hexresult += hex; } color = hexresult; } return color; }; OpenDocument.StyleManager = function () { this.maps = new Map([ ["cell-named", new Map()], ["row-named", new Map()], ["cell-automatic", new Map()], ["column-named", new Map()], ["column-automatic", new Map()] ]); this.matchingClassMaps = new Map([ ["cell", new Map()], ["row", new Map()], ["column", new Map()] ]); for(let object of OpenDocument.StyleManager.DEFAULT_STYLES ) { this.putStyle(object.type + "-named", _buildDefault(object)); } this.automaticCellStyleNumber = 1; this.dataStyleNumber = 1; this.currencyDataStyleMap = new Map(); this.dateDataStyleMap = new Map(); OpenDocument.StyleManager.readDocumentStyleSheets(this); function _buildDefault(object) { let style = new OpenDocument.Style(object.type, object.name); if (object.parent) { style.setParent(object.parent); } for(let propertyName in object.properties) { let stylePropertyDef = OpenDocument.Style.getStylePropertyDef(object.type, propertyName); if (stylePropertyDef) { style.putStyleProperty(stylePropertyDef, object.properties[propertyName]); } } return style; } }; OpenDocument.StyleManager.prototype.putStyle = function (mapName, style, styleKey) { if (!styleKey) { styleKey = style.styleName; } var map = this.maps.get(mapName); if (map.has(styleKey)) { let existingStyle = map.get(styleKey); existingStyle.copyProperties(style); } else { map.set(styleKey, style); } }; OpenDocument.StyleManager.prototype.hasStyle = function (mapName, styleKey) { var map = this.maps.get(mapName); if (map) { return map.has(styleKey); } else { return false; } }; OpenDocument.StyleManager.prototype.getStyle = function (mapName, styleKey) { var map = this.maps.get(mapName); if (map) { return map.get(styleKey); } else { return null; } return this.map.get(styleKey); }; OpenDocument.StyleManager.prototype.getAutomaticCellStyleName = function (type, parentStyleName, cellOption) { var styleKey = _buildStyleKey(); if (this.hasStyle("cell-automatic", styleKey)) { return this.getStyle("cell-automatic", styleKey).styleName; } var automaticCellStyleName = this.getNewAutomaticeCellStyleName(); var dataStyleName = null; switch(type) { case "date": dataStyleName = this.getMatchingDateDataStyleName(cellOption); break; case "currency": dataStyleName = this.getMatchingCurrencyDataStyleName(cellOption); break; } var cellStyle = new OpenDocument.Style("cell", automaticCellStyleName); if (parentStyleName) { cellStyle.setParent(parentStyleName); } else { cellStyle.setParent(OpenDocument.DEFAULT_CELLSTYLE_NAME); } if (dataStyleName) { cellStyle.setDataStyle(dataStyleName); } this.putStyle("cell-automatic", cellStyle, styleKey); return automaticCellStyleName; function _buildStyleKey() { let key = type + ":"; if (cellOption) { key += cellOption + ":"; } key += parentStyleName; return key; } }; OpenDocument.StyleManager.prototype.getNewAutomaticeCellStyleName = function () { var name = OpenDocument.CELLSTYLE_PREFIX + this.automaticCellStyleNumber; this.automaticCellStyleNumber++; return name; }; OpenDocument.StyleManager.prototype.getMatchingCurrencyDataStyleName = function (currencyCode) { if (this.currencyDataStyleMap.has(currencyCode)) { return this.currencyDataStyleMap.get(currencyCode); } else { let dataStyleName = OpenDocument.DATASTYLE_PREFIX + this.dataStyleNumber; this.dataStyleNumber++; this.currencyDataStyleMap.set(currencyCode, dataStyleName); return dataStyleName; } }; OpenDocument.StyleManager.prototype.getMatchingDateDataStyleName = function (datePattern) { if (this.dateDataStyleMap.has(datePattern)) { return this.dateDataStyleMap.get(datePattern); } else { let dataStyleName = OpenDocument.DATASTYLE_PREFIX + this.dataStyleNumber; this.dataStyleNumber++; this.dateDataStyleMap.set(datePattern, dataStyleName); return dataStyleName; } }; OpenDocument.StyleManager.prototype.getMatchingStyleName = function (type, element) { var map = this.matchingClassMaps.get(type); if (map) { for(let className of element.classList) { if (map.has(className)) { return map.get(className); } } } return ""; }; OpenDocument.StyleManager.prototype.writeStyles = function (mapName, xmlWriter) { var map = this.maps.get(mapName); if (map) { for(let style of map.values()) { style.write(xmlWriter); } } }; OpenDocument.StyleManager.prototype.writeDataStyles = function (xmlWriter) { for(let entry of this.dateDataStyleMap) { xmlWriter .addDateStyle(entry[0], entry[1]); } for(let entry of this.currencyDataStyleMap) { xmlWriter .addCurrencyStyle(entry[0], entry[1]); } }; OpenDocument.StyleManager.readDocumentStyleSheets = function (styleManager) { var styleSheetList = document.styleSheets; for(let i = 0, len = styleSheetList.length; i < len; i++) { OpenDocument.StyleManager.readStyleSheet(styleManager, styleSheetList[i]); } }; OpenDocument.StyleManager.readStyleSheet = function (styleManager, styleSheet) { var ruleList = styleSheet.cssRules; for(let i = 0, len = ruleList.length; i < len; i++) { let rule = ruleList[i]; if ((rule.selectorText) && (rule.style)) { let selectorArray = _parseSelectorText(rule.selectorText); for(let selector of selectorArray) { _addStyle(selector, rule.style); } } } function _parseSelectorText(selectorText) { let resultArray = new Array(); for(let token of selectorText.split(',')) { let result = __parseToken(token); if (result) { switch(result[0]) { case "cell": case "row": case "column": resultArray.push(result); break; } } } return resultArray; function __parseToken(token) { token = token.trim(); let idx = token.indexOf(' '); let followingPart = ""; if (idx !== -1) { followingPart = token.substring(idx +1).trim(); token = token.substring(0, idx); } let dotIndex = token.indexOf('.'); if (dotIndex === -1) { return null; } let type = token.substring(0, dotIndex); let name = token.substring(dotIndex + 1); return [type, name, followingPart]; } } function _addStyle(selector, cssStyleDeclaration) { let type = selector[0]; let style = new OpenDocument.Style(type, selector[1]); let borderBuffer = false; if (type === "cell") { borderBuffer = new OpenDocument.StyleManager.BorderBuffer(); } for(let i = 0, len = cssStyleDeclaration.length; i < len; i++) { let propertyName = cssStyleDeclaration[i]; let propertyValue = cssStyleDeclaration.getPropertyValue(propertyName); if (borderBuffer) { let borderTest = propertyName.match(/^border-([a-z]+)-([a-z]+)/); if (borderTest) { borderBuffer.putSubproperty(borderTest[1], borderTest[2], propertyValue); continue; } } if (propertyName === "content") { __parseDeclarationText(propertyValue); } else { let stylePropertyDef = OpenDocument.Style.getStylePropertyDef(type, propertyName); if (stylePropertyDef) { style.putStyleProperty(stylePropertyDef, propertyValue); } } } if (borderBuffer) { borderBuffer.fillStyle(style); } _parseFollowingPart(selector[2]); styleManager.putStyle(type + "-named", style); function __parseDeclarationText(declarationText) { let start = declarationText.indexOf('"'); if (start === -1) { return; } let end = declarationText.lastIndexOf('"'); if (end === start) { return; } let tokens = declarationText.substring(start + 1, end).split(';'); for(let token of tokens) { let paire = token.split(':'); if (paire.length === 2) { let name = paire[0].trim(); let value = paire[1].trim(); let stylePropertyDef = OpenDocument.Style.getStylePropertyDef(type, name); if (stylePropertyDef) { style.putStyleProperty(stylePropertyDef, value); } } } } function _parseFollowingPart(followingPart) { if (!followingPart) { return; } let tokens = new Array(); for(let token of followingPart.split(" ")) { token = token.trim(); if (token.length > 0) { tokens.push(token); } } let index = 0; let length = tokens.length - 1; while(index < length) { let operatorToken = tokens[index]; switch(operatorToken) { case '~': for(let i = index +1; i <= length; i++) { __addMatchingClasses(tokens[i]); } index = length; break; case '+': __setParent(tokens[index +1]); index ++; break; } index ++; } } function __addMatchingClasses(token) { if (!token) { return; } let map = styleManager.matchingClassMaps.get(type); if (!map) { return; } if (token.startsWith('.')) { map.set(token.substring(1), style.styleName); } } function __setParent(token) { if (!token) { return; } let dotIndex = token.indexOf('.'); if (dotIndex !== -1) { style.setParent(token.substring(dotIndex + 1)); } } } }; OpenDocument.StyleManager.BorderBuffer = function () { this.map = new Map([ ["bottom", false], ["left", false], ["right", false], ["top", false] ]); }; OpenDocument.StyleManager.BorderBuffer.prototype.putSubproperty = function (position, subproperty, value) { if (!this.map.has(position)) { return; } let positionObject = this.map.get(position); if (!positionObject) { positionObject = { width: "0.75pt", color: "rgb(0, 0, 0)", style: "solid" }; this.map.set(position, positionObject); } if (positionObject.hasOwnProperty(subproperty)) { if (subproperty === "color") { value = OpenDocument.Style.formatColor(value); } positionObject[subproperty] = value; }; }; OpenDocument.StyleManager.BorderBuffer.prototype.fillStyle = function (style) { for(let entry of this.map) { let position = entry[0]; let object = entry[1]; if (object) { let stylePropertyDef = OpenDocument.Style.getStylePropertyDef("type", "border-" + position); if (stylePropertyDef) { let value = object.width + " " + object.style + " " + object.color; style.putStyleProperty(stylePropertyDef, value); } } } }; OpenDocument.StyleManager.DEFAULT_STYLES = [ { type: "cell", name: "Standard", parent: "", properties: { } }, { type: "cell", name: "Bold", parent: "Standard", properties: { "font-weight": "bold" } }, { type: "cell", name: "Italic", parent: "Standard", properties: { "font-style": "italic" } }, { type: "cell", name: "BoldItalic", parent: "Standard", properties: { "font-weight": "bold", "font-style": "italic" } }, { type: "cell", name: "Header", properties: { "font-weight": "bold", "text-align": "center", "vertical-align": "middle" } }, { type: "row", name: "Standard", parent: "", properties: { } }, { type: "row", name: "Header", parent: "", properties: { } } ]; OpenDocument.OdsConverter = function (xmlWriter, options) { 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; this.textDataAttribute = "text"; this.defaultCurrencyCode = ""; this.defaultDatePattern = "YYYY-MM-DD"; if (options) { if (options.datePattern) { this.defaultDatePattern = options.datePattern; } if (options.currency) { this.defaultCurrencyCode = options.currency; } if (options.textAlias) { this.textDataAttribute = options.textAlias; } } }; 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, options); odsConverter.convert(table); return xmlWriter.xml; }; OpenDocument.OdsConverter.prototype.checkOdData = function (table) { let odCurrency = table.dataset["odCurrency"]; if (odCurrency) { this.defaultCurrencyCode = odCurrency; } let sheetName = table.dataset["odSheetname"]; if (sheetName) { this.sheetName = sheetName; } let fixedRows = table.dataset["odFixedRows"]; if (fixedRows) { this.fixedRows = fixedRows; } let fixedColumns = table.dataset["odFixedColumns"]; if (fixedColumns) { this.fixedColumns = fixedColumns; } let odDatePattern = table.dataset["odDatePattern"]; if (odDatePattern) { this.defaultDatePattern = odDatePattern; } }; OpenDocument.OdsConverter.prototype.convert = function (table) { if (typeof table === "string") { table = document.getElementById(table); } this.checkOdData(table); var converter = this; var styleManager = this.styleManager; var _getRowStyleName = OpenDocument.OdsConverter.default_getRowStyleName; var _getCellStyleName = OpenDocument.OdsConverter.default_getCellStyleName; 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) { let display = window.getComputedStyle(row).display; let odHidden = OpenDocument.checkHiddenValue(row); if (((display === "none") && (odHidden !== -1)) || (odHidden === 1)) { continue; } xw .openTableRow(_getRowStyleName(row, styleManager)); for(let cell of row.cells) { _addCell(cell); } xw .closeTableRow(); } xw .closeTable(xw); this.ods(xw.xml); 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": let datePattern = cell.dataset["odDatePattern"]; if (!datePattern) { datePattern = converter.defaultDatePattern; } odCell.styleName = styleManager.getAutomaticCellStyleName("date", odCell.styleName, datePattern); xw .addDateTableCell(odCell); break; case "currency": let currencyCode = cell.dataset["odCurrency"]; if (!currencyCode) { currencyCode = converter.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[converter.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 = OpenDocument.checkHiddenValue(node); switch(display) { case "none": break; case "block": if (odHidden !== 1) { __addText(node.innerText, true); } previousBlock = true; break; default: if (odHidden !== 1) { __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; } if ((row.parentNode.tagName) && (row.parentNode.tagName.toLowerCase() === "thead")) { return "Header"; } else { return "Standard"; } }; 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"; } }; switch(output) { case "blob": return OpenDocument.OdsConverter.convertToBlob(table, options); case "xml": return OpenDocument.OdsConverter.convertToXml(table, options); default: return null; } }; Html2Ods.blob = function (table, options) { return Html2Ods("blob", table, options); }; Html2Ods.xml = function (table, options) { return Html2Ods("xml", table, options); };