UNPKG

jqwidgets-framework

Version:

jQWidgets is an advanced Angular, Vue, Blazor, React, Web Components, jquery, ASP .NET MVC, Custom Elements and HTML5 UI framework.

1,413 lines (1,145 loc) 138 kB
/* tslint:disable */ /* eslint-disable */ (function ($) { window.jqxToDash = function(value) { return value.split(/(?=[A-Z])/).join('-').toLowerCase(); } class DataExporter { constructor(exportDetails, groupBy, filterBy, conditionalFormatting) { const that = this; if (!exportDetails) { exportDetails = {}; } /* * "style" object definition (all properties are optional): * * «any valid CSS property» - applied to whole table * header (Object) * «any valid CSS property» - applied to header cells * «any column name» (Object) * «any valid CSS property» - applied to particular column header cell * columns (Object) * «any valid CSS property» - applied to column cells * «any column name» (Object) * «any valid CSS property» - applied to the cells of particular column * format - applicable to numeric and date columns * «n» (Object), where «n» is a row index (related to use of "ConditionalFormatting" object) * background * border * color * rows (Object) * «any valid CSS property» - applied to rows * alternationCount * alternationStart * alternationEnd * alternationIndex«n»Color, where «n» is an integer * alternationIndex«n»BorderColor, where «n» is an integer * alternationIndex«n»BackgroundColor, where «n» is an integer * «n» (Object), where «n» is a row index * «any valid CSS property» - applied to particular row */ that.style = exportDetails.style; that.header = exportDetails.header; that.exportHeader = exportDetails.exportHeader || true; that.hierarchical = exportDetails.hierarchical; that.expandChar = exportDetails.expandChar || '+'; that.collapseChar = exportDetails.collapseChar || '-'; that.pageOrientation = exportDetails.pageOrientation; if (!that.hierarchical && groupBy && groupBy.length > 0) { that.groupBy = groupBy; } else { that.mergedCells = exportDetails.mergedCells; } if (!that.groupBy && filterBy && Object.keys(filterBy).length > 0) { that.filterBy = filterBy; } if (conditionalFormatting) { that.conditionalFormatting = conditionalFormatting; } that.timeBetween1900And1970 = new Date(1970, 0, 1).getTime() - new Date(1900, 0, 1).getTime(); } /** * Generates and downloads a file. */ downloadFile(data, type, fileName) { let file; if (!fileName) { return data; } if (data instanceof Blob) { file = data; } else { file = new Blob([data], { type: type }); } if (window.navigator.msSaveOrOpenBlob) { // Edge window.navigator.msSaveOrOpenBlob(file, fileName); } else { // Chrome, Firefox, Safari const a = document.createElement('a'), url = URL.createObjectURL(file); a.href = url; a.download = fileName; a.style.position = 'absolute'; a.style.visibility = 'hidden'; document.body.appendChild(a); a.click(); setTimeout(function () { document.body.removeChild(a); window.URL.revokeObjectURL(url); }, 0); } } /** * Exports data. */ exportData(data, format, fileName, callback) { const that = this; that.actualHierarchy = that.hierarchical; format = format.toLowerCase(); if (that.exportHeader) { if (that.header) { data = data.slice(0); if (data.length === 0) { that.actualHierarchy = false; } that.processComplexHeader(that.header, data, format); } else if (data.length === 1) { that.actualHierarchy = false; } } if (data.length === 0) { // eslint-disable-next-line console.warn('No data to export.'); return; } if (format === 'xlsx') { that.xlsxStartIndex = that.complexHeader ? that.complexHeader.length : +that.exportHeader; } if (that.actualHierarchy) { data = that.processHierarchicalData(data, format); } that.getDatafields(data); if (fileName && fileName.slice(fileName.length - format.length - 1, fileName.length) !== '.' + format) { fileName += '.' + format; } let output = null; switch (format) { case 'csv': output = that.exportToCSVAndTSV(data, { delimiter: ', ', MIME: 'text/csv', toRemove: 2 }, fileName); break; case 'html': output = that.exportToHTML(data, fileName); break; case 'jpeg': case 'png': that.exportToImage(data, fileName, format, callback); break; case 'json': output = that.exportToJSON(data, fileName); break; case 'pdf': output = that.exportToPDF(data, fileName); break; case 'tsv': output = that.exportToCSVAndTSV(data, { delimiter: '\t', MIME: 'text/tab-separated-values', toRemove: 1 }, fileName); break; case 'xlsx': output = that.exportToXLSX(data, fileName); break; case 'xml': output = that.exportToXML(data, fileName); break; } if (callback && output) { callback(output); } delete that.complexHeader; return output; } /** * Exports to CSV and TSV. */ exportToCSVAndTSV(data, formatOptions, fileName) { const that = this, datafields = that.datafields; let stringResult = ''; for (let i = 0; i < data.length; i++) { const currentRecord = data[i]; let stringifiedCurrentRecord = ''; for (let j = 0; j < datafields.length; j++) { if (that.actualHierarchy && j === 0) { stringifiedCurrentRecord += ('""' + formatOptions.delimiter).repeat(currentRecord._level - 1) + '"' + currentRecord[datafields[j]] + '"' + formatOptions.delimiter + ('""' + formatOptions.delimiter).repeat(that.maxLevel - currentRecord._level); continue; } stringifiedCurrentRecord += '"' + currentRecord[datafields[j]] + '"' + formatOptions.delimiter; } stringifiedCurrentRecord = stringifiedCurrentRecord.slice(0, stringifiedCurrentRecord.length - formatOptions.toRemove) + '\n'; stringResult += stringifiedCurrentRecord; } return this.downloadFile(stringResult, formatOptions.MIME, fileName); } /** * Exports to HTML. */ exportToHTML(data, fileName) { const that = this, datafields = that.datafields, style = that.style; let header = '', startIndex = 0, html2canvas = ''; data = that.processGroupingInformation(data); that.data = data; if (that.exportHeader) { header = that.getHTMLHeader(datafields, data); startIndex = 1; } if (arguments[2]) { const scripts = Array.from(document.getElementsByTagName('script')), html2canvasScript = scripts.find(script => script.src.indexOf('html2canvas') !== -1); html2canvas = `<script type="text/javascript" src="${html2canvasScript.src}"></script>`; } let htmlContent = `<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style type="text/css"> ${that.getRowStyle()}${that.getColumnStyle()} </style>${html2canvas}${that.toggleableFunctionality()} </head> <body> <table${that.getTableStyle()}>${header} <tbody>\n`; const mergedMainCells = {}, mergedSecondaryCells = {}, groupsHandled = []; that.getMergedCellsInfo(mergedMainCells, mergedSecondaryCells); mainLoop: for (let i = startIndex; i < data.length; i++) { const currentRecord = data[i], row = i - startIndex; let n = that.getAlternationIndex(row, ' rowN'), toCollapse = '', level = '', groupId = '', outlineLevel = 0; if (that.actualHierarchy) { if (currentRecord._collapsed) { toCollapse = ' collapsed'; } level = ` level="${currentRecord._level}"`; } else if (that.groupBy) { for (let k = 0; k < that.groupBy.length; k++) { const datafield = that.groupBy[k], currentGroup = currentRecord[datafield], currentGroupLabel = that.groups[datafield][currentGroup]; groupId += currentGroup; if (groupsHandled.indexOf(groupId) === -1) { htmlContent += ` <tr class="row"> <td class="column group" style="padding-left: ${outlineLevel * 25}px;" colspan="${that.datafields.length}">${currentGroupLabel}</td> </tr>`; groupsHandled.push(groupId); i--; continue mainLoop; } outlineLevel++; } } let currentContent = ` <tr class="row row${row}${n}${toCollapse}"${level}`; if (!fileName) { currentContent += ' style="page-break-inside: avoid;"' } currentContent += '>\n'; for (let j = 0; j < datafields.length; j++) { const cellCode = j + ',' + (row); let colspan = 1, rowspan = 1; if (mergedMainCells[cellCode]) { colspan = mergedMainCells[cellCode].colspan; rowspan = mergedMainCells[cellCode].rowspan; } else if (mergedSecondaryCells[cellCode]) { continue; } const datafield = datafields[j]; let value = currentRecord[datafield], indent = ''; if (that.actualHierarchy && j === 0) { let sign = ''; if (currentRecord._expanded) { sign = that.collapseChar; } else if (currentRecord._expanded === false) { sign = that.expandChar; } indent = `<div class="toggle-element" style="margin-left: ${25 * (currentRecord._level - 1) + 5}px;" expanded>${sign}</div>`; } value = that.getFormattedValue(value, datafield); let css = ''; if (style && style.columns && style.columns[datafield] && style.columns[datafield][row]) { const uniqueStyle = style.columns[datafield][row]; css += `border-color: ${uniqueStyle.border}; background-color: ${uniqueStyle.background}; color: ${uniqueStyle.color};"`; } if (j === 0 && outlineLevel > 1) { css += `padding-left: ${(outlineLevel - 1) * 25}px;"`; } if (css) { css = ` style="${css}"`; } currentContent += ` <td class="column column${datafield}"${css} colspan="${colspan}" rowspan="${rowspan}">${indent + value}</td>\n`; } htmlContent += currentContent + ' </tr>\n'; } htmlContent += ` </tbody> </table> </body> </html>`; if (arguments[2]) { return htmlContent; } return this.downloadFile(htmlContent, 'text/html', fileName); } /** * Exports to an image (PNG/JPEG). */ exportToImage(data, fileName, fileExtension, callback) { const that = this; try { html2canvas; } catch (error) { throw new Error('jqx-grid: Missing reference to \'html2canvas.min.js\'.'); } let imageData = null; const htmlContent = that.exportToHTML(data, fileName, true), iframe = document.createElement('iframe'); iframe.style.position = 'absolute'; iframe.style.top = 0; iframe.style.left = 0; iframe.style.border = 'none'; iframe.style.width = '100%'; iframe.style.height = '100%'; iframe.style.opacity = 0; document.body.appendChild(iframe); iframe.contentDocument.write(htmlContent); function checkIframePopulated() { if (!iframe.contentDocument.body || !iframe.contentDocument.body.firstElementChild) { requestAnimationFrame(checkIframePopulated); } else { iframe.contentWindow.html2canvas(iframe.contentDocument.body.firstElementChild).then(canvas => { const draw = $.jqxDraw(document.createElement('div')); imageData = canvas.toDataURL('image/png'); if (callback) { callback(imageData); } else { document.body.appendChild(canvas); draw.exportImage(undefined, canvas, fileExtension, fileName); } iframe.remove(); canvas.remove(); }); } } checkIframePopulated(); return imageData; } /** * Gets merged cells information (for use in HTML and PDF export). */ getMergedCellsInfo(mergedMainCells, mergedSecondaryCells, mapping) { const that = this; if (!that.mergedCells) { return; } const multipleTables = mapping && mapping[that.datafields.length - 1] !== 0; that.mergedCellsPDF = that.mergedCells.slice(0); for (let i = 0; i < that.mergedCellsPDF.length; i++) { const cellDefinition = that.mergedCellsPDF[i]; let colspan = cellDefinition.colspan, rowspan = cellDefinition.rowspan; if (rowspan < 2 && colspan < 2) { continue; } const row = cellDefinition.cell[1]; let col = cellDefinition.cell[0]; if (multipleTables && colspan > 1) { const startTable = mapping[col], endTable = mapping[col + colspan - 1], splitCells = []; if (endTable > startTable) { let currentTable = startTable, currentColumn = col, overal = 0; mainLoop: for (let i = startTable; i <= endTable; i++) { let start = currentColumn, span = 0; while (mapping[currentColumn] === currentTable) { currentColumn++; overal++; span++; if (overal === colspan) { splitCells.push({ start: start, span: span }); break mainLoop; } } splitCells.push({ start: start, span: span }); currentTable = mapping[currentColumn]; } colspan = splitCells[0].span; for (let i = 1; i < splitCells.length; i++) { that.mergedCellsPDF.push({ cell: [splitCells[i].start, row], colspan: splitCells[i].span, rowspan: rowspan, originalCell: col }); } } } for (let j = col; j < col + colspan; j++) { for (let k = row; k < row + rowspan; k++) { const code = j + ',' + k; if (j === col && k === row) { mergedMainCells[code] = { colspan: colspan, rowspan: rowspan, originalCell: cellDefinition.originalCell }; continue; } mergedSecondaryCells[code] = true; } } } } /** * Gets alternation index. */ getAlternationIndex(row, prefix) { const that = this; if (!that.style) { return ''; } const rowsDefinition = that.style.rows, alternationCount = rowsDefinition && rowsDefinition.alternationCount; if (alternationCount && (((rowsDefinition.alternationStart === undefined || row >= rowsDefinition.alternationStart) && (rowsDefinition.alternationEnd === undefined || row <= rowsDefinition.alternationEnd)) || rowsDefinition.alternationStart === rowsDefinition.alternationEnd)) { return prefix + (row % rowsDefinition.alternationCount); } return ''; } /** * Gets formatted numeric or date value (for use in HTML and PDF export). */ getFormattedValue(value, datafield) { const that = this, style = that.style; if (datafield && style && style.columns && style.columns[datafield] && style.columns[datafield].format) { if (typeof value === 'number') { return that.formatNumber(value, style.columns[datafield].format); } else if (value instanceof Date) { return that.formatDate(value, style.columns[datafield].format); } } else if (value instanceof Date) { return that.formatDate(value, 'd'); } return value; } /** * Exports to JSON. */ exportToJSON(data, fileName) { return this.downloadFile(JSON.stringify(data, this.datafields.concat('rows')), 'application/json', fileName); } /** * Exports to PDF. */ exportToPDF(data, fileName) { const that = this, datafields = that.datafields, startIndex = +that.exportHeader, groupsHandled = [], mergedMainCells = {}, mergedSecondaryCells = {}, mapping = {}, headerRows = startIndex ? that.complexHeader ? that.complexHeader.length : 1 : 0, docDefinition = { pageOrientation: that.pageOrientation || 'portrait' }; let header = [], content = [], tables; function createTableRow() { let tableRow = []; for (let i = 0; i < tables.length; i++) { tableRow.push([]); } return tableRow; } data = that.processGroupingInformation(data); that.data = data; that.headerRows = headerRows; that.getPDFStyle(); const styleInfo = that.styleInfo; tables = styleInfo ? that.wrapPDFColumns(docDefinition, mapping) : [{ body: header, datafields: datafields }]; if (startIndex) { header = that.getPDFHeader(datafields, tables, mapping); } that.getMergedCellsInfo(mergedMainCells, mergedSecondaryCells, mapping); mainLoop: for (let i = startIndex; i < data.length; i++) { const currentRecord = data[i]; let groupId = '', outlineLevel = 0; if (that.groupBy) { for (let k = 0; k < that.groupBy.length; k++) { const datafield = that.groupBy[k], currentGroup = currentRecord[datafield], currentGroupLabel = that.groups[datafield][currentGroup]; groupId += currentGroup; if (groupsHandled.indexOf(groupId) === -1) { that.createGroupHeaderRow(tables, { text: currentGroupLabel, style: ['row', 'cell', 'group'], marginLeft: outlineLevel * 7.5 }); groupsHandled.push(groupId); i--; continue mainLoop; } outlineLevel++; } } const tableRow = createTableRow(), row = i - startIndex; let n = that.getAlternationIndex(row, ''); for (let j = 0; j < datafields.length; j++) { const datafield = datafields[j], entry = { style: ['row', 'row' + row, 'cell', 'cell' + datafield] }, tableIndex = mapping[j] || 0; if (n !== undefined) { entry.style.splice(1, 0, 'rowN' + n); } if (that.mergedCellsPDF) { const cellCode = j + ',' + row, mergeInfo = mergedMainCells[cellCode]; if (mergeInfo) { entry.colSpan = mergeInfo.colspan; entry.rowSpan = mergeInfo.rowspan; if (mergeInfo.originalCell !== undefined) { entry.text = ''; entry.style[entry.style.length - 1] = 'cell' + datafields[mergeInfo.originalCell]; tableRow[tableIndex].push(entry); continue; } } else if (mergedSecondaryCells[cellCode]) { tableRow[tableIndex].push({}); continue; } } const value = that.getFormattedValue(currentRecord[datafield], datafield); entry.text = value.toString(); that.getUniqueStylePDF(entry, datafield, row); that.setIndentation(entry, { j: j, currentRecord: currentRecord, value: value, outlineLevel: outlineLevel }); tableRow[tableIndex].push(entry); } for (let k = 0; k < tables.length; k++) { tables[k].body.push(tableRow[k]); } } if (styleInfo) { for (let i = 0; i < tables.length; i++) { const body = tables[i].body; for (let j = headerRows - 1; j >= 0; j--) { body.unshift(header[i][j]); } content.push({ table: { headerRows: headerRows, widths: tables[i].widths, heights: function (row) { if (styleInfo.heights[row]) { return styleInfo.heights[row]; } if (styleInfo.defaultHeight) { return styleInfo.defaultHeight; } }, body: body }, pageBreak: 'after' }); } delete content[tables.length - 1].pageBreak; docDefinition.styles = styleInfo.styles; } else { const body = tables[0].body; for (let j = headerRows - 1; j >= 0; j--) { body.unshift(header[0][j]); } content = [{ table: { headerRows: headerRows, body: body } }]; docDefinition.styles = { header: { bold: true }, group: { bold: true } }; } docDefinition.content = content; pdfMake.createPdf(docDefinition).download(fileName); delete that.mergedCellsPDF; delete that.styleInfo; } /** * Gets the header content when exporting to PDF. */ getPDFStyle() { const that = this, style = that.style; if (!style) { return ''; } const sampleRecord = that.data[0], headerDefinition = style.header, columnsDefinition = style.columns, rowsDefinition = style.rows, styleInfo = { heights: [], widths: Array(that.datafields.length).fill('*'), styles: { header: {}, row: {}, cell: {}, group: { fillColor: '#FFFFFF', color: '#000000', bold: true } } }; that.styleInfo = styleInfo; function processStyleDefinition(definition, type) { if (!definition) { return; } for (let prop in definition) { if (!definition.hasOwnProperty(prop)) { continue; } if (sampleRecord[prop] === undefined) { if (prop === 'height' && type === 'header') { for (let i = 0; i < that.headerRows; i++) { styleInfo.heights[i] = (parseInt(definition[prop], 10) / that.headerRows) / 1.57; } } else { that.storePDFStyle({ prop: prop, value: definition[prop], toUpdate: type }); } } else { for (let columnProp in definition[prop]) { if (!isNaN(columnProp) || !definition[prop].hasOwnProperty(columnProp)) { continue; } const value = definition[prop][columnProp], index = that.datafields.indexOf(prop); if (columnProp === 'width' && styleInfo.widths[index] === '*') { styleInfo.widths[index] = parseFloat(value); } else { that.storePDFStyle({ prop: columnProp, value: value, toUpdate: type + prop }); } } } } } processStyleDefinition(headerDefinition, 'header'); processStyleDefinition(columnsDefinition, 'cell'); if (!rowsDefinition) { return; } for (let prop in rowsDefinition) { if (!rowsDefinition.hasOwnProperty(prop) || prop.indexOf('alt') !== -1) { continue; } const value = rowsDefinition[prop]; if (!isNaN(prop)) { for (let rowProp in value) { if (value.hasOwnProperty(rowProp)) { if (rowProp === 'height') { styleInfo.heights[parseFloat(prop) + that.headerRows] = parseFloat(value[rowProp]) / 1.57; } else { that.storePDFStyle({ prop: rowProp, value: value[rowProp], toUpdate: 'row' + prop }); } } } continue; } if (prop === 'height') { styleInfo.defaultHeight = parseFloat(value) / 1.57; } else { that.storePDFStyle({ prop: prop, value: value, toUpdate: 'row' }); } } if (!rowsDefinition.alternationCount) { return; } for (let i = 0; i < rowsDefinition.alternationCount; i++) { const styleN = {}; if (rowsDefinition[`alternationIndex${i}Color`]) { styleN.color = rowsDefinition[`alternationIndex${i}Color`]; } if (rowsDefinition[`alternationIndex${i}BackgroundColor`]) { styleN.fillColor = rowsDefinition[`alternationIndex${i}BackgroundColor`]; } styleInfo.styles['rowN' + i] = styleN; } } /** * Stores style in object to be applied to generated PDF. */ storePDFStyle(details) { const that = this; let objectToUpdate = that.styleInfo.styles[details.toUpdate]; if (!objectToUpdate) { objectToUpdate = {}; that.styleInfo.styles[details.toUpdate] = objectToUpdate; } let value = details.value; switch (details.prop) { case 'backgroundColor': objectToUpdate.fillColor = value; break; case 'color': objectToUpdate.color = value; break; case 'fontSize': objectToUpdate.fontSize = parseFloat(value); break; case 'fontStyle': if (value === 'italic') { objectToUpdate.italics = true; } break; case 'fontWeight': if (value === 'bold') { objectToUpdate.bold = true; } break; case 'textAlign': objectToUpdate.alignment = value; break; } } /** * Enables column wrapping when exporting to PDF. */ wrapPDFColumns(docDefinition, mapping) { const that = this, styleInfo = this.styleInfo, maxPerPage = docDefinition.pageOrientation === 'portrait' ? 775 : 1155, // maximum of 775px (portrait) or 1155px (landscape) per A4 page tables = []; let currentPage = 0; for (let i = 0; i < styleInfo.widths.length; i++) { let currentWidth = styleInfo.widths[i], numericWidth = currentWidth; if (currentWidth === '*') { numericWidth = 150; } else if (currentWidth >= maxPerPage) { numericWidth = maxPerPage currentWidth = '*'; } else { currentWidth /= 1.57; } if (tables[currentPage] === undefined) { const body = []; tables[currentPage] = { body: body, width: numericWidth, widths: [currentWidth], datafields: [that.datafields[i]] }; mapping[i] = currentPage; continue; } const table = tables[currentPage]; if (table.width + numericWidth > maxPerPage) { currentPage++; i--; continue; } mapping[i] = currentPage; table.width += numericWidth; table.widths.push(currentWidth); table.datafields.push(that.datafields[i]); } return tables; } /** * Gets the header content when exporting to PDF. */ getPDFHeader(datafields, tables, mapping) { const that = this, headerArray = [], headerRows = that.headerRows, headerStructure = that.complexHeader ? that.complexHeader : [Object.values(that.data[0])], headers = []; let result = []; for (let i = 0; i < headerRows; i++) { const row = headerStructure[i]; for (let k = 0; k < row.length; k++) { let tableIndex = mapping[k] || 0; if (!headers[tableIndex]) { headers[tableIndex] = []; } if (!headers[tableIndex][i]) { headers[tableIndex][i] = []; } headers[tableIndex][i].push(row[k]); } } function processHeader(header, result, table) { for (let j = 0; j < headerRows; j++) { const row = header[j]; const tableRow = []; for (let k = 0; k < row.length; k++) { const currentLabel = row[k]; let colspan = 1, rowspan = 1; if ((row[k - 1] && row[k - 1] === currentLabel) || (header[j - 1] && (header[j - 1][k] === currentLabel))) { tableRow.push({}); continue; } let iterator = k + 1; while (row[iterator] && row[iterator] === row[iterator - 1]) { colspan++; iterator++; } iterator = j + 1; while (header[iterator] && header[iterator][k] === currentLabel) { rowspan++; iterator++; } const datafield = j === headerRows - 1 || rowspan + j === headerRows ? table.datafields[k] : null, entry = { text: currentLabel, colSpan: colspan, rowSpan: rowspan }; if (!datafield) { entry.alignment = 'center'; entry.style = 'header'; } else { entry.style = ['header', 'header' + datafield]; } tableRow.push(entry); } result.push(tableRow); } } for (let i = 0; i < tables.length; i++) { result = []; processHeader(headers[i], result, tables[i]); headerArray.push(result); } return headerArray; } /** * Creates group header rows when exporting to PDF. */ createGroupHeaderRow(tables, entryTemplate) { for (let i = 0; i < tables.length; i++) { const entry = Object.assign({}, entryTemplate), colspan = tables[i].datafields.length, tableRow = [entry]; entry.colSpan = colspan; tableRow.length = colspan; tableRow.fill({}, 1, colspan - 1); tables[i].body.push(tableRow); } } /** * Gets unique cell style when exporting to PDF. */ getUniqueStylePDF(entry, datafield, row) { const style = this.style; function toHex(background) { const parts = /rgba\((\d+),(\d+),(\d+)\,(\d*.\d+|\d+)\)/gi.exec(background.replace(/\s/g, '')), r = parseFloat(parts[1]).toString(16).toUpperCase(), g = parseFloat(parts[2]).toString(16).toUpperCase(), b = parseFloat(parts[3]).toString(16).toUpperCase(); return '#' + ('0').repeat(2 - r.length) + r + ('0').repeat(2 - g.length) + g + ('0').repeat(2 - b.length) + b; } if (!style || !style.columns || !style.columns[datafield]) { return; } const uniqueStyle = style.columns[datafield][row]; if (!uniqueStyle) { return; } entry.fillColor = toHex(uniqueStyle.background); entry.color = uniqueStyle.color.toLowerCase(); } /** * Sets the indentation of a PDF cell. */ setIndentation(entry, details) { if (details.j !== 0) { return; } const that = this; if (that.actualHierarchy) { const currentRecord = details.currentRecord; if (currentRecord._expanded !== undefined) { entry.marginLeft = 25 * (currentRecord._level - 1); entry.text = that.collapseChar + ' ' + details.value; } else { entry.marginLeft = 25 * (currentRecord._level - 1) + 6; } } else if (details.outlineLevel > 1) { entry.marginLeft = (details.outlineLevel - 1) * 7.5; } } /** * Exports to XLSX. */ exportToXLSX(data, fileName) { const that = this; let style = that.style; data = that.processGroupingInformation(data, true); that.data = data; that.getColumnsArray(); that.complexHeaderMergedCells = []; if (that.complexHeaderMergeInfo) { for (let cell in that.complexHeaderMergeInfo) { if (that.complexHeaderMergeInfo.hasOwnProperty(cell)) { const currentEntry = that.complexHeaderMergeInfo[cell]; if (currentEntry.from[0] === currentEntry.to[0] && currentEntry.from[1] === currentEntry.to[1]) { continue; } that.complexHeaderMergedCells.push({ from: that.columnsArray[currentEntry.from[1]] + (currentEntry.from[0] + 1), to: that.columnsArray[currentEntry.to[1]] + (currentEntry.to[0] + 1) }); } } } that.getConditionalFormatting(); if (!style) { style = that.generateDefaultStyle(data); } const sharedStrings = that.generateSharedStrings(data), sharedStringsCollection = sharedStrings.collection, sharedStringsXML = sharedStrings.xml, stylesXML = that.generateStyles(style), sheet1XML = that.groupBy ? that.generateSheet1WithGrouping(data, sharedStringsCollection) : that.generateSheet1(data, sharedStringsCollection), auxiliaryFiles = that.generateAuxiliaryFiles(), // eslint-disable-next-line zip = new JSZip(), _rels = zip.folder('_rels'), docProps = zip.folder('docProps'), xl = zip.folder('xl'), xl_rels = xl.folder('_rels'), theme = xl.folder('theme'), worksheets = xl.folder('worksheets'); _rels.file('.rels', auxiliaryFiles._relsRels); docProps.file('app.xml', auxiliaryFiles.docPropsAppXml); docProps.file('core.xml', auxiliaryFiles.docPropsCoreXml); xl_rels.file('workbook.xml.rels', auxiliaryFiles.xl_relsWorkbookXmlRels); theme.file('theme1.xml', auxiliaryFiles.xlThemeTheme1Xml); worksheets.file('sheet1.xml', sheet1XML); xl.file('sharedStrings.xml', sharedStringsXML); xl.file('styles.xml', stylesXML); xl.file('workbook.xml', auxiliaryFiles.xlWorkbookXml); zip.file('[Content_Types].xml', auxiliaryFiles.Content_TypesXml); zip.generateAsync({ type: 'blob', mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }) .then(function (content) { return that.downloadFile(content, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', fileName); }); delete that.conditionalFormattingXLSX; delete that.complexHeaderMergeInfo; delete that.defaultRowHeight; delete that.rowHeight; } /** * Processes grouping information. */ processGroupingInformation(data, xlsx) { const that = this; if (!that.groupBy) { return data; } let header; data = data.slice(0); if (that.exportHeader) { if (xlsx && that.complexHeader) { header = data.slice(0, that.complexHeader.length); data.splice(0, that.complexHeader.length); } else { header = [data[0]]; data.splice(0, 1); } } if (data.length > 1) { const getCompareFunction = function (a, knownDataType) { // gets data type of column (not necessary if the Grid provides this information) const dataType = knownDataType || typeof a; let compareFunction; switch (dataType) { case 'string': compareFunction = new Intl.Collator().compare; break; case 'number': compareFunction = function (a, b) { return a - b; }; break; case 'boolean': case 'bool': compareFunction = function (a, b) { if (a === b) { return 0; } else if (a === false) { return -1; } else { return 1; } }; break; case 'date': case 'time': case 'dateTime': if (a instanceof Date) { compareFunction = function (a, b) { return a.compare(b); }; } break; case 'object': if (a instanceof Date) { compareFunction = function (a, b) { return a.getTime() - b.getTime(); }; } break; } return compareFunction; } const sortByMultipleColumns = function (dataSource, sortColumns, directions, customSortingCallback) { if (!dataSource || !(Array.isArray(dataSource)) || dataSource.length === 0 || !sortColumns || Array.isArray(sortColumns) && sortColumns.length === 0) { return; } if (typeof sortColumns === 'string') { sortColumns = [sortColumns]; } const directionCoefficients = [], compareFunctions = []; if (directions === undefined) { directions = []; } for (let i = 0; i < sortColumns.length; i++) { if (directions[i] === undefined || directions[i] === 'asc' || directions[i] === 'ascending') { directionCoefficients[i] = 1; } else { directionCoefficients[i] = -1; } compareFunctions[i] = getCompareFunction(dataSource[0][sortColumns[i]]); } if (customSortingCallback) { customSortingCallback(dataSource, sortColumns, directions, compareFunctions); return; } dataSource.sort(function (a, b) { for (let i = 0; i < sortColumns.length; i++) { const result = compareFunctions[i](a[sortColumns[i]], b[sortColumns[i]]); if (result === 0) { if (sortColumns[i + 1]) { continue; } else if (a._index !== undefined) { // makes sorting stable return (a._index - b._index) * directionCoefficients[i]; } return 0; } return result * directionCoefficients[i]; } }); } sortByMultipleColumns(data, that.groupBy); } if (header) { data = header.concat(data); } that.getGroupLabels(data); return data; } /** * Exports to XML. */ exportToXML(data, fileName) { const datafields = this.datafields.slice(0); let xmlContent = '<?xml version="1.0" encoding="UTF-8" ?>\n<table>\n'; if (datafields.indexOf('rows') === -1) { datafields.push('rows'); } function recursion(records, indent) { let content = ''; for (let i = 0; i < records.length; i++) { const currentRecord = records[i]; content += indent + '<row>\n'; for (let j = 0; j < datafields.length; j++) { const datafield = datafields[j]; if (datafield === 'rows') { if (!currentRecord.rows) { continue; } content += `${indent} <rows>\n${recursion(currentRecord.rows, indent + ' ')}${indent} </rows>\n`; continue; } content += indent + ` <${datafield}>${currentRecord[datafield]}</${datafield}>\n`; } content += indent + '</row>\n'; } return content; } xmlContent += recursion(data, ' ') + '</table>'; return this.downloadFile(xmlContent, 'application/xml', fileName); } /** * Formats a date. */ formatDate(value, format) { var date = $.jqx.formatDate(value, format); return date; } /** * Formats a number. */ formatNumber(value, format) { var number = $.jqx.formatNumber(value, format); return number; } /** * Generates auxiliary files necessary for XLSX. */ generateAuxiliaryFiles() { // _rels\.rels const _relsRels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>`; // docProps\app.xml const docPropsAppXml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"><Application>Microsoft Excel</Application><DocSecurity>0</DocSecurity><ScaleCrop>false</ScaleCrop><HeadingPairs><vt:vector size="2" baseType="variant"><vt:variant><vt:lpstr>Worksheets</vt:lpstr></vt:variant><vt:variant><vt:i4>1</vt:i4></vt:variant></vt:vector></HeadingPairs><TitlesOfParts><vt:vector size="1" baseType="lpstr"><vt:lpstr>Sheet1</vt:lpstr></vt:vector></TitlesOfParts><Company></Company><LinksUpToDate>false</LinksUpToDate><SharedDoc>false</SharedDoc><HyperlinksChanged>false</HyperlinksChanged><AppVersion>16.0300</AppVersion></Properties>`; // docProps\core.xml const now = new Date().toISOString(), docPr