var parse_content_xml = (function() {
var parse_text_p = function(text/*::, tag*/) { var fixed = text .replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ") .replace(/<text:s\/>/g," ") .replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); }) .replace(/<text:tab[^>]*\/>/g,"\t") .replace(/<text:line-break\/>/g,"\n"); var v = unescapexml(fixed.replace(/<[^>]*>/g,""));
return [v]; };
var number_formats = { day: ["d", "dd"], month: ["m", "mm"], year: ["y", "yy"], hours: ["h", "hh"], minutes: ["m", "mm"], seconds: ["s", "ss"], "am-pm": ["A/P", "AM/PM"], "day-of-week": ["ddd", "dddd"], era: ["e", "ee"], quarter: ["\\Qm", "m\\\"th quarter\""] };
return function pcx(d, _opts) { var opts = _opts || {}; if(DENSE != null && opts.dense == null) opts.dense = DENSE; var str = xlml_normalize(d); var state = [], tmp; var tag; var NFtag = {name:""}, NF = "", pidx = 0; var sheetag; var rowtag; var Sheets = {}, SheetNames = []; var ws = opts.dense ? ([]) : ({}); var Rn, q; var ctag = ({value:""}); var textp = "", textpidx = 0, textptag; var textR = []; var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}}; var row_ol = 0; var number_format_map = {}; var merges = [], mrange = {}, mR = 0, mC = 0; var rowinfo = [], rowpeat = 1, colpeat = 1; var arrayf = []; var WB = {Names:[]}; var atag = ({}); var _Ref = ["", ""]; var comments = [], comment = ({}); var creator = "", creatoridx = 0; var isstub = false, intable = false; var i = 0; xlmlregex.lastIndex = 0; str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,""); while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
case 'table': case 'ๅทฅไฝ่กจ': if(Rn[1]==='/') { if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range); else ws['!ref'] = "A1:A1"; if(opts.sheetRows > 0 && opts.sheetRows <= range.e.r) { ws['!fullref'] = ws['!ref']; range.e.r = opts.sheetRows - 1; ws['!ref'] = encode_range(range); } if(merges.length) ws['!merges'] = merges; if(rowinfo.length) ws["!rows"] = rowinfo; sheetag.name = sheetag['ๅ็งฐ'] || sheetag.name; if(typeof JSON !== 'undefined') JSON.stringify(sheetag); SheetNames.push(sheetag.name); Sheets[sheetag.name] = ws; intable = false; } else if(Rn[0].charAt(Rn[0].length-2) !== '/') { sheetag = parsexmltag(Rn[0], false); R = C = -1; range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0; ws = opts.dense ? ([]) : ({}); merges = []; rowinfo = []; intable = true; } break;
case 'table-row-group': if(Rn[1] === "/") --row_ol; else ++row_ol; break; case 'table-row': case '่ก': if(Rn[1] === '/') { R+=rowpeat; rowpeat = 1; break; } rowtag = parsexmltag(Rn[0], false); if(rowtag['่กๅท']) R = rowtag['่กๅท'] - 1; else if(R == -1) R = 0; rowpeat = +rowtag['number-rows-repeated'] || 1; if(rowpeat < 10) for(i = 0; i < rowpeat; ++i) if(row_ol > 0) rowinfo[R + i] = {level: row_ol}; C = -1; break; case 'covered-table-cell': if(Rn[1] !== '/') ++C; if(opts.sheetStubs) { if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; } else ws[encode_cell({r:R,c:C})] = {t:'z'}; } textp = ""; textR = []; break; case 'table-cell': case 'ๆฐๆฎ': if(Rn[0].charAt(Rn[0].length-2) === '/') { ++C; ctag = parsexmltag(Rn[0], false); colpeat = parseInt(ctag['number-columns-repeated']||"1", 10); q = ({t:'z', v:null}); if(ctag.formula && opts.cellFormula != false) q.f = ods_to_csf_formula(unescapexml(ctag.formula)); if((ctag['ๆฐๆฎ็ฑปๅ'] || ctag['value-type']) == "string") { q.t = "s"; q.v = unescapexml(ctag['string-value'] || ""); if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = q; } else { ws[encode_cell({r:R,c:C})] = q; } } C+= colpeat-1; } else if(Rn[1]!=='/') { ++C; textp = ""; textpidx = 0; textR = []; colpeat = 1; var rptR = rowpeat ? R + rowpeat - 1 : R; if(C > range.e.c) range.e.c = C; if(C < range.s.c) range.s.c = C; if(R < range.s.r) range.s.r = R; if(rptR > range.e.r) range.e.r = rptR; ctag = parsexmltag(Rn[0], false); comments = []; comment = ({}); q = ({t:ctag['ๆฐๆฎ็ฑปๅ'] || ctag['value-type'], v:null}); if(opts.cellFormula) { if(ctag.formula) ctag.formula = unescapexml(ctag.formula); if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) { mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0; mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0; mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}}; q.F = encode_range(mrange); arrayf.push([mrange, q.F]); } if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula); else for(i = 0; i < arrayf.length; ++i) if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r) if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c) q.F = arrayf[i][1]; } if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) { mR = parseInt(ctag['number-rows-spanned'],10) || 0; mC = parseInt(ctag['number-columns-spanned'],10) || 0; mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}}; merges.push(mrange); }
if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
switch(q.t) { case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break; case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break; case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break; case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break; case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']); if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v); } q.z = 'm/d/yy'; break; case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); } q.z = 'HH:MM:SS'; break; case 'number': q.t = 'n'; q.v = parseFloat(ctag['ๆฐๆฎๆฐๅผ']); break; default: if(q.t === 'string' || q.t === 'text' || !q.t) { q.t = 's'; if(ctag['string-value'] != null) { textp = unescapexml(ctag['string-value']); textR = []; } } else throw new Error('Unsupported value type ' + q.t); } } else { isstub = false; if(q.t === 's') { q.v = textp || ''; if(textR.length) q.R = textR; isstub = textpidx == 0; } if(atag.Target) q.l = atag; if(comments.length > 0) { q.c = comments; comments = []; } if(textp && opts.cellText !== false) q.w = textp; if(isstub) { q.t = "z"; delete q.v; } if(!isstub || opts.sheetStubs) { if(!(opts.sheetRows && opts.sheetRows <= R)) { for(var rpt = 0; rpt < rowpeat; ++rpt) { colpeat = parseInt(ctag['number-columns-repeated']||"1", 10); if(opts.dense) { if(!ws[R + rpt]) ws[R + rpt] = []; ws[R + rpt][C] = rpt == 0 ? q : dup(q); while(--colpeat > 0) ws[R + rpt][C + colpeat] = dup(q); } else { ws[encode_cell({r:R + rpt,c:C})] = q; while(--colpeat > 0) ws[encode_cell({r:R + rpt,c:C + colpeat})] = dup(q); } if(range.e.c <= C) range.e.c = C; } } } colpeat = parseInt(ctag['number-columns-repeated']||"1", 10); C += colpeat-1; colpeat = 0; q = {}; textp = ""; textR = []; } atag = ({}); break;
case 'document': case 'document-content': case '็ตๅญ่กจๆ ผๆๆกฃ': case 'spreadsheet': case 'ไธปไฝ': case 'scripts': case 'styles': case 'font-face-decls': case 'master-styles': if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;} else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]); break;
case 'annotation': if(Rn[1]==='/'){ if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp; comment.t = textp; if(textR.length) comment.R = textR; comment.a = creator; comments.push(comment); } else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);} creator = ""; creatoridx = 0; textp = ""; textpidx = 0; textR = []; break;
case 'creator': if(Rn[1]==='/') { creator = str.slice(creatoridx,Rn.index); } else creatoridx = Rn.index + Rn[0].length; break;
case 'meta': case 'ๅ
ๆฐๆฎ': case 'settings': case 'config-item-set': case 'config-item-map-indexed': case 'config-item-map-entry': case 'config-item-map-named': case 'shapes': case 'frame': case 'text-box': case 'image': case 'data-pilot-tables': case 'list-style': case 'form': case 'dde-links': case 'event-listeners': case 'chart': if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;} else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]); textp = ""; textpidx = 0; textR = []; break;
case 'scientific-number': break; case 'currency-symbol': break; case 'currency-style': break; case 'number-style': case 'percentage-style': case 'date-style': case 'time-style': if(Rn[1]==='/'){ number_format_map[NFtag.name] = NF; if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp; } else if(Rn[0].charAt(Rn[0].length-2) !== '/') { NF = ""; NFtag = parsexmltag(Rn[0], false); state.push([Rn[3], true]); } break;
case 'script': break; case 'libraries': break; case 'automatic-styles': break;
case 'default-style': case 'page-layout': break; case 'style': break; case 'map': break; case 'font-face': break;
case 'paragraph-properties': break; case 'table-properties': break; case 'table-column-properties': break; case 'table-row-properties': break; case 'table-cell-properties': break;
case 'number': switch(state[state.length-1][0]) { case 'time-style': case 'date-style': tag = parsexmltag(Rn[0], false); NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break; } break;
case 'fraction': break;
case 'day': case 'month': case 'year': case 'era': case 'day-of-week': case 'week-of-year': case 'quarter': case 'hours': case 'minutes': case 'seconds': case 'am-pm': switch(state[state.length-1][0]) { case 'time-style': case 'date-style': tag = parsexmltag(Rn[0], false); NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break; } break;
case 'boolean-style': break; case 'boolean': break; case 'text-style': break; case 'text': if(Rn[0].slice(-2) === "/>") break; else if(Rn[1]==="/") switch(state[state.length-1][0]) { case 'number-style': case 'date-style': case 'time-style': NF += str.slice(pidx, Rn.index); break; } else pidx = Rn.index + Rn[0].length; break;
case 'named-range': tag = parsexmltag(Rn[0], false); _Ref = ods_to_csf_3D(tag['cell-range-address']); var nrange = ({Name:tag.name, Ref:_Ref[0] + '!' + _Ref[1]}); if(intable) nrange.Sheet = SheetNames.length; WB.Names.push(nrange); break;
case 'text-content': break; case 'text-properties': break; case 'embedded-text': break;
case 'body': case '็ตๅญ่กจๆ ผ': break;
case 'forms': break; case 'table-column': break; case 'table-header-rows': break; case 'table-rows': break; case 'table-column-group': break; case 'table-header-columns': break; case 'table-columns': break;
case 'null-date': break;
case 'graphic-properties': break; case 'calculation-settings': break; case 'named-expressions': break; case 'label-range': break; case 'label-ranges': break; case 'named-expression': break; case 'sort': break; case 'sort-by': break; case 'sort-groups': break;
case 'tab': break; case 'line-break': break; case 'span': break; case 'p': case 'ๆๆฌไธฒ': if(['master-styles'].indexOf(state[state.length-1][0]) > -1) break; if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) { var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag); textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0]; } else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; } break; case 's': break;
case 'database-range': if(Rn[1]==='/') break; try { _Ref = ods_to_csf_3D(parsexmltag(Rn[0])['target-range-address']); Sheets[_Ref[0]]['!autofilter'] = { ref:_Ref[1] }; } catch(e) {} break;
case 'date': break;
case 'object': break; case 'title': case 'ๆ ้ข': break; case 'desc': break; case 'binary-data': break;
case 'table-source': break; case 'scenario': break;
case 'iteration': break; case 'content-validations': break; case 'content-validation': break; case 'help-message': break; case 'error-message': break; case 'database-ranges': break; case 'filter': break; case 'filter-and': break; case 'filter-or': break; case 'filter-condition': break;
case 'list-level-style-bullet': break; case 'list-level-style-number': break; case 'list-level-properties': break;
case 'sender-firstname': case 'sender-lastname': case 'sender-initials': case 'sender-title': case 'sender-position': case 'sender-email': case 'sender-phone-private': case 'sender-fax': case 'sender-company': case 'sender-phone-work': case 'sender-street': case 'sender-city': case 'sender-postal-code': case 'sender-country': case 'sender-state-or-province': case 'author-name': case 'author-initials': case 'chapter': case 'file-name': case 'template-name': case 'sheet-name': break;
case 'event-listener': break; case 'initial-creator': case 'creation-date': case 'print-date': case 'generator': case 'document-statistic': case 'user-defined': case 'editing-duration': case 'editing-cycles': break;
case 'config-item': break;
case 'page-number': break; case 'page-count': break; case 'time': break;
case 'cell-range-source': break; case 'detective': break; case 'operation': break; case 'highlighted-range': break;
case 'data-pilot-table': case 'source-cell-range': case 'source-service': case 'data-pilot-field': case 'data-pilot-level': case 'data-pilot-subtotals': case 'data-pilot-subtotal': case 'data-pilot-members': case 'data-pilot-member': case 'data-pilot-display-info': case 'data-pilot-sort-info': case 'data-pilot-layout-info': case 'data-pilot-field-reference': case 'data-pilot-groups': case 'data-pilot-group': case 'data-pilot-group-member': break;
case 'rect': break;
case 'dde-connection-decls': case 'dde-connection-decl': case 'dde-link': case 'dde-source': break;
case 'properties': break; case 'property': break;
case 'a': if(Rn[1]!== '/') { atag = parsexmltag(Rn[0], false); if(!atag.href) break; atag.Target = unescapexml(atag.href); delete atag.href; if(atag.Target.charAt(0) == "#" && atag.Target.indexOf(".") > -1) { _Ref = ods_to_csf_3D(atag.Target.slice(1)); atag.Target = "#" + _Ref[0] + "!" + _Ref[1]; } else if(atag.Target.match(/^\.\.[\\\/]/)) atag.Target = atag.Target.slice(3); } break;
case 'table-protection': break; case 'data-pilot-grand-total': break; case 'office-document-common-attrs': break; default: switch(Rn[2]) { case 'dc:': case 'calcext:': case 'loext:': case 'ooo:': case 'chartooo:': case 'draw:': case 'style:': case 'chart:': case 'form:': case 'uof:': case '่กจ:': case 'ๅญ:': break; default: if(opts.WTF) throw new Error(Rn); } } var out = ({ Sheets: Sheets, SheetNames: SheetNames, Workbook: WB }); if(opts.bookSheets) delete out.Sheets; return out; };})();
function parse_ods(zip, opts) { opts = opts || ({}); if(safegetzipfile(zip, 'META-INF/manifest.xml')) parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts); var content = getzipstr(zip, 'content.xml'); if(!content) throw new Error("Missing content.xml in ODS / UOF file"); var wb = parse_content_xml(utf8read(content), opts); if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml')); return wb;}function parse_fods(data, opts) { return parse_content_xml(data, opts);}