——————————☆☆☆——————————

Node 系列相应地址:

  • 代码仓库:https://github.com/LiangJunrong/all-for-one

  • 文章仓库:https://github.com/LiangJunrong/document-library/tree/master/系列-前端资料/Node

——————————☆☆☆——————————

在通过 Puppeteer 操作浏览器下载到 Excel 之后,我们终于可以将预备将多语言的操作玩出花来了。

本篇我们将通过 node-xlsx,对 Excel 进行多语言导入导出的操作。

一 目录

不折腾的前端,和咸鱼有什么区别

目录
一 目录
二 前言
三 快速开始
 3.1 测试导入
 3.2 测试导出
 3.3 测试定制宽度
四 多语言操作
 4.1 导入
 4.2 导出
五 后续
六 参考文献

二 前言

在服务端的工作中,生成报表并送给运营、产品进行分析应该是一门简单手艺。

但是在前端中,能这样耍的机会并不多,所以多语言操作是个好玩的点(没接触过的会觉得比较新鲜)。

当然,既然服务端可以,对 Node.js 来说,提供这种功能也无可厚非。

jsliang 非常懒,所以直奔主题打开 GitHub:

那就第 1 个了,不要搞什么调研不调研的,对于非生产数据来说,我就是玩~

看第一行简介:Excel file parser/builder that relies on js-xlsx.

js-xlsx?这个我知道啊,在 2021.06.03 这一刻有 25.7k Star 的仓库地址:https://github.com/SheetJS/sheetjs

其实一开始试了下它关于 Node 的,enm...一时半会没入门!

但是,我还是用我的 node-xlsx 吧,毕竟例子都在它仓库的 README.md 贴出来了!

三 快速开始

  • 安装包:npm i node-xlsx -S

  • 安装 TypeScript:npm i @types/node-xlsx -D

3.1 测试导入

src/index.ts

import program from 'commander';
import common from './common';
import './base/console';
import xlsx from 'node-xlsx';
import fs from 'fs';program.version('0.0.1').description('工具库')program.command('jsliang').description('jsliang 帮助指令').action(() => {common();});program.command('test').description('测试频道').action(async () => {// 测试新功能的时候使用// 以 buffer 形式导入const workSheetsFromBuffer = xlsx.parse(fs.readFileSync(`${__dirname}/common/dist/Excel 试用文件.xlsx`));console.log(JSON.stringify(workSheetsFromBuffer, null, 2));// 以文件形式导入const workSheetsFromFile = xlsx.parse(`${__dirname}/common/dist/Excel 试用文件.xlsx`);console.log(JSON.stringify(workSheetsFromFile, null, 2));});program.parse(process.argv);

执行 npm run test,控制台打印如下:

---1---
[{"name": "Sheet1","data": [["key","zh-CN","en-US","zh-TW","zh-GZ"],["noMoney","我没钱啦!","I have no money","我沒錢啦!","我冇钱啦!"]]}
]---2---
[{"name": "Sheet1","data": [["key","zh-CN","en-US","zh-TW","zh-GZ"],["noMoney","我没钱啦!","I have no money","我沒錢啦!","我冇钱啦!"]]}
]

OK,都能正常导入~

3.2 测试导出

import program from 'commander';
import common from './common';
import './base/console';
import xlsx from 'node-xlsx';
import fs from 'fs';program.version('0.0.1').description('工具库')program.command('jsliang').description('jsliang 帮助指令').action(() => {common();});program.command('test').description('测试频道').action(async () => {// 测试新功能的时候使用// 导出数据const data = [[1, 2, 3],[true, false, null, 'sheetjs'],['foo', 'bar', new Date('2014-02-19T14:30Z'), '0.3'],['baz', null, 'qux'],];const buffer = xlsx.build([{ name: "jsliang", data: data }]); // 拿到文件 buffer// 写入文件fs.writeFileSync(`${__dirname}/common/dist/test-sheet.xlsx`, Buffer.from(buffer));});program.parse(process.argv);

执行 npm run test 后,目录变成:

打开这个 Excel 文件,可以看到:

好的,导出也 OK 了~

3.3 测试定制宽度

当然,有时候产品非常懒,需要我们将表格宽度给做好成每一列都能宽一点,那就要定制下页面宽度:

index.ts

import program from 'commander';
import common from './common';
import './base/console';
import xlsx from 'node-xlsx';
import fs from 'fs';program.version('0.0.1').description('工具库')program.command('jsliang').description('jsliang 帮助指令').action(() => {common();});program.command('test').description('测试频道').action(async () => {// 测试新功能的时候使用// 导出数据const data = [['key', 'zh-CN', 'en-US', 'zh-TW', 'zh-GZ'],['noMoney', '我没钱啦!', 'I have no money', '我沒錢啦!', '我冇钱啦!'],];// 列宽设置const options = {'!cols': [{ wch: 10 },{ wch: 15 },{ wch: 15 },{ wch: 15 },{ wch: 15 },]}// 生成 bufferconst buffer = xlsx.build([{ name: "jsliang", data: data }], options); // 拿到文件 buffer// 写入文件fs.writeFileSync(`${__dirname}/common/dist/Excel 导出文件.xlsx`, Buffer.from(buffer));});program.parse(process.argv);

执行 npm run test,看到 dist 目录生成:

然后点开「Excel 导出文件.xlsx」,里面内容为:

安逸,满屏飘满 no money~

四 多语言操作

在我们简单了解 node-xlsx 之后,我们就可以通过它完成多语言的导入导出,以及下一章会讲解如何获取需要的资源。

4.1 导入

接「006 - Puppeteer」,我们在上一篇文章已经完成了资源的下载,实际上我们应该一条龙服务,从下载到导入统统给安排了。

那么,我们当前的目录需要改造一番:

- src+ base- common- language+ dist- download.ts- export.ts- import.ts- source.json- index.ts- questionList.ts- sortCatalog.ts- index.ts

文字目录好像没那么清晰,还是贴个图吧:

那么,开始写代码:

questionList.ts - 先明确自己的提问路线

// common 板块的问题咨询路线
export const questionList = {'公共服务': { // q0'文件排序': { // q1'需要排序的文件夹': 'Work 工作', // q2},},'多语言': { // q0'下载多语言资源': { // q3'下载地址': 'Work 工作', // q4},'导入多语言资源': { // q3'下载地址': 'Work 工作', // q4},'导出多语言资源': { // q3'导出全量资源': 'Work 工作','导出单门资源': 'Work 工作',}},
};

index.ts

import { inquirer } from '../base/inquirer';
import { Result } from '../base/interface';
import { sortCatalog } from './sortCatalog';
import { downLoadExcel } from './language/download';
import { importLanguage } from './language/import';
import { exportLanguage } from './language/export';// 问题记录器
const answers = {q0: '',q1: '',q2: '',q3: '',q4: '',
};const common = (): void => {// 问题路线:看 questionList.tsconst questionList = [// q0{type: 'list',message: '请问需要什么服务?',choices: ['公共服务', '多语言']},// q1{type: 'list',message: '当前公共服务有:',choices: ['文件排序']},// q2{type: 'input',message: '需要排序的文件夹为?(绝对路径)',},// q3{type: 'list',message: '请问多语言需要什么支持?',choices: ['下载多语言资源','导入多语言资源','导出多语言资源',],},// q4{type: 'input',message: '资源下载地址(HTTP)?',default: 'https://www.kdocs.cn/l/sdwvJUKBzkK2',}];const answerList = [// q0 - 请问需要什么服务?async (result: Result, questions: any) => {answers.q0 = result.answer;switch (result.answer) {case '公共服务':questions[1]();break;case '多语言':questions[3]();break;default: break;}},// q1 - 当前公共服务有:async (result: Result, questions: any) => {answers.q1 = result.answer;if (result.answer === '文件排序') {questions[2]();}},// q2 - 需要排序的文件夹为?(绝对路径)async (result: Result, _questions: any, prompts: any) => {answers.q2 = result.answer;const sortResult = await sortCatalog(result.answer);if (sortResult) {console.log('排序成功!');prompts.complete();}},// q3 - 请问多语言需要什么支持?async (result: Result, questions: any, prompts: any) => {answers.q3 = result.answer;switch (result.answer) {case '下载多语言资源':case '导入多语言资源':questions[4]();break;case '导出多语言资源':const exportResult = await exportLanguage();if (exportResult) {console.log('导出成功!');prompts.complete();}default: break;}},// q4 - 资源下载地址(HTTP)?async (result: Result) => {answers.q4 = result.answer;const download = async (): Promise<any> => {const downloadResult = await downLoadExcel(result.answer);if (downloadResult) {console.log('下载成功!');return true;}};switch (answers.q3) {case '下载多语言资源':await download();break;case '导入多语言资源':await download();const importResult = await importLanguage();if (importResult) {console.log('导入完毕!');}default:break;}},];inquirer(questionList, answerList);
};export default common;

需要注意的是,我们如果要导入的话,肯定有个对应的资源文件,这边就用 source.json 演示:

source.json

{"zh-CN": {},"en-US": {},"zh-TW": {},"zh-GZ": {}
}

简版内容如下,通过 import.ts 导入资源并填充里面内容:

import.ts

import xlsx from 'node-xlsx';
import fs from 'fs';
import path from 'path';export const importLanguage = async (): Promise<boolean> => {const language = JSON.parse(fs.readFileSync(path.join(__dirname, './source.json'), 'utf8'));const workSheetsFromBuffer = xlsx.parse(fs.readFileSync(path.join(__dirname, '/dist/Excel 试用文件.xlsx'),),);const sheet1Data = workSheetsFromBuffer[0].data.map(i => i.map(j => String(j)));// 获取头部数据const header = sheet1Data[0];// 查找 key 对应列let keyIndex = 0;for (let i = 0; i < header.length; i++) {if (header[i] === 'key') {keyIndex = i;break;}}if (keyIndex < 0) {console.error('未找到 key 对应列!');return false;}// 设置资源内容const fullLanguage: any[] = [...Object.keys(language), ...header.filter((item: any) => item !== 'key')];const filterFullLanguage = new Set();for (let i = 0; i < fullLanguage.length; i++) {if (!filterFullLanguage.has(fullLanguage[i])) {filterFullLanguage.add(fullLanguage[i]);// 如果没有该种语言,则新增if (!language[fullLanguage[i]]) {language[fullLanguage[i]] = {};}}}// 获取内容数据const body = sheet1Data.slice(1);for (let i = 0; i < body.length; i++) {for (let j = 0; j < body[i].length; j++) {if (j !== keyIndex) {const nowLanguage = language[header[j]]; // 一个损耗性能的操作,每次都会读取新列表,但是我不想优化const nowKey = body[i][keyIndex]; // 获取这一行的 keynowLanguage[nowKey] = body[i][j]; // 替换 key}}}fs.writeFileSync(path.join(__dirname, './source.json'), JSON.stringify(language, null, 2), 'utf8');return true;
};

export.ts

export const exportLanguage = async (): Promise<boolean> => {// 详细内容待补充return await true;
};

编写完毕,执行 npm run jsliang,按照提问逐个回车:

然后代码跑起来(姿势很帅),成功导入:

这样导入流程就完毕了。

当然,导入的过程中,还需要修复对齐 key(即某中文 key 情况下,其他资源未翻译;或者删除 key 资源),这些就不哆嗦列举了,需要的时候补充写一写,也不难~

4.2 导出

导入尚且如此,导出就更轻松了:

export.ts

import xlsx from 'node-xlsx';
import fs from 'fs';
import path from 'path';export const exportLanguage = async (): Promise<boolean> => {const languageData = JSON.parse(fs.readFileSync(path.join(__dirname, './source.json'), 'utf8'));// 组装头部数据const header = Object.keys(languageData);// 组装内容数据const chineseKeyList = Object.keys(languageData['zh-CN']);const body: any[] = [];for (let i = 0; i < chineseKeyList.length; i++) {const nowKey = chineseKeyList[i];const nowFloor = [nowKey];console.log(nowFloor, nowKey);for (let j = 0; j < header.length; j++) {const nowLanguage = header[j];nowFloor.push(languageData[nowLanguage][nowKey]);}body.push(nowFloor);}// 导出数据const data = [['keys', ...header],...body,];const buffer = xlsx.build([{ name: "jsliang", data: data }]); // 拿到文件 buffer// 写入文件fs.writeFileSync(path.join(__dirname, './dist/Excel 导出文件.xlsx'), Buffer.from(buffer));return await true;
};

执行 npm run jsliang,按流程点点:

然后就看下 dist 目录有没有对应的文件:

在打开文件看看:

OK,搞定,收工~

五 后续

那么,Excel 的操作流程我们就安排得明明白白了。

再往下一章,jsliang 可能开启 Node 服务,完成简单网站的搭建,不过 jsliang 于 2018 年写过一篇 Node 从 0 基础到企业官网的文章了,所以咱们尝试搞个小游戏吧,嘿嘿~

当前阶段算上 Node 初篇完毕,主要也没啥内容,后续会补充开启服务,WebSocket 等内容,冲鸭~

六 参考文献

  • nodejs 实现导出 excel 报表

  • GitHub:SheetJS

  • GitHub:node-xlsx


jsliang 的文档库由 梁峻荣 采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议 进行许可。
基于 https://github.com/LiangJunrong/document-library 上的作品创作。
本许可协议授权之外的使用权限可以从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处获得。

Node 系列 - 007 - node-xlsx相关推荐

  1. 入门到放弃node系列之网络模块(二)

    为什么80%的码农都做不了架构师?>>>    前言 本文首发[一名打字员] 上一节我们刚刚介绍完node的HTTP和HTTPS模块,相信我们也对nodejs有了更深层次的理解,接下 ...

  2. 一头扎进Node系列 - 目录

    前言 本系列是属于初级教程.博主我也还只是一个node的新兵蛋子,想通过学习官网的API文档,慢慢的打好Node基础.当然后期这系列文档会慢慢完善,并且会添加一些项目实战中遇到的一些问题以及解决方案! ...

  3. 四、node系列之购物车的业务逻辑

    node系列之购物车的业务逻辑 1.加入购物车业务逻辑 1.1 创建购物车模块 myapp/routes/cart.js 1.2 app.js中注册路由 1.3 设计购物车的数据库集合 1.4 加入购 ...

  4. Node 系列 - 003 - commander.js

    ----------☆☆☆---------- Node 系列相应地址: 代码仓库:https://github.com/LiangJunrong/all-for-one 文章仓库:https://g ...

  5. Node.js(一)——(Node.js安装及使用,通过Node.js搭建服务器,模块化及自定义模块,npm/yarn/nvm,内置模块fs的使用,buffer及stream,新闻列表案例)

    目录 1.Node.js介绍 2.安装Node.js 3.使用Node.js实现第一个服务器 3.1初步感受Node.js 3.2Google Chrome 默认非安全端口列表,尽量避免以下端口. 3 ...

  6. 安装node.js 附带node.js以及npm初步认识 设置淘宝/npm镜像 命令

    1,安装: 下载地址:https://nodejs.org/en/download/ 0积分:https://download.csdn.net/download/weixin_42859280/12 ...

  7. elasticsearch负载均衡节点——客户端节点 node.master: false node.data: false 其他配置和master 数据节点一样...

    elasticSearch的配置文件中有2个参数:node.master和node.data.这两个参 数搭配使用时,能够帮助提供服务器性能. 数据节点node.master: false node. ...

  8. node n 切换node版本失败_node版本如何升级

    爬坑后的结论:window系统升级node只能到node官网下载window安装包来覆盖之前的node. 以下为我的爬坑之路: 今天安装了vue cli 3,使用命令时报: You are using ...

  9. 什么是node网站服务器,node.js

    Node.js发布于2009年5月,由Ryan Dahl开发,是一个基于Chrome V8引擎的JavaScript运行环境,使用了一个事件驱动.非阻塞式I/O模型,[1] 让JavaScript 运 ...

最新文章

  1. 学以致提高学生操作计算机能力,【学以致用】提供学习平台,提升学生实际应用能力...
  2. 种子谋定翻身-农民丰收节交易会·万建民:破解卡脖子难题
  3. 2008秋季-计算机软件基础-0917课堂用例(2)
  4. cta策略 有哪些_【投资理财】基本面拐点已至,当前环境适合配置哪些策略?...
  5. Android MVC模式在android系统中的体现
  6. Javaweb学习笔记——(三)——————JavaScript基础DOM基础
  7. 中蜂几月份自然分蜂_蜜蜂什么时候自然分蜂?
  8. 阿里巴巴分布式消息系统的演进之路
  9. qrect在图片上显示矩形框_Mac上用LabelImg手动标记图片
  10. html简单网页代码
  11. C语言实现“轰炸”代码(QQ)
  12. Meshlab快捷键与菜单功能翻译
  13. 365抽奖软件 v6.1.7
  14. 计算机的显示器颜色怎么调,电脑显示器怎样调色差
  15. 如何把项目部署到腾讯云服务器(附带常见错误)
  16. 我的三年自学深度学习之路
  17. OpenWrt网络配置
  18. Nacos 简介与 本地调试环境搭建
  19. 线性代数基本知识-思维导图
  20. [iOS]-Category、Extension和关联对象

热门文章

  1. 操作Doris数据库错误记录——insert has filtered data in strict mode
  2. App成功开发3条法则
  3. 什么是组合索引?在哪些场景中,组合索引会失效?
  4. python从右向左第三个字符_字符串是一个字符序列,例如,字符串s,从右侧向左第3个字符用________索引。...
  5. 《游戏编程模式》--行为模式--学习
  6. 15分钟!一键部署Oracle 12CR2单机CDB+PDB
  7. 在Facebook广告投放时需要注意这些问题
  8. Amount of Degrees
  9. USACO December 2022 Contest 铜级题目
  10. 【并发】线程同步——锁Lock与synchronized比较