xlsx.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. layui.define(['jquery','layer','table'], function(exports) {
  2. var $ = layui.$,
  3. layer = layui.layer,
  4. table = layui.table;
  5. var MOD_NAME = 'xlsx';
  6. var modFile = layui.cache.modules['xlsx'];
  7. var modPath = modFile.substr(0, modFile.lastIndexOf('.'));
  8. var tableXlsx=$.extend({},table);
  9. tableXlsx._render = tableXlsx.render;
  10. tableXlsx.excel = function(data,page_size,obj,filter,merge){
  11. //表头工具栏导出按钮
  12. $('[lay-id="'+obj.id+'"]').find('[lay-event="LAYTABLE_EXCEL"]').off().on('click',function(){
  13. if(data.count==0){
  14. layer.msg('暂无数据');
  15. return false;
  16. }
  17. else{
  18. let _page = parseInt(data.count/page_size);
  19. let page = data.count%page_size>0?(_page+1):_page;
  20. let pageHtml='<p style="padding:16px 10px 0; text-align:center; color:red">由于导出数据比较消耗服务器资源,建议使用搜索功能筛选好数据再导出</p><p style="padding:5px 10px 10px; text-align:center; color:red">如果点击导出后,没有立即导出文件,请耐心等待一下,30秒内请勿重复点击。</p><p style="padding:0 10px; text-align:center;">共查询到<strong> '+data.count+' </strong>条数据,每次最多导出<strong>'+page_size+'</strong>条,共<strong>'+page+'</strong>页,请点击下面的页码导出</p><div id="exportPage" class="layui-box layui-laypage" style="padding:10px 0; width:100%;text-align:center;">';
  21. for (i = 1; i <= page; i++) {
  22. pageHtml += '<a href="javascript:;" data-page="'+i+'">'+i+'</a>';
  23. }
  24. pageHtml+='</div>';
  25. layer.open({
  26. type: 1,
  27. title: '导出数据',
  28. area:['580px','240px'],
  29. content: pageHtml,
  30. success:function(res){
  31. var tableWhere = JSON.parse(JSON.stringify(obj.where));
  32. tableWhere.limit=page_size;
  33. $('#exportPage').on('click','a',function(){
  34. tableWhere.page=$(this).data('page');
  35. let msg = layer.msg('正在导出数据...', {time:5000});
  36. $.ajax({
  37. url: obj.url,
  38. data: tableWhere,
  39. success:function(res){
  40. //table.exportFile(obj.id, res.data,'xls');
  41. //console.log(res.data);
  42. tableXlsx.xsls(res.data,obj.cols[0],obj.title,filter,merge);
  43. layer.close(msg);
  44. }
  45. });
  46. })
  47. }
  48. });
  49. return false;
  50. }
  51. });
  52. }
  53. tableXlsx.xsls = function(jsonData,field,name,filter,merge){
  54. let new_jsonData;
  55. //数据过滤
  56. if(filter.length>0){
  57. new_jsonData = jsonData.map((item, index) => {
  58. const newProps = {}; // 创建一个空对象,用于存放新增的属性和对应的计算值
  59. filter.forEach((obj) => {
  60. for (const [key, func] of Object.entries(obj)) {
  61. newProps[key] = func(item); // 调用函数计算属性值,并赋给新的属性
  62. }
  63. });
  64. return { ...item, ...newProps }; // 创建新对象,将原有的属性展开并新增 newProps 中的属性
  65. });
  66. }
  67. else{
  68. new_jsonData = jsonData;
  69. }
  70. console.log("===========打印初始化后的json数据============");
  71. console.log(new_jsonData);
  72. //需要显示的表格字段,及表头文字描述
  73. let field_array =[],customHeaders = [];
  74. for (var f=0; f<field.length;f++){
  75. if(!field[f]['ignoreExport']){
  76. field_array.push(field[f].field);
  77. customHeaders.push(field[f].title);
  78. }
  79. }
  80. console.log("===========打印需要显示的表格字段及表头文字描述============");
  81. console.log(field_array);
  82. console.log(customHeaders);
  83. const desiredOrder = field_array; // 按照这个顺序重新排序
  84. const desiredProps = field_array; // 只保留这些属性
  85. // 对 JSON 数据集进行排序和过滤
  86. const sortedAndFilteredData = new_jsonData.map(entry => {
  87. const sortedAndFilteredEntry = {};
  88. desiredOrder.forEach(key => {
  89. if (desiredProps.includes(key) && entry.hasOwnProperty(key)) {
  90. sortedAndFilteredEntry[key] = entry[key];
  91. }
  92. });
  93. return sortedAndFilteredEntry;
  94. });
  95. console.log("===========打印排序和过滤处理过的JSON 数据集============");
  96. console.log(sortedAndFilteredData);
  97. //设置表头
  98. const worksheet = XLSX.utils.json_to_sheet(sortedAndFilteredData);
  99. const headerRowIndex = 0;
  100. customHeaders.forEach((header, columnIndex) => {
  101. const address = XLSX.utils.encode_cell({ r: headerRowIndex, c: columnIndex });
  102. if (worksheet[address]) {
  103. worksheet[address].v = header;
  104. }
  105. });
  106. //设置需要合并的单元格
  107. var mergeCells = [];
  108. if(!isObjectEmpty(merge)){
  109. for (var i = 1; i < sortedAndFilteredData.length; i++) {
  110. if (sortedAndFilteredData[i][merge.target] === sortedAndFilteredData[i - 1][merge.target]) {
  111. // 数据相同,合并单元格
  112. let sons = getSonIndex(sortedAndFilteredData,merge);
  113. //console.log(sons);
  114. for(var m=0; m<sons.length;m++){
  115. mergeCells.push({
  116. s:{r: i, c: sons[m]},e:{r: i+1, c: sons[m]}
  117. });
  118. }
  119. }
  120. }
  121. }
  122. console.log("===========打印需要合并的单元格集合============");
  123. console.log(mergeCells);
  124. if (mergeCells.length > 0) {
  125. worksheet['!merges'] = mergeCells;
  126. }
  127. const workbook = XLSX.utils.book_new();
  128. XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
  129. setTimeout(function(){
  130. layer.msg('导出完成');
  131. },3000)
  132. // Export to Excel file
  133. XLSX.writeFile(workbook, name+'.xlsx');
  134. }
  135. //重写渲染方法
  136. tableXlsx.render=function(params){
  137. let is_excel = params.is_excel||false;
  138. let excel_limit = params.excel_limit||1000;
  139. let filter = params.xlsx_filter||[];
  140. let merge = params.xlsx_merge||{};
  141. if(is_excel){
  142. let toolbar = ['filter', {title:'导出EXCEL',layEvent: 'LAYTABLE_EXCEL',icon: 'layui-icon-export'}];
  143. if(!params.defaultToolbar){
  144. params.defaultToolbar = toolbar;
  145. }
  146. else{
  147. let _toolbar = params.defaultToolbar;
  148. params.defaultToolbar = _toolbar.concat(toolbar);
  149. }
  150. if(typeof params.done === "function"){
  151. let _done = params.done;
  152. params.done = function(data, curr, count){
  153. let obj = this;
  154. _done(data, curr, count);
  155. if(!isObjectEmpty(merge)){
  156. tableMerge (obj);
  157. }
  158. tableXlsx.excel(data,excel_limit,obj,filter,merge);
  159. }
  160. }
  161. else{
  162. params.done = function(data){
  163. let obj = this;
  164. if(!isObjectEmpty(merge)){
  165. tableMerge (obj);
  166. }
  167. tableXlsx.excel(data,excel_limit,obj,filter,merge);
  168. }
  169. }
  170. }
  171. var init = tableXlsx._render(params);
  172. return init;
  173. //console.log(params);
  174. };
  175. function tableMerge (myTable) {
  176. var tableBox = $(myTable.elem).next().children('.layui-table-box'),
  177. $main = $(tableBox.children('.layui-table-body').children('table').children('tbody').children('tr').toArray().reverse()),
  178. $fixLeft = $(tableBox.children('.layui-table-fixed-l').children('.layui-table-body').children('table').children('tbody').children('tr').toArray().reverse()),
  179. $fixRight = $(tableBox.children('.layui-table-fixed-r').children('.layui-table-body').children('table').children('tbody').children('tr').toArray().reverse()),
  180. mergeRecord = {},cols = myTable.cols[0];
  181. for (let i = 0; i < cols.length; i++) {
  182. var item3 = cols[i], field=item3.field;
  183. if (item3.merge) {
  184. var mergeField = [field];
  185. if (item3.merge !== true) {
  186. if (typeof item3.merge == 'string') {
  187. mergeField = [item3.merge]
  188. } else {
  189. mergeField = item3.merge
  190. }
  191. }
  192. mergeRecord[i] = {mergeField: mergeField, rowspan:1}
  193. }
  194. }
  195. //console.log(myTable);
  196. $main.each(function (i) {
  197. for (var item in mergeRecord) {
  198. if (i==$main.length-1 || isMaster(i, item)) {
  199. $(this).children('[data-key$="-'+item+'"]').attr('rowspan', mergeRecord[item].rowspan).css('position','static');
  200. $fixLeft.eq(i).children('[data-key$="-'+item+'"]').attr('rowspan', mergeRecord[item].rowspan).css('position','static');
  201. $fixRight.eq(i).children('[data-key$="-'+item+'"]').attr('rowspan', mergeRecord[item].rowspan).css('position','static');
  202. mergeRecord[item].rowspan = 1;
  203. } else {
  204. $(this).children('[data-key$="-'+item+'"]').remove();
  205. $fixLeft.eq(i).children('[data-key$="-'+item+'"]').remove();
  206. $fixRight.eq(i).children('[data-key$="-'+item+'"]').remove();
  207. mergeRecord[item].rowspan +=1;
  208. }
  209. }
  210. })
  211. function isMaster (index, item) {
  212. var mergeField = mergeRecord[item].mergeField;
  213. var dataLength = layui.table.cache[myTable.id].length;
  214. for (var i=0; i<mergeField.length; i++) {
  215. if (layui.table.cache[myTable.id][dataLength-2-index][mergeField[i]]
  216. !== layui.table.cache[myTable.id][dataLength-1-index][mergeField[i]]) {
  217. return true;
  218. }
  219. }
  220. return false;
  221. }
  222. }
  223. function getSonIndex(targetData,mergeField){
  224. let index=[];
  225. index.push(Object.keys(targetData[0]).indexOf(mergeField.target));
  226. if(mergeField.son.length>0){
  227. for(var a=0; a<mergeField.son.length;a++){
  228. index.push(Object.keys(targetData[0]).indexOf(mergeField.son[a]));
  229. }
  230. }
  231. return index;
  232. }
  233. function isObjectEmpty(obj) {
  234. return JSON.stringify(obj) === '{}';
  235. }
  236. function loadScript() {
  237. if (typeof XLSX == 'undefined') {
  238. $.ajax({ //获取插件
  239. url: modPath + '/xlsx.full.min.js' ,
  240. dataType: 'script',
  241. cache: true,
  242. async: false
  243. });
  244. }
  245. }
  246. loadScript();
  247. exports(MOD_NAME, tableXlsx);
  248. });