Prechádzať zdrojové kódy

自动行高导出excel调整(合并相关单元格)

TonyKang 6 rokov pred
rodič
commit
812edc5b79

+ 104 - 9
modules/reports/rpt_component/jpc_flow_tab.js

@@ -11,6 +11,8 @@ let JpcCommonOutputHelper = require('./helper/jpc_helper_common_output');
 let JpcAreaHelper = require('./helper/jpc_helper_area');
 let PDFKit = require('pdfkit');
 let fontUtil = require('../util/rpt_font_util');
+let fsUtil = require("../../../public/fsUtil");
+
 
 let JpcFlowTabSrv = function(){};
 JpcFlowTabSrv.prototype.createNew = function(){
@@ -422,10 +424,12 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 JpcBandHelper.setBandArea(bands, rptTpl, pageStatus, !me.isEx, me.isEx);
                 maxRowRec = JpcFlowTabHelper.getMaxRowsPerPage(bands, rptTpl, me.isEx);
             }
+            let handledRowAmt = 0; //handledRowAmt纪录的是真正处理过的显示行数,包含了空白行,主要是为分页用(自动行高)
             function private_addPage(segIdx, grpSeqInfo, isFollow, isMix, mixSplitPoint) {
                 private_resetBandArea();
                 me.pageStatusLst.push(pageStatus.slice(0));
                 currentRecAmt += maxRowRec; //在自动行高的场景下,currentRecAmt在后面还需要调整
+                handledRowAmt += maxRowRec;
                 let redundantRecAmt = 0;
                 pageIdx++;
                 function private_chk_handle_rec_amt(dv, isEx) {
@@ -473,6 +477,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 let grpRecAmt = (grpSeqInfo)?(grpSeqInfo.length*me.group_lines_amt):0;
                 let grpRecAmtEx = 0;
                 let accAutoHeightAmt = 0; //累计的自动行高数量
+                handledRowAmt = 0; //初始化每一段的已处理纪录行数
                 if (followTabEx && followTabEx.group_node_info) {
                     grpRecAmtEx = followTabEx.group_node_info.length * followTabEx.group_lines_amt;
                 }
@@ -574,17 +579,16 @@ JpcFlowTabSrv.prototype.createNew = function(){
                         }
                     } else {
                         //普通流水数据情况
-                        // if ((currentRecAmt + adHocAutoHeightAmt + maxRowRec >= ttlSegRecAmt)
-                        if ((currentRecAmt + accAutoHeightAmt + adHocAutoHeightAmt + maxRowRec >= ttlSegRecAmt)
-                             //&& (adHocAutoHeightAmt < 2 * maxRowRec) ) {
-                             // && ((currentRecAmt + adHocAutoHeightAmt + maxRowRec - ttlSegRecAmt) < maxRowRec) ) {
-                            && ((currentRecAmt + accAutoHeightAmt + adHocAutoHeightAmt + maxRowRec - ttlSegRecAmt) < maxRowRec) ) {
+                        if (handledRowAmt + maxRowRec >= ttlSegRecAmt) {
                             //备注: 理论上自动行高是没有上限的,有可能正常一页的数据可以拓展到3页及以上,在此极端情况下,必须做一些限制判断,否则会出现缺页情况。
+                            // 2018-08-04 其实之前的判断逻辑完全是自找麻烦,而且还不够正确。其实只需要判断已经处理了多少行纪录(所有的都算,包括空白行),
+                            // 与总的seg纪录数想比较,就很容易得到结果,而且能处理更极端的情况。
                             pageStatus[JV.STATUS_SEGMENT_END] = true;
                             pageStatus[JV.STATUS_REPORT_END] = true;
                             private_resetBandArea();
-                            let hasAdHocRow = ((adHocAutoHeightAmt > maxRowRec) ||
-                                              !JpcFlowTabHelper.chkSegEnd(bands, rptTpl, ttlSegRecAmt, currentRecAmt + adHocAutoHeightAmt, maxRowRec, me.isEx));
+                            let hasAdHocRow = ((adHocAutoHeightAmt > maxRowRec) || !JpcFlowTabHelper.chkSegEnd(bands, rptTpl, ttlSegRecAmt, handledRowAmt, maxRowRec, me.isEx));
+                                              // !JpcFlowTabHelper.chkSegEnd(bands, rptTpl, ttlSegRecAmt, currentRecAmt + adHocAutoHeightAmt, maxRowRec, me.isEx));
+
                             if (hasAdHocRow) {
                                 //add page info(pre segment end)
                                 pageStatus[JV.STATUS_SEGMENT_END] = false;
@@ -602,7 +606,8 @@ JpcFlowTabSrv.prototype.createNew = function(){
                         }
                     }
                     //检测是否可退出
-                    if ((currentRecAmt + accAutoHeightAmt + adHocAutoHeightAmt >= ttlSegRecAmt) && (pageIdx % me.multiCols === 0)) {
+                    // if ((currentRecAmt + accAutoHeightAmt + adHocAutoHeightAmt >= ttlSegRecAmt) && (pageIdx % me.multiCols === 0)) {
+                    if (handledRowAmt >= ttlSegRecAmt && (pageIdx % me.multiCols === 0)) {
                         //备注:这里必须得考虑多栏的情况,否则会造成pageStatus出界的问题
                         break;
                     }
@@ -737,7 +742,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
         return rst;
     };
     JpcFlowTabResult.outputContent = function(rptTpl, dataObj, page, bands, unitFactor, controls, multiColIdx, $CURRENT_RPT, customizeCfg) {
-        let me = this, rst = [];
+        let me = this, rst = [], prepareObj = {};
         let FLOW_NODE_STR = me.isEx?JV.NODE_FLOW_INFO_EX:JV.NODE_FLOW_INFO;
         let tab = rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_CONTENT];
         let tabEx = (rptTpl[JV.NODE_FLOW_INFO_EX])?rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_CONTENT]:null;
@@ -805,6 +810,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                                     } else {
                                         cellItem[JV.PROP_STYLE] = cellItem[JV.PROP_STYLE] + '_AutoHeightMerge_Middle';
                                     }
+                                    prepareAutoHeightCells(prepareObj, cellItem, rst.length - 1, rst);
                                 }
                             }
                         }
@@ -864,6 +870,13 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 }
             }
         }
+        let eliminateCells = combineAutoHeightCells(prepareObj, page, controls);
+        // console.log("rst.length: " + rst.length);
+        // console.log("eliminateCells.length: " + eliminateCells.length);
+        for (let idIdx = eliminateCells.length - 1; idIdx >= 0; idIdx--) {
+            rst.splice(eliminateCells[idIdx], 1);
+        }
+        console.log("rst.length: " + rst.length);
         return rst;
     };
     JpcFlowTabResult.outputColumn = function (rptTpl, dataObj, page, segIdx, bands, unitFactor, multiColIdx) {
@@ -1012,4 +1025,86 @@ JpcFlowTabSrv.prototype.createNew = function(){
     return JpcFlowTabResult;
 };
 
+function push_cell(pageCellObj, cell, cellIdx) {
+    if (!pageCellObj[cell[JV.PROP_AREA][JV.PROP_LEFT] + '_' + cell[JV.PROP_AREA][JV.PROP_RIGHT]]) {
+        pageCellObj[cell[JV.PROP_AREA][JV.PROP_LEFT] + '_' + cell[JV.PROP_AREA][JV.PROP_RIGHT]] = [];
+    }
+    let cellArr = pageCellObj[cell[JV.PROP_AREA][JV.PROP_LEFT] + '_' + cell[JV.PROP_AREA][JV.PROP_RIGHT]];
+    cellArr.push({"cellIdx": cellIdx, "cell": cell});
+}
+
+function prepareAutoHeightCells(prepareObj, cellItem, cellIdx, cellsArr) {
+    if (prepareObj) {
+        if (prepareObj.cellsArr === undefined) {
+            prepareObj.cellsArr = cellsArr;
+            prepareObj.pageCellObj = {};
+        }
+        push_cell(prepareObj.pageCellObj, cellItem, cellIdx);
+    }
+}
+
+function setupControl(mergeCell, controls) {
+    let orgCtrl = null;
+    if ( typeof mergeCell[JV.PROP_CONTROL] === "string") {
+        orgCtrl = controls[mergeCell[JV.PROP_CONTROL]];
+        mergeCell[JV.PROP_CONTROL] = {
+            "Shrink": "T",
+            "ShowZero": orgCtrl.ShowZero,
+            "Horizon": orgCtrl.Horizon,
+            "Vertical": "top",
+            "Wrap": "T"
+        };
+    } else {
+        mergeCell[JV.PROP_CONTROL].Shrink = "T";
+        mergeCell[JV.PROP_CONTROL].Vertical = "top";
+        mergeCell[JV.PROP_CONTROL].Wrap = "T";
+        orgCtrl = mergeCell[JV.PROP_CONTROL];
+    }
+    return orgCtrl;
+}
+
+function combineAutoHeightCells(prepareObj, page, controls) {
+    let rst = [];
+    if (prepareObj.cellsArr) {
+        //merge cells' value and area
+        for (let mergeKey in prepareObj.pageCellObj) {
+            if (prepareObj.pageCellObj[mergeKey].length > 1) {
+                let firstMergeCell = prepareObj.pageCellObj[mergeKey][0].cell;
+                firstMergeCell[JV.PROP_STYLE] = firstMergeCell[JV.PROP_STYLE].slice(0, firstMergeCell[JV.PROP_STYLE].indexOf("_AutoHeightMerge"));
+                let orgCtrl = setupControl(firstMergeCell, controls);
+                let validValueAmt = 0;
+                for (let i = 1; i < prepareObj.pageCellObj[mergeKey].length; i++) {
+                    let mergeCell = prepareObj.pageCellObj[mergeKey][i].cell;
+                    if (mergeCell[JV.PROP_STYLE].indexOf("_AutoHeightMerge_Top") < 0) {
+                        //merge into the firstMergeCell!
+                        firstMergeCell[JV.PROP_AREA][JV.PROP_BOTTOM] = mergeCell[JV.PROP_AREA][JV.PROP_BOTTOM];
+                        firstMergeCell[JV.PROP_VALUE] = firstMergeCell[JV.PROP_VALUE] + "|" + mergeCell[JV.PROP_VALUE];
+                        if (mergeCell[JV.PROP_VALUE]) validValueAmt++;
+                        rst.push(prepareObj.pageCellObj[mergeKey][i].cellIdx);
+                        if (i === prepareObj.pageCellObj[mergeKey].length - 1 && validValueAmt === 0) {
+                            firstMergeCell[JV.PROP_CONTROL].Shrink = orgCtrl.Shrink;
+                            firstMergeCell[JV.PROP_CONTROL].Wrap = "F";
+                        }
+                    } else {
+                        if (validValueAmt === 0) {
+                            firstMergeCell[JV.PROP_CONTROL].Shrink = orgCtrl.Shrink;
+                            firstMergeCell[JV.PROP_CONTROL].Wrap = "F";
+                        }
+                        firstMergeCell = prepareObj.pageCellObj[mergeKey][i].cell;
+                        firstMergeCell[JV.PROP_STYLE] = firstMergeCell[JV.PROP_STYLE].slice(0, firstMergeCell[JV.PROP_STYLE].indexOf("_AutoHeightMerge"));
+                        orgCtrl = setupControl(firstMergeCell, controls);
+                        validValueAmt = 0;
+                    }
+                }
+            }
+        }
+        rst.sort(function (i1, i2) {
+            return (i1 > i2)?1:-1;
+        });
+    }
+    // fsUtil.writeObjToFile(prepareObj, "D:/GitHome/ConstructionCost/tmp/afterMergeCellsPrepareObj_" + page + ".jsp");
+    // fsUtil.writeObjToFile(rst, "D:/GitHome/ConstructionCost/tmp/eliminateCells_" + page + ".jsp");
+    return rst;
+}
+
 module.exports = new JpcFlowTabSrv();

+ 2 - 5
modules/reports/util/rpt_font_util.js

@@ -6,12 +6,10 @@ let fontMapObj = {
     "宋体": "Smart"
     ,"楷体": "simkai"
     ,"黑体": "simhei"
-    // ,"华文中宋": "STZHONGS"
-    // ,"华文宋体": "STSONG"
-    //"宋体": "Smart"
 };
 //下划线在option中支持
-//另注意:
+//另注意:PDFkit设置字体的时候会检测是否同源,也就是说,如果是同一种字体转换不同的特性(如粗体、斜体),那么在设置的时候会无效
+//      比如前一种是普通的字体,后来想设置这种字体的斜体,实际上这种设置会失效
 
 module.exports = {
     getActualFont: getActualFont
@@ -20,7 +18,6 @@ module.exports = {
 function getActualFont(mapName, isBold, isItalic) {
     let rst = ["Smart"];
     if (fontMapObj[mapName]) rst[0] = fontMapObj[mapName];
-    // rst = rst + (isBold?"_bold":"") + (isItalic?"_italic":"");
     if (isBold) {
         rst.push("_bold");
     }

+ 8 - 7
test/unit/reports/test_rpt_test_template.js

@@ -31,7 +31,8 @@ let demoPrjId = - 1;
 // let demoRptId = 337; //19表
 // let demoRptId = 361; //封1
 // let demoRptId = 279; //表04
-let demoRptId = 261; //封3
+// let demoRptId = 261; //封3
+let demoRptId = 232; //09
 // let demoRptId = 2260; //测试基本信息
 let pagesize = "A4";
 //288: 11-2表(新)
@@ -42,7 +43,7 @@ let userId_Leng = "5acac1e885bf55000bd055ba"; //小冷User Id2
 // demoPrjId = 720; //QA: DW3
 //demoPrjId = 1626; //QA:
 // demoPrjId = 2260; //QA:
-demoPrjId = 3532; //QA:
+demoPrjId = 3391; //QA:
 //*/
 let userId_Dft = userId_Leng;
 // let userId_Dft = "5a025c4c15074d134c2b9689";
@@ -88,12 +89,12 @@ test('测试 - 测试模板啦: ', function (t) {
                     let pageRst = printCom.outputAsSimpleJSONPageArray(rptTpl, tplData, 1, maxPages, defProperties);
                     if (pageRst) {
                         // fsUtil.writeObjToFile(pageRst, "D:/GitHome/ConstructionCost/tmp/testBuiltPageResult_测试模板.jsp");
-                        // rpt_xl_util.exportExcel(pageRst, pagesize, "local_test_rpt_excel", true, null, null, function(uuidName){
-                        //     console.log("excel uuid: " + uuidName);
-                        // });
-                        rpt_pdf_util.export_pdf_file(pageRst, pagesize, 'local_test_rpt_pdf', function(uuidName){
-                            console.log("pdf uuid: " + uuidName);
+                        rpt_xl_util.exportExcel(pageRst, pagesize, "local_test_rpt_excel", true, null, null, function(uuidName){
+                            console.log("excel uuid: " + uuidName);
                         });
+                        // rpt_pdf_util.export_pdf_file(pageRst, pagesize, 'local_test_rpt_pdf', function(uuidName){
+                        //     console.log("pdf uuid: " + uuidName);
+                        // });
                     } else {
                         console.log("oh! no pages were created!");
                     }