先放结果吧。
这里的记录将会成为我私人项目(基于node.js和react)里的一个小小的模块。这一切都是开源的。数据库放在本地。你可以在github上找到它。 (https://github.com/dangjingtao/redCandle) 文中所涉及人名及事项均为虚构。
用Excel来设置排版是一件不是一件非常轻松的事情。对于经常发布排班的机构来说,办公自动化可以作坊式的排版方法。实现生产力的解放。
假设我手上拿到这样一份excel排班表
应当如何快速排版呢?
后端需要安装依赖:
"node-xlsx": "^0.11.2",
"xlsx": "^0.11.17"
在后端
/**
* src/controler/user.js
* 导入
* @returns {Promise|void|PreventPromise|*}
*/
import xlsx from 'node-xlsx'; async importAction() {
let param = this.file('file'); let obj = xlsx.parse(param.path); let list=obj[0].data; this.success({list:list}); }
那么这个接口就写好了。(httpL//localhost:8360/user/import)
它将解析出来的excel数据。
然而拿到的数据有点让人奔溃:
数据内容高度不齐整。而这个的根源,来自于合并单元格。
但是我是前端,这点数据必须能搞定。
思路:每循环一层,需要判断二重循环内是否为null,是则就需要跟上一层取值该元素的rowSpan为0。
所谓看的见的东西,其实都不一定是最重要的,排版就是如此,这个流程的重点在于重构数据,样式反而是次要的次要了。
考虑取模。
解析出来的数据是个五位数。经查阅资料得知,这五位数是从1900年1月1日到目前为止经历过的天数。需要和Unix时间戳进行转换。
一般来说,Unix时间戳(1970年1月1日)经过的毫秒数是可以为负值的。而经查阅1900年1月1日在时间戳为-2209017600000
毫秒。
首先写一个dateTime模块下的format方法,根据时间戳获取日期。
'use strict';export default class {
/*
* 通过时间戳获取日期。
* @param timestamp 时间戳(秒)
* @param format 日期格式
* @return 格式化后的日期
*/
static format(timestamp, format) {
if (timestamp === undefined) {
format = '';
} else {
const WEEK = ['日','一','二','三','四','五','六'];
timestamp/=1000;
let date = timestamp !== 0 ? new Date(timestamp * 1000) : new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let week = date.getDay();
let day = date.getDate();
let hour = date.getHours();
let minute = date.getMinutes();
let second = date.getSeconds(); format = format ? format : 'YYYY-MM-DD';
format = format.replace(/yyyy|YYYY/, year);
format = format.replace(/yy|YY/, (year % 100) > 9 ? (year % 100).toString() : '0' + (year % 100));
format = format.replace(/MM/, month > 9 ? month.toString() : '0' + month);
format = format.replace(/M/, month);
format = format.replace(/w|W/, WEEK[week]);
format = format.replace(/dd|DD/, day > 9 ? day.toString() : '0' + day);
format = format.replace(/d|D/, day);
format = format.replace(/hh|HH/, hour > 9 ? hour.toString() : '0' + hour);
format = format.replace(/h|H/, hour);
format = format.replace(/mm/, minute > 9 ? minute.toString() : '0' + minute);
format = format.replace(/m/, minute);
format = format.replace(/ss|SS/, second > 9 ? second.toString() : '0' + second);
format = format.replace(/s|S/, second);
} return format;
}
}
再写一个change方法
function change(date){
let base=-2209017600000;//1900年时间戳 let iNow=base+date*86400000;//1天
let a=DateTime.format(iNow,'MM/DD')
return a;
}
不得不说,这层数据可提取的共性真的不多。最后通过网页出来就可以用了
/*
* 渲染导出的表格
*/
static renderTable(data){
// console.log(data);
function change(date){
let base=-2209017600000;//1900年时间戳 let iNow=base+date*86400000;
let a=DateTime.format(iNow,'MM/DD')
return a;
} let table={
main:{
// ...
}, headerTd:{
// ...
}, tdOdd:{// 能被4整除
// ...
}, tdEven:{// 能被4整除
// ...
},
nameEven:{
//...
},
nameOdd:{
//...
}
} let header=null;
let _header=[];
let _header2=[]; let result=data.map((x,i)=>{
if(i==0){
header=(
<tHead>
<tr>
<td style={{textAlign:'center'}} colSpan="9">{x[0]}</td>
</tr>
</tHead>
)
} if(i==2){ x.map((y,j)=>{
if(j==0){
if(y!==null){
_header.push(<td style={{width:'76px',textAlign:'center',background:'rgb(77,77,77)',color:'#fff'}} key={j} rowSpan="2">{y}</td>)
}else{
_header.push(false)
}
}else{ _header2.push(
<td style={table.headerTd} key={j}>{typeof(y)=='string'?y:change(y)}</td>
)
} })
} if(i==3){ x.map((y,j)=>{
if(j==0){
if(y!==null){
_header2.push(<td key={j} rowSpan="2">{y}</td>)
}else{
_header2.push(false)
}
}else{ _header.push(
<td style={table.headerTd} key={j}>{y}</td>
)
} })
} if(i>3){
let row=[];
if(i%2==0){
// 有姓名信息
let info=x.map((y,j)=>{
if(j==0){ if(i%4!==0){
return (
<td style={table.nameEven} rowSpan="2" key={j}>{y}</td>
)
}else{
return (
<td style={table.nameOdd} rowSpan="2" key={j}>{y}</td>
)
} }else{
if(data[i+1][j]==null){ if(i%4==2||i%4==1){ // style={table.tdOdd}
return (
<td style={table.tdOdd} rowSpan="2" key={j}>{y}</td>
)
}else{
return (
<td style={table.tdEven} rowSpan="2" key={j}>{y}</td>
)
}
}else{
if(i%4==2||i%4==1){
// style={table.tdOdd}
return (
<td style={table.tdOdd} key={j}>{y}</td>
)
}else{
return (
<td style={table.tdEven} key={j}>{y}</td>
)
} }
}
}); return (
<tr key={i}>{info}</tr>
) }else{
// 无姓名信息 let _info=x.map((y,j)=>{
if(j==0){
return (
false
)
}else{ if(y==null){ return (
false
)
}else{ if(i%4==2||i%4==3){
// style={table.tdOdd}
return (
<td style={table.tdOdd} key={j}>{y}</td>
)
}else{
return (
<td style={table.tdEven} key={j}>{y}</td>
)
} // return (
// <td key={j}>{y}</td>
// )
} }
}); return (
<tr key={i}>{_info}</tr>
)
} } }) return (<table cellSpacing="0" style={table.main}>
{/* {header} */}
<tBody>
<tr>
{_header}
</tr>
<tr>
{_header2}
</tr> {result} </tBody>
</table>) }
自此核心功能已经完全实现。