UNPKG

excel-builder-vanilla

Version:

An easy way of building Excel files with javascript

1,358 lines 65 kB
var z = Object.defineProperty; var D = (h, e, t) => e in h ? z(h, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : h[e] = t; var n = (h, e, t) => D(h, typeof e != "symbol" ? e + "" : e, t); import { strToU8 as $, zip as X } from "fflate"; function y(h) { const e = typeof h; return h != null && (e === "object" || e === "function"); } function V(h) { if (typeof h != "object" || h === null || Object.prototype.toString.call(h) !== "[object Object]") return !1; const e = Object.getPrototypeOf(h); if (e === null) return !0; const t = Object.prototype.hasOwnProperty.call(e, "constructor") && e.constructor; return typeof t == "function" && t instanceof t && Function.prototype.call(t) === Function.prototype.call(h); } function A(h) { return h != null && typeof h.valueOf() == "string"; } const B = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }, I = (h) => (typeof h != "string" && (h = `${h}`), h.replace(/[&<>"']/g, (e) => B[e])); class N { constructor(e, t) { n(this, "documentElement"); this.documentElement = this.createElement(t), this.documentElement.setAttribute("xmlns", e); } createElement(e) { return new P({ nodeName: e }); } createTextNode(e) { return new _(e); } toString() { return this.documentElement.toString(); } } n(N, "Node", { Create: (e) => { switch (e.type) { case "XML": return new P(e); case "TEXT": return new _(e.nodeValue); default: return null; } } }); class _ { constructor(e) { n(this, "nodeValue"); this.nodeValue = e; } toJSON() { return { nodeValue: this.nodeValue, type: "TEXT" }; } toString() { return I(this.nodeValue); } } class P { constructor(e) { n(this, "nodeName", ""); n(this, "children"); n(this, "nodeValue"); n(this, "attributes"); n(this, "firstChild"); if (this.nodeName = e.nodeName, this.children = [], this.nodeValue = e.nodeValue || "", this.attributes = {}, e.children) for (let t = 0, i = e.children.length; t < i; t++) this.appendChild(N.Node.Create(e.children[t])); if (e.attributes) for (const t in e.attributes) e.attributes.hasOwnProperty(t) && this.setAttribute(t, e.attributes[t]); } toString() { let e = `<${this.nodeName}`; for (const i in this.attributes) this.attributes.hasOwnProperty(i) && (e = `${e} ${i}="${I(this.attributes[i])}"`); let t = ""; for (let i = 0, r = this.children.length; i < r; i++) t += this.children[i].toString(); return t ? e += `>${t}</${this.nodeName}>` : e += "/>", e; } toJSON() { const e = []; for (let t = 0, i = this.children.length; t < i; t++) e.push(this.children[t].toJSON()); return { nodeName: this.nodeName, children: e, nodeValue: this.nodeValue, attributes: this.attributes, type: "XML" }; } setAttribute(e, t) { if (t === null) { delete this.attributes[e], delete this[e]; return; } this.attributes[e] = t, this[e] = t; } appendChild(e) { this.children.push(e), this.firstChild = this.children[0]; } cloneNode(e) { return new P(this.toJSON()); } } const x = class x { /** * Returns a number based on a namespace. So, running with 'Picture' will return 1. Run again, you will get 2. Run with 'Foo', you'll get 1. * @param {String} space * @returns {Number} */ static uniqueId(e) { return x._idSpaces[e] || (x._idSpaces[e] = 1), x._idSpaces[e]++; } /** * Attempts to create an XML document. After some investigation, using the 'fake' document * is significantly faster than creating an actual XML document, so we're going to go with * that. Besides, it just makes it easier to port to node. * * Takes a namespace to start the xml file in, as well as the root element * of the xml file. * * @param {type} ns * @param {type} base * @returns {@new;XMLDOM} */ static createXmlDoc(e, t) { return new N(e || null, t); } /** * Creates an xml node (element). Used to simplify some calls, as IE is * very particular about namespaces and such. * * @param {XMLDOM} doc An xml document (actual DOM or fake DOM, not a string) * @param {type} name The name of the element * @param {type} attributes * @returns {XML Node} */ static createElement(e, t, i) { const r = e.createElement(t); i = i || []; let s = i.length; for (; s--; ) r.setAttribute(i[s][0], i[s][1]); return r; } /** * This is sort of slow, but it's a huge convenience method for the code. It probably shouldn't be used * in high repetition areas. * * @param {XMLDoc} doc * @param {Object} attrs */ static setAttributesOnDoc(e, t) { for (let [i, r] of Object.entries(t)) { if (V(r)) if (r.v !== null && r.v !== void 0) switch (r.type) { case Boolean: r = r.v ? "1" : "0"; break; } else r = null; r != null && e.setAttribute(i, r); } } static positionToLetterRef(e, t) { let i = 1, r, s = e, o = ""; const a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; if (x.LETTER_REFS[e]) return x.LETTER_REFS[e].concat(t); for (; s > 0; ) s -= Math.pow(26, i - 1), r = s % Math.pow(26, i), s -= r, r = r / Math.pow(26, i - 1), o = a.charAt(r) + o, i += 1; return x.LETTER_REFS[e] = o, o.concat(String(t)); } }; n(x, "_idSpaces", {}), n(x, "LETTER_REFS", {}), n(x, "schemas", { worksheet: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet", sharedStrings: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings", stylesheet: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles", relationships: "http://schemas.openxmlformats.org/officeDocument/2006/relationships", relationshipPackage: "http://schemas.openxmlformats.org/package/2006/relationships", contentTypes: "http://schemas.openxmlformats.org/package/2006/content-types", spreadsheetml: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", markupCompat: "http://schemas.openxmlformats.org/markup-compatibility/2006", x14ac: "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac", officeDocument: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", package: "http://schemas.openxmlformats.org/package/2006/relationships", table: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table", spreadsheetDrawing: "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing", drawing: "http://schemas.openxmlformats.org/drawingml/2006/main", drawingRelationship: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing", image: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", chart: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart", hyperlink: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" }); let l = x; class j { constructor(e) { n(this, "x", null); n(this, "y", null); n(this, "width", null); n(this, "height", null); e && (this.setPos(e.x, e.y), this.setDimensions(e.width, e.height)); } /** * Sets the X and Y offsets. * * @param {Number} x * @param {Number} y * @returns {undefined} */ setPos(e, t) { this.x = e, this.y = t; } /** * Sets the width and height of the image. * * @param {Number} width * @param {Number} height * @returns {undefined} */ setDimensions(e, t) { this.width = e, this.height = t; } toXML(e, t) { const i = l.createElement(e, "xdr:absoluteAnchor"), r = l.createElement(e, "xdr:pos"); r.setAttribute("x", this.x), r.setAttribute("y", this.y), i.appendChild(r); const s = l.createElement(e, "xdr:ext"); return s.setAttribute("cx", this.width), s.setAttribute("cy", this.height), i.appendChild(s), i.appendChild(t), i.appendChild(l.createElement(e, "xdr:clientData")), i; } } class re { } const v = {}; function g(h = "$lodash$") { v[h] || (v[h] = 0); const e = ++v[h]; return h === "$lodash$" ? `${e}` : `${h}${e}`; } class W { constructor(e) { n(this, "x", null); n(this, "y", null); n(this, "xOff", null); n(this, "yOff", null); n(this, "width", null); n(this, "height", null); e && (this.setPos(e.x, e.y, e.xOff, e.yOff), this.setDimensions(e.width, e.height)); } setPos(e, t, i, r) { this.x = e, this.y = t, i !== void 0 && (this.xOff = i), r !== void 0 && (this.yOff = r); } setDimensions(e, t) { this.width = e, this.height = t; } toXML(e, t) { const i = l.createElement(e, "xdr:oneCellAnchor"), r = l.createElement(e, "xdr:from"), s = l.createElement(e, "xdr:col"); s.appendChild(e.createTextNode(String(this.x))); const o = l.createElement(e, "xdr:colOff"); o.appendChild(e.createTextNode(String(this.xOff || 0))); const a = l.createElement(e, "xdr:row"); a.appendChild(e.createTextNode(String(this.y))); const d = l.createElement(e, "xdr:rowOff"); d.appendChild(e.createTextNode(String(this.yOff || 0))), r.appendChild(s), r.appendChild(o), r.appendChild(a), r.appendChild(d), i.appendChild(r); const p = l.createElement(e, "xdr:ext"); return p.setAttribute("cx", String(this.width)), p.setAttribute("cy", String(this.height)), i.appendChild(p), i.appendChild(t), i.appendChild(l.createElement(e, "xdr:clientData")), i; } } class G { constructor(e) { n(this, "from", { xOff: 0, yOff: 0 }); n(this, "to", { xOff: 0, yOff: 0 }); e && (this.setFrom(e.from.x, e.from.y, e.to.xOff, e.to.yOff), this.setTo(e.to.x, e.to.y, e.to.xOff, e.to.yOff)); } setFrom(e, t, i, r) { this.from.x = e, this.from.y = t, i !== void 0 && (this.from.xOff = i), r !== void 0 && (this.from.yOff = i); } setTo(e, t, i, r) { this.to.x = e, this.to.y = t, i !== void 0 && (this.to.xOff = i), r !== void 0 && (this.to.yOff = i); } toXML(e, t) { const i = l.createElement(e, "xdr:twoCellAnchor"), r = l.createElement(e, "xdr:from"), s = l.createElement(e, "xdr:col"); s.appendChild(e.createTextNode(this.from.x)); const o = l.createElement(e, "xdr:colOff"); o.appendChild(e.createTextNode(this.from.xOff)); const a = l.createElement(e, "xdr:row"); a.appendChild(e.createTextNode(this.from.y)); const d = l.createElement(e, "xdr:rowOff"); d.appendChild(e.createTextNode(this.from.yOff)), r.appendChild(s), r.appendChild(o), r.appendChild(a), r.appendChild(d); const p = l.createElement(e, "xdr:to"), c = l.createElement(e, "xdr:col"); c.appendChild(e.createTextNode(this.to.x)); const E = l.createElement(e, "xdr:colOff"); E.appendChild(e.createTextNode(this.from.xOff)); const F = l.createElement(e, "xdr:row"); F.appendChild(e.createTextNode(this.to.y)); const T = l.createElement(e, "xdr:rowOff"); return T.appendChild(e.createTextNode(this.from.yOff)), p.appendChild(c), p.appendChild(E), p.appendChild(F), p.appendChild(T), i.appendChild(r), i.appendChild(p), i.appendChild(t), i.appendChild(l.createElement(e, "xdr:clientData")), i; } } class H { constructor() { n(this, "anchor"); n(this, "id", g("Drawing")); } /** * * @param {String} type Can be 'absoluteAnchor', 'oneCellAnchor', or 'twoCellAnchor'. * @param {Object} config Shorthand - pass the created anchor coords that can normally be used to construct it. * @returns {Anchor} */ // TODO: couldn't get function override working, but hopefully in the future // createAnchor(type: 'absoluteAnchor', config: AnchorOption): AbsoluteAnchor; // createAnchor(type: 'oneCellAnchor', config: AnchorOption): OneCellAnchor; // createAnchor(type: 'twoCellAnchor', config: DualAnchorOption): TwoCellAnchor; createAnchor(e, t) { switch (t ?? (t = {}), t.drawing = this, e) { case "absoluteAnchor": this.anchor = new j(t); break; case "oneCellAnchor": this.anchor = new W(t); break; case "twoCellAnchor": this.anchor = new G(t); break; } return this.anchor; } } class se extends H { constructor() { super(); n(this, "id", g("Picture")); n(this, "pictureId", l.uniqueId("Picture")); n(this, "fill", {}); n(this, "mediaData", null); n(this, "description", ""); this.id = g("Picture"), this.pictureId = l.uniqueId("Picture"); } setMedia(t) { this.mediaData = t; } setDescription(t) { this.description = t; } setFillType(t) { this.fill.type = t; } setFillConfig(t) { Object.assign(this.fill, t); } getMediaType() { return "image"; } getMediaData() { return this.mediaData; } setRelationshipId(t) { this.mediaData.rId = t; } toXML(t) { const i = l.createElement(t, "xdr:pic"), r = l.createElement(t, "xdr:nvPicPr"), s = l.createElement(t, "xdr:cNvPr", [ ["id", this.pictureId], ["name", this.mediaData.fileName], ["descr", this.description || ""] ]); r.appendChild(s); const o = l.createElement(t, "xdr:cNvPicPr"); o.appendChild( l.createElement(t, "a:picLocks", [ ["noChangeAspect", "1"], ["noChangeArrowheads", "1"] ]) ), r.appendChild(o), i.appendChild(r); const a = l.createElement(t, "xdr:blipFill"); a.appendChild( l.createElement(t, "a:blip", [ ["xmlns:r", l.schemas.relationships], ["r:embed", this.mediaData.rId] ]) ), a.appendChild(l.createElement(t, "a:srcRect")); const d = l.createElement(t, "a:stretch"); d.appendChild(l.createElement(t, "a:fillRect")), a.appendChild(d), i.appendChild(a); const p = l.createElement(t, "xdr:spPr", [["bwMode", "auto"]]), c = l.createElement(t, "a:xfrm"); p.appendChild(c); const E = l.createElement(t, "a:prstGeom", [["prst", "rect"]]); return p.appendChild(E), i.appendChild(p), this.anchor.toXML(t, i); } } const S = {}; class R { constructor() { n(this, "relations", {}); n(this, "lastId", 1); g("rId"); } importData(e) { this.relations = e.relations, this.lastId = e.lastId; } exportData() { return { relations: this.relations, lastId: this.lastId }; } addRelation(e, t) { return this.relations[e.id] = { id: g("rId"), schema: l.schemas[t], object: e }, this.relations[e.id].id; } getRelationshipId(e) { return this.relations[e.id] ? this.relations[e.id].id : null; } toXML() { const e = l.createXmlDoc(l.schemas.relationshipPackage, "Relationships"), t = e.documentElement; for (const [i, r] of Object.entries(this.relations)) { const s = l.createElement(e, "Relationship", [ ["Id", r.id], ["Type", r.schema], ["Target", r.object.target || S[i]] ]); r.object.targetMode && s.setAttribute("TargetMode", r.object.targetMode), t.appendChild(s); } return e; } } class ne { constructor() { n(this, "drawings", []); n(this, "relations", new R()); n(this, "id", g("Drawings")); } /** * Adds a drawing (more likely a subclass of a Drawing) to the 'Drawings' for a particular worksheet. * * @param {Drawing} drawing * @returns {undefined} */ addDrawing(e) { this.drawings.push(e); } getCount() { return this.drawings.length; } toXML() { const e = l.createXmlDoc(l.schemas.spreadsheetDrawing, "xdr:wsDr"), t = e.documentElement; t.setAttribute("xmlns:a", l.schemas.drawing), t.setAttribute("xmlns:r", l.schemas.relationships), t.setAttribute("xmlns:xdr", l.schemas.spreadsheetDrawing); for (let i = 0, r = this.drawings.length; i < r; i++) { let s = this.relations.getRelationshipId(this.drawings[i].getMediaData()); s || (s = this.relations.addRelation(this.drawings[i].getMediaData(), this.drawings[i].getMediaType())), this.drawings[i].setRelationshipId(s), t.appendChild(this.drawings[i].toXML(e)); } return e; } } class q { constructor() { /* Possible Values: null split Split frozen Frozen frozenSplit Frozen Split http://www.datypic.com/sc/ooxml/t-ssml_ST_PaneState.html */ n(this, "state", null); n(this, "xSplit", null); n(this, "ySplit", null); n(this, "activePane", "bottomRight"); n(this, "topLeftCell", null); n(this, "_freezePane"); } freezePane(e, t, i) { this._freezePane = { xSplit: e, ySplit: t, cell: i }; } exportXML(e) { const t = e.createElement("pane"); return this.state !== null && (t.setAttribute("xSplit", this._freezePane.xSplit), t.setAttribute("ySplit", this._freezePane.ySplit), t.setAttribute("topLeftCell", this._freezePane.cell), t.setAttribute("activePane", "bottomRight"), t.setAttribute("state", "frozen")), t; } } class le { static pixelsToEMUs(e) { return Math.round(e * 914400 / 96); } } class L { constructor() { n(this, "strings", {}); n(this, "stringArray", []); n(this, "id", g("SharedStrings")); } /** * Adds a string to the shared string file, and returns the ID of the * string which can be used to reference it in worksheets. * * @param str {String} * @return int */ addString(e) { return this.strings[e] = this.stringArray.length, this.stringArray[this.stringArray.length] = e, this.strings[e]; } exportData() { return this.strings; } toXML() { const e = l.createXmlDoc(l.schemas.spreadsheetml, "sst"), t = e.documentElement; this.stringArray.reverse(); let i = this.stringArray.length; t.setAttribute("count", i), t.setAttribute("uniqueCount", i); const r = e.createElement("si"), s = e.createElement("t"); s.appendChild(e.createTextNode("--placeholder--")), r.appendChild(s); const o = this.stringArray; for (; i--; ) { const a = r.cloneNode(!0); typeof o[i] == "string" && o[i].match(/\s+/) && a.firstChild.setAttribute("xml:space", "preserve"), a.firstChild.firstChild.nodeValue = o[i], t.appendChild(a); } return e; } } class U { constructor(e) { n(this, "pane"); n(this, "showZeros", null); // Default n(this, "defaultGridColor", null); n(this, "colorId", null); n(this, "rightToLeft", null); n(this, "showFormulas", null); n(this, "showGridLines", null); n(this, "showOutlineSymbols", null); n(this, "showRowColHeaders", null); n(this, "showRuler", null); n(this, "showWhiteSpace", null); n(this, "tabSelected", null); n(this, "topLeftCell", null); n(this, "viewType", null); // http://www.datypic.com/sc/ooxml/t-ssml_ST_SheetViewType.html n(this, "windowProtection", null); n(this, "zoomScale", null); n(this, "zoomScaleNormal", null); n(this, "zoomScalePageLayoutView", null); n(this, "zoomScaleSheetLayoutView", null); const t = e || {}; this.pane = t.pane || new q(); } /** * Added froze pane * @param column - column number: 0, 1, 2 ... * @param row - row number: 0, 1, 2 ... * @param cell - 'A1' * @deprecated */ freezePane(e, t, i) { this.pane.state = "frozen", this.pane.xSplit = e, this.pane.ySplit = t, this.pane.topLeftCell = i; } exportXML(e) { const t = e.createElement("sheetViews"), i = e.createElement("sheetView"); return l.setAttributesOnDoc(i, { //TODO apparent you can add 'book views'.. investigate what these are workbookViewId: 0, showZeros: { v: this.showZeros, type: Boolean }, defaultGridColor: { v: this.defaultGridColor, type: Boolean }, //TODO: I have no idea what this even is :\ colorId: this.colorId, rightToLeft: { v: this.rightToLeft, type: Boolean }, showFormulas: { v: this.showFormulas, type: Boolean }, showGridLines: { v: this.showGridLines, type: Boolean }, showOutlineSymbols: { v: this.showOutlineSymbols, type: Boolean }, showRowColHeaders: { v: this.showRowColHeaders, type: Boolean }, showRuler: { v: this.showRuler, type: Boolean }, showWhiteSpace: { v: this.showWhiteSpace, type: Boolean }, tabSelected: { v: this.tabSelected, type: Boolean }, viewType: this.viewType, windowProtection: { v: this.windowProtection, type: Boolean }, zoomScale: { v: this.zoomScale, type: Boolean }, zoomScaleNormal: this.zoomScaleNormal, zoomScalePageLayoutView: this.zoomScalePageLayoutView, zoomScaleSheetLayoutView: this.zoomScaleSheetLayoutView }), i.appendChild(this.pane.exportXML(e)), t.appendChild(i), t; } } function J(h, e) { return e.reduce((t, i) => (h != null && h.hasOwnProperty(i) && (t[i] = h[i]), t), {}); } class M { constructor() { n(this, "id", g("StyleSheet")); n(this, "cellStyles", [ { name: "Normal", xfId: "0", builtinId: "0" } ]); n(this, "defaultTableStyle", !1); n(this, "differentialStyles", [{}]); n(this, "masterCellFormats", [ { numFmtId: 0, fontId: 0, fillId: 0, borderId: 0, xfid: 0 } ]); n(this, "masterCellStyles", [ { numFmtId: 0, fontId: 0, fillId: 0, borderId: 0 } ]); n(this, "fonts", [{}]); n(this, "numberFormatters", []); n(this, "fills", [ {}, { type: "pattern", patternType: "gray125", fgColor: "FF333333", bgColor: "FF333333" } ]); n(this, "borders", [ { top: {}, left: {}, right: {}, bottom: {}, diagonal: {} } ]); n(this, "tableStyles", []); } createSimpleFormatter(e) { const i = { id: this.masterCellFormats.length }; switch (e) { case "date": i.numFmtId = 14; break; } return this.masterCellFormats.push(i), i; } createFill(e) { const t = this.fills.length, i = e; return i.id = t, this.fills.push(i), i; } createNumberFormatter(e) { const i = { id: this.numberFormatters.length + 100, formatCode: e }; return this.numberFormatters.push(i), i; } /** * alignment: { * horizontal: http://www.schemacentral.com/sc/ooxml/t-ssml_ST_HorizontalAlignment.html * vertical: http://www.schemacentral.com/sc/ooxml/t-ssml_ST_VerticalAlignment.html * @param {Object} styleInstructions */ createFormat(e) { const i = { id: this.masterCellFormats.length }; if (e.protection && (i.protection = e.protection), e.font && y(e.font)) i.fontId = this.createFontStyle(e.font).id; else if (e.font) { if (Number.isNaN(Number.parseInt(e.font, 10))) throw new Error("Passing a non-numeric font id is not supported"); i.fontId = e.font; } if (e.format && A(e.format)) i.numFmtId = this.createNumberFormatter(e.format).id; else if (e.format) { if (Number.isNaN(Number.parseInt(e.format, 10))) throw new Error("Invalid number formatter id"); i.numFmtId = e.format; } if (e.border && y(e.border)) i.borderId = this.createBorderFormatter(e.border).id; else if (e.border) { if (Number.isNaN(Number.parseInt(e.border, 10))) throw new Error("Passing a non-numeric border id is not supported"); i.borderId = e.border; } if (e.fill && y(e.fill)) i.fillId = this.createFill(e.fill).id; else if (e.fill) { if (Number.isNaN(Number.parseInt(e.fill, 10))) throw new Error("Passing a non-numeric fill id is not supported"); i.fillId = e.fill; } return e.alignment && y(e.alignment) && (i.alignment = J(e.alignment, [ "horizontal", "justifyLastLine", "readingOrder", "relativeIndent", "shrinkToFit", "textRotation", "vertical", "wrapText" ])), this.masterCellFormats.push(i), i; } createDifferentialStyle(e) { const t = this.differentialStyles.length, i = { id: t }; return e.font && y(e.font) && (i.font = e.font), e.border && y(e.border) && (i.border = Object.assign( { top: {}, left: {}, right: {}, bottom: {}, diagonal: {} }, e.border )), e.fill && y(e.fill) && (i.fill = e.fill), e.alignment && y(e.alignment) && (i.alignment = e.alignment), e.format && A(e.format) && (i.numFmt = e.format), this.differentialStyles[t] = i, i; } /** * Should be an object containing keys that match with one of the keys from this list: * http://www.schemacentral.com/sc/ooxml/t-ssml_ST_TableStyleType.html * * The value should be a reference to a differential format (dxf) * @param {Object} instructions */ createTableStyle(e) { this.tableStyles.push(e); } /** * All params optional * Expects: { * top: {}, * left: {}, * right: {}, * bottom: {}, * diagonal: {}, * outline: boolean, * diagonalUp: boolean, * diagonalDown: boolean * } * Each border should follow: * { * style: styleString, http://www.schemacentral.com/sc/ooxml/t-ssml_ST_BorderStyle.html * color: ARBG color (requires the A, so for example FF006666) * } * @param {Object} border */ createBorderFormatter(e) { return e = { top: {}, left: {}, right: {}, bottom: {}, diagonal: {}, id: this.borders.length, ...e }, this.borders.push(e), e; } /** * Supported font styles: * bold * italic * underline (single, double, singleAccounting, doubleAccounting) * size * color * fontName * strike (strikethrough) * outline (does this actually do anything?) * shadow (does this actually do anything?) * superscript * subscript * * Color is a future goal - at the moment it's looking a bit complicated * @param {Object} instructions */ createFontStyle(e) { const i = { id: this.fonts.length }; return e.bold && (i.bold = !0), e.italic && (i.italic = !0), e.superscript && (i.vertAlign = "superscript"), e.subscript && (i.vertAlign = "subscript"), e.underline && (typeof e.underline == "string" && ["double", "singleAccounting", "doubleAccounting"].includes(e.underline) ? i.underline = e.underline : i.underline = !0), e.strike && (i.strike = !0), e.outline && (i.outline = !0), e.shadow && (i.shadow = !0), e.size && (i.size = e.size), e.color && (i.color = e.color), e.fontName && (i.fontName = e.fontName), this.fonts.push(i), i; } exportBorders(e) { const t = e.createElement("borders"); t.setAttribute("count", this.borders.length); for (let i = 0, r = this.borders.length; i < r; i++) t.appendChild(this.exportBorder(e, this.borders[i])); return t; } exportBorder(e, t) { const i = e.createElement("border"), r = (s) => { const o = e.createElement(s); return t[s].style && o.setAttribute("style", t[s].style), t[s].color && o.appendChild(this.exportColor(e, t[s].color)), o; }; return i.appendChild(r("left")), i.appendChild(r("right")), i.appendChild(r("top")), i.appendChild(r("bottom")), i.appendChild(r("diagonal")), i; } exportColor(e, t) { const i = e.createElement("color"); return A(t) ? (i.setAttribute("rgb", t), i) : (t.tint !== void 0 && i.setAttribute("tint", t.tint), t.auto !== void 0 && i.setAttribute("auto", String(!!t.auto)), t.theme !== void 0 && i.setAttribute("theme", t.theme), i); } exportMasterCellFormats(e) { const t = l.createElement(e, "cellXfs", [["count", this.masterCellFormats.length]]); for (let i = 0, r = this.masterCellFormats.length; i < r; i++) { const s = this.masterCellFormats[i]; t.appendChild(this.exportCellFormatElement(e, s)); } return t; } exportMasterCellStyles(e) { const t = l.createElement(e, "cellStyleXfs", [["count", this.masterCellStyles.length]]); for (let i = 0, r = this.masterCellStyles.length; i < r; i++) { const s = this.masterCellStyles[i]; t.appendChild(this.exportCellFormatElement(e, s)); } return t; } exportCellFormatElement(e, t) { const i = e.createElement("xf"), r = [ "applyAlignment", "applyBorder", "applyFill", "applyFont", "applyNumberFormat", "applyProtection", "borderId", "fillId", "fontId", "numFmtId", "pivotButton", "quotePrefix", "xfId" ], s = Object.keys(t).filter((a) => r.indexOf(a) !== -1); if (t.alignment) { const a = t.alignment; i.appendChild(this.exportAlignment(e, a)); } t.protection && (i.appendChild(this.exportProtection(e, t.protection)), i.setAttribute("applyProtection", "1")); let o = s.length; for (; o--; ) i.setAttribute(s[o], t[s[o]]); return t.fillId && i.setAttribute("applyFill", "1"), t.fontId && i.setAttribute("applyFont", "1"), t.borderId && i.setAttribute("applyBorder", "1"), t.alignment && i.setAttribute("applyAlignment", "1"), t.numFmtId && i.setAttribute("applyNumberFormat", "1"), t.numFmtId !== void 0 && t.xfId === void 0 && i.setAttribute("xfId", "0"), i; } exportAlignment(e, t) { const i = e.createElement("alignment"), r = Object.keys(t); for (let s = 0, o = r.length; s < o; s++) i.setAttribute(r[s], t[r[s]]); return i; } exportFonts(e) { const t = e.createElement("fonts"); t.setAttribute("count", String(this.fonts.length)); for (let i = 0, r = this.fonts.length; i < r; i++) { const s = this.fonts[i]; t.appendChild(this.exportFont(e, s)); } return t; } exportFont(e, t) { const i = e.createElement("font"); if (t.size) { const r = e.createElement("sz"); r.setAttribute("val", t.size), i.appendChild(r); } if (t.fontName) { const r = e.createElement("name"); r.setAttribute("val", t.fontName), i.appendChild(r); } if (t.bold && i.appendChild(e.createElement("b")), t.italic && i.appendChild(e.createElement("i")), t.vertAlign) { const r = e.createElement("vertAlign"); r.setAttribute("val", t.vertAlign), i.appendChild(r); } if (t.underline) { const r = e.createElement("u"); t.underline !== !0 && r.setAttribute("val", t.underline), i.appendChild(r); } return t.strike && i.appendChild(e.createElement("strike")), t.shadow && i.appendChild(e.createElement("shadow")), t.outline && i.appendChild(e.createElement("outline")), t.color && i.appendChild(this.exportColor(e, t.color)), i; } exportFills(e) { const t = e.createElement("fills"); t.setAttribute("count", String(this.fills.length)); for (let i = 0, r = this.fills.length; i < r; i++) { const s = this.fills[i]; t.appendChild(this.exportFill(e, s)); } return t; } exportFill(e, t) { let i; const r = e.createElement("fill"); return t.type === "pattern" ? (i = this.exportPatternFill(e, t), r.appendChild(i)) : t.type === "gradient" && (i = this.exportGradientFill(e, t), r.appendChild(i)), r; } exportGradientFill(e, t) { const i = e.createElement("gradientFill"); t.degree ? i.setAttribute("degree", t.degree) : t.left && (i.setAttribute("left", t.left), i.setAttribute("right", t.right), i.setAttribute("top", t.top), i.setAttribute("bottom", t.bottom)); const r = e.createElement("stop"); r.setAttribute("position", t.start.pureAt || 0); const s = e.createElement("color"); typeof t.start == "string" || t.start.color ? s.setAttribute("rgb", t.start.color || t.start) : t.start.theme && s.setAttribute("theme", t.start.theme); const o = e.createElement("stop"), a = e.createElement("color"); return o.setAttribute("position", t.end.pureAt || 1), typeof t.start == "string" || t.end.color ? a.setAttribute("rgb", t.end.color || t.end) : t.end.theme && a.setAttribute("theme", t.end.theme), r.appendChild(s), o.appendChild(a), i.appendChild(r), i.appendChild(o), i; } /** * Pattern types: http://www.schemacentral.com/sc/ooxml/t-ssml_ST_PatternType.html * @param {XMLDoc} doc * @param {Object} data */ exportPatternFill(e, t) { const i = l.createElement(e, "patternFill", [["patternType", t.patternType]]); t.bgColor || (t.bgColor = "FFFFFFFF"), t.fgColor || (t.fgColor = "FFFFFFFF"); const r = e.createElement("bgColor"); A(t.bgColor) ? r.setAttribute("rgb", t.bgColor) : t.bgColor.theme ? r.setAttribute("theme", t.bgColor.theme) : r.setAttribute("rgb", t.bgColor.rbg); const s = e.createElement("fgColor"); return A(t.fgColor) ? s.setAttribute("rgb", t.fgColor) : t.fgColor.theme ? s.setAttribute("theme", t.fgColor.theme) : s.setAttribute("rgb", t.fgColor.rbg), i.appendChild(s), i.appendChild(r), i; } exportNumberFormatters(e) { const t = e.createElement("numFmts"); t.setAttribute("count", String(this.numberFormatters.length)); for (let i = 0, r = this.numberFormatters.length; i < r; i++) { const s = this.numberFormatters[i]; t.appendChild(this.exportNumberFormatter(e, s)); } return t; } exportNumberFormatter(e, t) { const i = e.createElement("numFmt"); return i.setAttribute("numFmtId", t.id), i.setAttribute("formatCode", t.formatCode), i; } exportCellStyles(e) { const t = e.createElement("cellStyles"); t.setAttribute("count", String(this.cellStyles.length)); for (let i = 0, r = this.cellStyles.length; i < r; i++) { const s = this.cellStyles[i]; delete s.id; const o = l.createElement(e, "cellStyle"); t.appendChild(o); const a = Object.keys(s); let d = a.length; for (; d--; ) o.setAttribute(a[d], s[a[d]]); } return t; } exportDifferentialStyles(e) { const t = e.createElement("dxfs"); t.setAttribute("count", String(this.differentialStyles.length)); for (let i = 0, r = this.differentialStyles.length; i < r; i++) { const s = this.differentialStyles[i]; t.appendChild(this.exportDFX(e, s)); } return t; } exportDFX(e, t) { const i = e.createElement("dxf"); return t.font && i.appendChild(this.exportFont(e, t.font)), t.fill && i.appendChild(this.exportFill(e, t.fill)), t.border && i.appendChild(this.exportBorder(e, t.border)), t.numFmt && i.appendChild(this.exportNumberFormatter(e, t.numFmt)), t.alignment && i.appendChild(this.exportAlignment(e, t.alignment)), i; } exportTableStyles(e) { const t = e.createElement("tableStyles"); t.setAttribute("count", String(this.tableStyles.length)), this.defaultTableStyle && t.setAttribute("defaultTableStyle", String(this.defaultTableStyle)); for (let i = 0, r = this.tableStyles.length; i < r; i++) t.appendChild(this.exportTableStyle(e, this.tableStyles[i])); return t; } exportTableStyle(e, t) { const i = e.createElement("tableStyle"); i.setAttribute("name", t.name), i.setAttribute("pivot", String(0)); let r = 0; return Object.entries(t).forEach(([s, o]) => { if (s === "name") return; r++; const a = e.createElement("tableStyleElement"); a.setAttribute("type", s), a.setAttribute("dxfId", o), i.appendChild(a); }), i.setAttribute("count", String(r)), i; } exportProtection(e, t) { const i = e.createElement("protection"); for (const r in t) r in t && i.setAttribute(r, t[r]); return i; } toXML() { const e = l.createXmlDoc(l.schemas.spreadsheetml, "styleSheet"), t = e.documentElement; return t.appendChild(this.exportNumberFormatters(e)), t.appendChild(this.exportFonts(e)), t.appendChild(this.exportFills(e)), t.appendChild(this.exportBorders(e)), t.appendChild(this.exportMasterCellStyles(e)), t.appendChild(this.exportMasterCellFormats(e)), t.appendChild(this.exportCellStyles(e)), t.appendChild(this.exportDifferentialStyles(e)), this.tableStyles.length && t.appendChild(this.exportTableStyles(e)), e; } } class oe { constructor(e) { n(this, "name", ""); n(this, "id", ""); n(this, "tableId", ""); n(this, "displayName", ""); n(this, "dataCellStyle", null); n(this, "dataDfxId", null); n(this, "headerRowBorderDxfId", null); n(this, "headerRowCellStyle", null); n(this, "headerRowCount", 1); n(this, "headerRowDxfId", null); n(this, "insertRow", !1); n(this, "insertRowShift", !1); n(this, "ref", null); n(this, "tableBorderDxfId", null); n(this, "totalsRowBorderDxfId", null); n(this, "totalsRowCellStyle", null); n(this, "totalsRowCount", 0); n(this, "totalsRowDxfId", null); n(this, "tableColumns", []); n(this, "autoFilter", null); n(this, "sortState", null); n(this, "styleInfo", {}); this.initialize(e); } initialize(e) { this.displayName = g("Table"), this.name = this.displayName, this.id = this.name, this.tableId = this.id.replace("Table", ""), Object.assign(this, e); } setReferenceRange(e, t) { this.ref = [e, t]; } setTableColumns(e) { e.forEach((t) => { this.addTableColumn(t); }); } /** * Expects an object with the following optional properties: * name (required) * dataCellStyle * dataDxfId * headerRowCellStyle * headerRowDxfId * totalsRowCellStyle * totalsRowDxfId * totalsRowFunction * totalsRowLabel * columnFormula * columnFormulaIsArrayType (boolean) * totalFormula * totalFormulaIsArrayType (boolean) */ addTableColumn(e) { if (A(e) && (e = { name: e }), !e.name) throw new Error("Invalid argument for addTableColumn - minimum requirement is a name property"); this.tableColumns.push(e); } /** * Expects an object with the following properties: * caseSensitive (boolean) * dataRange * columnSort (assumes true) * sortDirection * sortRange (defaults to dataRange) */ setSortState(e) { this.sortState = e; } toXML() { const e = l.createXmlDoc(l.schemas.spreadsheetml, "table"), t = e.documentElement; t.setAttribute("id", this.tableId), t.setAttribute("name", this.name), t.setAttribute("displayName", this.displayName); const i = this.ref[0], r = this.ref[1]; if (t.setAttribute("ref", `${l.positionToLetterRef(i[0], i[1])}:${l.positionToLetterRef(r[0], r[1])}`), t.setAttribute("totalsRowCount", this.totalsRowCount), t.setAttribute("headerRowCount", this.headerRowCount), this.headerRowDxfId && t.setAttribute("headerRowDxfId", this.headerRowDxfId), this.headerRowBorderDxfId && t.setAttribute("headerRowBorderDxfId", this.headerRowBorderDxfId), !this.ref) throw new Error("Needs at least a reference range"); return this.autoFilter || this.addAutoFilter(this.ref[0], this.ref[1]), t.appendChild(this.exportAutoFilter(e)), t.appendChild(this.exportTableColumns(e)), t.appendChild(this.exportTableStyleInfo(e)), e; } exportTableColumns(e) { const t = e.createElement("tableColumns"); t.setAttribute("count", this.tableColumns.length); const i = this.tableColumns; for (let r = 0, s = i.length; r < s; r++) { const o = i[r], a = e.createElement("tableColumn"); a.setAttribute("id", String(r + 1)), a.setAttribute("name", o.name), t.appendChild(a), o.totalsRowFunction && a.setAttribute("totalsRowFunction", o.totalsRowFunction), o.totalsRowLabel && a.setAttribute("totalsRowLabel", o.totalsRowLabel); } return t; } exportAutoFilter(e) { const t = e.createElement("autoFilter"), i = this.autoFilter[0], r = this.autoFilter[1]; return t.setAttribute("ref", `${l.positionToLetterRef(i[0], i[1])}:${l.positionToLetterRef(r[0], r[1] - this.totalsRowCount)}`), t; } exportTableStyleInfo(e) { const t = this.styleInfo, i = e.createElement("tableStyleInfo"); return i.setAttribute("name", t.themeStyle), i.setAttribute("showFirstColumn", t.showFirstColumn ? "1" : "0"), i.setAttribute("showLastColumn", t.showLastColumn ? "1" : "0"), i.setAttribute("showColumnStripes", t.showColumnStripes ? "1" : "0"), i.setAttribute("showRowStripes", t.showRowStripes ? "1" : "0"), i; } addAutoFilter(e, t) { this.autoFilter = [e, t]; } } class Z { constructor(e) { n(this, "name", ""); n(this, "id", g("Worksheet")); n(this, "_timezoneOffset"); n(this, "relations", null); n(this, "columnFormats", []); n(this, "data", []); n(this, "mergedCells", []); n(this, "columns", []); n(this, "sheetProtection", !1); n(this, "_headers", []); n(this, "_footers", []); n(this, "_tables", []); n(this, "_drawings", []); n(this, "_orientation"); n(this, "_margin"); n(this, "_rowInstructions", {}); n(this, "_freezePane", {}); n(this, "sharedStrings", null); n(this, "hyperlinks", []); n(this, "sheetView"); n(this, "showZeros", null); this._timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset() * 60 * 1e3, this.sheetView = e.sheetView || new U(), this.initialize(e); } initialize(e) { e = e || {}, this.name = e.name, this.id = g("Worksheet"), this._timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset() * 60 * 1e3, e.columns && this.setColumns(e.columns), this.relations = new R(); } /** * Returns an object that can be consumed by a Worksheet/Export/Worker * @returns {Object} */ exportData() { return { relations: this.relations.exportData(), columnFormats: this.columnFormats, data: this.data, columns: this.columns, mergedCells: this.mergedCells, _headers: this._headers, _footers: this._footers, _tables: this._tables, _rowInstructions: this._rowInstructions, _freezePane: this._freezePane, name: this.name, id: this.id }; } /** * Imports data - to be used while inside of a WorksheetExportWorker. * @param {Object} data */ importData(e) { this.relations.importData(e.relations), delete e.relations, Object.assign(this, e); } setSharedStringCollection(e) { this.sharedStrings = e; } addTable(e) { this._tables.push(e), this.relations.addRelation(e, "table"); } addDrawings(e) { this._drawings.push(e), this.relations.addRelation(e, "drawingRelationship"); } setRowInstructions(e, t) { this._rowInstructions[e] = t; } /** * Expects an array length of three. * * @see Excel/Worksheet compilePageDetailPiece * @see <a href='/cookbook/addingHeadersAndFooters.html'>Adding headers and footers to a worksheet</a> * * @param {Array} headers [left, center, right] */ setHeader(e) { if (!Array.isArray(e)) throw "Invalid argument type - setHeader expects an array of three instructions"; this._headers = e; } /** * Expects an array length of three. * * @see Excel/Worksheet compilePageDetailPiece * @see <a href='/cookbook/addingHeadersAndFooters.html'>Adding headers and footers to a worksheet</a> * * @param {Array} footers [left, center, right] */ setFooter(e) { if (!Array.isArray(e)) throw "Invalid argument type - setFooter expects an array of three instructions"; this._footers = e; } /** * Turns page header/footer details into the proper format for Excel. * @param {type} data * @returns {String} */ compilePageDetailPackage(e) { return e = e || "", [ "&L", this.compilePageDetailPiece(e[0] || ""), "&C", this.compilePageDetailPiece(e[1] || ""), "&R", this.compilePageDetailPiece(e[2] || "") ].join(""); } /** * Turns instructions on page header/footer details into something * usable by Excel. * * @param {type} data * @returns {String|@exp;_@call;reduce} */ compilePageDetailPiece(e) { if (A(e)) return '&"-,Regular"'.concat(e); if (y(e) && !Array.isArray(e)) { let t = ""; if (e.font || e.bold) { const i = e.bold ? "Bold" : "Regular"; t += `&"${e.font || "-"}`, t += `,${i}"`; } else t += '&"-,Regular"'; return e.underline && (t += "&U"), e.fontSize && (t += `&${e.fontSize}`), t += e.text, t; } if (Array.isArray(e)) return e.reduce((t, i) => t.concat(this.compilePageDetailPiece(i)), ""); } /** * Creates the header node. * * @todo implement the ability to do even/odd headers * @param {XML Doc} doc * @returns {XML Node} */ exportHeader(e) { const t = e.createElement("oddHeader"); return t.appendChild(e.createTextNode(this.compilePageDetailPackage(this._headers))), t; } /** * Creates the footer node. * * @todo implement the ability to do even/odd footers * @param {XML Doc} doc * @returns {XML Node} */ exportFooter(e) { const t = e.createElement("oddFooter"); return t.appendChild(e.createTextNode(this.compilePageDetailPackage(this._footers))), t; } /** * This creates some nodes ahead of time, which cuts down on generation time due to * most cell definitions being essentially the same, but having multiple nodes that need * to be created. Cloning takes less time than creation. * * @private * @param {XML Doc} doc * @returns {_L8.Anonym$0._buildCache.Anonym$2} */ _buildCache(e) { const t = e.createElement("c"), i = e.createElement("v"); i.appendChild(e.createTextNode("--temp--")), t.appendChild(i); const r = e.createElement("c"), s = e.createElement("f"); s.appendChild(e.createTextNode("--temp--")), r.appendChild(s); const o = e.createElement("c"); o.setAttribute("t", "s"); const a = e.createElement("v"); return a.appendChild(e.createTextNode("--temp--")), o.appendChild(a), { number: t, date: t, string: o, formula: r }; } /** * Runs through the XML document and grabs all of the strings that will * be sent to the 'shared strings' document. * * @returns {Array} */ collectSharedStrings() { const e = this.data, t = {}; for (let i = 0, r = e.length; i < r; i++) { const s = e[i], o = s.length; for (let a = 0; a < o; a++) { let d = s[a]; const p = (d == null ? void 0 : d.metadata) || {}; d && typeof d == "object" && (d = d.value), p.type || typeof d == "number" && (p.type = "number"), (p.type === "text" || !p.type) && typeof t[d] > "u" && (t[d] = !0); } } return Object.keys(t); } toXML() { var E, F, T; const e = this.data, t = this.columns || [], i = l.createXmlDoc(l.schemas.spreadsheetml, "worksheet"), r = i.documentElement; let s, o, a; r.setAttribute("xmlns:r", l.schemas.relationships), r.setAttribute("xmlns:mc", l.schemas.markupCompat); let d = 0; const p = l.createElement(i, "sheetData"), c = this._buildCache(i); for (a = 0, o = e.length; a < o; a++) { const m = e[a], b = m.length; d = b > d ? b : d; const w = i.createElement("row"); for (let f = 0; f < b; f++) { t[f] = t[f] || {}; let u = m[f], C; const k = (u == null ? void 0 : u.metadata) || {}; switch (u && typeof u == "object" && (u = u.value), k.type || typeof u == "number" && (k.type = "number"), k.type) { case "number": C = c.number.cloneNode(!0), C.firstChild.firstChild.nodeValue = u; break; case "date": C = c.date.cloneNode(!0), u instanceof Date && (u = u.getTime()), C.firstChild.firstChild.nodeValue = 25569 + (u - this._timezoneOffset) / (60 * 60 * 24 * 1e3); break; case "formula": C = c.formula.cloneNode(!0), C.firstChild.firstChild.nodeValue = u; break; // biome-ignore lint: original implementation case "text": /*falls through*/ default: { let O; typeof ((E = this.sharedStrings) == null ? void 0 : E.strings[u]) < "u" ? O = this.sharedStrings.strings[u] : O = (F = this.sharedStrings) == null ? void 0 : F.addString(u), C = c.string.cloneNode(!0), C.firstChild.firstChild.nodeValue = O; break; } } k.style ? C.setAttribute("s", k.style) : ((T = this._rowInstructions[a]) == null ? void 0 : T.style) !== void 0 && C.setAttribute("s", this._rowInstructions[a].style), C.setAttribute("r", l.positionToLetterRef(f + 1, String(a + 1))), w.appendChild(C); } if (w.setAttribute("r", a + 1), this._rowInstructions[a]) { const f = this._rowInstructions[a]; f.height !== void 0 && (w.setAttribute("customHeight", "1"), w.setAttribute("ht", f.height)), f.style !== void 0 && (w.setAttribute("customFormat", "1"), w.setAttribute("s", f.style)); } p.appendChild(w); } if (d !== 0 ? r.appendChild( l.createElement(i, "dimension", [ ["ref", `${l.positionToLetterRef(1, 1)}:${l.positionToLetterRef(d, String(e.length))}`] ]) ) : r.appendChild(l.createElement(i, "dimension", [["ref", l.positionToLetterRef(1, 1)]])), r.appendChild(this.sheetView.exportXML(i)), this.columns.length && r.appendChild(this.exportColumns(i)), r.appendChild(p), this.sheetProtection && r.appendChild(this.sheetProtection.exportXML(i)), this.hyperlinks.length > 0) { const m = i.createElement("hyperlinks"), b = this.hyperlinks; for (s = 0, o = b.length; s < o; s++) { const w = i.createElement("hyperlink"), f = b[s]; w.setAttribute("ref", String(f.cell)), f.id = l.uniqueId("hyperlink"), this.relations.addRelation( { id: f.id, target: f.location, targetMode: f.targetMode || "External" }, "hyperlink" ), w.setAttribute("r:id", this.relations.getRelationshipId(f)), m.appendChild(w); } r.appendChild(m); } if (this.mergedCells.length > 0) { const m = i.createElement("mergeCells"); for (s = 0, o = this.mergedCells.length; s < o; s++) { const b = i.createElement("mergeCell"); b.setAttribute("ref", `${this.mergedCells[s][0]}:${this.mergedCells[s][1]}`), m.appendChild(b)