nodejs操作excel文件实例,读取sheets, 设置cell颜色

本代码是我帮客户做的兼职的实例,涉及用node读取excel文件,遍历sheets,给单元格设置颜色等操作,希望对大家接活有所帮助。

gen.js

 
let dir="Z:\\武汉烟厂\\山东区域\\备档资料\\销区零售终端APP维护清单\\走访档案\\2024年6月\\200户走访档案\\修改\\";
let dir2="Z:\\liujuan\\new_gen4\\";
 
 
const fs = require('fs');
const path = require('path');
const ExcelJS = require('exceljs');
 
 
// get text in cell
function gv(cell) {
  let v=cell.value; if(!v) return '';
  v = (v.richText? v.richText.map(({ text }) => text).join(''): v.toString());
  return v.trim().toLowerCase().replace(/[(]/g, '(').replace(/[)]/g, ')').replace(/\s/g, '');
}
 
async function make_console(filename, sheetname, list)
{
  const FilePath = path.join(dir2, `console_${filename}_${sheetname}.js`);    
  const file_content=`
let sheet_name="${sheetname}";
let list=${list};
let diffs='', diffj=[]; let nl='\\r\\n';
let noinput=document.getElementById('licensenum');
function check_one(list, itemno) 
{ 
  if(itemno>=list.length){ console.log(diffs); console.log(diffj); return; }
  console.log('checking '+itemno);
  let item=list[itemno]; let { no }=item; noinput.value=no; queryInfo(); 
  setTimeout(()=>{
    let diff={no, cols:[]}; let pushed_diff=false;
    let tbody=document.getElementById('detailTbodyId'); 
    if(!tbody || !tbody.children || tbody.children.length<1 || !tbody.children[0].children || tbody.children[0].children.length<4)
    { let msg='许可证不存在1: '+no; console.log(msg); diffs+=(msg+nl+nl); diffj.push(diff); check_one(list, itemno+1); return; }
    let tds=tbody.children[0].children; 
    if(tds[0].innerText.toLowerCase().trim()!=no) 
    { let msg='许可证不存在2: '+no; console.log(msg); diffs+=(msg+nl+nl); diffj.push(diff); check_one(list, itemno+1); return; }
    
    if(tds[1].innerText.toLowerCase().trim().replace(/[(]/g, '(').replace(/[)]/g, ')').replace(/\\s/g, '')!=item.company) 
    { if(!pushed_diff) { pushed_diff=true; diffj.push(diff); } diff.cols.push('company'); diffs+=(no+': '+nl+tds[1].innerText+nl+item.company+nl+nl);}
    if(tds[2].innerText.toLowerCase().trim().replace(/[(]/g, '(').replace(/[)]/g, ')').replace(/\\s/g, '')!=item.addr) 
    { if(!pushed_diff) { pushed_diff=true; diffj.push(diff); } diff.cols.push('addr'); diffs+=(no+': '+nl+tds[2].innerText+nl+item.addr+nl+nl);}
    if(!tds[3].innerText.toLowerCase().includes(item.date)) 
    { if(!pushed_diff) { pushed_diff=true; diffj.push(diff); } diff.cols.push('date');  diffs+=(no+': '+nl+tds[3].innerText+nl+item.date+nl+nl);}
    check_one(list, itemno+1);
  }, 2000);  
}
check_one(list, 0);
`;
  fs.writeFileSync(FilePath, file_content);
}
 
async function make_mark(filename, sheetname)
{
  const FilePath = path.join(dir2, `mark_${filename}_${sheetname}.js`);    
  const file_content=`
let diffs=
;
let filename='${filename}';
let sheet_name="${sheetname}";
let dir="${ dir.replace(/\\/g, "\\\\") }";
const ExcelJS = require('exceljs');
const fs = require('fs');
 
let style_red={font:{color:{ argb: 'FFFF0000'}}};
let style_black={font:{color:{ argb: 'FF000000'}}};
let style_blue={font:{color:{ argb: 'FF0000FF'}}};
function gv(cell) {
  let v=cell.value; if(!v) return '';
  v = (v.richText? v.richText.map(({ text }) => text).join(''): v.toString());
  return v.trim().toLowerCase().replace(/[(]/g, '(').replace(/[)]/g, ')').replace(/\\s/g, '');
}
 
async function ProcessSheet(sheet)
{
  let rows=sheet.rowCount, cols=sheet.columnCount;
  let found_first_row=false, no_col=0, addr_col=0, date_col=0, company_col=0, result=[];
  for(let row=1; row<=rows; row++)
  {
    console.log('row: ', row);
    let r=sheet.getRow(row);
    if(found_first_row)
    {
      let no_cell=r.getCell(no_col), no=gv(no_cell); if(!no){ for(let col=1; col<=cols; col++) r.getCell(col).style=style_black; continue; }
      let diff; if(diff=diffs.find(d=>d.no==no))
      {  
        let dcols=diff.cols;
        if(dcols.length==0) { for(let col=1; col<=cols; col++) r.getCell(col).style=style_black; no_cell.style=style_blue; continue;}
        for(let col=1; col<=cols; col++)
        {
          let cell=r.getCell(col); 
          if((company_col==col && dcols.includes('company'))||(addr_col==col && dcols.includes('addr'))||(date_col==col && dcols.includes('date'))) 
          { cell.style=style_red; }
          else cell.style=style_black;
        } 
      }
      else
      {  
        for(let col=1; col<=cols; col++) r.getCell(col).style=style_black;
      }
    }
    else
    {
      if(gv(r.getCell(1))=='区域' && gv(r.getCell(3))=='人员')
      { 
        // console.log('成功找到区域和人员列');
        for(let col=3; col<=cols; col++)
        {
          let cell=r.getCell(col); let v=gv(cell);
          if(v=='专卖许可证名称') company_col=col;     
          else if(v=='地址') addr_col=col;     
          else if(v=='许可证到期日期') date_col=col;     
          else if(v=='编号') no_col=col;
        }
        if(company_col==0 || addr_col==0 || date_col==0 || no_col==0) {  console.log('未找到指定的4列'); return;  }
        else { found_first_row=true; console.log('成功找到指定的4列'); }
      }
    }
  } 
}
 
 
async function ProcessFile(ExcelFilePath)
{
  const workbook = new ExcelJS.Workbook(); await workbook.xlsx.readFile(ExcelFilePath);
  let sheets=workbook.worksheets, sheetsCount=sheets.length;
  for(let sheet_index=0; sheet_index<sheetsCount; sheet_index++)
  {
    let sheet=sheets[sheet_index]; if(sheet.name==sheet_name) { await ProcessSheet(sheet); break; }
  }
  await workbook.xlsx.writeFile(ExcelFilePath);
} 
ProcessFile(dir+filename+'.xlsx');
`;
  fs.writeFileSync(FilePath, file_content);
}
 
async function traverseFolder(folderPath) {
  const items = fs.readdirSync(folderPath);
  for(let item of items)
  {
    console.log(item);
    if(item.toLowerCase().includes(".xlsx") && item.indexOf("~")<0)
    {
      const filename=item.substring(0, item.length-5); const ExcelFilePath = path.join(folderPath, item);      
      const workbook = new ExcelJS.Workbook(); await workbook.xlsx.readFile(ExcelFilePath);
      let sheets=workbook.worksheets, sheetsCount=sheets.length;
      for(let sheet_index=0; sheet_index<sheetsCount; sheet_index++)
      {
        let sheet=sheets[sheet_index]; console.log(`sheet ${sheet.id}: ${sheet.name}`); //await ProcessSheet(sheet);
        let rows=sheet.rowCount, cols=sheet.columnCount; console.log(`${rows} rows, ${cols} cols`);
        let found_first_row=false, no_col=0, addr_col=0, date_col=0, company_col=0, result=[];
        for(let row=1; row<=rows; row++)
        {
          let r=sheet.getRow(row);
          if(found_first_row)
          {
            let no=gv(r.getCell(no_col)); if(!no) continue;
            result.push({no, addr: gv(r.getCell(addr_col)), company: gv(r.getCell(company_col)), date: gv(r.getCell(date_col)), });
          }
          else
          {
            if(gv(r.getCell(1))=='区域' && gv(r.getCell(3))=='人员')
            { 
              //console.log('成功找到区域和人员列');
              for(let col=3; col<=cols; col++)
              {
                let cell=r.getCell(col); let v=gv(cell);
                if(v=='专卖许可证名称') company_col=col;     
                else if(v=='地址') addr_col=col;     
                else if(v=='许可证到期日期') date_col=col;     
                else if(v=='编号') no_col=col;               
                // console.log(`  [${row}, ${col}] ${v}`);
              }
              if(company_col==0 || addr_col==0 || date_col==0 || no_col==0) {  console.log('未找到指定的4列'); return;  }
              else { found_first_row=true; console.log('成功找到指定的4列'); }
            }
          }
        }
        //console.log(result.length, result[0]);
        try 
        {
          await make_console(filename, sheet.name, JSON.stringify(result)); await make_mark(filename, sheet.name);
          fs.writeFileSync(`${dir2}${filename}_${sheet.name}_差异.txt`, '');
        } catch (err) {   console.error(err);  }
 
      }        
      
    }
  }
}
 
traverseFolder(dir);
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/781574.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ollama报错:Error: llama runner process has terminated: exit status 0xc0000409

0&#xff0c;背景 今天听说谷歌家的Gemma2性能很好&#xff0c;于是在Ollama上下载到本地测试一下 ollama run gemma2 结果终端里报错 Error: llama runner process has terminated: exit status 0xc0000409 1&#xff0c;原因 原因很简单&#xff0c;新的模型&#xff…

vue项目实现堆叠卡片拖动切换效果

实际效果 实现流程 1. 实现卡片位置堆叠 将父元素的 position 设置成relative &#xff0c;卡片的position 设置成 absolute 即可。 2. 消除图片的移动 如果卡片上有图片&#xff0c;默认拖动的时候就会导致像上图一样变成了选中图片移动&#xff0c;从而没法触发拖动事件。消…

Canal架构以及使用规范

Canal架构以及使用规范 一、Canal的作用 相关文档&#xff1a;GitHub - alibaba/canal: 阿里巴巴 MySQL binlog 增量订阅&消费组件 MySQL主备复制原理 MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events&#xff0c;可…

上网监控软件有哪些?3款实力出众的上网监控软件

为什么需要上网监控软件&#xff1f; 据说&#xff0c;99%的员工上班都会摸鱼&#xff0c;1%的员工上班会窃取公司信息。 所以&#xff0c;因此&#xff0c;监控员工的上网行为是很有必要滴。 总结下来&#xff0c;上网监控软件的作用是&#xff1a; 1.提高生产力&#xff1…

Vben:表格的表头和表格的内容对不齐,以及解决方法

文章目录 一、问题描述二、解决方法 一、问题描述 基于Vue-Vbne-admin框架进行前端开发的时候&#xff0c;调用表格useTable函数实现表格之后&#xff0c;发现表格的表头和表格的内容对不齐。如下图所示。针对这种情况&#xff0c;本文记录了解决方法。 调用的模块如下&#x…

1958.力扣每日一题7/7 Java(100%解)

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;算法练习关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 目录 思路 解题方法 时间复杂度 空间复杂度 Code 思路 首先将指定位…

浏览器插件利器-allWebPluginV2.0.0.14-stable版发布

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX插件直接嵌入浏览器&#xff0c;实现插件加载、界面显示、接口调用、事件回调等。支持谷歌、火狐等浏…

并查集(还有反集也在)

一.定义 定义&#xff1a; 并查集是一种树型的数据结构&#xff0c;用于处理一些不相交集合的合并及查询问题&#xff08;即所谓的并、查&#xff09;。比如说&#xff0c;我们可以用并查集来判断一个森林中有几棵树、某个节点是否属于某棵树等。 主要构成&#xff1a; 并查集…

2-27 基于matlab的一种混凝土骨料三维随机投放模型

基于matlab的一种混凝土骨料三维随机投放模型&#xff0c;为混凝土细观力学研究提供一种快捷的三维建模源代码。可设置骨料数量&#xff0c;边界距离、骨料大小等参数。程序已调通&#xff0c;可直接运行。 2-27 matlab 混凝土骨料三维随机投放模型 - 小红书 (xiaohongshu.com)…

Redis 7.x 系列【16】持久化机制之 AOF

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 概述2. 执行原理2.1 Redis 6.x2.1.1 直接写2.1.2 重写 2.2 Redis 7.x2.2.1 直接写2…

PTA甲级1005:Spell It Right

错误代码&#xff1a; #include<iostream> #include<vector> #include<unordered_map> using namespace std;int main() {unordered_map<int, string> map {{0, "zero"}, {1, "one"}, {2, "two"}, {3, "three&qu…

线程安全的原因及解决方法

什么是线程安全问题 线程安全问题指的是在多线程编程环境中&#xff0c;由于多个线程共享数据或资源&#xff0c;并且这些线程对共享数据或资源的访问和操作没有正确地同步&#xff0c;导致数据的不一致、脏读、不可重复读、幻读等问题。线程安全问题的出现&#xff0c;通常是…

【大数据综合试验区1008】揭秘企业数字化转型:大数据试验区政策数据集大公开!

今天给大家分享的是国内顶级期刊中国工业经济2023年发布的最新期刊《政策赋能、数字生态与企业数字化转型——基于国家大数据综合试验区的准自然实验》文章中所使用到的数据集——国家大数据综合试验区政策数据集以及工具变量数据&#xff0c;该文章基于2009-2019年中国上市企业…

两个全开源的3D模型素材下载网站源码 3D图纸模型素材 三维图形素材会员下载站源码

今天推荐两个全开源的3D模型素材下载网站源码 3D图纸模型素材 三维图形素材会员下载站源码&#xff0c;这两个源码完整&#xff0c;都是基于thinkphp内核开发的&#xff0c;框架稳定&#xff0c;带数据库&#xff0c;源码文件&#xff0c;可以直接部署使用。 第一个&#xff1a…

【数据结构与算法】快速排序挖坑法

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法》 期待您的关注 ​

Redis源码整体结构

一 前言 Redis源码研究为什么先介绍整体结构呢?其实也很简单,作为程序员的,要想对一个项目有快速的认知,对项目整体目录结构有一个清晰认识,有助于我们更好的了解这个系统。 二 目录结构 Redis源码download到本地之后,对应结构如下: 从上面的截图可以看出,Redis源码一…

【密码学】信息安全五大属性

信息安全的五大属性&#xff0c;通常被称为CIA三元组加上两个额外的属性&#xff0c;他们是确保信息在存储、处理和传输过程中保持安全、完整和可用的关键要素。这些属性共同构成了信息安全的基础框架。 一、信息安全五大属性 我先给出一个直观的列表&#xff0c;方面大家后续…

BigDecimal(double)和BigDecimal(String)有什么区别?BigDecimal如何精确计数?

BigDecimal(double)和BigDecimal(String)的区别 double是不精确的&#xff0c;所以使用一个不精确的数字来创建BigDecimal&#xff0c;得到的数字也是不精确的。如0.1这个数字&#xff0c;double只能表示他的近似值。所以&#xff0c;当我们使用new BigDecimal(0.1)创建一个Bi…

69.WEB渗透测试-信息收集- WAF、框架组件识别(9)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;68.WEB渗透测试-信息收集- WAF、框架组件识别&#xff08;8&#xff09; 有无waf存在&am…