使用xlsx.js导出为excel,并实现自适应列宽

介绍使用xlsx.js库实现在导出Excel时自动调整列宽的方法,通过计算单元格中文字长度来确定最佳列宽。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

1 思路:

计算每一列所有单元格的文本长度(包括列头),取最大值作为列宽

2 代码:

getCellWidth为核心方法,用于计算单元格宽度的
如果包含中文,则宽度为:文本长度2.1,否则为:文本长度1.1,这个是我多次测试得到的数值
可以在此方法增加其他规则

function getCellWidth(value) {
  
  // 判断是否为null或undefined
  if (value == null) {
    return 10
  } else if (/.*[\u4e00-\u9fa5]+.*$/.test(value)) {
    // 判断是否包含中文
    return value.toString().length * 2.1
  } else {
    return value.toString().length * 1.1
    /* 另一种方案
    value = value.toString()
    return value.replace(/[\u0391-\uFFE5]/g, 'aa').length
    */
  }
}


// 经过评论反馈优化
function getCellWidth(value) {
  // 判断是否为null或undefined
  if (value == null) {
    return 10;
  } else if (/.*[\u4e00-\u9fa5]+.*$/.test(value)) {
    // 中文的长度
    const chineseLength = value.match(/[\u4e00-\u9fa5]/g).length;
    // 其他不是中文的长度
    const otherLength = value.length - chineseLength;
    return chineseLength * 2.1 + otherLength * 1.1;
  } else {
    return value.toString().length * 1.1;
    /* 另一种方案
    value = value.toString()
    return value.replace(/[\u0391-\uFFE5]/g, 'aa').length
    */
  }
}


/**
 * 将table、json数据导出为excel
 * @param {object} options 
 * @param {[]} options.data 数据源
 * @param {"table"|"json"|"aoe"} options.dataType 数据类型 
 * @param {string} options.sheetName sheet名称
 * @param {boolean} options.saveFile 是否保存为文件,如果为false则返回workBook
 * @param {string} options.fileName 文件名称
 * @param {boolean} options.fitWidth是否自适应列宽(如果dataType="json",配置此属性将无效)
 * @param {[]} options.header xlsx内部参数
 */
export function exportTo(
  {
    data = [],
    dataType = 'table',
    sheetName = 'Sheet1',
    saveFile = true,
    fileName = new Date().$toString() + '.xlsx',
    fitWidth= true,
    header = []
  } = {}
) {
  try {
    if (!XLSX) throw 'exportTo: the plug-in "XLSX" is undefined.'
    if (!data || data.length === 0) throw 'exportTo: data is null or undefined.'

    let sheet = {}
    switch (dataType) {
      case 'table':
        sheet = XLSX.utils.table_to_sheet(data, { raw: true })
        break
      case 'json':
        sheet = XLSX.utils.json_to_sheet(data, { raw: true, header: header })

        if (fitWidth) {
          let colWidths = [],
            colNames = Object.keys(data[0]) // 所有列的名称数组

          // 计算每一列的所有单元格宽度
          // 先遍历行
          data.forEach((row) => {
            // 列序号
            let index = 0
            // 遍历列
            for (const key in row) {
              if (colWidths[index] == null) colWidths[index] = []

              switch (typeof row[key]) {
                case 'string':
                case 'number':
                case 'boolean':
                  colWidths[index].push(getCellWidth(row[key]))
                  break
                case 'object':
                case 'function':
                  colWidths[index].push(0)
                  break
              }
              index++
            }
          })

          sheet['!cols'] = []
          // 每一列取最大值最为列宽
          colWidths.forEach((widths, index) => {
            // 计算列头的宽度
            widths.push(getCellWidth(colNames[index]))
            // 设置最大值为列宽
            sheet['!cols'].push({ wch: Math.max(...widths) })
          })
        }
        break
      case 'aoe':
        // 未实现
        sheet = []
        break
    }

    let workBook = {
      SheetNames: [sheetName],
      Sheets: {
        [sheetName]: sheet
      }
    }

    if (saveFile) {
      XLSX.writeFile(workBook, fileName)
      return true
    } else {
      return workBook
    }
  } catch (error) {
    console.error('exportTo: ', error)
    throw error
  }
}

3 最终效果

在这里插入图片描述
在这里插入图片描述

后语

  • getCellWidth方法可根据实际场景优化编写,尽量简洁,如果做过多判断和计算,数据量大了就会变得很慢
  • exportTo方法在导出三列,4万行数据时的性能如下图,可参考
    在这里插入图片描述
  • 实现更复杂的导出功能,建议在后端服务实现,前端能力有限
  • 其实wps都有这功能,鼠标点一下就行了,不过用户是上帝啊
    在这里插入图片描述
在Vue项目中,使用xlsx导出表格数据实现自适应,通常涉及到操作工作簿(Workbook)、工作表(Sheet)以及样式设置。以下是基本步骤: 1. 首先,你需要安装`xlsx`库,可以使用npm或yarn添加依赖: ```bash npm install xlsx ``` 2. 创建一个方法来生成Excel文件,比如`exportToExcel`,在这个方法中初始化工作簿和工作表: ```javascript import XLSX from 'xlsx'; export function exportToExcel(data, filename) { const workbook = XLSX.utils.book_new(); const worksheet = XLSX.utils.json_to_sheet(data); } ``` 3. 将数据转换为适合导出的工作表,这里可以利用`XLSX.utils.aoa_to_sheet`方法将数组对象数组(AOA)转换成工作表: ```javascript const excelData = data.map(row => Object.values(row)); const worksheet = XLSX.utils.aoa_to_sheet(excelData); ``` 4. 接下来处理自适应。在导出前,遍历数据根据数据的最大长度设置单元格度。例如,我们可以使用`XLSX.SSF`来动态计算: ```javascript const columnWidths = []; for (let i = 0; i < data[0].length; i++) { let cellValue = ''; for (const row of data) { cellValue += row[i] + ','; } const trimmedValue = cellValue.trim(); const width = Math.max(trimmedValue.length * 8, 8); // 简单地假设每个字符需要8个字符的空间 columnWidths.push(width); } // 设置工作表的 XLSX.utils.sheet_add_column(worksheet, {w: columnWidths}); ``` 5. 最后,保存为Excel文件: ```javascript const.xlsx.writeFile(workbook, filename); ```
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云帆Plan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值