jsHtml2Ods/src/js/opendocument/OpenDocument.OdsConverter.js

347 lines
11 KiB
JavaScript

/* 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";
}
};