前端 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自动单元格格式转化的机制。

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

相关推荐
F-2H39 分钟前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
gqkmiss1 小时前
Chrome 浏览器插件获取网页 iframe 中的 window 对象
前端·chrome·iframe·postmessage·chrome 插件
m0_748247553 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
m0_748255024 小时前
前端常用算法集合
前端·算法
真的很上进4 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web130933203984 小时前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_2345 小时前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1235 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~6 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语6 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js