在上一篇文章中,介绍了如何使用handsontable绘制表格,且配置可操作表格。这一篇将介绍如何把用户绘制的表格和填入的数据保存下来与使用公式验证:
首先是保存用户绘制的表格:
一、获取行数、列数:
var count_col = hot.countCols();//获取列数
var count_row = hot.countRows();//获取行数
二、获取每行的高度和每列的宽度:
var row_h = '';
var col_w = '';
for(var i = 0;i < count_col;i++ ){
col_w = col_w+hot.getColWidth(i)+',';
}
for(var i = 0;i < count_row;i++ ){
row_h = row_h+hot.getRowHeight(i)+',';
}
这里介绍最重要的一个函数:getCell(i,j,true).i 和 j表示行号和列号,true表示只取最上面一格的数据。而且获取的数据结果是这样的:
<td class="htCenter htMiddle htDimmed" rowspan="2" colspan="2">10</td>
赋值给cell的className里即可。rowspan和colspan是这个单元格跨越的行和列的数量,比如上面就是一个2*2的单元格合并成的一个大格子。值得一提的是,
合并在一起的单元格会取相同的数据。例如,上例是getCell(1,1,true)获取的结果,那么getCell(1,2,true)和getCell(2,1,true)和getCell(2,2,true)的结果都是上例。
所以在取数据的时候,如果每个单元格都取数据,对于合并过的单元格,那么就会重复取2*2-1个数据。所以在实际取数据的时候,一旦遇到i和j是合并的单元格。
假设合并了m列和n行,那就只能获取i和j的值,而忽略i+m和j+n以及之间的单元格。这里我的做法是每次遇到带合并的单元格,就为需要忽略的单元格加上
一个class,在计算中,不计算带有此class的单元格。最后的10当然就是这个单元格的值。所以,获取每个单元格的格式和数据的完整代码如下:
var row_h = '';
var col_w = '';
//获取行列的宽度和高度
var count_col = hot.countCols();//获取列数
var count_row = hot.countRows();//获取行数
for(var i = 0;i < count_col;i++ ){
col_w = col_w+hot.getColWidth(i)+',';
}
for(var i = 0;i < count_row;i++ ){
row_h = row_h+hot.getRowHeight(i)+',';
}
col_w = col_w.substr(0,col_w.length-1); //列宽
row_h = row_h.substr(0,row_h.length-1); //行高
//获取每个单元格的格式和数据
var cells_o = new Array(); //每个单元格数据
var cells_mer = new Array();//合并单元格信息
for(var i=0;i < count_row;i++){
for(var j = 0;j < count_col;j++ ){
var cell_e1 = hot.getCell(i,j,true);
console.log(cell_e1);
cell_e = $(cell_e1);
//只计算未添加忽略规则的
if(!cell_e.hasClass("lina_ig")){
var cell_o = new Object();
cell_o['row'] = i;
cell_o['col'] = j;
//console.log(cell_e1);
//获取表格值
cell_o['val'] = cell_e.text();
//判断表格是否只读
if(cell_e.hasClass("htDimmed")){
cell_o['readOnly'] = 1;
}else{
cell_o['readOnly'] = 0;
};
//获取表格的格式
cell_o['class'] = cell_e.attr("class");
cells_o.push(cell_o);
//获取表格合并信息
if( typeof(cell_e.attr("rowspan"))!="undefined" ){
var cell_mer = new Object();
cell_mer['row'] = i;
cell_mer['col'] = j;//rowspan: 2, colspan: 2
cell_mer['rowspan'] = Number(cell_e.attr("rowspan"));
cell_mer['colspan'] = Number(cell_e.attr("colspan"));
//为被合并的单元格添加标记,保证一个格子只计算一次
for(var m=0;m < cell_mer['rowspan'];m++){
for(var n=0;n < cell_mer['colspan'];n++){
if((m+n)>0){
//console.log(m+"+"+n);
var cell_ig = hot.getCell(i+m,j+n,true);
cell_ig = $(cell_ig);
cell_ig.addClass("lina_ig");
}
}
}
cells_mer.push(cell_mer);
}
}
}
}
获取到单元格的格式和值后,就可以存在数据库中,下次加载表格的时候一并加载。
下面是规则验证:
js(php)中规则验证,最重要的是eval函数:将一个字符串当作一条语句执行。例如eval('6>1');
所以要做规则验证,我们首先需要一个函数,获取每个单元格的值,然后用值去做运算。
function _A(i,j){
//判断输入是否为正确的坐标值
var this_i = Number(i)-1;
var this_j = Number(j)-1;
var count_col = Number(hot.countCols());//获取列数
var count_row = Number(hot.countRows());//获取行数
//对输入值判错
if( (this_i<0)||(this_i>=count_row)||(isNaN(this_i)) ){
return 'yourwrong';
}
if( (this_j<0)||(this_j>=count_col)||(isNaN(this_j)) ){
return 'yourwrong';
}
//获取坐标对应单元格的值
var cell = hot.getCell(this_i,this_j,true);
cell = $(cell);
var cell_val = cell.text();
if(cell_val == ''){
return 0;
}else{
var res = parseFloat(cell.text());
if( isNaN(res)){
return 'yourwrong';
}else{
return res;
}
}
}
我们只需要在公司中使用_A函数即可:
var rule = [
"_A(2,1)>_A(3,5)",
"_A(2,2)==_A(3,4)+_A(3,5)",
"_A(2,2)>=(_A(3,4)+_A(3,5))%_A(4,3)",
"_A(2,2)<=_A(1,3)+_A(3,4)",
"_A(woc,2)<=_A('wc',3)+_A(3,4)",
];
rule.forEach(function(value,index){
try{
var res = eval(value);
console.log(res);
}
catch(exception) {
console.log("规则编辑错误");
}
});