xlsx-style 设置行宽,行高,字体大小方法。(Vue2—基于项目需求)

xlsx-style 设置行宽,行高,字体大小方法。(Vue2—基于项目需求)

1.首先安装依赖

  1. npm install xlsx –save
  2. npm install xlsx-style –save

报错解决方法

1.1.在vue.config.js中添加这段代码,然后重启。

module.exports = {
externals: {
‘./cptable’: ‘var cptable’
}
}

1.2.修改源码

位置在\node_modules\xlsx-style\dist\cpexcel.js

将var cpt = require(‘./cpt’ + ‘able’);修改成var cpt = cptable;

2.随便创建一个目录(vendor)

2.1创建ExcelUtil2.js。

/* eslint-disable eqeqeq */
/**
 * Excel带样式的工具类
 */
/**
 //    * @param dataList Array 查询的数据列表
 //    * @param tHeader Array 最后一行表头
 //    * @param filterKey Array 要导出的字段
 //    * @param merges Array 控制表头的跨行跨列
 //    * @param filename String 导出的excel文件名称
 * @param percent Array 填写有百分号行数,处理百分号
 * @param num Number||string 根据index_type的值来判断,处理百分号
 * @param indexArr Array 获取index_type的值,进行判断
 */

export function exportStyleExcel(tHeader, filterKey, dataList, filename, multiHeader, merges, num, indexArr) {
    import('@/vendor/styleExcel').then(excel => {
        // 过滤表格输出的数据
        const filterData = formatJson(filterKey, dataList)
        const percent = searchKeys(num, indexArr)
        excel.export_json_to_excel({
            multiHeader,
            header: tHeader,
            data: filterData,
            filename,
            percent,
            merges,
            autoWidth: true,
            bookType: 'xlsx',
            myRowFont: '2'
        })
    })
}

function formatJson(filterKey, dataList) {
    return dataList.map(v => filterKey.map(j => {
        // 如果是金额相关的字段,则导出时返回数字格式,以便计算合计
        if (j.indexOf('money') > -1) {
            var num = v[j]
            if (num === null || num === '' || num === undefined) {
                num = 0
            }
            return parseFloat(num)
        } else {
            return v[j]
        }
    }))
}
function searchKeys(needle, haystack) {
    var percent = []
    for (const i in haystack) {
        if (haystack[i] == needle) {
            percent.push(+i + 2)
        }
    }
    return percent
}

2.2创建styleExcel.js

/* eslint-disable no-empty */
/* eslint-disable eqeqeq */
import {saveAs} from 'file-saver'
// import XLSX from "xlsx";
import XLSX from 'xlsx-style'

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
            // eslint-disable-next-line eqeqeq
            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) {
                cell.v = ''
            }
            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()
    var 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({
                                         multiHeader = [],
                                         header,
                                         data,
                                         filename,
                                         merges = [],
                                         percent = [],
                                         autoWidth = true,
                                         bookType = 'xlsx'
                                     } = {}) {
    /* original data */
    filename = filename || 'excel-list'
    data = [...data]
    data.unshift(header)
    for (let i = multiHeader.length - 1; i > -1; i--) {
        data.unshift(multiHeader[i])
    }
    var ws_name = 'SheetJS'
    var wb = new Workbook()
    var 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))
        })
    }
    //设置单元格高度
    const colHeight = data.map(row => row.map(val => {
        /*先判断是否为null/undefined*/
        if (val == null || val == undefined) {
            return {
                'hpx': 50
            };
        }
        /*再判断是否为中文*/
        else if (val.toString().charCodeAt(0) > 255) {
            return {
                'hpx': 50
            };
        } else {
            return {
                'hpx': 50
            };
        }
    }))
    /*以第一行为初始值*/
    let result1 = colHeight[0];
    for (let i = 1; i < colHeight.length; i++) {
        for (let j = 0; j < colHeight[i].length; j++) {
            if (result1[j]['hpx'] < colHeight[i][j]['hpx']) {
                result1[j]['hpx'] = colHeight[i][j]['hpx'];
            }
        }
    }
    debugger
    ws['!rows'] = result1;
// 设置单元格宽度
    if (autoWidth) {
        /* 设置worksheet每列的最大宽度*/
        const colWidth = data.map(row =>
            row.map(val => {
                /* 先判断是否为null/undefined*/
                if (val == null || val == undefined) {
                    return {
                        wch: 120,
                    }
                } else if (val.toString().charCodeAt(0) > 255) {
                    /* 再判断是否为中文*/
                    return {
                        wch: val.toString().length * 3.5,
                    }
                } else {
                    return {
                        wch: val.toString().length * 2,
                    }
                }
            })
        )
        /* 以主表第二行为初始值,因为我的第一行是表格标题,会比较长,所以以主表第二行为初始值*/
        const 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 dataInfo = wb.Sheets[wb.SheetNames[0]]
// 设置单元格框线
    const borderAll = {
        top: {
            style: 'thin'
        },
        bottom: {
            style: 'thin'
        },
        left: {
            style: 'thin'
        },
        right: {
            style: 'thin'
        }
    }

// 给所有单元格加上边框,内容居中,字体,字号,标题表头特殊格式部分后面替换
    for (var i in dataInfo) {
        if (
            i == '!ref' ||
            i == '!merges' ||
            i == '!cols' ||
            i == '!rows' ||
            i == 'A1'
        ) {
        } else {
            dataInfo[i + ''].s = {
                border: borderAll,
                alignment: {
                    horizontal: 'center',
                    vertical: 'center'
                },
                font: {
                    name: '宋体',
                    row: 50,
                    sz: 18
                }
            }
        }
    }

    const arrabc = [
        'A',
        'B',
        'C',
        'D',
        'E',
        'F',
        'G',
        'H',
        'I',
        'J',
        'K',
        'L',
        'M',
        'N',
        'O',
        'P',
        'Q',
        'R',
        'S',
        'T',
        'U',
        'V',
        'W',
        'X',
        'Y',
        'Z'
    ]

// 给标题、表格描述信息、表头等部分加上特殊格式
    arrabc.some(function (v) {
        for (let j = 1; j < (data.length + 1); j++) {
            const _v = v + j
            if (dataInfo[_v]) {
                dataInfo[_v].s = {}
                // 标题部分A1-Z1
                dataInfo['A' + j].s = {
                    border: borderAll,
                    font: {
                        name: '宋体',
                        row: 50,
                        sz: 18,
                        color: {
                            rgb: '000000'
                        },
                        bold: true
                    },
                    alignment: {
                        horizontal: 'center',
                        vertical: 'center'
                    }
                }
                dataInfo[v + j].s = {
                    border: borderAll,
                    numFmt: '0.00',
                    font: {
                        name: '宋体',
                        row: 50,
                        sz: 18,
                        color: {
                            rgb: '000000'
                        }
                    },
                    alignment: {
                        horizontal: 'center',
                        vertical: 'center'
                    }
                }
                // 头部
                if (j == 1) {
                    dataInfo[v + j].s = {
                        border: borderAll,
                        font: {
                            name: '宋体',
                            row: 50,
                            sz: 18,
                            color: {
                                rgb: '000000'
                            },
                            bold: true
                        },
                        alignment: {
                            horizontal: 'center',
                            vertical: 'center'
                        },
                        fill: {
                            fgColor: {
                                rgb: 'f0f0f0'
                            }
                        }
                    }
                }
                // 百分比 %
                if (percent.length != 0) {
                    for (let index = 0; index < percent.length; index++) {
                        if (j == percent[index]) {
                            dataInfo[v + percent[index]].s = {
                                numFmt: '0.00%',
                                border: borderAll,
                                font: {
                                    name: '宋体',
                                    sz: 18,
                                    row: 50,
                                    color: {
                                        rgb: '000000'
                                    }
                                },
                                alignment: {
                                    horizontal: 'center',
                                    vertical: 'center'
                                },
                                fill: {
                                    fgColor: {
                                        rgb: 'FFF8DC'
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    })

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

3.因为xlsx是支持行高的,所以要将xlsx.js(node_modules\xlsx\dist\xlsx.js)里的write_ws_xml_data方法替换到xlsx-style(node_modules\xlsx-style\dist\xlsx.js)里面的write_ws_xml_data。

var DEF_PPI = 96, PPI = DEF_PPI;

function px2pt(px) {
    return px * 96 / PPI;
}

function pt2px(pt) {
    return pt * PPI / 96;
}

function write_ws_xml_data(ws, opts, idx, wb) {
    var o = [], r = [], range = safe_decode_range(ws['!ref']), cell = "", ref, rr = "", cols = [], R = 0, C = 0,
        rows = ws['!rows'];
    var dense = Array.isArray(ws);
    var params = ({r: rr}), row, height = -1;
    for (C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
    for (R = range.s.r; R <= range.e.r; ++R) {
        r = [];
        rr = encode_row(R);
        for (C = range.s.c; C <= range.e.c; ++C) {
            ref = cols[C] + rr;
            var _cell = dense ? (ws[R] || [])[C] : ws[ref];
            if (_cell === undefined) continue;
            if ((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
        }
        if (r.length > 0 || (rows && rows[R])) {
            params = ({r: rr});
            if (rows && rows[R]) {
                row = rows[R];
                if (row.hidden) params.hidden = 1;
                height = -1;
                if (row.hpx) height = px2pt(row.hpx);
                else if (row.hpt) height = row.hpt;
                if (height > -1) {
                    params.ht = height;
                    params.customHeight = 1;
                }
                if (row.level) {
                    params.outlineLevel = row.level;
                }
            }
            o[o.length] = (writextag('row', r.join(""), params));
        }
    }
    if (rows) for (; R < rows.length; ++R) {
        if (rows && rows[R]) {
            params = ({r: R + 1});
            row = rows[R];
            if (row.hidden) params.hidden = 1;
            height = -1;
            if (row.hpx) height = px2pt(row.hpx);
            else if (row.hpt) height = row.hpt;
            if (height > -1) {
                params.ht = height;
                params.customHeight = 1;
            }
            if (row.level) {
                params.outlineLevel = row.level;
            }
            o[o.length] = (writextag('row', "", params));
        }
    }
    return o.join("");
}


效果图
![在这里插入图片描述](https://img-blog.csdnimg.cn/71eb433308854dbab3efbab0cab1edae.png#pic_center)
    调用方法
    import {exportStyleExcel} from '@/vendor/ExcelUtil2'
    handleDownload() {
      this.$message('正在导出,请稍等')
      const tHeader = ['隐患名称', '线路名称', '端点名称', '隐患类型', '隐患位置', '隐患时间', '像素面积', '活动开始时间', '活动结束时间', '是否已读', '是否处理',]  //导出表头
      const filterVal = ['objectName', 'lineName', 'siteName', 'objectType', 'actualPosition', 'time', 'objectArea', 'startTime', 'endTime', 'isRead', 'isHandle',]	//表头对应的字段
      const todoListXlsx = this.DetailsForm  //接口调取的数据
      //tHeader 指的是表头 filterVal 指的是表头字段 this.todoListXlsx 指的是内容 重要的这三个 4 是我处理百分号导出为文本型改为数字型
      exportStyleExcel(tHeader, filterVal, todoListXlsx, '隐患测试报告', [], [], null, false)
    },
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值