tableExport.js 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528
  1. /**
  2. * @preserve tableExport.jquery.plugin
  3. *
  4. * Copyright (c) 2015,2016 hhurz, https://github.com/hhurz/tableExport.jquery.plugin
  5. * Original work Copyright (c) 2014 Giri Raj, https://github.com/kayalshri/
  6. *
  7. * Licensed under the MIT License, http://opensource.org/licenses/mit-license
  8. */
  9. (function ($) {
  10. $.fn.extend({
  11. tableExport: function (options) {
  12. var defaults = {
  13. consoleLog: false,
  14. csvEnclosure: '"',
  15. csvSeparator: ',',
  16. csvUseBOM: true,
  17. displayTableName: false,
  18. escape: false,
  19. excelstyles: [], // e.g. ['border-bottom', 'border-top', 'border-left', 'border-right']
  20. fileName: 'tableExport',
  21. htmlContent: false,
  22. ignoreColumn: [],
  23. ignoreRow:[],
  24. jsonScope: 'all', // head, data, all
  25. jspdf: {orientation: 'p',
  26. unit: 'pt',
  27. format: 'a4', // jspdf page format or 'bestfit' for autmatic paper format selection
  28. margins: {left: 20, right: 10, top: 10, bottom: 10},
  29. autotable: {styles: {cellPadding: 2,
  30. rowHeight: 12,
  31. fontSize: 8,
  32. fillColor: 255, // color value or 'inherit' to use css background-color from html table
  33. textColor: 50, // color value or 'inherit' to use css color from html table
  34. fontStyle: 'normal', // normal, bold, italic, bolditalic or 'inherit' to use css font-weight and fonst-style from html table
  35. overflow: 'ellipsize', // visible, hidden, ellipsize or linebreak
  36. halign: 'left', // left, center, right
  37. valign: 'middle' // top, middle, bottom
  38. },
  39. headerStyles: {fillColor: [52, 73, 94],
  40. textColor: 255,
  41. fontStyle: 'bold',
  42. halign: 'center'
  43. },
  44. alternateRowStyles: {fillColor: 245
  45. },
  46. tableExport: {onAfterAutotable: null,
  47. onBeforeAutotable: null,
  48. onTable: null
  49. }
  50. }
  51. },
  52. numbers: {html: {decimalMark: '.',
  53. thousandsSeparator: ','
  54. },
  55. output: {decimalMark: '.',
  56. thousandsSeparator: ','
  57. }
  58. },
  59. onCellData: null,
  60. onCellHtmlData: null,
  61. outputMode: 'file', // 'file', 'string' or 'base64'
  62. pdfmake: {enabled: false}, // true: use pdfmake instead of jspdf(-autotable)
  63. tbodySelector: 'tr',
  64. tfootSelector: 'tr', // set empty ('') to prevent export of tfoot rows
  65. theadSelector: 'tr',
  66. tableName: 'myTableName',
  67. type: 'csv', // 'csv', 'txt', 'sql', 'json', 'xml', 'excel', 'doc', 'png' or 'pdf'
  68. worksheetName: 'xlsWorksheetName'
  69. };
  70. var FONT_ROW_RATIO = 1.15;
  71. var el = this;
  72. var DownloadEvt = null;
  73. var $hrows = [];
  74. var $rows = [];
  75. var rowIndex = 0;
  76. var rowspans = [];
  77. var trData = '';
  78. var colNames = [];
  79. $.extend(true, defaults, options);
  80. colNames = GetColumnNames (el);
  81. if (defaults.type == 'csv' || defaults.type == 'txt') {
  82. var csvData = "";
  83. var rowlength = 0;
  84. rowIndex = 0;
  85. function CollectCsvData (tgroup, tselector, rowselector, length) {
  86. $rows = $(el).find(tgroup).first().find(tselector);
  87. $rows.each(function () {
  88. trData = "";
  89. ForEachVisibleCell(this, rowselector, rowIndex, length + $rows.length,
  90. function (cell, row, col) {
  91. trData += csvString(cell, row, col) + defaults.csvSeparator;
  92. });
  93. trData = $.trim(trData).substring(0, trData.length - 1);
  94. if (trData.length > 0) {
  95. if (csvData.length > 0)
  96. csvData += "\n";
  97. csvData += trData;
  98. }
  99. rowIndex++;
  100. });
  101. return $rows.length;
  102. }
  103. rowlength += CollectCsvData ('thead', defaults.theadSelector, 'th,td', rowlength);
  104. rowlength += CollectCsvData ('tbody', defaults.tbodySelector, 'td', rowlength);
  105. if (defaults.tfootSelector.length)
  106. CollectCsvData ('tfoot', defaults.tfootSelector, 'td', rowlength);
  107. csvData += "\n";
  108. //output
  109. if (defaults.consoleLog === true)
  110. console.log(csvData);
  111. if (defaults.outputMode === 'string')
  112. return csvData;
  113. if (defaults.outputMode === 'base64')
  114. return base64encode(csvData);
  115. try {
  116. var blob = new Blob([csvData], {type: "text/" + (defaults.type == 'csv' ? 'csv' : 'plain') + ";charset=utf-8"});
  117. saveAs(blob, defaults.fileName + '.' + defaults.type, (defaults.type != 'csv' || defaults.csvUseBOM === false));
  118. }
  119. catch (e) {
  120. downloadFile(defaults.fileName + '.' + defaults.type,
  121. 'data:text/' + (defaults.type == 'csv' ? 'csv' : 'plain') + ';charset=utf-8,' + ((defaults.type == 'csv' && defaults.csvUseBOM)? '\ufeff' : ''),
  122. csvData);
  123. }
  124. } else if (defaults.type == 'sql') {
  125. // Header
  126. rowIndex = 0;
  127. var tdData = "INSERT INTO `" + defaults.tableName + "` (";
  128. $hrows = $(el).find('thead').first().find(defaults.theadSelector);
  129. $hrows.each(function () {
  130. ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
  131. function (cell, row, col) {
  132. tdData += "'" + parseString(cell, row, col) + "',";
  133. });
  134. rowIndex++;
  135. tdData = $.trim(tdData);
  136. tdData = $.trim(tdData).substring(0, tdData.length - 1);
  137. });
  138. tdData += ") VALUES ";
  139. // Row vs Column
  140. $rows = $(el).find('tbody').first().find(defaults.tbodySelector);
  141. if (defaults.tfootSelector.length)
  142. $rows.push.apply ($rows, $(el).find('tfoot').find(defaults.tfootSelector));
  143. $rows.each(function () {
  144. trData = "";
  145. ForEachVisibleCell(this, 'td', rowIndex, $hrows.length + $rows.length,
  146. function (cell, row, col) {
  147. trData += "'" + parseString(cell, row, col) + "',";
  148. });
  149. if (trData.length > 3) {
  150. tdData += "(" + trData;
  151. tdData = $.trim(tdData).substring(0, tdData.length - 1);
  152. tdData += "),";
  153. }
  154. rowIndex++;
  155. });
  156. tdData = $.trim(tdData).substring(0, tdData.length - 1);
  157. tdData += ";";
  158. //output
  159. if (defaults.consoleLog === true)
  160. console.log(tdData);
  161. if (defaults.outputMode === 'string')
  162. return tdData;
  163. if (defaults.outputMode === 'base64')
  164. return base64encode(tdData);
  165. try {
  166. var blob = new Blob([tdData], {type: "text/plain;charset=utf-8"});
  167. saveAs(blob, defaults.fileName + '.sql');
  168. }
  169. catch (e) {
  170. downloadFile(defaults.fileName + '.sql',
  171. 'data:application/sql;charset=utf-8,',
  172. tdData);
  173. }
  174. } else if (defaults.type == 'json') {
  175. var jsonHeaderArray = [];
  176. $hrows = $(el).find('thead').first().find(defaults.theadSelector);
  177. $hrows.each(function () {
  178. var jsonArrayTd = [];
  179. ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
  180. function (cell, row, col) {
  181. jsonArrayTd.push(parseString(cell, row, col));
  182. });
  183. jsonHeaderArray.push(jsonArrayTd);
  184. });
  185. var jsonArray = [];
  186. $rows = $(el).find('tbody').first().find(defaults.tbodySelector);
  187. if (defaults.tfootSelector.length)
  188. $rows.push.apply ($rows, $(el).find('tfoot').find(defaults.tfootSelector));
  189. $rows.each(function () {
  190. var jsonObjectTd = {};
  191. var colIndex = 0;
  192. ForEachVisibleCell(this, 'td', rowIndex, $hrows.length + $rows.length,
  193. function (cell, row, col) {
  194. if (jsonHeaderArray.length) {
  195. jsonObjectTd[jsonHeaderArray[jsonHeaderArray.length-1][colIndex]] = parseString(cell, row, col);
  196. } else {
  197. jsonObjectTd[colIndex] = parseString(cell, row, col);
  198. }
  199. colIndex++;
  200. });
  201. if ($.isEmptyObject(jsonObjectTd) == false)
  202. jsonArray.push(jsonObjectTd);
  203. rowIndex++;
  204. });
  205. var sdata = "";
  206. if (defaults.jsonScope == 'head')
  207. sdata = JSON.stringify(jsonHeaderArray);
  208. else if (defaults.jsonScope == 'data')
  209. sdata = JSON.stringify(jsonArray);
  210. else // all
  211. sdata = JSON.stringify({header: jsonHeaderArray, data: jsonArray});
  212. if (defaults.consoleLog === true)
  213. console.log(sdata);
  214. if (defaults.outputMode === 'string')
  215. return sdata;
  216. if (defaults.outputMode === 'base64')
  217. return base64encode(sdata);
  218. try {
  219. var blob = new Blob([sdata], {type: "application/json;charset=utf-8"});
  220. saveAs(blob, defaults.fileName + '.json');
  221. }
  222. catch (e) {
  223. downloadFile(defaults.fileName + '.json',
  224. 'data:application/json;charset=utf-8;base64,',
  225. sdata);
  226. }
  227. } else if (defaults.type === 'xml') {
  228. rowIndex = 0;
  229. var xml = '<?xml version="1.0" encoding="utf-8"?>';
  230. xml += '<tabledata><fields>';
  231. // Header
  232. $hrows = $(el).find('thead').first().find(defaults.theadSelector);
  233. $hrows.each(function () {
  234. ForEachVisibleCell(this, 'th,td', rowIndex, $rows.length,
  235. function (cell, row, col) {
  236. xml += "<field>" + parseString(cell, row, col) + "</field>";
  237. });
  238. rowIndex++;
  239. });
  240. xml += '</fields><data>';
  241. // Row Vs Column
  242. var rowCount = 1;
  243. $rows = $(el).find('tbody').first().find(defaults.tbodySelector);
  244. if (defaults.tfootSelector.length)
  245. $rows.push.apply ($rows, $(el).find('tfoot').find(defaults.tfootSelector));
  246. $rows.each(function () {
  247. var colCount = 1;
  248. trData = "";
  249. ForEachVisibleCell(this, 'td', rowIndex, $hrows.length + $rows.length,
  250. function (cell, row, col) {
  251. trData += "<column-" + colCount + ">" + parseString(cell, row, col) + "</column-" + colCount + ">";
  252. colCount++;
  253. });
  254. if (trData.length > 0 && trData != "<column-1></column-1>") {
  255. xml += '<row id="' + rowCount + '">' + trData + '</row>';
  256. rowCount++;
  257. }
  258. rowIndex++;
  259. });
  260. xml += '</data></tabledata>';
  261. //output
  262. if (defaults.consoleLog === true)
  263. console.log(xml);
  264. if (defaults.outputMode === 'string')
  265. return xml;
  266. if (defaults.outputMode === 'base64')
  267. return base64encode(xml);
  268. try {
  269. var blob = new Blob([xml], {type: "application/xml;charset=utf-8"});
  270. saveAs(blob, defaults.fileName + '.xml');
  271. }
  272. catch (e) {
  273. downloadFile(defaults.fileName + '.xml',
  274. 'data:application/xml;charset=utf-8;base64,',
  275. xml);
  276. }
  277. } else if (defaults.type == 'excel' || defaults.type == 'xls' || defaults.type == 'word' || defaults.type == 'doc') {
  278. var MSDocType = (defaults.type == 'excel' || defaults.type == 'xls') ? 'excel' : 'word';
  279. var MSDocExt = (MSDocType == 'excel') ? 'xls' : 'doc';
  280. var MSDocSchema = 'xmlns:x="urn:schemas-microsoft-com:office:' + MSDocType + '"';
  281. var $tables = $(el).filter(function() {
  282. return $(this).data("tableexport-display") != 'none' &&
  283. ($(this).is(':visible') ||
  284. $(this).data("tableexport-display") == 'always');
  285. });
  286. var docData = '';
  287. $tables.each(function(){
  288. rowIndex = 0;
  289. colNames = GetColumnNames (this);
  290. docData += '<table><thead>';
  291. // Header
  292. $hrows = $(this).find('thead').first().find(defaults.theadSelector);
  293. $hrows.each(function() {
  294. trData = "";
  295. ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
  296. function(cell, row, col) {
  297. if (cell != null) {
  298. var thstyle = '';
  299. trData += '<th';
  300. for (var styles in defaults.excelstyles) {
  301. if (defaults.excelstyles.hasOwnProperty(styles)) {
  302. var thcss = $(cell).css(defaults.excelstyles[styles]);
  303. if (thcss != '' && thcss !='0px none rgb(0, 0, 0)') {
  304. if (thstyle == '')
  305. thstyle = 'style="';
  306. thstyle += defaults.excelstyles[styles] + ':' + thcss + ';';
  307. }
  308. }
  309. }
  310. if (thstyle != '' )
  311. trData += ' ' + thstyle + '"';
  312. if ($(cell).is("[colspan]"))
  313. trData += ' colspan="' + $(cell).attr('colspan') + '"';
  314. if ($(cell).is("[rowspan]"))
  315. trData += ' rowspan="' + $(cell).attr('rowspan') + '"';
  316. trData += '>' + parseString(cell, row, col) + '</th>';
  317. }
  318. });
  319. if (trData.length > 0)
  320. docData += '<tr>' + trData + '</tr>';
  321. rowIndex++;
  322. });
  323. docData += '</thead><tbody>';
  324. // Row Vs Column
  325. $rows = $(this).find('tbody').first().find(defaults.tbodySelector);
  326. if (defaults.tfootSelector.length)
  327. $rows.push.apply ($rows, $(el).find('tfoot').find(defaults.tfootSelector));
  328. $rows.each(function() {
  329. trData = "";
  330. ForEachVisibleCell(this, 'td', rowIndex, $hrows.length + $rows.length,
  331. function(cell, row, col) {
  332. if (cell != null) {
  333. var tdstyle = '';
  334. var tdcss = $(cell).data("tableexport-msonumberformat");
  335. if (typeof tdcss == 'undefined' && typeof defaults.onMsoNumberFormat === 'function')
  336. tdcss = defaults.onMsoNumberFormat(cell, row, col);
  337. if (typeof tdcss != 'undefined' && tdcss != '') {
  338. if (tdstyle == '')
  339. tdstyle = 'style="';
  340. tdstyle = 'style="mso-number-format:\'' + tdcss + '\'';
  341. }
  342. trData += '<td';
  343. for (var styles in defaults.excelstyles) {
  344. if (defaults.excelstyles.hasOwnProperty(styles)) {
  345. tdcss = $(cell).css(defaults.excelstyles[styles]);
  346. if (tdcss != '' && tdcss !='0px none rgb(0, 0, 0)') {
  347. if (tdstyle == '')
  348. tdstyle = 'style="';
  349. tdstyle += defaults.excelstyles[styles] + ':' + tdcss + ';';
  350. }
  351. }
  352. }
  353. if (tdstyle != '' )
  354. trData += ' ' + tdstyle + '"';
  355. if ($(cell).is("[colspan]"))
  356. trData += ' colspan="' + $(cell).attr('colspan') + '"';
  357. if ($(cell).is("[rowspan]"))
  358. trData += ' rowspan="' + $(cell).attr('rowspan') + '"';
  359. trData += '>' + parseString(cell, row, col) + '</td>';
  360. }
  361. });
  362. if (trData.length > 0)
  363. docData += '<tr>' + trData + '</tr>';
  364. rowIndex++;
  365. });
  366. if (defaults.displayTableName)
  367. docData += '<tr><td></td></tr><tr><td></td></tr><tr><td>' + parseString($('<p>' + defaults.tableName + '</p>')) + '</td></tr>';
  368. docData += '</tbody></table>';
  369. if (defaults.consoleLog === true)
  370. console.log(docData);
  371. });
  372. var docFile = '<html xmlns:o="urn:schemas-microsoft-com:office:office" ' + MSDocSchema + ' xmlns="http://www.w3.org/TR/REC-html40">';
  373. docFile += '<meta http-equiv="content-type" content="application/vnd.ms-' + MSDocType + '; charset=UTF-8">';
  374. docFile += "<head>";
  375. if (MSDocType === 'excel') {
  376. docFile += "<!--[if gte mso 9]>";
  377. docFile += "<xml>";
  378. docFile += "<x:ExcelWorkbook>";
  379. docFile += "<x:ExcelWorksheets>";
  380. docFile += "<x:ExcelWorksheet>";
  381. docFile += "<x:Name>";
  382. docFile += defaults.worksheetName;
  383. docFile += "</x:Name>";
  384. docFile += "<x:WorksheetOptions>";
  385. docFile += "<x:DisplayGridlines/>";
  386. docFile += "</x:WorksheetOptions>";
  387. docFile += "</x:ExcelWorksheet>";
  388. docFile += "</x:ExcelWorksheets>";
  389. docFile += "</x:ExcelWorkbook>";
  390. docFile += "</xml>";
  391. docFile += "<![endif]-->";
  392. }
  393. docFile += "</head>";
  394. docFile += "<body>";
  395. docFile += docData;
  396. docFile += "</body>";
  397. docFile += "</html>";
  398. if (defaults.consoleLog === true)
  399. console.log(docFile);
  400. if (defaults.outputMode === 'string')
  401. return docFile;
  402. if (defaults.outputMode === 'base64')
  403. return base64encode(docFile);
  404. try {
  405. var blob = new Blob([docFile], {type: 'application/vnd.ms-' + defaults.type});
  406. saveAs(blob, defaults.fileName + '.' + MSDocExt);
  407. }
  408. catch (e) {
  409. downloadFile(defaults.fileName + '.' + MSDocExt,
  410. 'data:application/vnd.ms-' + MSDocType + ';base64,',
  411. docFile);
  412. }
  413. } else if (defaults.type == 'xlsx') {
  414. var data = [];
  415. var ranges = [];
  416. rowIndex = 0;
  417. $rows = $(el).find('thead').first().find(defaults.theadSelector);
  418. $rows.push.apply ($rows, $(el).find('tbody').first().find(defaults.tbodySelector));
  419. if (defaults.tfootSelector.length)
  420. $rows.push.apply ($rows, $(el).find('tfoot').find(defaults.tfootSelector));
  421. $rows.each(function () {
  422. var cols = [];
  423. ForEachVisibleCell(this, 'th,td', rowIndex, $rows.length,
  424. function (cell, row, col) {
  425. if (typeof cell !== 'undefined' && cell != null) {
  426. var colspan = cell.getAttribute('colspan');
  427. var rowspan = cell.getAttribute('rowspan');
  428. var cellValue = parseString(cell, row, col);
  429. if(cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
  430. //Skip ranges
  431. ranges.forEach(function(range) {
  432. if(rowIndex >= range.s.r && rowIndex <= range.e.r && cols.length >= range.s.c && cols.length <= range.e.c) {
  433. for(var i = 0; i <= range.e.c - range.s.c; ++i) cols.push(null);
  434. }
  435. });
  436. //Handle Row Span
  437. if (rowspan || colspan) {
  438. rowspan = rowspan || 1;
  439. colspan = colspan || 1;
  440. ranges.push({s:{r:rowIndex, c:cols.length},e:{r:rowIndex+rowspan-1, c:cols.length+colspan-1}});
  441. };
  442. //Handle Value
  443. cols.push(cellValue !== "" ? cellValue : null);
  444. //Handle Colspan
  445. if (colspan) for (var k = 0; k < colspan - 1; ++k) cols.push(null);
  446. }
  447. });
  448. data.push(cols);
  449. rowIndex++;
  450. });
  451. console.log(data);
  452. var wb = new jx_Workbook(),
  453. ws = jx_createSheet(data);
  454. // add ranges to worksheet
  455. ws['!merges'] = ranges;
  456. // add worksheet to workbook
  457. wb.SheetNames.push(defaults.worksheetName);
  458. wb.Sheets[defaults.worksheetName] = ws;
  459. var wbout = XLSX.write(wb, {bookType: defaults.type, bookSST: false, type: 'binary'});
  460. try {
  461. var blob = new Blob([jx_s2ab(wbout)], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=UTF-8'});
  462. saveAs(blob, defaults.fileName + '.' + defaults.type);
  463. }
  464. catch (e) {
  465. downloadFile(defaults.fileName + '.' + defaults.type,
  466. 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=UTF-8',
  467. data);
  468. }
  469. } else if (defaults.type == 'png') {
  470. //html2canvas($(el)[0], {
  471. // onrendered: function (canvas) {
  472. html2canvas($(el)[0]).then(
  473. function (canvas) {
  474. var image = canvas.toDataURL();
  475. image = image.substring(22); // remove data stuff
  476. var byteString = atob(image);
  477. var buffer = new ArrayBuffer(byteString.length);
  478. var intArray = new Uint8Array(buffer);
  479. for (var i = 0; i < byteString.length; i++)
  480. intArray[i] = byteString.charCodeAt(i);
  481. if (defaults.consoleLog === true)
  482. console.log(byteString);
  483. if (defaults.outputMode === 'string')
  484. return byteString;
  485. if (defaults.outputMode === 'base64')
  486. return base64encode(image);
  487. try {
  488. var blob = new Blob([buffer], {type: "image/png"});
  489. saveAs(blob, defaults.fileName + '.png');
  490. }
  491. catch (e) {
  492. downloadFile(defaults.fileName + '.png',
  493. 'data:image/png,',
  494. image);
  495. }
  496. //}
  497. });
  498. } else if (defaults.type == 'pdf') {
  499. if (defaults.pdfmake.enabled === true) {
  500. // pdf output using pdfmake
  501. // https://github.com/bpampuch/pdfmake
  502. var widths = [];
  503. var body = [];
  504. rowIndex = 0;
  505. $hrows = $(this).find('thead').find(defaults.theadSelector);
  506. $hrows.each(function () {
  507. var h = [];
  508. ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
  509. function (cell, row, col) {
  510. h.push(parseString(cell, row, col));
  511. });
  512. if (h.length)
  513. body.push(h);
  514. for(var i = widths.length; i < h.length;i++)
  515. widths.push("*");
  516. rowIndex++;
  517. });
  518. $rows = $(this).find('tbody').find(defaults.tbodySelector);
  519. if (defaults.tfootSelector.length)
  520. $rows.push.apply ($rows, $(el).find('tfoot').find(defaults.tfootSelector));
  521. $rows.each(function () {
  522. var r = [];
  523. ForEachVisibleCell(this, 'td', rowIndex, $hrows.length + $rows.length,
  524. function (cell, row, col) {
  525. r.push(parseString(cell, row, col));
  526. });
  527. if (r.length)
  528. body.push(r);
  529. rowIndex++;
  530. });
  531. var docDefinition = {
  532. pageOrientation: 'landscape',
  533. content: [
  534. {
  535. table: {
  536. headerRows: $hrows.length,
  537. widths: widths,
  538. body: body
  539. }
  540. }
  541. ]
  542. };
  543. pdfMake.createPdf(docDefinition).getBuffer(function (buffer) {
  544. try {
  545. var blob = new Blob([buffer], {type: "application/pdf"});
  546. saveAs(blob, defaults.fileName + '.pdf');
  547. }
  548. catch (e) {
  549. downloadFile(defaults.fileName + '.pdf',
  550. 'data:application/pdf;base64,',
  551. buffer);
  552. }
  553. });
  554. }
  555. else if (defaults.jspdf.autotable === false) {
  556. // pdf output using jsPDF's core html support
  557. var addHtmlOptions = {
  558. dim: {
  559. w: getPropertyUnitValue($(el).first().get(0), 'width', 'mm'),
  560. h: getPropertyUnitValue($(el).first().get(0), 'height', 'mm')
  561. },
  562. pagesplit: false
  563. };
  564. var doc = new jsPDF(defaults.jspdf.orientation, defaults.jspdf.unit, defaults.jspdf.format);
  565. doc.addHTML($(el).first(),
  566. defaults.jspdf.margins.left,
  567. defaults.jspdf.margins.top,
  568. addHtmlOptions,
  569. function () {
  570. jsPdfOutput(doc);
  571. });
  572. //delete doc;
  573. }
  574. else {
  575. // pdf output using jsPDF AutoTable plugin
  576. // https://github.com/simonbengtsson/jsPDF-AutoTable
  577. var teOptions = defaults.jspdf.autotable.tableExport;
  578. // When setting jspdf.format to 'bestfit' tableExport tries to choose
  579. // the minimum required paper format and orientation in which the table
  580. // (or tables in multitable mode) completely fits without column adjustment
  581. if (typeof defaults.jspdf.format === 'string' && defaults.jspdf.format.toLowerCase() === 'bestfit') {
  582. var pageFormats = {
  583. 'a0': [2383.94, 3370.39], 'a1': [1683.78, 2383.94],
  584. 'a2': [1190.55, 1683.78], 'a3': [841.89, 1190.55],
  585. 'a4': [595.28, 841.89]
  586. };
  587. var rk = '', ro = '';
  588. var mw = 0;
  589. $(el).filter(':visible').each(function () {
  590. if ($(this).css('display') != 'none') {
  591. var w = getPropertyUnitValue($(this).get(0), 'width', 'pt');
  592. if (w > mw) {
  593. if (w > pageFormats['a0'][0]) {
  594. rk = 'a0';
  595. ro = 'l';
  596. }
  597. for (var key in pageFormats) {
  598. if (pageFormats.hasOwnProperty(key)) {
  599. if (pageFormats[key][1] > w) {
  600. rk = key;
  601. ro = 'l';
  602. if (pageFormats[key][0] > w)
  603. ro = 'p';
  604. }
  605. }
  606. }
  607. mw = w;
  608. }
  609. }
  610. });
  611. defaults.jspdf.format = (rk == '' ? 'a4' : rk);
  612. defaults.jspdf.orientation = (ro == '' ? 'w' : ro);
  613. }
  614. // The jsPDF doc object is stored in defaults.jspdf.autotable.tableExport,
  615. // thus it can be accessed from any callback function
  616. teOptions.doc = new jsPDF(defaults.jspdf.orientation,
  617. defaults.jspdf.unit,
  618. defaults.jspdf.format);
  619. $(el).filter(function() {
  620. return $(this).data("tableexport-display") != 'none' &&
  621. ($(this).is(':visible') ||
  622. $(this).data("tableexport-display") == 'always');
  623. }).each(function () {
  624. var colKey;
  625. var rowIndex = 0;
  626. colNames = GetColumnNames (this);
  627. teOptions.columns = [];
  628. teOptions.rows = [];
  629. teOptions.rowoptions = {};
  630. // onTable: optional callback function for every matching table that can be used
  631. // to modify the tableExport options or to skip the output of a particular table
  632. // if the table selector targets multiple tables
  633. if (typeof teOptions.onTable === 'function')
  634. if (teOptions.onTable($(this), defaults) === false)
  635. return true; // continue to next iteration step (table)
  636. // each table works with an own copy of AutoTable options
  637. defaults.jspdf.autotable.tableExport = null; // avoid deep recursion error
  638. var atOptions = $.extend(true, {}, defaults.jspdf.autotable);
  639. defaults.jspdf.autotable.tableExport = teOptions;
  640. atOptions.margin = {};
  641. $.extend(true, atOptions.margin, defaults.jspdf.margins);
  642. atOptions.tableExport = teOptions;
  643. // Fix jsPDF Autotable's row height calculation
  644. if (typeof atOptions.beforePageContent !== 'function') {
  645. atOptions.beforePageContent = function (data) {
  646. if (data.pageCount == 1) {
  647. var all = data.table.rows.concat(data.table.headerRow);
  648. all.forEach(function (row) {
  649. if ( row.height > 0 ) {
  650. row.height += (2 - FONT_ROW_RATIO) / 2 * row.styles.fontSize;
  651. data.table.height += (2 - FONT_ROW_RATIO) / 2 * row.styles.fontSize;
  652. }
  653. });
  654. }
  655. }
  656. }
  657. if (typeof atOptions.createdHeaderCell !== 'function') {
  658. // apply some original css styles to pdf header cells
  659. atOptions.createdHeaderCell = function (cell, data) {
  660. // jsPDF AutoTable plugin v2.0.14 fix: each cell needs its own styles object
  661. cell.styles = $.extend({}, data.row.styles);
  662. if (typeof teOptions.columns [data.column.dataKey] != 'undefined') {
  663. var col = teOptions.columns [data.column.dataKey];
  664. if (typeof col.rect != 'undefined') {
  665. var rh;
  666. cell.contentWidth = col.rect.width;
  667. if (typeof teOptions.heightRatio == 'undefined' || teOptions.heightRatio == 0) {
  668. if (data.row.raw [data.column.dataKey].rowspan)
  669. rh = data.row.raw [data.column.dataKey].rect.height / data.row.raw [data.column.dataKey].rowspan;
  670. else
  671. rh = data.row.raw [data.column.dataKey].rect.height;
  672. teOptions.heightRatio = cell.styles.rowHeight / rh;
  673. }
  674. rh = data.row.raw [data.column.dataKey].rect.height * teOptions.heightRatio;
  675. if (rh > cell.styles.rowHeight)
  676. cell.styles.rowHeight = rh;
  677. }
  678. if (typeof col.style != 'undefined' && col.style.hidden !== true) {
  679. cell.styles.halign = col.style.align;
  680. if (atOptions.styles.fillColor === 'inherit')
  681. cell.styles.fillColor = col.style.bcolor;
  682. if (atOptions.styles.textColor === 'inherit')
  683. cell.styles.textColor = col.style.color;
  684. if (atOptions.styles.fontStyle === 'inherit')
  685. cell.styles.fontStyle = col.style.fstyle;
  686. }
  687. }
  688. }
  689. }
  690. if (typeof atOptions.createdCell !== 'function') {
  691. // apply some original css styles to pdf table cells
  692. atOptions.createdCell = function (cell, data) {
  693. var rowopt = teOptions.rowoptions [data.row.index + ":" + data.column.dataKey];
  694. if (typeof rowopt != 'undefined' &&
  695. typeof rowopt.style != 'undefined' &&
  696. rowopt.style.hidden !== true) {
  697. cell.styles.halign = rowopt.style.align;
  698. if (atOptions.styles.fillColor === 'inherit')
  699. cell.styles.fillColor = rowopt.style.bcolor;
  700. if (atOptions.styles.textColor === 'inherit')
  701. cell.styles.textColor = rowopt.style.color;
  702. if (atOptions.styles.fontStyle === 'inherit')
  703. cell.styles.fontStyle = rowopt.style.fstyle;
  704. }
  705. }
  706. }
  707. if (typeof atOptions.drawHeaderCell !== 'function') {
  708. atOptions.drawHeaderCell = function (cell, data) {
  709. var colopt = teOptions.columns [data.column.dataKey];
  710. if ((colopt.style.hasOwnProperty("hidden") != true || colopt.style.hidden !== true) &&
  711. colopt.rowIndex >= 0 )
  712. return prepareAutoTableText (cell, data, colopt);
  713. else
  714. return false; // cell is hidden
  715. }
  716. }
  717. if (typeof atOptions.drawCell !== 'function') {
  718. atOptions.drawCell = function (cell, data) {
  719. var rowopt = teOptions.rowoptions [data.row.index + ":" + data.column.dataKey];
  720. if ( prepareAutoTableText (cell, data, rowopt) ) {
  721. teOptions.doc.rect(cell.x, cell.y, cell.width, cell.height, cell.styles.fillStyle);
  722. if (typeof rowopt != 'undefined' && typeof rowopt.kids != 'undefined' && rowopt.kids.length > 0) {
  723. var dh = cell.height / rowopt.rect.height;
  724. if ( dh > teOptions.dh || typeof teOptions.dh == 'undefined' )
  725. teOptions.dh = dh;
  726. teOptions.dw = cell.width / rowopt.rect.width;
  727. drawCellElements (cell, rowopt.kids, teOptions);
  728. }
  729. teOptions.doc.autoTableText(cell.text, cell.textPos.x, cell.textPos.y, {
  730. halign: cell.styles.halign,
  731. valign: cell.styles.valign
  732. });
  733. }
  734. return false;
  735. }
  736. }
  737. // collect header and data rows
  738. teOptions.headerrows = [];
  739. $hrows = $(this).find('thead').find(defaults.theadSelector);
  740. $hrows.each(function () {
  741. colKey = 0;
  742. teOptions.headerrows[rowIndex] = [];
  743. ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
  744. function (cell, row, col) {
  745. var obj = getCellStyles (cell);
  746. obj.title = parseString(cell, row, col);
  747. obj.key = colKey++;
  748. obj.rowIndex = rowIndex;
  749. teOptions.headerrows[rowIndex].push(obj);
  750. });
  751. rowIndex++;
  752. });
  753. if (rowIndex > 0) {
  754. // iterate through last row
  755. $.each(teOptions.headerrows[rowIndex-1], function () {
  756. if (rowIndex > 1 && this.rect == null)
  757. obj = teOptions.headerrows[rowIndex-2][this.key];
  758. else
  759. obj = this;
  760. if (obj != null)
  761. teOptions.columns.push(obj);
  762. });
  763. }
  764. var rowCount = 0;
  765. $rows = $(this).find('tbody').find(defaults.tbodySelector);
  766. if (defaults.tfootSelector.length)
  767. $rows.push.apply ($rows, $(el).find('tfoot').find(defaults.tfootSelector));
  768. $rows.each(function () {
  769. var rowData = [];
  770. colKey = 0;
  771. ForEachVisibleCell(this, 'td', rowIndex, $hrows.length + $rows.length,
  772. function (cell, row, col) {
  773. if (typeof teOptions.columns[colKey] === 'undefined') {
  774. // jsPDF-Autotable needs columns. Thus define hidden ones for tables without thead
  775. var obj = {
  776. title: '',
  777. key: colKey,
  778. style: {
  779. hidden: true
  780. }
  781. };
  782. teOptions.columns.push(obj);
  783. }
  784. if (typeof cell !== 'undefined' && cell != null) {
  785. var obj = getCellStyles (cell);
  786. obj.kids = $(cell).children();
  787. teOptions.rowoptions [rowCount + ":" + colKey++] = obj;
  788. }
  789. else {
  790. var obj = $.extend(true, {}, teOptions.rowoptions [rowCount + ":" + (colKey-1)]);
  791. obj.colspan = -1;
  792. teOptions.rowoptions [rowCount + ":" + colKey++] = obj;
  793. }
  794. rowData.push(parseString(cell, row, col));
  795. });
  796. if (rowData.length) {
  797. teOptions.rows.push(rowData);
  798. rowCount++
  799. }
  800. rowIndex++;
  801. });
  802. // onBeforeAutotable: optional callback function before calling
  803. // jsPDF AutoTable that can be used to modify the AutoTable options
  804. if (typeof teOptions.onBeforeAutotable === 'function')
  805. teOptions.onBeforeAutotable($(this), teOptions.columns, teOptions.rows, atOptions);
  806. teOptions.doc.autoTable(teOptions.columns, teOptions.rows, atOptions);
  807. // onAfterAutotable: optional callback function after returning
  808. // from jsPDF AutoTable that can be used to modify the AutoTable options
  809. if (typeof teOptions.onAfterAutotable === 'function')
  810. teOptions.onAfterAutotable($(this), atOptions);
  811. // set the start position for the next table (in case there is one)
  812. defaults.jspdf.autotable.startY = teOptions.doc.autoTableEndPosY() + atOptions.margin.top;
  813. });
  814. jsPdfOutput(teOptions.doc);
  815. if (typeof teOptions.headerrows != 'undefined')
  816. teOptions.headerrows.length = 0;
  817. if (typeof teOptions.columns != 'undefined')
  818. teOptions.columns.length = 0;
  819. if (typeof teOptions.rows != 'undefined')
  820. teOptions.rows.length = 0;
  821. delete teOptions.doc;
  822. teOptions.doc = null;
  823. }
  824. }
  825. function FindColObject (objects, colIndex, rowIndex) {
  826. var result = null;
  827. $.each(objects, function () {
  828. if (this.rowIndex == rowIndex && this.key == colIndex) {
  829. result = this;
  830. return false;
  831. }
  832. });
  833. return result;
  834. }
  835. function GetColumnNames (table) {
  836. var result = [];
  837. $(table).find('thead').first().find('th').each(function(index, el) {
  838. if ($(el).attr("data-field") !== undefined)
  839. result[index] = $(el).attr("data-field");
  840. else
  841. result[index] = index.toString();
  842. });
  843. return result;
  844. }
  845. function isColumnIgnored($row, colIndex) {
  846. var result = false;
  847. if (defaults.ignoreColumn.length > 0) {
  848. if (typeof defaults.ignoreColumn[0] == 'string') {
  849. if (colNames.length > colIndex && typeof colNames[colIndex] != 'undefined')
  850. if ($.inArray(colNames[colIndex], defaults.ignoreColumn) != -1)
  851. result = true;
  852. }
  853. else if (typeof defaults.ignoreColumn[0] == 'number') {
  854. if ($.inArray(colIndex, defaults.ignoreColumn) != -1 ||
  855. $.inArray(colIndex-$row.length, defaults.ignoreColumn) != -1)
  856. result = true;
  857. }
  858. }
  859. return result;
  860. }
  861. function ForEachVisibleCell(tableRow, selector, rowIndex, rowCount, cellcallback) {
  862. if ($.inArray(rowIndex, defaults.ignoreRow) == -1 &&
  863. $.inArray(rowIndex-rowCount, defaults.ignoreRow) == -1) {
  864. var $row = $(tableRow).filter(function() {
  865. return $(this).data("tableexport-display") != 'none' &&
  866. ($(this).is(':visible') ||
  867. $(this).data("tableexport-display") == 'always' ||
  868. $(this).closest('table').data("tableexport-display") == 'always');
  869. }).find(selector);
  870. var rowColspan = 0;
  871. var rowColIndex = 0;
  872. $row.each(function (colIndex) {
  873. if ($(this).data("tableexport-display") == 'always' ||
  874. ($(this).css('display') != 'none' &&
  875. $(this).css('visibility') != 'hidden' &&
  876. $(this).data("tableexport-display") != 'none')) {
  877. if (isColumnIgnored($row, colIndex) == false) {
  878. if (typeof (cellcallback) === "function") {
  879. var c, Colspan = 0;
  880. var r, Rowspan = 0;
  881. // handle rowspans from previous rows
  882. if (typeof rowspans[rowIndex] != 'undefined' && rowspans[rowIndex].length > 0) {
  883. for (c = 0; c <= colIndex; c++) {
  884. if (typeof rowspans[rowIndex][c] != 'undefined') {
  885. cellcallback(null, rowIndex, c);
  886. delete rowspans[rowIndex][c];
  887. colIndex++;
  888. }
  889. }
  890. }
  891. rowColIndex = colIndex;
  892. if ($(this).is("[colspan]")) {
  893. Colspan = parseInt($(this).attr('colspan'));
  894. rowColspan += Colspan > 0 ? Colspan - 1 : 0;
  895. }
  896. if ($(this).is("[rowspan]"))
  897. Rowspan = parseInt($(this).attr('rowspan'));
  898. // output content of current cell
  899. cellcallback(this, rowIndex, colIndex);
  900. // handle colspan of current cell
  901. for (c = 0; c < Colspan - 1; c++)
  902. cellcallback(null, rowIndex, colIndex + c);
  903. // store rowspan for following rows
  904. if (Rowspan) {
  905. for (r = 1; r < Rowspan; r++) {
  906. if (typeof rowspans[rowIndex + r] == 'undefined')
  907. rowspans[rowIndex + r] = [];
  908. rowspans[rowIndex + r][colIndex + rowColspan] = "";
  909. for (c = 1; c < Colspan; c++)
  910. rowspans[rowIndex + r][colIndex + rowColspan - c] = "";
  911. }
  912. }
  913. }
  914. }
  915. }
  916. });
  917. // handle rowspans from previous rows
  918. if (typeof rowspans[rowIndex] != 'undefined' && rowspans[rowIndex].length > 0) {
  919. for (c = 0; c <= rowspans[rowIndex].length; c++) {
  920. if (typeof rowspans[rowIndex][c] != 'undefined') {
  921. cellcallback(null, rowIndex, c);
  922. delete rowspans[rowIndex][c];
  923. }
  924. }
  925. }
  926. }
  927. }
  928. function jsPdfOutput(doc) {
  929. if (defaults.consoleLog === true)
  930. console.log(doc.output());
  931. if (defaults.outputMode === 'string')
  932. return doc.output();
  933. if (defaults.outputMode === 'base64')
  934. return base64encode(doc.output());
  935. try {
  936. var blob = doc.output('blob');
  937. saveAs(blob, defaults.fileName + '.pdf');
  938. }
  939. catch (e) {
  940. downloadFile(defaults.fileName + '.pdf',
  941. 'data:application/pdf;base64,',
  942. doc.output());
  943. }
  944. }
  945. function prepareAutoTableText (cell, data, cellopt) {
  946. var cs = 0;
  947. if ( typeof cellopt != 'undefined' )
  948. cs = cellopt.colspan;
  949. if ( cs >= 0 ) {
  950. // colspan handling
  951. var cellWidth = cell.width;
  952. var textPosX = cell.textPos.x;
  953. var i = data.table.columns.indexOf(data.column);
  954. for (var c = 1; c < cs; c++) {
  955. var column = data.table.columns[i+c];
  956. cellWidth += column.width;
  957. }
  958. if ( cs > 1 ) {
  959. if ( cell.styles.halign === 'right' )
  960. textPosX = cell.textPos.x + cellWidth - cell.width;
  961. else if ( cell.styles.halign === 'center' )
  962. textPosX = cell.textPos.x + (cellWidth - cell.width) / 2;
  963. }
  964. cell.width = cellWidth;
  965. cell.textPos.x = textPosX;
  966. if ( typeof cellopt != 'undefined' && cellopt.rowspan > 1 )
  967. cell.height = cell.height * cellopt.rowspan;
  968. // fix jsPDF's calculation of text position
  969. if ( cell.styles.valign === 'middle' || cell.styles.valign === 'bottom' ) {
  970. var splittedText = typeof cell.text === 'string' ? cell.text.split(/\r\n|\r|\n/g) : cell.text;
  971. var lineCount = splittedText.length || 1;
  972. if (lineCount > 2)
  973. cell.textPos.y -= ((2 - FONT_ROW_RATIO) / 2 * data.row.styles.fontSize) * (lineCount-2) / 3 ;
  974. }
  975. return true;
  976. }
  977. else
  978. return false; // cell is hidden (colspan = -1), don't draw it
  979. }
  980. function drawCellElements (cell, elements, teOptions) {
  981. elements.each(function () {
  982. var kids = $(this).children();
  983. if ( $(this).is("div") ) {
  984. var bcolor = rgb2array(getStyle(this, 'background-color'), [255, 255, 255]);
  985. var lcolor = rgb2array(getStyle(this, 'border-top-color'), [0, 0, 0]);
  986. var lwidth = getPropertyUnitValue(this, 'border-top-width', defaults.jspdf.unit);
  987. var r = this.getBoundingClientRect();
  988. var ux = this.offsetLeft * teOptions.dw;
  989. var uy = this.offsetTop * teOptions.dh;
  990. var uw = r.width * teOptions.dw;
  991. var uh = r.height * teOptions.dh;
  992. teOptions.doc.setDrawColor.apply (undefined, lcolor);
  993. teOptions.doc.setFillColor.apply (undefined, bcolor);
  994. teOptions.doc.setLineWidth (lwidth);
  995. teOptions.doc.rect(cell.x + ux, cell.y + uy, uw, uh, lwidth ? "FD" : "F");
  996. }
  997. if (typeof kids != 'undefined' && kids.length > 0)
  998. drawCellElements (cell, kids, teOptions);
  999. });
  1000. }
  1001. function escapeRegExp(string) {
  1002. return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
  1003. }
  1004. function replaceAll(string, find, replace) {
  1005. return string.replace(new RegExp(escapeRegExp(find), 'g'), replace);
  1006. }
  1007. // Takes a string and encapsulates it (by default in double-quotes) if it
  1008. // contains the csv field separator, spaces, or linebreaks.
  1009. function csvString(cell, rowIndex, colIndex) {
  1010. var result = '';
  1011. if (cell != null) {
  1012. var dataString = parseString(cell, rowIndex, colIndex);
  1013. var csvValue = (dataString === null || dataString == '') ? '' : dataString.toString();
  1014. if (dataString instanceof Date)
  1015. result = defaults.csvEnclosure + dataString.toLocaleString() + defaults.csvEnclosure;
  1016. else {
  1017. result = replaceAll(csvValue, defaults.csvEnclosure, defaults.csvEnclosure + defaults.csvEnclosure);
  1018. if (result.indexOf(defaults.csvSeparator) >= 0 || /[\r\n ]/g.test(result))
  1019. result = defaults.csvEnclosure + result + defaults.csvEnclosure;
  1020. }
  1021. }
  1022. return result;
  1023. }
  1024. function parseNumber(value) {
  1025. value = value || "0";
  1026. value = replaceAll(value, defaults.numbers.html.decimalMark, '.');
  1027. value = replaceAll(value, defaults.numbers.html.thousandsSeparator, '');
  1028. return typeof value === "number" || jQuery.isNumeric(value) !== false ? value : false;
  1029. }
  1030. function parseString(cell, rowIndex, colIndex) {
  1031. var result = '';
  1032. if (cell != null) {
  1033. var $cell = $(cell);
  1034. var htmlData;
  1035. if ($cell[0].hasAttribute("data-tableexport-value"))
  1036. htmlData = $cell.data("tableexport-value");
  1037. else
  1038. htmlData = $cell.html();
  1039. if (typeof defaults.onCellHtmlData === 'function')
  1040. htmlData = defaults.onCellHtmlData($cell, rowIndex, colIndex, htmlData);
  1041. if (defaults.htmlContent === true) {
  1042. result = $.trim(htmlData);
  1043. }
  1044. else {
  1045. var text = htmlData.replace(/\n/g,'\u2028').replace(/<br\s*[\/]?>/gi, '\u2060');
  1046. var obj = $('<div/>').html(text).contents();
  1047. text = '';
  1048. $.each(obj.text().split("\u2028"), function(i, v) {
  1049. if (i > 0)
  1050. text += " ";
  1051. text += $.trim(v);
  1052. });
  1053. $.each(text.split("\u2060"), function(i, v) {
  1054. if (i > 0)
  1055. result += "\n";
  1056. result += $.trim(v).replace(/\u00AD/g, ""); // remove soft hyphens
  1057. });
  1058. if (defaults.numbers.html.decimalMark != defaults.numbers.output.decimalMark ||
  1059. defaults.numbers.html.thousandsSeparator != defaults.numbers.output.thousandsSeparator) {
  1060. var number = parseNumber (result);
  1061. if ( number !== false ) {
  1062. var frac = ("" + number).split('.');
  1063. if ( frac.length == 1 )
  1064. frac[1] = "";
  1065. var mod = frac[0].length > 3 ? frac[0].length % 3 : 0;
  1066. result = (number < 0 ? "-" : "") +
  1067. (defaults.numbers.output.thousandsSeparator ? ((mod ? frac[0].substr(0, mod) + defaults.numbers.output.thousandsSeparator : "") + frac[0].substr(mod).replace(/(\d{3})(?=\d)/g, "$1" + defaults.numbers.output.thousandsSeparator)) : frac[0]) +
  1068. (frac[1].length ? defaults.numbers.output.decimalMark + frac[1] : "");
  1069. }
  1070. }
  1071. }
  1072. if (defaults.escape === true) {
  1073. result = escape(result);
  1074. }
  1075. if (typeof defaults.onCellData === 'function') {
  1076. result = defaults.onCellData($cell, rowIndex, colIndex, result);
  1077. }
  1078. }
  1079. return result;
  1080. }
  1081. function hyphenate(a, b, c) {
  1082. return b + "-" + c.toLowerCase();
  1083. }
  1084. function rgb2array(rgb_string, default_result) {
  1085. var re = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/;
  1086. var bits = re.exec(rgb_string);
  1087. var result = default_result;
  1088. if (bits)
  1089. result = [ parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]) ];
  1090. return result;
  1091. }
  1092. function getCellStyles (cell) {
  1093. var a = getStyle(cell, 'text-align');
  1094. var fw = getStyle(cell, 'font-weight');
  1095. var fs = getStyle(cell, 'font-style');
  1096. var f = '';
  1097. if (a == 'start')
  1098. a = getStyle(cell, 'direction') == 'rtl' ? 'right' : 'left';
  1099. if (fw >= 700)
  1100. f = 'bold';
  1101. if (fs == 'italic')
  1102. f += fs;
  1103. if (f == '')
  1104. f = 'normal';
  1105. var result = {
  1106. style: {
  1107. align: a,
  1108. bcolor: rgb2array(getStyle(cell, 'background-color'), [255, 255, 255]),
  1109. color: rgb2array(getStyle(cell, 'color'), [0, 0, 0]),
  1110. fstyle: f
  1111. },
  1112. colspan: (parseInt($(cell).attr('colspan')) || 0),
  1113. rowspan: (parseInt($(cell).attr('rowspan')) || 0)
  1114. };
  1115. if (cell !== null) {
  1116. var r = cell.getBoundingClientRect();
  1117. result.rect = {
  1118. width: r.width,
  1119. height: r.height
  1120. };
  1121. }
  1122. return result;
  1123. }
  1124. // get computed style property
  1125. function getStyle(target, prop) {
  1126. try {
  1127. if (window.getComputedStyle) { // gecko and webkit
  1128. prop = prop.replace(/([a-z])([A-Z])/, hyphenate); // requires hyphenated, not camel
  1129. return window.getComputedStyle(target, null).getPropertyValue(prop);
  1130. }
  1131. if (target.currentStyle) { // ie
  1132. return target.currentStyle[prop];
  1133. }
  1134. return target.style[prop];
  1135. }
  1136. catch (e) {
  1137. }
  1138. return "";
  1139. }
  1140. function getUnitValue(parent, value, unit) {
  1141. var baseline = 100; // any number serves
  1142. var temp = document.createElement("div"); // create temporary element
  1143. temp.style.overflow = "hidden"; // in case baseline is set too low
  1144. temp.style.visibility = "hidden"; // no need to show it
  1145. parent.appendChild(temp); // insert it into the parent for em, ex and %
  1146. temp.style.width = baseline + unit;
  1147. var factor = baseline / temp.offsetWidth;
  1148. parent.removeChild(temp); // clean up
  1149. return (value * factor);
  1150. }
  1151. function getPropertyUnitValue(target, prop, unit) {
  1152. var value = getStyle(target, prop); // get the computed style value
  1153. var numeric = value.match(/\d+/); // get the numeric component
  1154. if (numeric !== null) {
  1155. numeric = numeric[0]; // get the string
  1156. return getUnitValue (target.parentElement, numeric, unit);
  1157. }
  1158. return 0;
  1159. }
  1160. function jx_Workbook() {
  1161. if(!(this instanceof jx_Workbook)) return new jx_Workbook();
  1162. this.SheetNames = [];
  1163. this.Sheets = {};
  1164. }
  1165. function jx_s2ab(s) {
  1166. var buf = new ArrayBuffer(s.length);
  1167. var view = new Uint8Array(buf);
  1168. for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
  1169. return buf;
  1170. }
  1171. function jx_datenum(v, date1904) {
  1172. if(date1904) v+=1462;
  1173. var epoch = Date.parse(v);
  1174. return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
  1175. }
  1176. function jx_createSheet(data) {
  1177. var ws = {};
  1178. var range = {s: {c:10000000, r:10000000}, e: {c:0, r:0 }};
  1179. for(var R = 0; R != data.length; ++R) {
  1180. for(var C = 0; C != data[R].length; ++C) {
  1181. if(range.s.r > R) range.s.r = R;
  1182. if(range.s.c > C) range.s.c = C;
  1183. if(range.e.r < R) range.e.r = R;
  1184. if(range.e.c < C) range.e.c = C;
  1185. var cell = {v: data[R][C] };
  1186. if(cell.v == null) continue;
  1187. var cell_ref = XLSX.utils.encode_cell({c:C,r:R});
  1188. if(typeof cell.v === 'number') cell.t = 'n';
  1189. else if(typeof cell.v === 'boolean') cell.t = 'b';
  1190. else if(cell.v instanceof Date) {
  1191. cell.t = 'n'; cell.z = XLSX.SSF._table[14];
  1192. cell.v = datenum(cell.v);
  1193. }
  1194. else cell.t = 's';
  1195. ws[cell_ref] = cell;
  1196. }
  1197. }
  1198. if(range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
  1199. return ws;
  1200. }
  1201. function downloadFile(filename, header, data) {
  1202. var ua = window.navigator.userAgent;
  1203. if (ua.indexOf("MSIE ") > 0 || !!ua.match(/Trident.*rv\:11\./)) {
  1204. // Internet Explorer (<= 9) workaround by Darryl (https://github.com/dawiong/tableExport.jquery.plugin)
  1205. // based on sampopes answer on http://stackoverflow.com/questions/22317951
  1206. // ! Not working for json and pdf format !
  1207. var frame = document.createElement("iframe");
  1208. if (frame) {
  1209. document.body.appendChild(frame);
  1210. frame.setAttribute("style", "display:none");
  1211. frame.contentDocument.open("txt/html", "replace");
  1212. frame.contentDocument.write(data);
  1213. frame.contentDocument.close();
  1214. frame.focus();
  1215. frame.contentDocument.execCommand("SaveAs", true, filename);
  1216. document.body.removeChild(frame);
  1217. }
  1218. }
  1219. else {
  1220. var DownloadLink = document.createElement('a');
  1221. if (DownloadLink) {
  1222. DownloadLink.style.display = 'none';
  1223. DownloadLink.download = filename;
  1224. if (header.toLowerCase().indexOf("base64,") >= 0)
  1225. DownloadLink.href = header + base64encode(data);
  1226. else
  1227. DownloadLink.href = header + encodeURIComponent(data);
  1228. document.body.appendChild(DownloadLink);
  1229. if (document.createEvent) {
  1230. if (DownloadEvt == null)
  1231. DownloadEvt = document.createEvent('MouseEvents');
  1232. DownloadEvt.initEvent('click', true, false);
  1233. DownloadLink.dispatchEvent(DownloadEvt);
  1234. }
  1235. else if (document.createEventObject)
  1236. DownloadLink.fireEvent('onclick');
  1237. else if (typeof DownloadLink.onclick == 'function')
  1238. DownloadLink.onclick();
  1239. document.body.removeChild(DownloadLink);
  1240. }
  1241. }
  1242. }
  1243. function utf8Encode(string) {
  1244. string = string.replace(/\x0d\x0a/g, "\x0a");
  1245. var utftext = "";
  1246. for (var n = 0; n < string.length; n++) {
  1247. var c = string.charCodeAt(n);
  1248. if (c < 128) {
  1249. utftext += String.fromCharCode(c);
  1250. }
  1251. else if ((c > 127) && (c < 2048)) {
  1252. utftext += String.fromCharCode((c >> 6) | 192);
  1253. utftext += String.fromCharCode((c & 63) | 128);
  1254. }
  1255. else {
  1256. utftext += String.fromCharCode((c >> 12) | 224);
  1257. utftext += String.fromCharCode(((c >> 6) & 63) | 128);
  1258. utftext += String.fromCharCode((c & 63) | 128);
  1259. }
  1260. }
  1261. return utftext;
  1262. }
  1263. function base64encode(input) {
  1264. var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  1265. var output = "";
  1266. var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
  1267. var i = 0;
  1268. input = utf8Encode(input);
  1269. while (i < input.length) {
  1270. chr1 = input.charCodeAt(i++);
  1271. chr2 = input.charCodeAt(i++);
  1272. chr3 = input.charCodeAt(i++);
  1273. enc1 = chr1 >> 2;
  1274. enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
  1275. enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
  1276. enc4 = chr3 & 63;
  1277. if (isNaN(chr2)) {
  1278. enc3 = enc4 = 64;
  1279. } else if (isNaN(chr3)) {
  1280. enc4 = 64;
  1281. }
  1282. output = output +
  1283. keyStr.charAt(enc1) + keyStr.charAt(enc2) +
  1284. keyStr.charAt(enc3) + keyStr.charAt(enc4);
  1285. }
  1286. return output;
  1287. }
  1288. return this;
  1289. }
  1290. });
  1291. })(jQuery);