前端导出多级表头excel

利用js-xlsx插件实现纯前端导出多级表头excel

1、安装插件

npm install xlsx --save
npm install file-saver --save

2、使用

Export2Excel.js 文件中:

/* eslint-disable */
import { saveAs } from 'file-saver'
import XLSX from 'xlsx'

function generateArray(table) {
    var out = [];
    var rows = table.querySelectorAll('tr');
    var ranges = [];
    for (var R = 0; R < rows.length; ++R) {
        var outRow = [];
        var row = rows[R];
        var columns = row.querySelectorAll('td');
        for (var C = 0; C < columns.length; ++C) {
            var cell = columns[C];
            var colspan = cell.getAttribute('colspan');
            var rowspan = cell.getAttribute('rowspan');
            var cellValue = cell.innerText;
            if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;

            //Skip ranges
            ranges.forEach(function (range) {
                if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
                for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
                }
            });

            //Handle Row Span
            if (rowspan || colspan) {
                rowspan = rowspan || 1;
                colspan = colspan || 1;
                ranges.push({
                s: {
                    r: R,
                    c: outRow.length
                },
                e: {
                    r: R + rowspan - 1,
                    c: outRow.length + colspan - 1
                }
                });
            };

            //Handle Value
            outRow.push(cellValue !== "" ? cellValue : null);

            //Handle Colspan
            if (colspan)
                for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
        }
        out.push(outRow);
    }
    return [out, ranges];
};

function datenum(v, date1904) {
    if (date1904) v += 1462;
    var epoch = Date.parse(v);
    return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
}

function sheet_from_array_of_arrays(data, opts) {
    var ws = {};
    var range = {
        s: {
            c: 10000000,
            r: 10000000
        },
        e: {
            c: 0,
            r: 0
        }
    };
    for (var R = 0; R != data.length; ++R) {
        for (var C = 0; C != data[R].length; ++C) {
            if (range.s.r > R) range.s.r = R;
            if (range.s.c > C) range.s.c = C;
            if (range.e.r < R) range.e.r = R;
            if (range.e.c < C) range.e.c = C;
            var cell = {
                v: data[R][C]
            };
            if (cell.v == null) continue;
            var cell_ref = XLSX.utils.encode_cell({
                c: C,
                r: R
            });

            if (typeof cell.v === 'number') cell.t = 'n';
            else if (typeof cell.v === 'boolean') cell.t = 'b';
            else if (cell.v instanceof Date) {
                cell.t = 'n';
                cell.z = XLSX.SSF._table[14];
                cell.v = datenum(cell.v);
            } 
            else cell.t = 's';
            ws[cell_ref] = cell;
        }
    }
    if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
    return ws;
}

function Workbook() {
    if (!(this instanceof Workbook)) return new Workbook();
    this.SheetNames = [];
    this.Sheets = {};
}

function s2ab(s) {
    var buf = new ArrayBuffer(s.length);
    var view = new Uint8Array(buf);
    for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
    return buf;
}

export function export_table_to_excel(id) {
    var theTable = document.getElementById(id);
    var oo = generateArray(theTable);
    var ranges = oo[1];

    /* original data */
    var data = oo[0];
    var ws_name = "SheetJS";

    var wb = new Workbook(),
        ws = sheet_from_array_of_arrays(data);

    /* add ranges to worksheet */
    // ws['!cols'] = ['apple', 'banan'];
    ws['!merges'] = ranges;

    /* add worksheet to workbook */
    wb.SheetNames.push(ws_name);
    wb.Sheets[ws_name] = ws;

    var wbout = XLSX.write(wb, {
        bookType: 'xlsx',
        bookSST: false,
        type: 'binary'
    });

    saveAs(new Blob([s2ab(wbout)], {
        type: "application/octet-stream"
    }), "test.xlsx")
}
// 对此方法进行修改,如下:
export function export_json_to_excel({
    multiHeader2 = [],	// 第一行表头
    multiHeader = [], // 第二行表头
    header,	// 第三行表头   在项目中没有使用到三级表头
    data,
    filename, //文件名
    merges = [], // 合并
    autoWidth = true,
    bookType = 'xlsx'
} = {}) {
    /* original data */
    filename = filename || '列表';
    data = [...data]
    // data.unshift(header);

    for (let i = multiHeader2.length - 1; i > -1; i--) {
        data.unshift(multiHeader2[i])
    }

    for (let i = multiHeader.length - 1; i > -1; i--) {
        data.unshift(multiHeader[i])
    }

    var ws_name = "SheetJS";
    var wb = new Workbook(),
        ws = sheet_from_array_of_arrays(data);

    if (merges.length > 0) {
        if (!ws['!merges']) ws['!merges'] = [];
            merges.forEach(item => {
            ws['!merges'].push(XLSX.utils.decode_range(item))
        })
    }

    if (autoWidth) {
        /*设置worksheet每列的最大宽度*/
        const colWidth = data.map(row => row.map(val => {
        /*先判断是否为null/undefined*/
            if (val == null) {
                return {
                    'wch': 10
                };
            }
            return {
              'wch': 20
          };
            // /*再判断是否为中文*/
            // else if (val.toString().charCodeAt(0) > 255) {
            //     return {
            //         'wch': val.toString().length * 2
            //     };
            // } else {
            //     return {
            //         'wch': val.toString().length
            //     };
            // }
        }))
        /*以第一行为初始值*/
        let result = colWidth[0];
        for (let i = 1; i < colWidth.length; i++) {
            for (let j = 0; j < colWidth[i].length; j++) {
                if (result[j]['wch'] < colWidth[i][j]['wch']) {
                result[j]['wch'] = colWidth[i][j]['wch'];
                }
            }
        }
        ws['!cols'] = result;
    }

    /* add worksheet to workbook */
    wb.SheetNames.push(ws_name);
    wb.Sheets[ws_name] = ws;

    var wbout = XLSX.write(wb, {
        bookType: bookType,
        bookSST: false,
        type: 'binary'
    });
    saveAs(new Blob([s2ab(wbout)], {
        type: "application/octet-stream"
    }), `${filename}.${bookType}`);
}

vue页面中使用:


    // 导出
    download() {
      // 懒加载,@/utils/Export2Excel 此路径为本地路径
      this.downloadLoading = true
        import('@/utils/Export2Excel').then((excel) => {
          const multiHeader = [
            [
              '单据', '', '', '', '', '', '', '', '', '', '', '', '明细', '', '', '', '', '', '', ''
            ]
          ]
          const header = [
            [
              '日期', '单号', '客户', '大区', '经手人', '代码', '名称', '型号', '编码',
              '单位', '数量', '维修员', '代码', '名称', '型号', '单位', '数量', '性质'
            ]
          ]
          const filterVal = ['billDate', 'billNo', 'customer', 'region', 'makePeople', 'code', 'name', 'model', 'coded', 'unit', 'number', 'people', 'listCode', 'listName', 'listModel', 'listUnit', 'listNumber', 'type']// 表头所对应的字段
          const obj = {}
          for (const key in this.conditions) {
            if (key !== 'page' && key !== 'size' && key !== 'sort') {
              obj[key] = this.conditions[key]
            }
          }
          console.log(obj, '传递值')
          // 去后台获取数据
            creatProcessExcel(obj).then(res => {
              this.downloadLoading = false
              const data = res.map(v => filterVal.map(j => v[j]))
              // 进行所有表头的单元格合并
              const merges = [
                'A1:L1', 'M1:R1', 'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2', 'J2', 'K2', 'L2', 'M2', 'N2', 'O2', 'P2', 'Q2', 'R2'
              ]
              excel.export_json_to_excel({
                multiHeader, // 这里是第一行的表头
                header, // 这里是第二行的表头
                data,
                filename: '报表',
                merges
              })
            }).catch(err => {
              this.downloadLoading = false
              console.log(err)
            })
            }
        })
    }

在这里插入图片描述

一、对于MyMulDataGridViewHeader的使用的一个简单的示例 1、数据表 use master go --创建数据库 if exists(select * from sys.sysdatabases where name='TestDB') drop database TestDB go create database TestDB on ( name ='TestDB_data', filename = 'E:\Data\TestDB_data.mdf', size = 5mb, maxsize = 20mb, filegrowth = 10% ) log on ( name ='TestDB_log', filename = 'E:\Data\TestDB_log.ldf', size =3mb, maxsize = 10mb, filegrowth = 1mb ) go use TestDB go if exists(select * from sys.tables where name='UserInfo') drop table UserInfo go create table UserInfo ( id int primary key identity(1,1), uname varchar(20) not null, usex int not null, uage int not null, chineseremark int not null, matchremark int not null, englishremark int not null ) go insert into userinfo values('小谭',1,21,82,90,81) insert into userinfo values('小花',0,21,83,90,82) insert into userinfo values('小华',0,20,84,90,99) insert into userinfo values('小方',0,20,85,92,85) insert into userinfo values('小高',0,21,86,90,88) insert into userinfo values('小宁',1,21,87,90,89) insert into userinfo values('小江',1,21,88,90,92) insert into userinfo values('小艳',0,20,89,90,93) insert into userinfo values('小琼',0,21,92,98,95) go select * from userinfo //后台调用 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.SqlClient; using MyDataGridMultiHeaderHelp; namespace MyTest { public partial class Form3 : Form { public Form3() { InitializeComponent(); } DataGridView dgv = new DataGridView(); private void Form3_Load(object sender, EventArgs e) { SqlConnection conn = new SqlConnection("Server=.;DataBase=TestDB;Uid=sa;Pwd=123456"); SqlCommand cmd = new SqlCommand("select * from userinfo", conn); SqlDataAdapter sda = new SqlDataAdapter(); sda.SelectCommand = cmd; DataSet ds = new DataSet(); sda.Fill(ds); DataTable dt = ds.Tables[0]; //清除原有的控件 if (dgv != null && dgv.Name != "Mydgv") { panel1.Controls.RemoveByKey(dgv.Name); dgv.Dispose(); dgv = null; } dgv = CreateDataGridView(); dgv.DataSource = dt; this.panel1.Controls.Add(dgv); } private MyMulDataGridViewHeader CreateDataGridView() { MyMulDataGridViewHeader dgv = DataIntance.InstanceDataGridView(); DataIntance intance = new DataIntance(dgv); TreeView mytv = new TreeView();//实例树。以树节点为多表头节点 intance.SetData(mytv.Nodes, "学员信息表"); intance.SetData(mytv.Nodes[0].Nodes, "ID编号"); intance.SetData(mytv.Nodes[0].Nodes, "姓名"); intance.SetData(mytv.Nodes[0].Nodes, "性别"); intance.SetData(mytv.Nodes[0].Nodes, "年龄"); intance.SetData(mytv.Nodes[0].Nodes, "成绩"); intance.SetData(mytv.Nodes[0].Nodes[4].Nodes, "语文"); intance.SetData(mytv.Nodes[0].Nodes[4].Nodes, "数学"); intance.SetData(mytv.Nodes[0].Nodes[4].Nodes, "英语"); intance.SetProperty("ID"); intance.SetProperty("uname"); intance.SetProperty("usex"); intance.SetProperty("uage"); intance.SetProperty("chineseremark"); intance.SetProperty("matchremark"); intance.SetProperty("englishremark"); dgv.ColumnTreeView = new TreeView[] { mytv }; dgv.ColumnDeep = 3; return dgv; } } } 二、GridView多表头的使用 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data.SqlClient; using System.Data; using MyDataGridMultiHeaderHelp; namespace MyWeb { public partial class GridViewMulRow : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { GetMulData(); } } private void GetMulData() { SqlConnection conn = new SqlConnection("Server=.;DataBase=TestDB;Uid=sa;Pwd=123456"); SqlCommand cmd = new SqlCommand("select * from userinfo", conn); SqlDataAdapter sda = new SqlDataAdapter(); sda.SelectCommand = cmd; DataSet ds = new DataSet(); sda.Fill(ds); DataTable dt = ds.Tables[0]; this.gvTest.DataSource = dt; this.gvTest.DataBind(); TableCellCollection tcHeader = this.gvTest.HeaderRow.Cells; tcHeader.Clear(); GridViewMulRowHeader gv = new GridViewMulRowHeader(tcHeader); gv.InstanceTableCell("学员信息表</th></tr><tr>", "colspan", "7"); gv.InstanceTableCell("ID编号", "rowspan", "2"); gv.InstanceTableCell("姓名", "rowspan", "2"); gv.InstanceTableCell("性别", "rowspan", "2"); gv.InstanceTableCell("年龄", "rowspan", "2"); gv.InstanceTableCell("成绩</th></tr><tr>", "colspan", "3"); gv.InstanceTableCell("语文"); gv.InstanceTableCell("数学"); gv.InstanceTableCell("英语"); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值