js 导出多sheet表格

原文github地址:https://github.com/wangyunhui1993/neo-export-excel

var tablesToExcel = (function () {
  var uri = "data:application/vnd.ms-excel;base64,",
    html_start = `<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">`,
    template_ExcelWorksheet = `<x:ExcelWorksheet><x:Name>{SheetName}</x:Name><x:WorksheetSource HRef="sheet{SheetIndex}.htm"/></x:ExcelWorksheet>`,
    template_ListWorksheet = `<o:File HRef="sheet{SheetIndex}.htm"/>`,
    style = `<style type="text/css">
    table th{text-align: center;font-weight: bold;font-size:16px;background-color: #559EC6;color:#fff;height:30px;}
    table td{text-align: center;font-size:16px;}
    </style>`,
    template_HTMLWorksheet =
      `
------=_NextPart_dummy
Content-Location: sheet{SheetIndex}.htm
Content-Type: text/html; charset=utf-8
` +
      html_start +
      `
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link id="Main-File" rel="Main-File" href="../WorkBook.htm">
    <link rel="File-List" href="filelist.xml">
    ${style}
</head>
<body><table  border="1">{SheetContent}</table></body>
</html>`,
    template_WorkBook =
      `MIME-Version: 1.0
X-Document-Type: Workbook
Content-Type: multipart/related; boundary="----=_NextPart_dummy"
------=_NextPart_dummy
Content-Location: WorkBook.htm
Content-Type: text/html; charset=utf-8
` +
      html_start +
      `
<head>
<meta name="Excel Workbook Frameset">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="File-List" href="filelist.xml">
<!--[if gte mso 9]><xml>
 <x:ExcelWorkbook>
    <x:ExcelWorksheets>{ExcelWorksheets}</x:ExcelWorksheets>
    <x:ActiveSheet>0</x:ActiveSheet>
 </x:ExcelWorkbook>
</xml><![endif]-->
</head>
<frameset>
    <frame src="sheet0.htm" name="frSheet">
    <noframes><body><p>This page uses frames, but your browser does not support them.</p></body></noframes>
</frameset>
</html>
{HTMLWorksheets}
Content-Location: filelist.xml
Content-Type: text/xml; charset="utf-8"
<xml xmlns:o="urn:schemas-microsoft-com:office:office">
    <o:MainFile HRef="../WorkBook.htm"/>
    {ListWorksheets}
    <o:File HRef="filelist.xml"/>
</xml>
------=_NextPart_dummy--
`,
    base64 = function (s) {
      return window.btoa(unescape(encodeURIComponent(s)));
    },
    format = function (s, c) {
      return s.replace(/{(\w+)}/g, function (m, p) {
        return c[p];
      });
    };
  return function (tables, filename) {
    var context_WorkBook = {
      ExcelWorksheets: "",
      HTMLWorksheets: "",
      ListWorksheets: "",
    };
    tables.forEach((item, index) => {
      var SheetName = item.name || `sheet${index + 1}`;
      context_WorkBook.ExcelWorksheets += format(template_ExcelWorksheet, {
        SheetIndex: index,
        SheetName: SheetName,
      });
      context_WorkBook.HTMLWorksheets += format(template_HTMLWorksheet, {
        SheetIndex: index,
        SheetContent: item.html,
      });
      context_WorkBook.ListWorksheets += format(template_ListWorksheet, {
        SheetIndex: index,
      });
    });
    console.log(
      "context_WorkBook",
      format(template_WorkBook, context_WorkBook)
    );
    var link = document.createElement("A");
    link.href = uri + base64(format(template_WorkBook, context_WorkBook));
    link.download = filename || "Workbook.xls";
    link.target = "_blank";
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };
})();
/* var sheet_1 = `<thead><tr><th>这是sheet1的表头</th></tr><thead><tbody><tr><td>这是sheet1的表体</td></tr><tbody>`
var sheet_2 = `<thead><tr><th>这是sheet2的表头</th></tr><thead><tbody><tr><td>这是sheet2的表体</td></tr><tbody>`
var sheets = [
  { name: "合并详情", html: sheet_1 },
  { name: "发票详情", html: sheet_2 }
];
tablesToExcel(sheets, "导出的excel"); */
function getTable(head, list, tableInfo) {
  //获取完整表格
  let content = "";
  content += getH(head);
  content += "<tbody>";
  list.forEach((item) => {
    content += getB(item, tableInfo);
  });
  content += "</tbody>";
  return content;
  // let ele = document.createElement("table");
  // ele.innerHTML = content;
  // return ele;
}

function getH(list) {
  //拼接表头
  let strH = "<thead><tr>";
  for (var item of list) {
    strH += `<th>${item}</th>`;
  }
  strH += "</tr></thead>";
  return strH;
}

/* 
  用写html的方法导出excel时,excel会自动把一些格式转换一下,有时达不预期的效果,此时可以通过样式进行调整
  mso-number-format:@   文本
  mso-number-format:"0.000"   数字 
  mso-number-format:"mm/dd/yy"    日期 
  mso-number-format:"d\-mmm\-yyyy"   日期
  mso-number-format:Percent   百分比
*/

function getB(list, tableInfo) {
  console.log("list, tableInfo", list, tableInfo);
  //拼接表体
  let strB = "<tr>";
  list.forEach((item, index) => {
    let format = tableInfo[index].format;
    let style = tableInfo[index].style;
    var styleStr = "";
    if (typeof style == "function") {
      let styleFn = style(item, tableInfo);
      style = styleFn;
    }
    if (style instanceof Object) {
      for (var eleKey in style) {
        styleStr += `${eleKey}:${style[eleKey]};`;
      }
    } else {
      style = "";
    }
    if (typeof format == "string") {
      strB += `<td style="mso-number-format:'${format}';${styleStr}">${item}</td>`;
    } else if (typeof format == "function") {
      strB += `<td style="mso-number-format:'${format(
        item,
        tableInfo
      )}';${styleStr}">${item}</td>`;
    } else {
      // eslint-disable-next-line no-useless-escape
      strB += `<td style="mso-number-format:'\@';${styleStr}">${item}</td>`;
    }
  });
  strB += "</tr>";
  return strB;
}

const exportToExcel = function (excelInfo) {
  let excelName = excelInfo.name || "Workbook";
  let sheetList = excelInfo.sheets;
  if (sheetList && sheetList instanceof Array) {
    sheetList.forEach((item) => {
      let content = item.content;
      if (content.nodeType) {
        item.html = content.innerHTML;
      } else if (content instanceof Array) {
        let t_c = [],
          t_e = [];
        for (var H of item.tHeader) {
          t_e.push(H.key);
          t_c.push(H.name || "");
        }
        let data = formatJson(t_e, item.content);
        item.html = getTable(t_c, data, item.tHeader);
      } else if (typeof content == "string") {
        item.html = content;
      }
    });
    tablesToExcel(sheetList, excelName);
  } else {
    console.error("sheets为必传属性");
  }
};
const formatJson = (filterVal, jsonData) => {
  return jsonData.map((v) => filterVal.map((j) => v[j] || ""));
};

/* 
// 单元格内换行:<br style='mso-data-placement:same-cell;'/>
style:单元格样式,支持函数、对象
format:单元格格式,支持函数、对象
content:当为数组是需要和tHeader搭配使用,当为字符串时表示导出的表格元素
const tHeader = [
            { key: "tbbm", name: "填报部门" },
            {
              key: "ypsj",
              name: "研判时间",
              style:'',
              format:'',
            },
            { key: "yxq", name: "有效期" },
            { key: "dtfxsj", name: "动态风险事件" },
            { key: "sjly", name: "事件来源" },
            { key: "jhlb", name: "计划类别" },
            {
              key: "jczdnr",
              name: "检查重点内容",
            },
          ];
          let excelInfo = {
            name: "动态风险事件上报",
            sheets: [
              {
                name: "动态风险事件上报sheet1",
                content: list,
                tHeader: tHeader,
              },
              {
                name: "动态风险事件上报sheet2",
                content: list,
                tHeader: tHeader,
              },
            ],
          };
          importToExcel(excelInfo)
*/

  

posted @ 2020-09-10 14:24  neo_o  阅读(1394)  评论(0编辑  收藏  举报

愿你的生活只有诗和远方