table2excel.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. * jQuery table2excel - v1.1.2
  3. * jQuery plugin to export an .xls file in browser from an HTML table
  4. * https://github.com/rainabba/jquery-table2excel
  5. *
  6. * Made by rainabba
  7. * Under MIT License
  8. */
  9. (function ($, window, document, undefined) {
  10. var pluginName = "table2excel",
  11. defaults = {
  12. exclude: ".noExl",
  13. name: "Table2Excel",
  14. filename: "table2excel",
  15. fileext: ".xls",
  16. exclude_img: true,
  17. exclude_links: true,
  18. exclude_inputs: true,
  19. preserveColors: true,
  20. subtotal: 0,//"合计"行所在的行号(不包括标题行),0表示没有合计行...
  21. width: 50,//表格宽度百分比,默认100%
  22. trHeight:32,//表格行高,默认32px
  23. thBackgroundColor:"#eeeeee"//TH背景色
  24. };
  25. //插件配置
  26. function Plugin(element, options) {
  27. this.element = element;
  28. this.settings = $.extend({}, defaults, options);
  29. this._defaults = defaults;
  30. this._name = pluginName;
  31. this.init();
  32. }
  33. Plugin.prototype = {
  34. init: function () {
  35. var e = this;
  36. var w = getWidth(e.settings);//导出EXCEL表格的宽度,默认100%
  37. var utf8Heading = "<meta http-equiv=\"content-type\" content=\"application/vnd.ms-excel; charset=UTF-8\">";
  38. e.template = {
  39. head: "<html xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:x=\"urn:schemas-microsoft-com:office:excel\" xmlns=\"http://www.w3.org/TR/REC-html40\">" + utf8Heading + "<head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets>",
  40. sheet: {
  41. head: "<x:ExcelWorksheet><x:Name>",
  42. tail: "</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>"
  43. },
  44. mid: "</x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body>",
  45. table: {
  46. head: " <table border='1' style='width:" + w + "%;'>",//<table>的边框&宽度
  47. tail: " </table>"
  48. },
  49. foot: "</body></html>"
  50. };
  51. e.tableRows = [];
  52. //读取原始表
  53. var rowNumber = 0;//行号
  54. $(e.element).each(function (i, o) {
  55. var tempRows = "";//table的html
  56. $(o).find("tr").not(e.settings.exclude).each(function (i, p) {
  57. //<tr>的样式
  58. var trStyles = "height:"+e.settings.trHeight+"px;";//整行样式
  59. //开始创建一行表格
  60. tempRows += "<tr align='center' style='" + trStyles + "'>";//内容居中:align='center'
  61. //读取原始<table>的<th>表头行(表头必须是<th>!表头如果是<td>的话则会当做普通数据行处理...)
  62. $(p).find("th").not(e.settings.exclude).each(function (i, q) {
  63. //<th>的样式:
  64. var thStyles = "background-color: "+e.settings.thBackgroundColor+";";
  65. var rc = {
  66. rows: $(this).attr("rowspan"),
  67. cols: $(this).attr("colspan"),
  68. flag: $(q).find(e.settings.exclude)
  69. };
  70. if (rc.flag.length > 0) {
  71. tempRows += "<td> </td>"; //空格!
  72. } else {
  73. tempRows += "<td";
  74. if (rc.rows > 0) {
  75. tempRows += " rowspan='" + rc.rows + "' ";//跨行
  76. }
  77. if (rc.cols > 0) {
  78. tempRows += " colspan='" + rc.cols + "' ";//跨列
  79. }
  80. if (thStyles) {
  81. tempRows += " style='" + thStyles + "'";//样式
  82. }
  83. tempRows += ">" + $(q).html() + "</td>";//内容
  84. }
  85. });
  86. //读取原始<table>的<td>数据行
  87. $(p).find("td").not(e.settings.exclude).each(function (i, q) {
  88. // Reset for this column
  89. additionalStyles = "";
  90. // Preserve background and text colors on the row
  91. if(e.settings.preserveColors){
  92. let compStyle = getComputedStyle(q);
  93. additionalStyles += (compStyle && compStyle.backgroundColor ? "background-color: " + compStyle.backgroundColor + ";" : "");
  94. additionalStyles += (compStyle && compStyle.color ? "color: " + compStyle.color + ";" : "");
  95. }
  96. //<td>的样式
  97. var tdStyles = "background-color:#8DB4E2;";//合计行的样式
  98. var rc = {
  99. rows: $(this).attr("rowspan"),
  100. cols: $(this).attr("colspan"),
  101. align:$(this).attr("align"),
  102. flag: $(q).find(e.settings.exclude)
  103. };
  104. var align='';
  105. if( rc.align && rc.align.length > 1 ) {
  106. align =' align="'+rc.align+'" valign="center" ';
  107. }
  108. if (rc.flag.length > 0) {
  109. tempRows += "<td "+align+"> </td>"; //空格!
  110. } else {
  111. tempRows += "<td "+align;
  112. if (rc.rows > 0) {
  113. tempRows += " rowspan='" + rc.rows + "' ";//跨行
  114. }
  115. if (rc.cols > 0) {
  116. tempRows += " colspan='" + rc.cols + "' ";//跨列
  117. }
  118. var subtotal = getSubtotal(e.settings);//获取"合计"行所在的行号(不包括标题行)
  119. if (rowNumber == subtotal) {//if(当前行行号 == 合计行行号)
  120. if (tdStyles) {
  121. tempRows += " style='mso-number-format:\"\@\"; " + tdStyles + "' ";//样式
  122. }
  123. else {
  124. tempRows += " style='mso-number-format:\"\@\";' ";//纯文本
  125. }
  126. }
  127. else {
  128. if(additionalStyles!=''){
  129. tempRows += " style='" + additionalStyles + "'";
  130. }
  131. else{
  132. tempRows += " style='mso-number-format:\"\@\";' ";//纯文本
  133. }
  134. }
  135. tempRows += ">" + $(q).html() + "</td>";
  136. }
  137. });
  138. tempRows += "</tr>";//生成一行结束
  139. rowNumber++;//行号+1
  140. });
  141. // exclude img tags
  142. if (e.settings.exclude_img) {
  143. tempRows = exclude_img(tempRows);
  144. }
  145. // exclude link tags
  146. if (e.settings.exclude_links) {
  147. tempRows = exclude_links(tempRows);
  148. }
  149. // exclude input tags
  150. if (e.settings.exclude_inputs) {
  151. tempRows = exclude_inputs(tempRows);
  152. }
  153. e.tableRows.push(tempRows);
  154. });
  155. e.tableToExcel(e.tableRows, e.settings.name, e.settings.sheetName);
  156. },
  157. tableToExcel: function (table, name, sheetName) {
  158. var e = this, fullTemplate = "", i, link, a;
  159. e.format = function (s, c) {
  160. return s.replace(/{(\w+)}/g, function (m, p) {
  161. return c[p];
  162. });
  163. };
  164. sheetName = typeof sheetName === "undefined" ? "Sheet" : sheetName;
  165. e.ctx = {
  166. worksheet: name || "Worksheet",
  167. table: table,
  168. sheetName: sheetName
  169. };
  170. fullTemplate = e.template.head;
  171. if ($.isArray(table)) {
  172. Object.keys(table).forEach(function (i) {
  173. //fullTemplate += e.template.sheet.head + "{worksheet" + i + "}" + e.template.sheet.tail;
  174. fullTemplate += e.template.sheet.head + sheetName + i + e.template.sheet.tail;
  175. });
  176. }
  177. fullTemplate += e.template.mid;
  178. if ($.isArray(table)) {
  179. Object.keys(table).forEach(function (i) {
  180. fullTemplate += e.template.table.head + "{table" + i + "}" + e.template.table.tail;
  181. });
  182. }
  183. fullTemplate += e.template.foot;
  184. for (i in table) {
  185. e.ctx["table" + i] = table[i];
  186. }
  187. delete e.ctx.table;
  188. var isIE = navigator.appVersion.indexOf("MSIE 10") !== -1 || (navigator.userAgent.indexOf("Trident") !== -1 && navigator.userAgent.indexOf("rv:11") !== -1); // this works with IE10 and IE11 both :)
  189. //if (typeof msie !== "undefined" && msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) // this works ONLY with IE 11!!!
  190. if (isIE) {
  191. if (typeof Blob !== "undefined") {
  192. //use blobs if we can
  193. fullTemplate = e.format(fullTemplate, e.ctx); // with this, works with IE
  194. fullTemplate = [fullTemplate];
  195. //convert to array
  196. var blob1 = new Blob(fullTemplate, { type: "text/html" });
  197. window.navigator.msSaveBlob(blob1, getFileName(e.settings));
  198. } else {
  199. //otherwise use the iframe and save
  200. //requires a blank iframe on page called txtArea1
  201. txtArea1.document.open("text/html", "replace");
  202. txtArea1.document.write(e.format(fullTemplate, e.ctx));
  203. txtArea1.document.close();
  204. txtArea1.focus();
  205. sa = txtArea1.document.execCommand("SaveAs", true, getFileName(e.settings));
  206. }
  207. } else {
  208. var blob = new Blob([e.format(fullTemplate, e.ctx)], { type: "application/vnd.ms-excel" });
  209. window.URL = window.URL || window.webkitURL;
  210. link = window.URL.createObjectURL(blob);
  211. a = document.createElement("a");
  212. a.download = getFileName(e.settings);
  213. a.href = link;
  214. document.body.appendChild(a);
  215. a.click();
  216. document.body.removeChild(a);
  217. }
  218. return true;
  219. }
  220. };
  221. //获取excel文件名
  222. function getFileName(settings) {
  223. return (settings.filename ? settings.filename : "table2excel");
  224. }
  225. //获取"合计"行所在的行号(不包括标题行)
  226. function getSubtotal(settings) {
  227. return (settings.subtotal ? settings.subtotal : 0);//默认值0
  228. }
  229. //导出Excel的表格宽度百分比的值(不含%号),默认100%
  230. function getWidth(settings) {
  231. return (settings.width ? settings.width : 100);
  232. }
  233. // Removes all img tags
  234. function exclude_img(string) {
  235. var _patt = /(\s+alt\s*=\s*"([^"]*)"|\s+alt\s*=\s*'([^']*)')/i;
  236. return string.replace(/<img[^>]*>/gi, function myFunction(x) {
  237. var res = _patt.exec(x);
  238. if (res !== null && res.length >= 2) {
  239. return res[2];
  240. } else {
  241. return "";
  242. }
  243. });
  244. }
  245. // Removes all link tags
  246. function exclude_links(string) {
  247. return string.replace(/<a[^>]*>|<\/a>/gi, "");
  248. }
  249. // Removes input params
  250. function exclude_inputs(string) {
  251. var _patt = /(\s+value\s*=\s*"([^"]*)"|\s+value\s*=\s*'([^']*)')/i;
  252. return string.replace(/<input[^>]*>|<\/input>/gi, function myFunction(x) {
  253. var res = _patt.exec(x);
  254. if (res !== null && res.length >= 2) {
  255. return res[2];
  256. } else {
  257. return "";
  258. }
  259. });
  260. }
  261. $.fn[pluginName] = function (options) {
  262. var e = this;
  263. e.each(function () {
  264. if (!$.data(e, "plugin_" + pluginName)) {
  265. $.data(e, "plugin_" + pluginName, new Plugin(this, options));
  266. }
  267. });
  268. // chain jQuery functions
  269. return e;
  270. };
  271. })(jQuery, window, document);