【Vue项目】使用 xlsx-template 在xlsx文件内实现占位符替换

为什么有这种需求

有时候我们需要在网页进行 office 文本编辑,但是 office 文件的编辑选项过多且不开源,一定需要集成其它在线编辑方案才可以,比如金山文档的在线协作方案
但是有时候我们并不需要如此健壮的成熟方案,很多时候我们对一个现在 office 模版只需要修改其中几项的文字就可以了。这种情况下,我们只需要写一个现成的表单,像问卷一样填写相关内容,把填写的内容再转入到 office 文件中就可以了。

模版文件.png

如上,现在我希望用户在我的网页上只填写 name 与 id
之后网页会将 xlsx 文件中对应占位符替换成用户填写的对应内容,这个需求可以通过 xlsx-template 来实现

项目版本

测试项目为Vue项目,Vue版本为3,webpack版本为5(重点,xlsx-template库与这个版本有冲突,后面讲解决方案),包管理器为 yarn(npm也可以),测试文件类型为 typeScript(使用javaScript也可以,稍作修改即可)

代码

安装 xlsx-template: 
npm i xlsx-template 或 yarn add xlsx-template
安装 jszip-utils: 
npm i jszip-utils 或 yarn add jszip-utils
安装 file-saver: 
npm i file-saver 或 yarn add file-saver

// @ts-ignore
import JSZipUtils from 'jszip-utils'
import {saveAs} from 'file-saver'
执行代码:
const XlsxTemplate = require('xlsx-template');
JSZipUtils.getBinaryContent('/xlsx/template1.xlsx',(err: any, data: Buffer) => {
const template = new XlsxTemplate(data);

// Replacements take place on first sheet
const sheetNumber = 1;

// Set up some placeholder values matching the placeholders in the template
const values = {
    name: '人人人',
    id: 888888
};

// Perform substitution
template.substitute(sheetNumber, values);

// Get binary data
let templateData = template.generate({type: 'blob'});
    saveAs(templateData, 'new.xlsx')
})
vue.config.js 设置

const {defineConfig} = require('@vue/cli-service')
const webpack = require('webpack')

module.exports = defineConfig({
    lintOnSave: false,
    transpileDependencies: true,
    configureWebpack: {
        plugins: [
            new webpack.ProvidePlugin({
                process: 'process/browser',
                Buffer: ['buffer', 'Buffer']
            })
        ],
        resolve: {
            fallback: {
                "path": require.resolve('path-browserify'),
                "util": require.resolve("util/"),
                "stream": require.resolve("stream-browserify"),
                "constants": require.resolve("constants-browserify"),
                "assert": require.resolve("assert/"),
                "fs": false,
            }
        }
    }
})

注意:上文中类似库名的地方,除了fs和buffer外都需要使用 npm 或 yarn 安装对应的库
比如:npm i util 与 yarn add assert
需要加载的库名如下:
webpack  process  path-browserify  util  stream-browserify  constants-browserify  assert

vue.config.js 讲解

因为 xlsx-template 库是在 webpack4 的基础上打包的,在 webpack5 的项目上出现在非常多的错误,故需要如上 vue.config.js 的设置。
上面的设置虽少,但是解决了至少4个类型的错误,共数十个具体错误

  1. Can't resolve 'fs' 问题
    这个问题其实是因为 fs 库已经无法直接调用,而在 xlsx-template 代码却有调用
    使用 resolve.fallback: { fs: false } 可以跳过编译检测
Can't resolve 'fs'

解决自:https://github.com/webpack-contrib/css-loader/issues/447#issuecomment-761853289

  1. process is not defined 问题
    这个问题可能是因为在 webpack5 中 process 已经无法在项目获取,需要使用外部引用并转换成同名引用
    使用 new webpack.ProvidePlugin({ process: 'process/browser' }) 可以解决
process is not defined

解决自:https://stackoverflow.com/questions/41359504/webpack-bundle-js-uncaught-referenceerror-process-is-not-defined

  1. 各种 webpack < 5 开头的问题
    这种问题在控制台已经说明了解决方法,只是可能很多人不知道具体应该把解决代码写在哪里,上图中的 resolve.fallback: { ... } 中除了 fs:false 其它都是会出现问题的部分的解决方法
    这个问题仍然是 webpack 版本造成的,但是不能像 fs 一样忽略,必须注入
webpack < 5 开头的问题之一

解决自:https://stackoverflow.com/questions/64557638/how-to-polyfill-node-core-modules-in-webpack-5

  1. Cannot read properties of undefined (reading 'filename') 或 buffer 问题
    在vue3项目上会报 “Cannot read properties of undefined”,但是在我的另一个vue2项目中会直接报找不到 buffer 函数问题,所以这是个无法调用到 buffer api 的问题
buffer问题

解决自:https://stackoverflow.com/questions/66156756/how-to-polylfill-buffer-for-jsonwebtoken-in-wepack-5

成果

测试用 xlsx

写在后面

上文中的测试代码只有加载本地 xlsx 文件,如果需要从服务器下载再替换,无论您使用什么网络加载框架都需要注意:
xlsx-template 框架需要传入 buffer 类型数据,所以请做转换,或直接找以 buffer 类型下载的网络框架

xlsx-template 的 generate 函数注意传入 { type: 'blob' } 这样直接可以保存成 blob 类型数据,方便后面向服务器进行网络上传

为了避免后续文中出现的库有更新,使本文内容出现偏差,提供本测试项目的 package.json 中各个库的版本号:

    "assert": "^2.0.0",
    "constants-browserify": "^1.0.0",
    "core-js": "^3.8.3",
    "docxtemplater": "^3.37.11",
    "file-saver": "^2.0.5",
    "jszip-utils": "^0.1.0",
    "path": "^0.12.7",
    "pizzip": "^3.1.4",
    "stream-browserify": "^3.0.0",
    "util": "^0.12.5",
    "vue": "^3.2.13",
    "vue-router": "^4.0.3",
    "webpack": "^5.88.1",
    "xlsx-template": "^1.4.3"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容