用 node-xlsx 将从打卡机中导出的考勤信息处理生成考勤表

导出来的考勤信息表(只是获取打卡信息并处理成报表.xlsx , 初始的表格没了) 下图是 “报表.xlsx 

看起来乱糟糟的,虽然能看但是需要花费大量的精力去处理才能成标准表格,下面我直接上代码(代码里已有注释)

const xlsx = require(‘node-xlsx‘);
const fs = require(‘fs‘);

// 获取 xlsx 表格中的数据
let arr = xlsx.parse(‘./报表.xlsx‘)[0].data;
// 工号信息集合
let jobArr = [];
// 打卡时间集合
let timeArr = [];
// 打卡日期集合
let dateArr = [];
// xlsx 留出日期字段作为第一列,方便提取出日期
arr[0].forEach(val => {
  if (‘日期‘ !== val) {
    dateArr.push(val);
  }
})
for (let item of arr.slice(1)) {
  // 有数据
  if (item.length) {
    // 工号和姓名信息
    let numArr1 = [];
    // 打卡时间
    let numArr2 = [];
    if (‘工 号:‘ === item[1]) {
      for (let v = 0; v < item.length; v++) {
        if (‘工 号:‘ === item[v]) {
          numArr1.push(‘number‘);
        } else if (‘姓 名:‘ === item[v]) {
          numArr1.push(‘name‘);
        } else if (null !== item[v]) {
          numArr1.push(item[v]);
        }
      }
      jobArr.push(numArr1);
    } else {
      for (let it = 1; it < item.length; it++) {
        if (item[it]) {
          numArr2.push(item[it]);
        } else {
          numArr2.push(‘ ‘);
        }
      }
      timeArr.push(numArr2);
    }
  } else {
    // 打卡时间无打卡时间记录给此行赋值空数组
    timeArr.push([
      []
    ]);
  }
}
// 工号信息进一步处理成 json 格式,方便后面使用
let arr1 = [];
for (let attr of jobArr) {
  let obj = {};
  for (let t = 0; t < attr.length; t++) {
    if (‘number‘ === attr[t]) {
      obj[‘number‘] = attr[t + 2];
    } else if (‘name‘ === attr[t]) {
      obj[‘name‘] = attr[t + 2];
    }
  }
  arr1.push(obj);
}
// 将上面的工号信息复制一份来与打卡时间处理成一个新的打卡集合
let tempArr = [...arr1];
timeArr.forEach((t, idx) => {
  let startTime = [];
  let endTime = [];
  t.forEach(k => {
    if (5 === k.length) {
      // 打卡时间只有一个,归为下班忘记打卡 -> 这部分人事在检查生成 xlsx 进行核对
      startTime.push(k);
      endTime.push(‘ ‘);
    } else if (10 === k.length) {
      // 有上下班打卡记录
      startTime.push(k.substr(0, 5));
      endTime.push(k.substr(5, 5));
    } else if (10 < k.length) {
      // 多次打卡记录,下班打卡按最后一次打卡为准
      startTime.push(k.substr(0, 5));
      endTime.push(k.substr(k.length - 5, 5));
    } else {
      // 无打卡记录
      startTime.push(‘ ‘);
      endTime.push(‘ ‘);
    }
  })
  tempArr[idx][‘startTime‘] = startTime;
  tempArr[idx][‘endTime‘] = endTime;
})
let array1 = [];
tempArr.forEach((val, index) => {
  let arrlen = [];
  // 将日期与每个人的打卡信息对应起来
  for (let a = 0; a < dateArr.length; a++) {
    let obj11 = {
      date: dateArr[a],
      number: val.number,
      name: val.name,
      start: val.startTime[a] || ‘‘,
      end: val.endTime[a] || ‘‘,
    }
    arrlen.push(obj11);
  }
  array1.push(arrlen);
})
let zs = [];
for (let a = 0; a < dateArr.length; a++) {
  let tt = [];
  for (let b = 0; b < array1.length; b++) {
    array1[b].forEach((v, i) => {
      if (a === i) { // 同一日期下的不同工号打卡时间存到 tt 数组
        tt.push(v);
      }
    })
  }
  // 将同一日期打卡按照时间前后存放到 zs
  zs.push(tt);
}
// xls 表格格式
var temp2 = [];
// 表头
temp2.push([
  ‘日期‘,
  ‘姓名‘,
  ‘上班时间‘,
  ‘下班时间‘,
  ‘备注‘,
])
// 表格的格式是多维数组需要在之前的格式进行处理
zs.forEach((v1) => {
  v1.forEach(v2 => {
    let temp1 = []
    temp1.push(v2.date)
    temp1.push(v2.name)
    let start = ‘‘;
    let end = ‘‘;
    if (v2.start) {
      start = v2.start;
    }
    if (v2.end) {
      end = v2.end;
    }
    temp1.push(start)
    temp1.push(end)
    temp1.push(‘‘)
    temp2.push(temp1)
  })
})
// 单元格的名称
var data = [
  {
    name: ‘打卡考勤‘,
  }
]
data[0][‘data‘] = temp2;
var buffer = xlsx.build(data);
fs.writeFile(‘./考勤.xls‘, buffer, function (err) {
  if (err)
    throw err;
}
);

这里有几个点需要说明一下, 那张导出的考勤表需要处理一下成上面第一张图一样的格式,即第一列写上日期,然后第一列开始放置考勤表里的数据 -> 报表.xlsx

可以直接 node xls.js 

这里我是 windows 系统,所以写了一个 bat (由于我把代码放在 D 盘的 excel 目录下)

D:
D:\excel
node xls.js  

这里附上处理好的图 (注:上班时间 10:00-12:30,14:00-19:00)

如果有大牛路过发现代码错误,希望能指出好让小弟学习,要是有更好的处理方式能够告诉小弟,不胜感激。

原文地址:https://www.cnblogs.com/webBlog-gqs/p/11177594.html

时间: 2024-11-08 22:53:03

用 node-xlsx 将从打卡机中导出的考勤信息处理生成考勤表的相关文章

你知道 http 响应头中的 ETag 是如何生成的吗

关于 etag 的生成需要满足几个条件 当文件不会更改时,etag 值保持不变.所以不能单纯使用 inode 便于计算,不会特别耗 CPU.这样子 hash 不是特别合适 便于横向扩展,多个 node 上生成的 etag 值一致.这样子 inode 就排除了 关于服务器中 etag 如何生成可以参考 HTTP: Generating ETag Header 那么在 nginx 中的 etag 是如何生成的? nginx 中 ETag 的生成 我在网上找到一些资料与源代码了解到了 etag 的计算

GNS3中不同型号路由器支持的模块表

Dynamips 支持的模块 C7200 开始Slot 0:C7200-IO-FE <------> 支持1 个Fastethernet 接口C7200-IO-2FE <------> 支持2 个Fastethernet 接口(DynamipsGUI 2.3 里面没有这个选项,想用只有自己添加了)C7200-IO-GE-E <------> 插这个卡以后会同时出现2 个端口,Ethernet0/0 和GigabitEthernet0/0 (反正我没有用到过这个卡)注意:

[转]从普通DLL中导出C++类 – dllexport和dllimport的使用方法(中英对照、附注解)

这几天写几个小程序练手,在准备将一个类导出时,发现还真不知道如果不用MFC的扩展DLL,是怎么导出的.但我知道dllexport可以导出函数和变量,而且MFC扩展DLL就算是使用了MFC的功能,但能否导出类应该也不是必须用MFC才能够做到,一定是有相应的机制可以实现.于是查了一下MSDN,发现这个机制简单的可怕,原来就和导出函数一样,把dllexport关键字加到类名前就可以了.估计和我一样的同学大有人在,把MSDN的相关文档翻译出来,附上我的注解,希望对大家有用. 评注程序均在Visual S

在Entity Framework 中实现继承关系映射到数据库表

继承关系映射到数据库表中有多种方式: 第一种:TPH(table-per-hiaerachy) 每一层次一张表 (只有一张表) 仅使用名为父类的类型名的一张表,它包含了各个子类的所有属性信息,使用区分列(Disciriminator column)(通常内容为子类的类型名)来区分哪一行表示什么类型的数据. 第二种:TPT(Table-per-type) 每种类型都有一张表(父类及每个子类都有表) 父类.各子类各自都有一张表.父类的表中只有共同的数据,子类表中有子类特定的属性.TPT很像类的继承结

SqlServer将表中数据复制到另一张表

insert into phone2(ph,attr,type,carrier) select top 1000 ph,attr,type,carrier from phone 将表phone的字段和前1000条数据复制到Phone2表 数据库中的某个表删除重复数据(phone2表不能存在) select distinct  * into phone2 from phone 表phone的数据放到phone2中(phone2表可以存在) insert into phone2(ph,attr,ty

C# 中使用 ThoughtWorks.QRCode.dll 生成指定尺寸和边框宽度的二维码

本文介绍在 C# 中使用 ThoughtWorks.QRCode.dll 生成指定尺寸和边框宽度的二维码.网上文章大多只是简单介绍内置参数的设置,根据我的使用目的,增加了自定义目标二维码图片尺寸和白边边框.有需要的朋友们可以试一下,如有bug欢迎指正. 首先,将 ThoughtWorks.QRCode.dll 放在 bin 目录后,在页面中引用: using ThoughtWorks.QRCode.Codec; 生成二维码图片: 1 2 3 4 5 6 7 8 9 10 11 12 13 14

word中导出目录

word中导出目录是一个常见的问题.详细代码如下: public static void ExportMenu(int maxLevel, Document word) //利用标题样式生成目录 { //GoToTheBeginning(word); GotoBookMark("bmContent", word); object start = 0; object end = 0; Range myRange = word.Application.Selection.Range; //

从MySQL全库备份中恢复某个库和某张表【转】

从MySQL全库备份中恢复某个库和某张表 一.全库备份-A [[email protected] backup]#mysqldump -uroot -p123456 --default-character-set=utf8 --single-transaction --extended-insert=false --hex-blob --master-data=2 --log-error=/tmp/test.err --routines --triggers --events --quick -

asp.net中导出Execl的方法

一.asp.net中导出Execl的方法: 在 asp.net中导出Execl有两种方法,一种是将导出的文件存放在服务器某个文件夹下面,然后将文件地址 输出在浏览器上:一种是将文件直接将文件输出流写给浏览器.在Response输出时,\t分隔的数据,导出 execl时,等价于分列,\n等价于换行. 1.将整个html全部输出execl 此法将html中所有的内容,如按钮,表格,图片等全部输出到Execl中.   Response.Clear();       Response.Buffer=