You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1463 lines
43 KiB
1463 lines
43 KiB
/*! |
|
* HTML5 export buttons for Buttons and DataTables. |
|
* 2016 SpryMedia Ltd - datatables.net/license |
|
* |
|
* FileSaver.js (1.3.3) - MIT license |
|
* Copyright © 2016 Eli Grey - http://eligrey.com |
|
*/ |
|
|
|
(function( factory ){ |
|
if ( typeof define === 'function' && define.amd ) { |
|
// AMD |
|
define( ['jquery', 'datatables.net', 'datatables.net-buttons'], function ( $ ) { |
|
return factory( $, window, document ); |
|
} ); |
|
} |
|
else if ( typeof exports === 'object' ) { |
|
// CommonJS |
|
module.exports = function (root, $, jszip, pdfmake) { |
|
if ( ! root ) { |
|
root = window; |
|
} |
|
|
|
if ( ! $ || ! $.fn.dataTable ) { |
|
$ = require('datatables.net')(root, $).$; |
|
} |
|
|
|
if ( ! $.fn.dataTable.Buttons ) { |
|
require('datatables.net-buttons')(root, $); |
|
} |
|
|
|
return factory( $, root, root.document, jszip, pdfmake ); |
|
}; |
|
} |
|
else { |
|
// Browser |
|
factory( jQuery, window, document ); |
|
} |
|
}(function( $, window, document, jszip, pdfmake, undefined ) { |
|
'use strict'; |
|
var DataTable = $.fn.dataTable; |
|
|
|
// Allow the constructor to pass in JSZip and PDFMake from external requires. |
|
// Otherwise, use globally defined variables, if they are available. |
|
function _jsZip () { |
|
return jszip || window.JSZip; |
|
} |
|
function _pdfMake () { |
|
return pdfmake || window.pdfMake; |
|
} |
|
|
|
DataTable.Buttons.pdfMake = function (_) { |
|
if ( ! _ ) { |
|
return _pdfMake(); |
|
} |
|
pdfmake = _; |
|
} |
|
|
|
DataTable.Buttons.jszip = function (_) { |
|
if ( ! _ ) { |
|
return _jsZip(); |
|
} |
|
jszip = _; |
|
} |
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
* FileSaver.js dependency |
|
*/ |
|
|
|
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ |
|
|
|
var _saveAs = (function(view) { |
|
"use strict"; |
|
// IE <10 is explicitly unsupported |
|
if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { |
|
return; |
|
} |
|
var |
|
doc = view.document |
|
// only get URL when necessary in case Blob.js hasn't overridden it yet |
|
, get_URL = function() { |
|
return view.URL || view.webkitURL || view; |
|
} |
|
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") |
|
, can_use_save_link = "download" in save_link |
|
, click = function(node) { |
|
var event = new MouseEvent("click"); |
|
node.dispatchEvent(event); |
|
} |
|
, is_safari = /constructor/i.test(view.HTMLElement) || view.safari |
|
, is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent) |
|
, throw_outside = function(ex) { |
|
(view.setImmediate || view.setTimeout)(function() { |
|
throw ex; |
|
}, 0); |
|
} |
|
, force_saveable_type = "application/octet-stream" |
|
// the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to |
|
, arbitrary_revoke_timeout = 1000 * 40 // in ms |
|
, revoke = function(file) { |
|
var revoker = function() { |
|
if (typeof file === "string") { // file is an object URL |
|
get_URL().revokeObjectURL(file); |
|
} else { // file is a File |
|
file.remove(); |
|
} |
|
}; |
|
setTimeout(revoker, arbitrary_revoke_timeout); |
|
} |
|
, dispatch = function(filesaver, event_types, event) { |
|
event_types = [].concat(event_types); |
|
var i = event_types.length; |
|
while (i--) { |
|
var listener = filesaver["on" + event_types[i]]; |
|
if (typeof listener === "function") { |
|
try { |
|
listener.call(filesaver, event || filesaver); |
|
} catch (ex) { |
|
throw_outside(ex); |
|
} |
|
} |
|
} |
|
} |
|
, auto_bom = function(blob) { |
|
// prepend BOM for UTF-8 XML and text/* types (including HTML) |
|
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF |
|
if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { |
|
return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type}); |
|
} |
|
return blob; |
|
} |
|
, FileSaver = function(blob, name, no_auto_bom) { |
|
if (!no_auto_bom) { |
|
blob = auto_bom(blob); |
|
} |
|
// First try a.download, then web filesystem, then object URLs |
|
var |
|
filesaver = this |
|
, type = blob.type |
|
, force = type === force_saveable_type |
|
, object_url |
|
, dispatch_all = function() { |
|
dispatch(filesaver, "writestart progress write writeend".split(" ")); |
|
} |
|
// on any filesys errors revert to saving with object URLs |
|
, fs_error = function() { |
|
if ((is_chrome_ios || (force && is_safari)) && view.FileReader) { |
|
// Safari doesn't allow downloading of blob urls |
|
var reader = new FileReader(); |
|
reader.onloadend = function() { |
|
var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;'); |
|
var popup = view.open(url, '_blank'); |
|
if(!popup) view.location.href = url; |
|
url=undefined; // release reference before dispatching |
|
filesaver.readyState = filesaver.DONE; |
|
dispatch_all(); |
|
}; |
|
reader.readAsDataURL(blob); |
|
filesaver.readyState = filesaver.INIT; |
|
return; |
|
} |
|
// don't create more object URLs than needed |
|
if (!object_url) { |
|
object_url = get_URL().createObjectURL(blob); |
|
} |
|
if (force) { |
|
view.location.href = object_url; |
|
} else { |
|
var opened = view.open(object_url, "_blank"); |
|
if (!opened) { |
|
// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html |
|
view.location.href = object_url; |
|
} |
|
} |
|
filesaver.readyState = filesaver.DONE; |
|
dispatch_all(); |
|
revoke(object_url); |
|
} |
|
; |
|
filesaver.readyState = filesaver.INIT; |
|
|
|
if (can_use_save_link) { |
|
object_url = get_URL().createObjectURL(blob); |
|
setTimeout(function() { |
|
save_link.href = object_url; |
|
save_link.download = name; |
|
click(save_link); |
|
dispatch_all(); |
|
revoke(object_url); |
|
filesaver.readyState = filesaver.DONE; |
|
}); |
|
return; |
|
} |
|
|
|
fs_error(); |
|
} |
|
, FS_proto = FileSaver.prototype |
|
, saveAs = function(blob, name, no_auto_bom) { |
|
return new FileSaver(blob, name || blob.name || "download", no_auto_bom); |
|
} |
|
; |
|
// IE 10+ (native saveAs) |
|
if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { |
|
return function(blob, name, no_auto_bom) { |
|
name = name || blob.name || "download"; |
|
|
|
if (!no_auto_bom) { |
|
blob = auto_bom(blob); |
|
} |
|
return navigator.msSaveOrOpenBlob(blob, name); |
|
}; |
|
} |
|
|
|
FS_proto.abort = function(){}; |
|
FS_proto.readyState = FS_proto.INIT = 0; |
|
FS_proto.WRITING = 1; |
|
FS_proto.DONE = 2; |
|
|
|
FS_proto.error = |
|
FS_proto.onwritestart = |
|
FS_proto.onprogress = |
|
FS_proto.onwrite = |
|
FS_proto.onabort = |
|
FS_proto.onerror = |
|
FS_proto.onwriteend = |
|
null; |
|
|
|
return saveAs; |
|
}( |
|
typeof self !== "undefined" && self |
|
|| typeof window !== "undefined" && window |
|
|| this.content |
|
)); |
|
|
|
|
|
// Expose file saver on the DataTables API. Can't attach to `DataTables.Buttons` |
|
// since this file can be loaded before Button's core! |
|
DataTable.fileSave = _saveAs; |
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
* Local (private) functions |
|
*/ |
|
|
|
/** |
|
* Get the sheet name for Excel exports. |
|
* |
|
* @param {object} config Button configuration |
|
*/ |
|
var _sheetname = function ( config ) |
|
{ |
|
var sheetName = 'Sheet1'; |
|
|
|
if ( config.sheetName ) { |
|
sheetName = config.sheetName.replace(/[\[\]\*\/\\\?\:]/g, ''); |
|
} |
|
|
|
return sheetName; |
|
}; |
|
|
|
/** |
|
* Get the newline character(s) |
|
* |
|
* @param {object} config Button configuration |
|
* @return {string} Newline character |
|
*/ |
|
var _newLine = function ( config ) |
|
{ |
|
return config.newline ? |
|
config.newline : |
|
navigator.userAgent.match(/Windows/) ? |
|
'\r\n' : |
|
'\n'; |
|
}; |
|
|
|
/** |
|
* Combine the data from the `buttons.exportData` method into a string that |
|
* will be used in the export file. |
|
* |
|
* @param {DataTable.Api} dt DataTables API instance |
|
* @param {object} config Button configuration |
|
* @return {object} The data to export |
|
*/ |
|
var _exportData = function ( dt, config ) |
|
{ |
|
var newLine = _newLine( config ); |
|
var data = dt.buttons.exportData( config.exportOptions ); |
|
var boundary = config.fieldBoundary; |
|
var separator = config.fieldSeparator; |
|
var reBoundary = new RegExp( boundary, 'g' ); |
|
var escapeChar = config.escapeChar !== undefined ? |
|
config.escapeChar : |
|
'\\'; |
|
var join = function ( a ) { |
|
var s = ''; |
|
|
|
// If there is a field boundary, then we might need to escape it in |
|
// the source data |
|
for ( var i=0, ien=a.length ; i<ien ; i++ ) { |
|
if ( i > 0 ) { |
|
s += separator; |
|
} |
|
|
|
s += boundary ? |
|
boundary + ('' + a[i]).replace( reBoundary, escapeChar+boundary ) + boundary : |
|
a[i]; |
|
} |
|
|
|
return s; |
|
}; |
|
|
|
var header = config.header ? join( data.header )+newLine : ''; |
|
var footer = config.footer && data.footer ? newLine+join( data.footer ) : ''; |
|
var body = []; |
|
|
|
for ( var i=0, ien=data.body.length ; i<ien ; i++ ) { |
|
body.push( join( data.body[i] ) ); |
|
} |
|
|
|
return { |
|
str: header + body.join( newLine ) + footer, |
|
rows: body.length |
|
}; |
|
}; |
|
|
|
/** |
|
* Older versions of Safari (prior to tech preview 18) don't support the |
|
* download option required. |
|
* |
|
* @return {Boolean} `true` if old Safari |
|
*/ |
|
var _isDuffSafari = function () |
|
{ |
|
var safari = navigator.userAgent.indexOf('Safari') !== -1 && |
|
navigator.userAgent.indexOf('Chrome') === -1 && |
|
navigator.userAgent.indexOf('Opera') === -1; |
|
|
|
if ( ! safari ) { |
|
return false; |
|
} |
|
|
|
var version = navigator.userAgent.match( /AppleWebKit\/(\d+\.\d+)/ ); |
|
if ( version && version.length > 1 && version[1]*1 < 603.1 ) { |
|
return true; |
|
} |
|
|
|
return false; |
|
}; |
|
|
|
/** |
|
* Convert from numeric position to letter for column names in Excel |
|
* @param {int} n Column number |
|
* @return {string} Column letter(s) name |
|
*/ |
|
function createCellPos( n ){ |
|
var ordA = 'A'.charCodeAt(0); |
|
var ordZ = 'Z'.charCodeAt(0); |
|
var len = ordZ - ordA + 1; |
|
var s = ""; |
|
|
|
while( n >= 0 ) { |
|
s = String.fromCharCode(n % len + ordA) + s; |
|
n = Math.floor(n / len) - 1; |
|
} |
|
|
|
return s; |
|
} |
|
|
|
try { |
|
var _serialiser = new XMLSerializer(); |
|
var _ieExcel; |
|
} |
|
catch (t) {} |
|
|
|
/** |
|
* Recursively add XML files from an object's structure to a ZIP file. This |
|
* allows the XSLX file to be easily defined with an object's structure matching |
|
* the files structure. |
|
* |
|
* @param {JSZip} zip ZIP package |
|
* @param {object} obj Object to add (recursive) |
|
*/ |
|
function _addToZip( zip, obj ) { |
|
if ( _ieExcel === undefined ) { |
|
// Detect if we are dealing with IE's _awful_ serialiser by seeing if it |
|
// drop attributes |
|
_ieExcel = _serialiser |
|
.serializeToString( |
|
( new window.DOMParser() ).parseFromString( excelStrings['xl/worksheets/sheet1.xml'], 'text/xml' ) |
|
) |
|
.indexOf( 'xmlns:r' ) === -1; |
|
} |
|
|
|
$.each( obj, function ( name, val ) { |
|
if ( $.isPlainObject( val ) ) { |
|
var newDir = zip.folder( name ); |
|
_addToZip( newDir, val ); |
|
} |
|
else { |
|
if ( _ieExcel ) { |
|
// IE's XML serialiser will drop some name space attributes from |
|
// from the root node, so we need to save them. Do this by |
|
// replacing the namespace nodes with a regular attribute that |
|
// we convert back when serialised. Edge does not have this |
|
// issue |
|
var worksheet = val.childNodes[0]; |
|
var i, ien; |
|
var attrs = []; |
|
|
|
for ( i=worksheet.attributes.length-1 ; i>=0 ; i-- ) { |
|
var attrName = worksheet.attributes[i].nodeName; |
|
var attrValue = worksheet.attributes[i].nodeValue; |
|
|
|
if ( attrName.indexOf( ':' ) !== -1 ) { |
|
attrs.push( { name: attrName, value: attrValue } ); |
|
|
|
worksheet.removeAttribute( attrName ); |
|
} |
|
} |
|
|
|
for ( i=0, ien=attrs.length ; i<ien ; i++ ) { |
|
var attr = val.createAttribute( attrs[i].name.replace( ':', '_dt_b_namespace_token_' ) ); |
|
attr.value = attrs[i].value; |
|
worksheet.setAttributeNode( attr ); |
|
} |
|
} |
|
|
|
var str = _serialiser.serializeToString(val); |
|
|
|
// Fix IE's XML |
|
if ( _ieExcel ) { |
|
// IE doesn't include the XML declaration |
|
if ( str.indexOf( '<?xml' ) === -1 ) { |
|
str = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+str; |
|
} |
|
|
|
// Return namespace attributes to being as such |
|
str = str.replace( /_dt_b_namespace_token_/g, ':' ); |
|
|
|
// Remove testing name space that IE puts into the space preserve attr |
|
str = str.replace( /xmlns:NS[\d]+="" NS[\d]+:/g, '' ); |
|
} |
|
|
|
// Safari, IE and Edge will put empty name space attributes onto |
|
// various elements making them useless. This strips them out |
|
str = str.replace( /<([^<>]*?) xmlns=""([^<>]*?)>/g, '<$1 $2>' ); |
|
|
|
zip.file( name, str ); |
|
} |
|
} ); |
|
} |
|
|
|
/** |
|
* Create an XML node and add any children, attributes, etc without needing to |
|
* be verbose in the DOM. |
|
* |
|
* @param {object} doc XML document |
|
* @param {string} nodeName Node name |
|
* @param {object} opts Options - can be `attr` (attributes), `children` |
|
* (child nodes) and `text` (text content) |
|
* @return {node} Created node |
|
*/ |
|
function _createNode( doc, nodeName, opts ) { |
|
var tempNode = doc.createElement( nodeName ); |
|
|
|
if ( opts ) { |
|
if ( opts.attr ) { |
|
$(tempNode).attr( opts.attr ); |
|
} |
|
|
|
if ( opts.children ) { |
|
$.each( opts.children, function ( key, value ) { |
|
tempNode.appendChild( value ); |
|
} ); |
|
} |
|
|
|
if ( opts.text !== null && opts.text !== undefined ) { |
|
tempNode.appendChild( doc.createTextNode( opts.text ) ); |
|
} |
|
} |
|
|
|
return tempNode; |
|
} |
|
|
|
/** |
|
* Get the width for an Excel column based on the contents of that column |
|
* @param {object} data Data for export |
|
* @param {int} col Column index |
|
* @return {int} Column width |
|
*/ |
|
function _excelColWidth( data, col ) { |
|
var max = data.header[col].length; |
|
var len, lineSplit, str; |
|
|
|
if ( data.footer && data.footer[col].length > max ) { |
|
max = data.footer[col].length; |
|
} |
|
|
|
for ( var i=0, ien=data.body.length ; i<ien ; i++ ) { |
|
var point = data.body[i][col]; |
|
str = point !== null && point !== undefined ? |
|
point.toString() : |
|
''; |
|
|
|
// If there is a newline character, workout the width of the column |
|
// based on the longest line in the string |
|
if ( str.indexOf('\n') !== -1 ) { |
|
lineSplit = str.split('\n'); |
|
lineSplit.sort( function (a, b) { |
|
return b.length - a.length; |
|
} ); |
|
|
|
len = lineSplit[0].length; |
|
} |
|
else { |
|
len = str.length; |
|
} |
|
|
|
if ( len > max ) { |
|
max = len; |
|
} |
|
|
|
// Max width rather than having potentially massive column widths |
|
if ( max > 40 ) { |
|
return 54; // 40 * 1.35 |
|
} |
|
} |
|
|
|
max *= 1.35; |
|
|
|
// And a min width |
|
return max > 6 ? max : 6; |
|
} |
|
|
|
// Excel - Pre-defined strings to build a basic XLSX file |
|
var excelStrings = { |
|
"_rels/.rels": |
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+ |
|
'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'+ |
|
'<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>'+ |
|
'</Relationships>', |
|
|
|
"xl/_rels/workbook.xml.rels": |
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+ |
|
'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'+ |
|
'<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>'+ |
|
'<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>'+ |
|
'</Relationships>', |
|
|
|
"[Content_Types].xml": |
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+ |
|
'<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">'+ |
|
'<Default Extension="xml" ContentType="application/xml" />'+ |
|
'<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" />'+ |
|
'<Default Extension="jpeg" ContentType="image/jpeg" />'+ |
|
'<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" />'+ |
|
'<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" />'+ |
|
'<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" />'+ |
|
'</Types>', |
|
|
|
"xl/workbook.xml": |
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+ |
|
'<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'+ |
|
'<fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="24816"/>'+ |
|
'<workbookPr showInkAnnotation="0" autoCompressPictures="0"/>'+ |
|
'<bookViews>'+ |
|
'<workbookView xWindow="0" yWindow="0" windowWidth="25600" windowHeight="19020" tabRatio="500"/>'+ |
|
'</bookViews>'+ |
|
'<sheets>'+ |
|
'<sheet name="Sheet1" sheetId="1" r:id="rId1"/>'+ |
|
'</sheets>'+ |
|
'<definedNames/>'+ |
|
'</workbook>', |
|
|
|
"xl/worksheets/sheet1.xml": |
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+ |
|
'<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">'+ |
|
'<sheetData/>'+ |
|
'<mergeCells count="0"/>'+ |
|
'</worksheet>', |
|
|
|
"xl/styles.xml": |
|
'<?xml version="1.0" encoding="UTF-8"?>'+ |
|
'<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">'+ |
|
'<numFmts count="6">'+ |
|
'<numFmt numFmtId="164" formatCode="#,##0.00_-\ [$$-45C]"/>'+ |
|
'<numFmt numFmtId="165" formatCode=""£"#,##0.00"/>'+ |
|
'<numFmt numFmtId="166" formatCode="[$€-2]\ #,##0.00"/>'+ |
|
'<numFmt numFmtId="167" formatCode="0.0%"/>'+ |
|
'<numFmt numFmtId="168" formatCode="#,##0;(#,##0)"/>'+ |
|
'<numFmt numFmtId="169" formatCode="#,##0.00;(#,##0.00)"/>'+ |
|
'</numFmts>'+ |
|
'<fonts count="5" x14ac:knownFonts="1">'+ |
|
'<font>'+ |
|
'<sz val="11" />'+ |
|
'<name val="Calibri" />'+ |
|
'</font>'+ |
|
'<font>'+ |
|
'<sz val="11" />'+ |
|
'<name val="Calibri" />'+ |
|
'<color rgb="FFFFFFFF" />'+ |
|
'</font>'+ |
|
'<font>'+ |
|
'<sz val="11" />'+ |
|
'<name val="Calibri" />'+ |
|
'<b />'+ |
|
'</font>'+ |
|
'<font>'+ |
|
'<sz val="11" />'+ |
|
'<name val="Calibri" />'+ |
|
'<i />'+ |
|
'</font>'+ |
|
'<font>'+ |
|
'<sz val="11" />'+ |
|
'<name val="Calibri" />'+ |
|
'<u />'+ |
|
'</font>'+ |
|
'</fonts>'+ |
|
'<fills count="6">'+ |
|
'<fill>'+ |
|
'<patternFill patternType="none" />'+ |
|
'</fill>'+ |
|
'<fill>'+ // Excel appears to use this as a dotted background regardless of values but |
|
'<patternFill patternType="none" />'+ // to be valid to the schema, use a patternFill |
|
'</fill>'+ |
|
'<fill>'+ |
|
'<patternFill patternType="solid">'+ |
|
'<fgColor rgb="FFD9D9D9" />'+ |
|
'<bgColor indexed="64" />'+ |
|
'</patternFill>'+ |
|
'</fill>'+ |
|
'<fill>'+ |
|
'<patternFill patternType="solid">'+ |
|
'<fgColor rgb="FFD99795" />'+ |
|
'<bgColor indexed="64" />'+ |
|
'</patternFill>'+ |
|
'</fill>'+ |
|
'<fill>'+ |
|
'<patternFill patternType="solid">'+ |
|
'<fgColor rgb="ffc6efce" />'+ |
|
'<bgColor indexed="64" />'+ |
|
'</patternFill>'+ |
|
'</fill>'+ |
|
'<fill>'+ |
|
'<patternFill patternType="solid">'+ |
|
'<fgColor rgb="ffc6cfef" />'+ |
|
'<bgColor indexed="64" />'+ |
|
'</patternFill>'+ |
|
'</fill>'+ |
|
'</fills>'+ |
|
'<borders count="2">'+ |
|
'<border>'+ |
|
'<left />'+ |
|
'<right />'+ |
|
'<top />'+ |
|
'<bottom />'+ |
|
'<diagonal />'+ |
|
'</border>'+ |
|
'<border diagonalUp="false" diagonalDown="false">'+ |
|
'<left style="thin">'+ |
|
'<color auto="1" />'+ |
|
'</left>'+ |
|
'<right style="thin">'+ |
|
'<color auto="1" />'+ |
|
'</right>'+ |
|
'<top style="thin">'+ |
|
'<color auto="1" />'+ |
|
'</top>'+ |
|
'<bottom style="thin">'+ |
|
'<color auto="1" />'+ |
|
'</bottom>'+ |
|
'<diagonal />'+ |
|
'</border>'+ |
|
'</borders>'+ |
|
'<cellStyleXfs count="1">'+ |
|
'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" />'+ |
|
'</cellStyleXfs>'+ |
|
'<cellXfs count="68">'+ |
|
'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="1" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="2" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="3" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="4" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="1" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="2" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="3" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="4" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="1" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="2" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="3" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="4" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="1" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="2" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="3" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="4" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="1" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="2" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="3" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="4" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="1" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="2" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="3" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="4" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="1" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="2" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="3" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="4" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="1" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="2" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="3" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="4" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="1" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="2" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="3" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="4" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="1" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="2" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="3" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="4" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+ |
|
'<alignment horizontal="left"/>'+ |
|
'</xf>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+ |
|
'<alignment horizontal="center"/>'+ |
|
'</xf>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+ |
|
'<alignment horizontal="right"/>'+ |
|
'</xf>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+ |
|
'<alignment horizontal="fill"/>'+ |
|
'</xf>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+ |
|
'<alignment textRotation="90"/>'+ |
|
'</xf>'+ |
|
'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+ |
|
'<alignment wrapText="1"/>'+ |
|
'</xf>'+ |
|
'<xf numFmtId="9" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+ |
|
'<xf numFmtId="164" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+ |
|
'<xf numFmtId="165" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+ |
|
'<xf numFmtId="166" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+ |
|
'<xf numFmtId="167" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+ |
|
'<xf numFmtId="168" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+ |
|
'<xf numFmtId="169" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+ |
|
'<xf numFmtId="3" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+ |
|
'<xf numFmtId="4" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+ |
|
'<xf numFmtId="1" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+ |
|
'<xf numFmtId="2" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+ |
|
'<xf numFmtId="14" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+ |
|
'</cellXfs>'+ |
|
'<cellStyles count="1">'+ |
|
'<cellStyle name="Normal" xfId="0" builtinId="0" />'+ |
|
'</cellStyles>'+ |
|
'<dxfs count="0" />'+ |
|
'<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4" />'+ |
|
'</styleSheet>' |
|
}; |
|
// Note we could use 3 `for` loops for the styles, but when gzipped there is |
|
// virtually no difference in size, since the above can be easily compressed |
|
|
|
// Pattern matching for special number formats. Perhaps this should be exposed |
|
// via an API in future? |
|
// Ref: section 3.8.30 - built in formatters in open spreadsheet |
|
// https://www.ecma-international.org/news/TC45_current_work/Office%20Open%20XML%20Part%204%20-%20Markup%20Language%20Reference.pdf |
|
var _excelSpecials = [ |
|
{ match: /^\-?\d+\.\d%$/, style: 60, fmt: function (d) { return d/100; } }, // Precent with d.p. |
|
{ match: /^\-?\d+\.?\d*%$/, style: 56, fmt: function (d) { return d/100; } }, // Percent |
|
{ match: /^\-?\$[\d,]+.?\d*$/, style: 57 }, // Dollars |
|
{ match: /^\-?£[\d,]+.?\d*$/, style: 58 }, // Pounds |
|
{ match: /^\-?€[\d,]+.?\d*$/, style: 59 }, // Euros |
|
{ match: /^\-?\d+$/, style: 65 }, // Numbers without thousand separators |
|
{ match: /^\-?\d+\.\d{2}$/, style: 66 }, // Numbers 2 d.p. without thousands separators |
|
{ match: /^\([\d,]+\)$/, style: 61, fmt: function (d) { return -1 * d.replace(/[\(\)]/g, ''); } }, // Negative numbers indicated by brackets |
|
{ match: /^\([\d,]+\.\d{2}\)$/, style: 62, fmt: function (d) { return -1 * d.replace(/[\(\)]/g, ''); } }, // Negative numbers indicated by brackets - 2d.p. |
|
{ match: /^\-?[\d,]+$/, style: 63 }, // Numbers with thousand separators |
|
{ match: /^\-?[\d,]+\.\d{2}$/, style: 64 }, |
|
{ match: /^[\d]{4}\-[\d]{2}\-[\d]{2}$/, style: 67, fmt: function (d) {return Math.round(25569 + (Date.parse(d) / (86400 * 1000)));}} //Date yyyy-mm-dd |
|
]; |
|
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
* Buttons |
|
*/ |
|
|
|
// |
|
// Copy to clipboard |
|
// |
|
DataTable.ext.buttons.copyHtml5 = { |
|
className: 'buttons-copy buttons-html5', |
|
|
|
text: function ( dt ) { |
|
return dt.i18n( 'buttons.copy', 'Copy' ); |
|
}, |
|
|
|
action: function ( e, dt, button, config ) { |
|
this.processing( true ); |
|
|
|
var that = this; |
|
var exportData = _exportData( dt, config ); |
|
var info = dt.buttons.exportInfo( config ); |
|
var newline = _newLine(config); |
|
var output = exportData.str; |
|
var hiddenDiv = $('<div/>') |
|
.css( { |
|
height: 1, |
|
width: 1, |
|
overflow: 'hidden', |
|
position: 'fixed', |
|
top: 0, |
|
left: 0 |
|
} ); |
|
|
|
if ( info.title ) { |
|
output = info.title + newline + newline + output; |
|
} |
|
|
|
if ( info.messageTop ) { |
|
output = info.messageTop + newline + newline + output; |
|
} |
|
|
|
if ( info.messageBottom ) { |
|
output = output + newline + newline + info.messageBottom; |
|
} |
|
|
|
if ( config.customize ) { |
|
output = config.customize( output, config, dt ); |
|
} |
|
|
|
var textarea = $('<textarea readonly/>') |
|
.val( output ) |
|
.appendTo( hiddenDiv ); |
|
|
|
// For browsers that support the copy execCommand, try to use it |
|
if ( document.queryCommandSupported('copy') ) { |
|
hiddenDiv.appendTo( dt.table().container() ); |
|
textarea[0].focus(); |
|
textarea[0].select(); |
|
|
|
try { |
|
var successful = document.execCommand( 'copy' ); |
|
hiddenDiv.remove(); |
|
|
|
if (successful) { |
|
dt.buttons.info( |
|
dt.i18n( 'buttons.copyTitle', 'Copy to clipboard' ), |
|
dt.i18n( 'buttons.copySuccess', { |
|
1: 'Copied one row to clipboard', |
|
_: 'Copied %d rows to clipboard' |
|
}, exportData.rows ), |
|
2000 |
|
); |
|
|
|
this.processing( false ); |
|
return; |
|
} |
|
} |
|
catch (t) {} |
|
} |
|
|
|
// Otherwise we show the text box and instruct the user to use it |
|
var message = $('<span>'+dt.i18n( 'buttons.copyKeys', |
|
'Press <i>ctrl</i> or <i>\u2318</i> + <i>C</i> to copy the table data<br>to your system clipboard.<br><br>'+ |
|
'To cancel, click this message or press escape.' )+'</span>' |
|
) |
|
.append( hiddenDiv ); |
|
|
|
dt.buttons.info( dt.i18n( 'buttons.copyTitle', 'Copy to clipboard' ), message, 0 ); |
|
|
|
// Select the text so when the user activates their system clipboard |
|
// it will copy that text |
|
textarea[0].focus(); |
|
textarea[0].select(); |
|
|
|
// Event to hide the message when the user is done |
|
var container = $(message).closest('.dt-button-info'); |
|
var close = function () { |
|
container.off( 'click.buttons-copy' ); |
|
$(document).off( '.buttons-copy' ); |
|
dt.buttons.info( false ); |
|
}; |
|
|
|
container.on( 'click.buttons-copy', close ); |
|
$(document) |
|
.on( 'keydown.buttons-copy', function (e) { |
|
if ( e.keyCode === 27 ) { // esc |
|
close(); |
|
that.processing( false ); |
|
} |
|
} ) |
|
.on( 'copy.buttons-copy cut.buttons-copy', function () { |
|
close(); |
|
that.processing( false ); |
|
} ); |
|
}, |
|
|
|
exportOptions: {}, |
|
|
|
fieldSeparator: '\t', |
|
|
|
fieldBoundary: '', |
|
|
|
header: true, |
|
|
|
footer: false, |
|
|
|
title: '*', |
|
|
|
messageTop: '*', |
|
|
|
messageBottom: '*' |
|
}; |
|
|
|
// |
|
// CSV export |
|
// |
|
DataTable.ext.buttons.csvHtml5 = { |
|
bom: false, |
|
|
|
className: 'buttons-csv buttons-html5', |
|
|
|
available: function () { |
|
return window.FileReader !== undefined && window.Blob; |
|
}, |
|
|
|
text: function ( dt ) { |
|
return dt.i18n( 'buttons.csv', 'CSV' ); |
|
}, |
|
|
|
action: function ( e, dt, button, config ) { |
|
this.processing( true ); |
|
|
|
// Set the text |
|
var output = _exportData( dt, config ).str; |
|
var info = dt.buttons.exportInfo(config); |
|
var charset = config.charset; |
|
|
|
if ( config.customize ) { |
|
output = config.customize( output, config, dt ); |
|
} |
|
|
|
if ( charset !== false ) { |
|
if ( ! charset ) { |
|
charset = document.characterSet || document.charset; |
|
} |
|
|
|
if ( charset ) { |
|
charset = ';charset='+charset; |
|
} |
|
} |
|
else { |
|
charset = ''; |
|
} |
|
|
|
if ( config.bom ) { |
|
output = '\ufeff' + output; |
|
} |
|
|
|
_saveAs( |
|
new Blob( [output], {type: 'text/csv'+charset} ), |
|
info.filename, |
|
true |
|
); |
|
|
|
this.processing( false ); |
|
}, |
|
|
|
filename: '*', |
|
|
|
extension: '.csv', |
|
|
|
exportOptions: {}, |
|
|
|
fieldSeparator: ',', |
|
|
|
fieldBoundary: '"', |
|
|
|
escapeChar: '"', |
|
|
|
charset: null, |
|
|
|
header: true, |
|
|
|
footer: false |
|
}; |
|
|
|
// |
|
// Excel (xlsx) export |
|
// |
|
DataTable.ext.buttons.excelHtml5 = { |
|
className: 'buttons-excel buttons-html5', |
|
|
|
available: function () { |
|
return window.FileReader !== undefined && _jsZip() !== undefined && ! _isDuffSafari() && _serialiser; |
|
}, |
|
|
|
text: function ( dt ) { |
|
return dt.i18n( 'buttons.excel', 'Excel' ); |
|
}, |
|
|
|
action: function ( e, dt, button, config ) { |
|
this.processing( true ); |
|
|
|
var that = this; |
|
var rowPos = 0; |
|
var dataStartRow, dataEndRow; |
|
var getXml = function ( type ) { |
|
var str = excelStrings[ type ]; |
|
|
|
//str = str.replace( /xmlns:/g, 'xmlns_' ).replace( /mc:/g, 'mc_' ); |
|
|
|
return $.parseXML( str ); |
|
}; |
|
var rels = getXml('xl/worksheets/sheet1.xml'); |
|
var relsGet = rels.getElementsByTagName( "sheetData" )[0]; |
|
|
|
var xlsx = { |
|
_rels: { |
|
".rels": getXml('_rels/.rels') |
|
}, |
|
xl: { |
|
_rels: { |
|
"workbook.xml.rels": getXml('xl/_rels/workbook.xml.rels') |
|
}, |
|
"workbook.xml": getXml('xl/workbook.xml'), |
|
"styles.xml": getXml('xl/styles.xml'), |
|
"worksheets": { |
|
"sheet1.xml": rels |
|
} |
|
|
|
}, |
|
"[Content_Types].xml": getXml('[Content_Types].xml') |
|
}; |
|
|
|
var data = dt.buttons.exportData( config.exportOptions ); |
|
var currentRow, rowNode; |
|
var addRow = function ( row ) { |
|
currentRow = rowPos+1; |
|
rowNode = _createNode( rels, "row", { attr: {r:currentRow} } ); |
|
|
|
for ( var i=0, ien=row.length ; i<ien ; i++ ) { |
|
// Concat both the Cell Columns as a letter and the Row of the cell. |
|
var cellId = createCellPos(i) + '' + currentRow; |
|
var cell = null; |
|
|
|
// For null, undefined of blank cell, continue so it doesn't create the _createNode |
|
if ( row[i] === null || row[i] === undefined || row[i] === '' ) { |
|
if ( config.createEmptyCells === true ) { |
|
row[i] = ''; |
|
} |
|
else { |
|
continue; |
|
} |
|
} |
|
|
|
var originalContent = row[i]; |
|
row[i] = typeof row[i].trim === 'function' |
|
? row[i].trim() |
|
: row[i]; |
|
|
|
// Special number formatting options |
|
for ( var j=0, jen=_excelSpecials.length ; j<jen ; j++ ) { |
|
var special = _excelSpecials[j]; |
|
|
|
// TODO Need to provide the ability for the specials to say |
|
// if they are returning a string, since at the moment it is |
|
// assumed to be a number |
|
if ( row[i].match && ! row[i].match(/^0\d+/) && row[i].match( special.match ) ) { |
|
var val = row[i].replace(/[^\d\.\-]/g, ''); |
|
|
|
if ( special.fmt ) { |
|
val = special.fmt( val ); |
|
} |
|
|
|
cell = _createNode( rels, 'c', { |
|
attr: { |
|
r: cellId, |
|
s: special.style |
|
}, |
|
children: [ |
|
_createNode( rels, 'v', { text: val } ) |
|
] |
|
} ); |
|
|
|
break; |
|
} |
|
} |
|
|
|
if ( ! cell ) { |
|
if ( typeof row[i] === 'number' || ( |
|
row[i].match && |
|
row[i].match(/^-?\d+(\.\d+)?$/) && |
|
! row[i].match(/^0\d+/) ) |
|
) { |
|
// Detect numbers - don't match numbers with leading zeros |
|
// or a negative anywhere but the start |
|
cell = _createNode( rels, 'c', { |
|
attr: { |
|
t: 'n', |
|
r: cellId |
|
}, |
|
children: [ |
|
_createNode( rels, 'v', { text: row[i] } ) |
|
] |
|
} ); |
|
} |
|
else { |
|
// String output - replace non standard characters for text output |
|
var text = ! originalContent.replace ? |
|
originalContent : |
|
originalContent.replace(/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F-\x9F]/g, ''); |
|
|
|
cell = _createNode( rels, 'c', { |
|
attr: { |
|
t: 'inlineStr', |
|
r: cellId |
|
}, |
|
children:{ |
|
row: _createNode( rels, 'is', { |
|
children: { |
|
row: _createNode( rels, 't', { |
|
text: text, |
|
attr: { |
|
'xml:space': 'preserve' |
|
} |
|
} ) |
|
} |
|
} ) |
|
} |
|
} ); |
|
} |
|
} |
|
|
|
rowNode.appendChild( cell ); |
|
} |
|
|
|
relsGet.appendChild(rowNode); |
|
rowPos++; |
|
}; |
|
|
|
if ( config.customizeData ) { |
|
config.customizeData( data ); |
|
} |
|
|
|
var mergeCells = function ( row, colspan ) { |
|
var mergeCells = $('mergeCells', rels); |
|
|
|
mergeCells[0].appendChild( _createNode( rels, 'mergeCell', { |
|
attr: { |
|
ref: 'A'+row+':'+createCellPos(colspan)+row |
|
} |
|
} ) ); |
|
mergeCells.attr( 'count', parseFloat(mergeCells.attr( 'count' ))+1 ); |
|
$('row:eq('+(row-1)+') c', rels).attr( 's', '51' ); // centre |
|
}; |
|
|
|
// Title and top messages |
|
var exportInfo = dt.buttons.exportInfo( config ); |
|
if ( exportInfo.title ) { |
|
addRow( [exportInfo.title], rowPos ); |
|
mergeCells( rowPos, data.header.length-1 ); |
|
} |
|
|
|
if ( exportInfo.messageTop ) { |
|
addRow( [exportInfo.messageTop], rowPos ); |
|
mergeCells( rowPos, data.header.length-1 ); |
|
} |
|
|
|
|
|
// Table itself |
|
if ( config.header ) { |
|
addRow( data.header, rowPos ); |
|
$('row:last c', rels).attr( 's', '2' ); // bold |
|
} |
|
|
|
dataStartRow = rowPos; |
|
|
|
for ( var n=0, ie=data.body.length ; n<ie ; n++ ) { |
|
addRow( data.body[n], rowPos ); |
|
} |
|
|
|
dataEndRow = rowPos; |
|
|
|
if ( config.footer && data.footer ) { |
|
addRow( data.footer, rowPos); |
|
$('row:last c', rels).attr( 's', '2' ); // bold |
|
} |
|
|
|
// Below the table |
|
if ( exportInfo.messageBottom ) { |
|
addRow( [exportInfo.messageBottom], rowPos ); |
|
mergeCells( rowPos, data.header.length-1 ); |
|
} |
|
|
|
// Set column widths |
|
var cols = _createNode( rels, 'cols' ); |
|
$('worksheet', rels).prepend( cols ); |
|
|
|
for ( var i=0, ien=data.header.length ; i<ien ; i++ ) { |
|
cols.appendChild( _createNode( rels, 'col', { |
|
attr: { |
|
min: i+1, |
|
max: i+1, |
|
width: _excelColWidth( data, i ), |
|
customWidth: 1 |
|
} |
|
} ) ); |
|
} |
|
|
|
// Workbook modifications |
|
var workbook = xlsx.xl['workbook.xml']; |
|
|
|
$( 'sheets sheet', workbook ).attr( 'name', _sheetname( config ) ); |
|
|
|
// Auto filter for columns |
|
if ( config.autoFilter ) { |
|
$('mergeCells', rels).before( _createNode( rels, 'autoFilter', { |
|
attr: { |
|
ref: 'A'+dataStartRow+':'+createCellPos(data.header.length-1)+dataEndRow |
|
} |
|
} ) ); |
|
|
|
$('definedNames', workbook).append( _createNode( workbook, 'definedName', { |
|
attr: { |
|
name: '_xlnm._FilterDatabase', |
|
localSheetId: '0', |
|
hidden: 1 |
|
}, |
|
text: _sheetname(config)+'!$A$'+dataStartRow+':'+createCellPos(data.header.length-1)+dataEndRow |
|
} ) ); |
|
} |
|
|
|
// Let the developer customise the document if they want to |
|
if ( config.customize ) { |
|
config.customize( xlsx, config, dt ); |
|
} |
|
|
|
// Excel doesn't like an empty mergeCells tag |
|
if ( $('mergeCells', rels).children().length === 0 ) { |
|
$('mergeCells', rels).remove(); |
|
} |
|
|
|
var jszip = _jsZip(); |
|
var zip = new jszip(); |
|
var zipConfig = { |
|
type: 'blob', |
|
mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' |
|
}; |
|
|
|
_addToZip( zip, xlsx ); |
|
|
|
if ( zip.generateAsync ) { |
|
// JSZip 3+ |
|
zip |
|
.generateAsync( zipConfig ) |
|
.then( function ( blob ) { |
|
_saveAs( blob, exportInfo.filename ); |
|
that.processing( false ); |
|
} ); |
|
} |
|
else { |
|
// JSZip 2.5 |
|
_saveAs( |
|
zip.generate( zipConfig ), |
|
exportInfo.filename |
|
); |
|
this.processing( false ); |
|
} |
|
}, |
|
|
|
filename: '*', |
|
|
|
extension: '.xlsx', |
|
|
|
exportOptions: {}, |
|
|
|
header: true, |
|
|
|
footer: false, |
|
|
|
title: '*', |
|
|
|
messageTop: '*', |
|
|
|
messageBottom: '*', |
|
|
|
createEmptyCells: false, |
|
|
|
autoFilter: false, |
|
|
|
sheetName: '' |
|
}; |
|
|
|
// |
|
// PDF export - using pdfMake - http://pdfmake.org |
|
// |
|
DataTable.ext.buttons.pdfHtml5 = { |
|
className: 'buttons-pdf buttons-html5', |
|
|
|
available: function () { |
|
return window.FileReader !== undefined && _pdfMake(); |
|
}, |
|
|
|
text: function ( dt ) { |
|
return dt.i18n( 'buttons.pdf', 'PDF' ); |
|
}, |
|
|
|
action: function ( e, dt, button, config ) { |
|
this.processing( true ); |
|
|
|
var that = this; |
|
var data = dt.buttons.exportData( config.exportOptions ); |
|
var info = dt.buttons.exportInfo( config ); |
|
var rows = []; |
|
|
|
if ( config.header ) { |
|
rows.push( $.map( data.header, function ( d ) { |
|
return { |
|
text: typeof d === 'string' ? d : d+'', |
|
style: 'tableHeader' |
|
}; |
|
} ) ); |
|
} |
|
|
|
for ( var i=0, ien=data.body.length ; i<ien ; i++ ) { |
|
rows.push( $.map( data.body[i], function ( d ) { |
|
if ( d === null || d === undefined ) { |
|
d = ''; |
|
} |
|
return { |
|
text: typeof d === 'string' ? d : d+'', |
|
style: i % 2 ? 'tableBodyEven' : 'tableBodyOdd' |
|
}; |
|
} ) ); |
|
} |
|
|
|
if ( config.footer && data.footer) { |
|
rows.push( $.map( data.footer, function ( d ) { |
|
return { |
|
text: typeof d === 'string' ? d : d+'', |
|
style: 'tableFooter' |
|
}; |
|
} ) ); |
|
} |
|
|
|
var doc = { |
|
pageSize: config.pageSize, |
|
pageOrientation: config.orientation, |
|
content: [ |
|
{ |
|
table: { |
|
headerRows: 1, |
|
body: rows |
|
}, |
|
layout: 'noBorders' |
|
} |
|
], |
|
styles: { |
|
tableHeader: { |
|
bold: true, |
|
fontSize: 11, |
|
color: 'white', |
|
fillColor: '#2d4154', |
|
alignment: 'center' |
|
}, |
|
tableBodyEven: {}, |
|
tableBodyOdd: { |
|
fillColor: '#f3f3f3' |
|
}, |
|
tableFooter: { |
|
bold: true, |
|
fontSize: 11, |
|
color: 'white', |
|
fillColor: '#2d4154' |
|
}, |
|
title: { |
|
alignment: 'center', |
|
fontSize: 15 |
|
}, |
|
message: {} |
|
}, |
|
defaultStyle: { |
|
fontSize: 10 |
|
} |
|
}; |
|
|
|
if ( info.messageTop ) { |
|
doc.content.unshift( { |
|
text: info.messageTop, |
|
style: 'message', |
|
margin: [ 0, 0, 0, 12 ] |
|
} ); |
|
} |
|
|
|
if ( info.messageBottom ) { |
|
doc.content.push( { |
|
text: info.messageBottom, |
|
style: 'message', |
|
margin: [ 0, 0, 0, 12 ] |
|
} ); |
|
} |
|
|
|
if ( info.title ) { |
|
doc.content.unshift( { |
|
text: info.title, |
|
style: 'title', |
|
margin: [ 0, 0, 0, 12 ] |
|
} ); |
|
} |
|
|
|
if ( config.customize ) { |
|
config.customize( doc, config, dt ); |
|
} |
|
|
|
var pdf = _pdfMake().createPdf( doc ); |
|
|
|
if ( config.download === 'open' && ! _isDuffSafari() ) { |
|
pdf.open(); |
|
} |
|
else { |
|
pdf.download( info.filename ); |
|
} |
|
|
|
this.processing( false ); |
|
}, |
|
|
|
title: '*', |
|
|
|
filename: '*', |
|
|
|
extension: '.pdf', |
|
|
|
exportOptions: {}, |
|
|
|
orientation: 'portrait', |
|
|
|
pageSize: 'A4', |
|
|
|
header: true, |
|
|
|
footer: false, |
|
|
|
messageTop: '*', |
|
|
|
messageBottom: '*', |
|
|
|
customize: null, |
|
|
|
download: 'download' |
|
}; |
|
|
|
|
|
return DataTable.Buttons; |
|
}));
|
|
|