操作Excel文件实现对Excel表格的数据筛选
需求
有多个表格数据,需要按月来分,筛选出每个月中做了胸部和腹部各一次以上的患者数据
技术使用
- node-xlsx: 操作Excel文件
- fs: 用来读写文件
- moment:用来格式化日期类型
实现思路
- 使用
fs.readdir
来读取Excel文件夹下的Excel文件,对文件进行遍历,根据文件名来分月份,把同一个月份的数据整合起来。 - 根据月份遍历数据,进行数据筛选,首先筛选进行胸部和腹部检查的数据,然后在这些数据中根据病历号进行对患者胸部和腹部数据进行统计,遍历对象获取腹部和胸部检查各一次以上的病例号数组,然后根据这个病例号数组与前面筛选进行胸部和腹部检查的数据进行过滤,最后得到的就是每个月中做了胸部和腹部各一次以上的患者数据。
- 根据月份进行对每个月的数据进行Excel文件的创建和文件写入
源码:
// First, we need to install the node-xlsx package using npm
// Run the following command in your terminal:
// npm install node-xlsx
const fs = require("fs");
// Import the node-xlsx package
const xlsx = require('node-xlsx');
const moment = require('moment')
const sheetObj = {};
fs.readdir('./Excel', function(err, files) {
if (err) {
return console.log('Unable to scan directory: ' + err);
}
files.forEach(function(file) {
let _arr = xlsx.parse(`./Excel/${file}`, {
type: 'binary',
cellDates: true
})[0].data
// 校验表格字段是否统一,不统一则会造成数据错乱问题
if (!compareArrays(_arr[0], [
' ', '病人姓名', '病 历 号', '性别',
'年龄', '检查号', '检查项目', '检查部位',
'检查类型', '申请科室', '检查状态', '报告状态',
'检查时间', '审核时间', '报告医生', '报告时间',
'审核医生', '门诊住院号', '病床', '预约号',
'检查分组', '检查设备', '申请医生', '登记医生',
'登记时间', '检查医生', '记录医生', '记录时间',
'复审医生', '复审时间', '检查费用', '报告属性',
'挂起状态', '拍片状态', '分发状态', '备用编号',
'出生日期', '联系电话', '联系地址', '身份证号',
'锁定医生', '签到时间', '申请单号', '临床诊断',
'民族', '所属院区', '费别', '报告修改',
'诊断结论', '检查备注', '胶片费用', '报告备注',
'预约时间', '登记备注', '报告打印次数', '分班',
'身高(cm)', '体重(kg)', 'BMI', '随访临床诊断',
'随访病理诊断', '随访内容', '随访符合', '就诊序号',
'危急分类', '转诊状态', '分配报告医生'
])) {
console.log('有不一致的表格title需要进行处理,否则数据有误', file);
}
if (!sheetObj[Number.parseInt(file)]) {
sheetObj[Number.parseInt(file)] = {
data: _arr
}
} else {
_arr.shift()
sheetObj[Number.parseInt(file)].data.push(_arr)
}
});
for (let i in sheetObj) {
const filteredData = filterData(sheetObj[i].data, {
// '病人姓名': "==='阿迪拉·阿布来提' && ",
'检查部位': ".match(/腹部|胸部/)"
});
let xlsxObj = [{
name: 'firstSheet',
data: filteredData
}]
var buffer = xlsx.build(xlsxObj);
//写入数据
fs.writeFile(`./shaixuan/${i}.XLS`, buffer, function(err) {
if (err) {
throw err;
}
//输出日志
console.log('Write to xls has finished');
})
}
})
// 比较两个数组值是否相等
function compareArrays(arr1, arr2) {
if (arr1.length !== arr2.length) {
console.log('表格标题长度不相等');
return false;
}
for (let i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i]) {
console.log(i, arr1[i]);
return false;
}
}
return true;
}
// Define a function to filter the data
function filterData(data, filter) {
const _filter = {}
for (let i in filter) {
const index = data[0].indexOf(i)
if (index !== -1) {
_filter[index] = filter[i]
}
}
let conditionString = ''
for (let i in _filter) {
conditionString += `data[i][${i}]${_filter[i]}`
}
console.log(conditionString);
const _dataTitle = data.shift()
// Create an empty array to store the filtered data
const filteredData = [];
// filteredData.push(data[0])
// Loop through each row of the data
// 筛选出检查为腹部或者胸部的患者数据
for (let i = 0; i < data.length; i++) {
// Check if the row matches the filter
try {
if (eval(conditionString)) {
// If it does, add it to the filtered data array
filteredData.push(data[i]);
}
} catch (error) {
}
}
// 筛选出有一条腹部和一条胸部及以上的患者数据
_obj = {}
filteredData.forEach((item) => {
let re = item[7].match(/腹部|胸部/)[0]
if (!_obj[item[2]]) {
_obj[item[2]] = {
'腹部': 0,
'胸部': 0
}
_obj[item[2]][re]++
} else {
_obj[item[2]][re]++
}
})
const xiongAndFuIds = []
for (let i in _obj) {
if (_obj[i]['腹部'] > 0 && _obj[i]['胸部'] > 0) {
xiongAndFuIds.push(i)
}
}
let result = []
result = filteredData.filter((item) => {
return (xiongAndFuIds.indexOf(item[2] + '') !== -1)
})
// Return the filtered data
result.unshift(_dataTitle)
// 遍历结果对日期数据进行处理
for (let i = 0; i < result.length; i++) {
for (let j = 0; j < result[i].length; j++) {
if (result[i][j] instanceof Date) {
result[i][j] = moment(result[i][j]).format('YYYY-MM-DD HH:mm:ss')
}
}
}
return result;
}
// Call the filterData function with the sheet data and the filter value
坑点:
1. 日期格式问题
在解析表格数据时,添加{ type: ‘binary’, cellDates: true }配置项
在最后的结果数据时遍历日期类型的数据,使用moment插件进行日期格式化
let _arr = xlsx.parse(`./Excel/${file}`, {
type: 'binary',
cellDates: true
})[0].data
// 遍历结果对日期数据进行处理
for (let i = 0; i < result.length; i++) {
for (let j = 0; j < result[i].length; j++) {
if (result[i][j] instanceof Date) {
result[i][j] = moment(result[i][j]).format('YYYY-MM-DD HH:mm:ss')
}
}
}
2. 写入数据时
需要构建buffer类型数据再使用fs.writeFile进行创建Excel并写入数据
let xlsxObj = [{
name: 'firstSheet',
data: filteredData
}]
var buffer = xlsx.build(xlsxObj);
//写入数据
fs.writeFile(`./shaixuan/${i}.XLS`, buffer, function(err) {
if (err) {
throw err;
}
//输出日志
console.log('Write to xls has finished');
})