姓名 | 数学得分 | 英语得分 | 总得分 | 总得分占比 |
---|---|---|---|---|
张三 | 100 | 80 | 180 | 0.6206896551724138 |
李四 | 50 | 60 | 110 | 0.3793103448275862 |
合计 | 150 | 140 | 290 | 1 |
其中灰色部分需要计算,那可以用js处理,需引用JQuery。
行是从tbody开始算的,tbody标记要有的。
给需要公式的td加上 data-s="0:[1,2]+[1,3]" 就可以,数字0代表计算优先级(因为考虑到带有公式的单元格也要参加另外一组的运算,那么另外一组的单元格优先级排后就是1,依次往后排),[1,2]+[1,3]代表[行索引,了列索引]
行索引和列索引从1开始。
公式可以嵌套函数哟,比如data-s="0:([1,2]+[1,3]).toFixed(2)"
data-total="true" 带有此标记的单元格的值是当前列汇总合计
后面优化了下算法,把单元格丢进Map里面,计算性能提升了100倍
<table class="calc-expression" style="500px;"> <thead> <tr> <th>姓名</th> <th>数学得分</th> <th>英语得分</th> <th>总得分</th> <th>总得分占比</th> </tr> </thead> <tbody> <tr> <td>张三</td> <td>100</td> <td>80</td> <td data-s="0:[1,2]+[1,3]"></td> <td data-s="1:[1,4]/([1,4]+[2,4])"></td> </tr> <tr> <td>李四</td> <td>50</td> <td>60</td> <td data-s="0:[2,2]+[2,3]"></td> <td data-s="1:[2,4]/([1,4]+[2,4])"></td> </tr> <tr> <td>合计</td> <td data-total="true"></td> <td data-total="true"></td> <td data-total="true"></td> <td data-total="true"></td> </tr> </tbody> </table>
$(function () { $(".calc-expression").each(function () { var mapcell = new Map; var re = /[d+(\,d+)?]/g; var map = []; var lmap = []; var tbody = $(this).find("tbody"); var rows = tbody.find("tr"); rows.each(function (r1) { var tds = $(this).find("td"); tds.each(function (c1) { var key = "[" + (Number(r1) + 1) + "," + (Number(c1) + 1) + "]"; if (!mapcell.has(key)) { mapcell.set(key, $(this).text()); } if ($(this).attr("data-s") != "" && $(this).attr("data-s") != undefined) { map.push($(this).attr("data-s")); } }); }); var compare = function (x, y) { if (lmap.indexOf(x.split(':')[0]) < 0) { lmap.push(x.split(':')[0]); } var a = x.split(':')[0]; var b = y.split(':')[0]; if (a < b) { return -1; } else if (a > b) { return 1; } else { return 0; } } map = map.sort(compare); console.time("setvalue"); for (var k = 0; k < lmap.length; k++) { rows.each(function (r1) { var tds = $(this).find("td"); tds.each(function (c1) { if ($(this).text() == "0" || $(this).text() == "") { var datas = $(this).attr("data-s"); if (datas != "" && datas != undefined) { var key = "[" + (Number(r1) + 1) + "," + (Number(c1) + 1) + "]"; var temp = datas.split(":")[1]; var result1 = temp.match(re); for (var j = 0; j < result1.length; j++) { var t1 = result1[j]; var v = mapcell.get(t1); if (v == "") { var c1 = getCellValue(rows, t1); mapcell.set(t1, c1); v = c1; } if (v == "") { v = 0; } temp = temp.replace(t1, (isNaN(v) ? v : parseFloat(v))); } try { var temp2 = eval(temp); mapcell.set(key, temp2); $(this).html(temp2); } catch (err) { $(this).html("NaN"); } } } }); }); } console.log("setvalue ok."); console.timeEnd("setvalue"); rows.each(function (rindex) { var tds = $(this).find("td"); tds.each(function (cindex) { if ($(this).attr("data-total") != "" && $(this).attr("data-total") != undefined) { if ($(this).attr("data-total") == "true") { var total = 0.0; rows.each(function (i) { if (i == rindex) { return false; } else { var tds2 = $(this).find("td"); tds2.each(function (j) { if (j == cindex) { if ($(this).html() != "") { total += parseFloat($(this).html()); } } }); } }); $(this).html(functoFixed(total)); } } }); }); rows.each(function (rindex) { var tds = $(this).find("td"); tds.each(function (cindex) { if ($(this).attr("data-type") != "" && $(this).attr("data-type") != undefined) { if ($(this).attr("data-type") == "Percent") { $(this).html(toPercent($(this).html())); } } }); }); }); }); //0:[1,11]+[1,2] function getCellValue(rows, a) { a = a.replace("[", ""); a = a.replace("]", ""); var result = 0; var x = a.split(",")[0]; var y = a.split(",")[1]; var h = false; rows.each(function (i1) { if (h) { return false; } if ((i1 + 1) == x) { var tds = $(this).find("td"); tds.each(function (i2) { if ((i2 + 1) == y) { h = true; result = $(this).text(); return false; } }); return false; } }); return result; }