基于node编写excel读取和导出的小工具

 更新时间:2024年11月08日 09:36:43   作者:双下巴大圆脸  
这篇文章主要为大家详细介绍了如何基于node编写一个小工具,可以实现excel读取和导出,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下

背景

领导给同事安排了一个体力活,根据表1(7k+条)筛选表2(4W+条),然后合并两个表相同的数据。听起来是挺简单的需求,加个外表筛选就完事了么,基础的excel操作他还是会的,但是仔细研究了下,发现行不通,FILTER和MATCH都会有一定的局限。并且最后的和并新表也是个困难。于是来求助,看能不能写个小脚本,跑一下解决问题。 我了解了下需求,觉得可行,于是便有了这个脚本

需求描述

表1格式

姓名年龄住址
张三20上海外滩18号
李四21上海浦东新区
王五22御青路1号
。。。。。。。。。

表2格式

昵称注册时间住址
二蛋202118号
双下巴大圆脸2015上海
狗子2022御青路
。。。。。。。。。

他的需求,就是根据表2的住址模糊筛选出表格1住址列所有匹配的数据。然后合并信息。

介绍结束、开始码代码

1、 node读取excel并解析数据

我这里是用了node的xlsx

// 安装xlsx
npm install --save xlsx

xlsx本身提供了一个读取文件方法,就不需要用fs的读取了,核心代码如下

 const workbook = xlsx.readFile(filePath);

 // 我这里只需要第一个,对于多个sheet的情况,这里加个循环就好了
 const sheetName = workbook.SheetNames[0];
 const sheet = workbook.Sheets[sheetName];

 // 将表内容转换为 JSON 数据
 const data = xlsx.utils.sheet_to_json(sheet);

这里推荐使用vscode的调试模式,可以很方便的查看变量的实际值,不用console一遍一遍查看

2、 过滤数据,并合并需要的数据

拿到表1和表2的数据后,就是过滤数据的逻辑了

// 过滤文件
const processingData = ({filterFileData,resourceFileData}) => {
    // 创建一个包含所有 filterFileData.地址 的正则表达式
    const areaPattern = new RegExp(filterFileData.map(item => item['地址']).join('|'));
    
    // 记录匹配结果
    const matches = resourceFileData.reduce((acc, item2) => {
        const match = item2['地址'].match(areaPattern);
        if (match) {
            // 找到匹配的 arr1 项
            const matchedItem1 = filterFileData.find(item1 => item1['地址'] === match[0]);
            
            acc.push({
                filterFileData: matchedItem1,
                resourceFileData: item2
            });
        }
        return acc;
    }, []);
    
    
    return matches
}

对于这种大数据过滤,尽可能的减少循环套循环,我这里是直接把表2住址拼接了一个正则,用match去校验表1的地址列,是否包含表2字符串,有更好的方案,可以在评论区打出来交流下

3、 导出excel

在第二步,我把匹配成功的表1和表2数据都存在了一个数组,然后再第三步使用,这里就是拼数据和写数据了

// 生成筛选后的excel
const writeExcel = ({writeData,resourceFileName}) => {
    const data = writeData.map((item, index) => {
        const {filterFileData,resourceFileData} = item
        return {
            '序号': index + 1,
            '所属区县': filterFileData['所属区县'],
            '户号': resourceFileData['户号'],
            '户名': resourceFileData['户名'],
            '户号地址': resourceFileData['地址'],
            '机构全称': filterFileData['机构全称'],
            '机构类型': filterFileData['机构类型'],
            '机构地址': filterFileData['地址'],
        }
    })
    // 将数据转换为 worksheet
    const worksheet = xlsx.utils.json_to_sheet(data);

    // 创建一个新的 workbook,并附加 worksheet
    const workbook = xlsx.utils.book_new();
    xlsx.utils.book_append_sheet(workbook, worksheet, 'Sheet1');

    let outputFileName = `${resourceFileName.split('.')[0]}-筛选结果.xlsx`
    let outputFilePath = path.join(outputFileDirPath,`./${outputFileName}`)

    // 保存 Excel 文件
    xlsx.writeFile(workbook, outputFilePath);
    
    console.log(`导出文件成功,地址在:${outputFilePath}`)
}

完整代码

// 1、读取filterFile和resourceFile目录下的文件
// 2、过滤源数据
// 3、将过滤好的数据,写入一个excel

const fs = require("fs");
const xlsx = require("xlsx");
const path = require("path");

const resourceFileDirPath = path.join(__dirname, "./resourceFile");
const filterFileName = "filter.xlsx";
const filterFileDirPath = path.join(__dirname, `./filterFile/${filterFileName}`);
const outputFileDirPath = path.join(__dirname, `./outputFile`);

// 读取excel文件
const readFile = (filePath) => {
  return new Promise((resolve, reject) => {
    const workbook = xlsx.readFile(filePath);
    
    // 暂时只解析第一个sheet
    const sheetName = workbook.SheetNames[0];
    const sheet = workbook.Sheets[sheetName];
    
    // 将表内容转换为 JSON 数据
    const data = xlsx.utils.sheet_to_json(sheet);
    
    resolve(data);
  });
};

// 过滤文件
const processingData = ({filterFileData,resourceFileData}) => {
    // 创建一个包含所有 filterFileData.地址 的正则表达式
    const areaPattern = new RegExp(filterFileData.map(item => item['地址']).join('|'));

    // 记录匹配结果
    const matches = resourceFileData.reduce((acc, item2) => {
        const match = item2['地址'].match(areaPattern);
        if (match) {
            // 找到匹配的 arr1 项
            const matchedItem1 = filterFileData.find(item1 => item1['地址'] === match[0]);
            acc.push({
                filterFileData: matchedItem1,
                resourceFileData: item2
            });
        }
        return acc;
    }, []);

    return matches
}
// 生成筛选后的excel
const writeExcel = ({writeData,resourceFileName}) => {
    const data = writeData.map((item, index) => {
        const {filterFileData,resourceFileData} = item
        return {
            '序号': index + 1,
            '所属区县': filterFileData['所属区县'],
            '户号': resourceFileData['户号'],
            '户名': resourceFileData['户名'],
            '户号地址': resourceFileData['地址'],
            '机构全称': filterFileData['机构全称'],
            '机构类型': filterFileData['机构类型'],
            '机构地址': filterFileData['地址'],
        }
    })
    // 将数据转换为 worksheet
    const worksheet = xlsx.utils.json_to_sheet(data);

    // 创建一个新的 workbook,并附加 worksheet
    const workbook = xlsx.utils.book_new();
    xlsx.utils.book_append_sheet(workbook, worksheet, 'Sheet1');

    let outputFileName = `${resourceFileName.split('.')[0]}-筛选结果.xlsx`
    let outputFilePath = path.join(outputFileDirPath,`./${outputFileName}`)

    // 保存 Excel 文件
    xlsx.writeFile(workbook, outputFilePath);
    
    console.log(`导出文件成功,地址在:${outputFilePath}`)
}

const main = async () => {
  
  console.time("总用时");
  const files = fs.readdirSync(resourceFileDirPath);
  let filterFile = await readFile(filterFileDirPath);
//   过滤掉没有地址 和指定关键字的文件
  filterFile = filterFile.filter(item => {
    let area = item['地址']
    let blackList = ['0','无', '无地址']
    return area && !blackList.includes(area)
  })


  console.log(files);
  for (const fileName of files) {
    
    console.time(`${fileName}用时:`);
    console.log(`正在读取文件${fileName}`)
    // 读取待筛选数据
    let resourceFile = await readFile(
      path.resolve(resourceFileDirPath, fileName)
    );
    console.log(`读取文件成功,正在解析文件`)
    // 解析文件
    const writeData = processingData({
        filterFileData: filterFile,
        resourceFileData: resourceFile,
    })
    console.log(`解析文件成功,正在导出文件`)
    // 写入数据
    writeExcel({
        writeData,
        resourceFileName: fileName
    })
    console.timeEnd(`${fileName}用时:`);

  }

  console.timeEnd("总用时");
};

// 执行
try {
  main();
  
} catch (error) {
    console.log('error',error)
}

结语

感觉没有合并这个要求的话,excel是不是可以直接筛选出来了?对excel函数不熟悉,尝试了几下没有实现。

到此这篇关于基于node编写excel读取和导出的小工具的文章就介绍到这了,更多相关node excel读取和导出内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • nodejs如何将高版本降为低版本

    nodejs如何将高版本降为低版本

    在遇到项目依赖低版本Node.js时,直接安装低版本可能会遇到困难,本文提供了一种通过卸载当前高版本Node.js并使用NVM(Node Version Manager)来管理和安装低版本Node.js的方法,首先,需要卸载现有的Node.js环境并清理相关文件
    2024-10-10
  • 简单了解node npm cnpm的具体使用方法

    简单了解node npm cnpm的具体使用方法

    这篇文章主要介绍了简单了解node npm cnpm的具体使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-02-02
  • node.js中fs文件系统模块的使用方法实例详解

    node.js中fs文件系统模块的使用方法实例详解

    这篇文章主要介绍了node.js中fs文件系统模块的使用方法,结合实例形式详细分析了node.js fs文件系统模块各种常见方法的基本使用技巧与相关操作注意事项,需要的朋友可以参考下
    2020-02-02
  • Node.js抓取中文网页乱码问题和解决方法

    Node.js抓取中文网页乱码问题和解决方法

    这篇文章主要介绍了Node.js抓取中文网页乱码问题和解决方法,本文讲解了使用一些开源库解决抓取中出现的乱码问题,需要的朋友可以参考下
    2015-02-02
  • Node.js 异步异常的处理与domain模块解析

    Node.js 异步异常的处理与domain模块解析

    本篇文章主要介绍了Node.js 异步异常的处理与domain模块解析,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • node.js 基于 STMP 协议和 EWS 协议发送邮件

    node.js 基于 STMP 协议和 EWS 协议发送邮件

    这篇文章主要介绍了node.js 基于 STMP 协议和 EWS 协议发送邮件的示例,帮助大家更好的理解和使用node.js,感兴趣的朋友可以了解下
    2021-02-02
  • node.js缺少mysql模块运行报错的解决方法

    node.js缺少mysql模块运行报错的解决方法

    前几天在工作中需要利用node.js连接数据库,通过网上的教程连接后运行却报错了,然后赶紧查找解决的方法,通过测试与朋友的提点,终于解决了这个问题,现在将解决的方法分享给大家,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2016-11-11
  • node.js-path模块你了解多少

    node.js-path模块你了解多少

    这篇文章主要为大家详细介绍了node.js-path模块,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • 解决nodejs报错Error:EPERM:operation not permitted,mkdir‘xxxxxxxxxxxxxxxx‘

    解决nodejs报错Error:EPERM:operation not permitted,mkdi

    这篇文章主要介绍了解决nodejs报错Error:EPERM:operation not permitted,mkdir‘xxxxxxxxxxxxxxxx‘问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • 简单两步使用node发送qq邮件的方法

    简单两步使用node发送qq邮件的方法

    这篇文章主要介绍了简单两步使用node发送qq邮件的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03

最新评论