前端 XLSX导表避免`1-2-3`字符串双击自动转日期

背景

关于这篇文章出的原因,这里说明一下,有个项目导表功能一直是前端用xlsx这个库去导的。有一天,运营人员过来反馈:"导出的表有瑕疵,当我双击文本11-3-9去修改的时候,它老是把这个11-3-9自动转成2011/3/9,这个能不能规避这个问题"。

问题

gif图看看👀:

拢共就这个问题(全篇解决的就是这个问题,如果遇到同样问题可以看下去,没有的话,也可以看👀也可以不看🙈,我只是做个笔记📒)。后端接口返回的本就是字符串: "9-4-17"... 等等

剖析

当我们重新创建一个新的xlsx表格文件的时候,

科普 : wps、office 等表格软件中当用户输入1-2-3双击或者是回车下,软件会自动将其解释为日期格式,并填充相应的日期。这种行为,是表格软件中具有一个内置的日期识别功能------"数字-数字-数字"这样格式的文本,会自动识别它将其转换成日期格式。

这就解释了运营人员为什么导出表时,一旦双击修改或者触碰到这种"数字-数字-数字"格式的文本会自动转成年/月/日,但这不是他们想要的,他们目前想要的是所见即所得的"数字-数字-数字"文本。

解决

(Excel)常用的自定义格式:

  • G/通用格式 : 设定为G/通用格式的单元格,我们输入数字1、...、9 阿拉伯数字,它会自认定为数字,我们输入文字a、...、z,它会自认定为文字,输入1-2-3,或者1/2/3会自动转为日期。

  • @ :不管我们输入1、...、9或者a、...、z或者1-2-3,或者1/2/3,它一律认定为文字。

这里统计了单元格格式的自定义详解,如有需要,可以去自取所用。

那么,以上去关于Excel的一些定义解释。

在前端,我们如何把表中的单元格设置为@这种通用文本呢。

由于这个项目用了xlsx的库去做的导表,以下就用xlsx来举例:

javascript 复制代码
function changeData (s) {
  if (typeof ArrayBuffer !== 'undefined') {
    buf = new ArrayBuffer(s.length)
    const view = new Uint8Array(buf)
    for (const i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
    return buf
  } else {
    buf = new Array(s.length)
    for (const j = 0; j !== s.length; ++j) buf[j] = s.charCodeAt(j) & 0xFF
    return buf
  }
}
javascript 复制代码
import XLSX from 'xlsx'
import FileSaver from 'file-saver'

/**
    type: '', // 不同的导出格式,比如: json_to_sheet、table_to_book
    elementOrArray: '', // 如果是json_to_sheet就是array, 如果是table_to_book就是元素(这里不涉及table_to_book这种方式)
    filename: '' // 文件名📃
**/
function exportExcel (type, elementOrArray, filename) {
    switch (type) {
    
        //... 有其它case
        
        case 'json_to_sheet':
            const wopts = {
                bookType: 'xlsx',
                bookSST: true,
                type: 'binary'
            }
            let workBook = {
                SheetNames: [],
                Sheets: {},
                Props: {}
            }
            // elementOrArray这里用array是一个表中有很多sheet的情况
            elementOrArray.forEach(element => {
                workBook.SheetNames.push(element.sheetName)
                workBook.Sheets[element.sheetName] = XLSX.utils.json_to_sheet(element.sheetArray)
            })
            
            FileSaver.saveAs(
                new Blob(
                    [changeData(XLSX.write(workBook, wopts))],
                    { type: 'application/octet-stream' }
                   ),
                filename
            )
            
            break
    }
}

✅ 这里的workBook.Sheets['表名']就是这里文件每个单元格的总对象:

A1对象里面有 { t: 's', v: 'id' }, t代表type类型,s即是string, v代表value,每个值的文本。

那么如果要设置每个'1-1-1'这种格式的文本的单元格为通用文本,忽略excel的自动转化日期。

只要在这个对象里添加 z: '@'即可。

kotlin 复制代码
for (const i in workBook.Sheets['表名']) {
    const val = String(workBook.Sheets['表名'][i].v)

    if (val && val.includes('-')) {
      workBook.Sheets['表名'][i].z = '@'
    }
}

如此一来,只要是这个单元格设置了 z: '@',就是告诉excel,这个单元格是文本占位符。不用自动识别转化成日期。

也就是通用代码如下:

javascript 复制代码
const XLSX = require('xlsx')

// 创建一个工作簿
const workbook = XLSX.readFile('文件路径', { cellStyles: true })

// 获得第一个sheet工作表
const worksheet = workbook.Sheets[workbook.SheetNames[0]]

// 设置A1单元格格式为文本
const cell = 'A1'
const style = { t: 's', z: '@' } // z: '@' 表示通用文本格式
worksheet[cell].s = style

// 之后就是导出
XLSX.writeFile(workbook, '存放的文件目录位置', { bookType: 'xlsx', cellStyles: true } )

原理:

把需要设置的单元格,循环去设置单元格格式样式,{ z: '@' } , 就能规避这种前端 XLSX导表避免1-2-3 这种字符串双击自动转日期,或者其他触发了excel自动单元格格式转化的机制。

☎️ 希望对大家有所帮助,如有错误,望不吝赐教,欢迎评论区留言互相学习。感谢阅读,祝您开发有乐趣。

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学2 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端