Browse Source

code sync for Excel output all-in-one-book

TonyKang 7 years ago
parent
commit
325533eadd

+ 80 - 13
modules/reports/controllers/rpt_controller.js

@@ -3,6 +3,7 @@
  */
 
 let mongoose = require('mongoose');
+let async = require('async');
 
 let JV = require('../rpt_component/jpc_value_define');
 
@@ -13,6 +14,7 @@ let demoTemplateFacade = require('../facade/rpt_tpl_data_demo_facade');
 let JpcEx = require('../rpt_component/jpc_ex');
 let rptUtil = require("../util/rpt_util");
 let rpt_xl_util = require('../util/rpt_excel_util');
+let rpt_pdf_util = require('../util/rpt_pdf_util');
 let fs = require('fs');
 let strUtil = require('../../../public/stringUtil');
 
@@ -27,7 +29,7 @@ let callback = function(req, res, err, data){
     }
 };
 
-function getAllPagesCommonOrg(req, res, rpt_id, pageSize, cb) {
+function getAllPagesCommonOrg(rpt_id, pageSize, cb) {
     let rptTpl = null;
     rptTplFacade.getRptTemplate(rpt_id).then(function(rst) {
         rptTpl = rst;
@@ -35,10 +37,12 @@ function getAllPagesCommonOrg(req, res, rpt_id, pageSize, cb) {
             if (rptTpl.ID_KEY) {
                 return demoTemplateFacade.getDemoData(rptTpl.ID_KEY);
             } else {
-                callback(req, res, 'No report template data were found!', null);
+                //callback(req, res, 'No report template data were found!', null);
+                cb('No report template data were found!', null);
             }
         } else {
-            callback(req, res, 'No report template was found!', null);
+            //callback(req, res, 'No report template was found!', null);
+            cb('No report template was found!', null);
         }
     }).then(function(tplData){
             if (tplData) {
@@ -50,18 +54,20 @@ function getAllPagesCommonOrg(req, res, rpt_id, pageSize, cb) {
                 let maxPages = printCom.totalPages;
                 let pageRst = printCom.outputAsSimpleJSONPageArray(rptTpl, tplData, 1, maxPages, defProperties);
                 if (pageRst) {
-                    cb(pageRst);
+                    cb(null, pageRst);
                 } else {
-                    callback(req, res, "Have errors while on going...", null);
+                    //callback(req, res, "Have errors while on going...", null);
+                    cb('Have errors while on going...', null);
                 }
             } else {
-                callback(req, res, 'No report data were found!', null);
+                //callback(req, res, 'No report data were found!', null);
+                cb('No report data were found!', null);
             }
         }
     );
 };
 
-function getAllPagesCommon(req, res, rpt_id, pageSize, cb) {
+function getAllPagesCommon(rpt_id, pageSize, cb) {
     let rptTpl = null;
     rptTplFacade.getRptTemplate(rpt_id).then(function(rst) {
         rptTpl = rst;
@@ -95,10 +101,10 @@ function getAllPagesCommon(req, res, rpt_id, pageSize, cb) {
                 //return demoTemplateData.findOne({"Data_Key": rptTpl.ID_KEY}).exec();
 
             } else {
-                callback(req, res, 'No report template data were found!', null);
+                cb('No report template data were found!', null);
             }
         } else {
-            callback(req, res, 'No report template was found!', null);
+            cb('No report template was found!', null);
         }
     })
 };
@@ -107,9 +113,9 @@ module.exports = {
     getReportAllPages: function(req, res){
         let rpt_id = req.body.ID;
         let pageSize = req.body.pageSize;
-        getAllPagesCommonOrg(req, res, rpt_id, pageSize, function(pageRst){
+        getAllPagesCommonOrg(rpt_id, pageSize, function(err, pageRst){
             //fs.writeFileSync('D:/GitHome/ConstructionOperation/tmp/testRpt.js', JSON.stringify(pageRst));
-            callback(req, res, null, pageRst);
+            callback(req, res, err, pageRst);
         })
     },
     getExcel: function(req, res) {
@@ -118,8 +124,8 @@ module.exports = {
             rptName = req.params.rptName,
             isOneSheet = req.params.isOneSheet;
         ;
-        getAllPagesCommonOrg(req, res, rpt_id, pageSize, function(pageRst){
-            rpt_xl_util.exportExcel(pageRst, pageSize, rptName, isOneSheet, function(newName){
+        getAllPagesCommonOrg(rpt_id, pageSize, function(err, pageRst){
+            rpt_xl_util.exportExcel(pageRst, pageSize, rptName, isOneSheet, null, function(newName){
                 res.setHeader('Content-Type', 'application/vnd.openxmlformats');
                 res.setHeader("Content-Disposition", "attachment; filename=" + strUtil.getPinYinCamelChars(rptName) + ".xlsx");
                 let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + newName + '.xlsx');
@@ -131,5 +137,66 @@ module.exports = {
                 });
             });
         })
+    },
+    getExcelInOneBook: function(req, res) {
+        let rpt_ids = req.params.ids.split(','),
+            pageSize = req.params.size,
+            rptName = req.params.rptName;
+        ;
+        let parallelFucs = [];
+        for (let id of rpt_ids) {
+            parallelFucs.push((function (rpt_id) {
+                return function (cb) {
+                    getAllPagesCommonOrg(rpt_id, pageSize, function (err, pageRst) {
+                        if(err){
+                            cb(err);
+                        }
+                        else{
+                            cb(null, pageRst);
+                        }
+                    })
+                }
+            })(parseInt(id)));
+        }
+        async.parallel(parallelFucs, function (err, pageRstArray) {
+            if (err) {
+                callback(req, res, '数据有误', null);
+            } else {
+                rpt_xl_util.exportExcelInOneBook(pageRstArray, pageSize, rptName, function(tmpFilePath){
+                    res.setHeader('Content-Type', 'application/vnd.openxmlformats');
+                    res.setHeader("Content-Disposition", "attachment; filename=" + strUtil.getPinYinCamelChars(rptName) + ".xlsx");
+                    let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + tmpFilePath + '.xlsx');
+                    filestream.on('data', function(chunk) {
+                        res.write(chunk);
+                    });
+                    filestream.on('end', function() {
+                        res.end();
+                    });
+                });
+                //callback(req, res, false, '', {compilation: rst, gljLibs: gljLibsRst});
+            }
+        })
+    },
+    getPDF:function (req, res) {
+        let rpt_id = req.params.id,
+            pageSize = req.params.size,
+            rptName = req.params.rptName;
+
+        getAllPagesCommonOrg(rpt_id, pageSize, function(err, pageRst){
+            rpt_pdf_util.export_pdf_file(pageRst, pageSize, rptName,function (newName) {
+                res.setHeader('Content-Type', 'application/vnd.openxmlformats');
+                res.setHeader("Content-Disposition", "attachment; filename=" + strUtil.getPinYinCamelChars(rptName) + ".pdf");
+
+                let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + newName + '.pdf');
+                filestream.on('data', function(chunk) {
+                    res.write(chunk);
+                });
+                filestream.on('end', function() {
+                    res.end();
+                });
+            })
+
+        })
+
     }
 };

+ 4 - 0
modules/reports/routes/report_router.js

@@ -18,6 +18,10 @@ module.exports =function (app) {
         }
     });
     rptRouter.post('/getReport', reportController.getReportAllPages);
+
     rptRouter.get('/getExcel/:id/:size/:rptName/:isOneSheet', reportController.getExcel);
+    rptRouter.get('/getExcelInOneBook/:ids/:size/:rptName', reportController.getExcelInOneBook);
+
+    rptRouter.get('/getPDF/:id/:size/:rptName', reportController.getPDF);//2/A4/07-1表
     app.use("/report_api", rptRouter);
 }

+ 4 - 1
modules/reports/rpt_component/jpc_ex.js

@@ -169,7 +169,10 @@ JpcExSrv.prototype.createNew = function(){
             rst[JV.NODE_CONTROL_COLLECTION] = private_buildDftControls(rptTpl, (defProperties == null)?null:defProperties.ctrls);
             rst[JV.NODE_STYLE_COLLECTION] = private_buildDftStyles(rptTpl, (defProperties == null)?null:defProperties.styles);
             rst[JV.NODE_FONT_COLLECTION] = private_buildDftFonts(rptTpl, (defProperties == null)?null:defProperties.fonts);
-            rst[JV.NODE_PAGE_INFO] = JpcCommonHelper.getPageSize(rptTpl);
+            rst[JV.NODE_PAGE_INFO] = {};
+            rst[JV.NODE_PAGE_INFO][JV.NODE_MAIN_INFO_RPT_NAME] = rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MAIN_INFO_RPT_NAME];
+            rst[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE] = JpcCommonHelper.getPageSize(rptTpl);
+            rst[JV.NODE_PAGE_INFO][JV.NODE_MARGINS] = rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS];
             rst.items = [];
             let bands = JpcBand.createNew(rptTpl, defProperties);
             try {

+ 230 - 0
modules/reports/util/canvas_util.js

@@ -0,0 +1,230 @@
+/**
+ * Created by chen on 2017/7/27.
+ */
+let can = require('canvas');
+let canvas = new can(1200, 900,'pdf'), fs = require('fs');
+let reportO = require('./reportOj');
+//,ctx = canvas.getContext('2d')
+/*var y = 80, x = 50;
+ctx.font = '22px Helvetica';
+ctx.fillText('node-canvas pdf', x, y);
+ctx.font = '10px Arial';
+ctx.fillText('Just a quick example of PDFs with node-canvas lonso', x, y += 20);
+ctx.globalAlpha = .5;
+ctx.fillRect(x, y += 20, 10, 10);
+ctx.fillRect(x += 20, y, 10, 10);
+ctx.fillRect(x += 20, y, 10, 10);*/
+//fs.writeFile('out.pdf', canvas.toBuffer());
+
+
+
+let JpcCanvasOutput = {
+    offsetX: 10,
+    offsetY: 10,
+    cleanCanvas: function (canvas) {
+        var ctx = canvas.getContext("2d");
+        ctx.save();
+        ctx.fillStyle="white";
+        ctx.clearRect(0,0, canvas.width, canvas.height);
+        ctx.restore();
+    },
+    drawToCanvas : function(pageObj, canvas, pageIdx) {
+        var me = this;
+        var ctx = canvas.getContext("2d");
+
+        function private_setupAreaH(area, type, fontAngle, dftFontHeight, outputPoint) {
+            var lType = type;
+            if (type != "left" && type != "right" && type != "center") lType = "left";
+            switch (lType) {
+                case "left":
+                    if (fontAngle == JV.VERTICAL_ANGLE) {
+                        outputPoint[1] = 1 * area[JV.IDX_TOP] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+                    } else if (fontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                        outputPoint[1] = 1 * area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+                    } else outputPoint[0] = 1 * area[JV.IDX_LEFT] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+                    ctx.textAlign="start";
+                    break;
+                case "right":
+                    if (fontAngle == JV.VERTICAL_ANGLE) {
+                        outputPoint[1] = 1 * area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+                    } else if (fontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                        outputPoint[1] = 1 * area[JV.IDX_TOP] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+                    } else outputPoint[0] = 1 * area[JV.IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+                    ctx.textAlign="end";
+                    break;
+                case "center":
+                    if (fontAngle == JV.VERTICAL_ANGLE || fontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                        outputPoint[1] = (1 * area[JV.IDX_TOP] + 1 * area[JV.IDX_BOTTOM]) / 2;
+                    } else outputPoint[0] = (1 * area[JV.IDX_LEFT] + 1 * area[JV.IDX_RIGHT]) / 2;
+                    ctx.textAlign="center";
+                    break;
+            }
+        }
+        function private_setupAreaV(area, type, fontAngle, dftFontHeight, outputPoint) {
+            var lType = type;
+            if (type != "top" && type != "bottom" && type != "center") lType = "top";
+            switch (lType) {
+                case "top":
+                    if (fontAngle == JV.VERTICAL_ANGLE) {
+                        outputPoint[0] = 1 * area[JV.IDX_RIGHT] - dftFontHeight - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+                    } else if (fontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                        outputPoint[0] = 1 * area[JV.IDX_LEFT] + dftFontHeight + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+                    } else outputPoint[1] = 1 * area[JV.IDX_TOP] + dftFontHeight + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+                    break;
+                case "bottom":
+                    if (fontAngle == JV.VERTICAL_ANGLE) {
+                        outputPoint[0] = 1 * area[JV.IDX_LEFT] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM];
+                    } else if (fontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                        outputPoint[0] = 1 * area[JV.IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM];
+                    } else outputPoint[1] = 1 * area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM];
+                    break;
+                case "center":
+                    if (fontAngle == JV.VERTICAL_ANGLE) {
+                        outputPoint[0] = (1 * area[JV.IDX_LEFT] + 1 * area[JV.IDX_RIGHT] - dftFontHeight) / 2;
+                    } else if (fontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                        outputPoint[0] = (1 * area[JV.IDX_LEFT] + 1 * area[JV.IDX_RIGHT] + dftFontHeight) / 2;
+                    } else outputPoint[1] = (1 * area[JV.IDX_TOP] + 1 * area[JV.IDX_BOTTOM] + dftFontHeight) / 2;
+                    break;
+            }
+        }
+        function private_drawText(val, area, font, control) {
+            var dftFontHeight = 12;
+            var output = [];
+            if (font) {
+                dftFontHeight = 1 * font[JV.FONT_PROPS[1]];
+                var dftOthers = "";
+                var dftFontBold = font[JV.FONT_PROPS[3]];
+                if (dftFontBold && dftFontBold == 'T') {
+                    dftOthers = "bold " + dftOthers ;
+                }
+                var dftFontItalic = font[JV.FONT_PROPS[4]];
+                if (dftFontItalic && dftFontItalic == 'T') {
+                    dftOthers = dftOthers + "italic ";
+                }
+                ctx.font = dftOthers + dftFontHeight + "px " + font[JV.PROP_NAME];
+            }
+            if (control) {
+                private_setupAreaH(area, control.Horizon, font.FontAngle, dftFontHeight, output);
+                private_setupAreaV(area, control.Vertical, font.FontAngle, dftFontHeight, output);
+            } else {
+                private_setupAreaH(area, "left", font.FontAngle, dftFontHeight, output);
+                private_setupAreaV(area, "bottom", font.FontAngle, dftFontHeight, output);
+            }
+            var w = area[JV.IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT] - area[JV.IDX_LEFT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+            if (font.FontAngle != "0") {
+                w = area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM] - area[JV.IDX_TOP] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+            }
+            ctx.save();
+            ctx.translate(output[0], output[1]);
+            if (font.FontAngle == JV.VERTICAL_ANGLE) {
+                ctx.rotate(Math.PI/2);
+            } else if (font.FontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                ctx.rotate(-Math.PI/2);
+            }
+            if (w >= ctx.measureText(val).width) {
+                ctx.fillText(val, 0, 0);
+            } else {
+                while (true) {
+                    dftFontHeight--;
+                    ctx.font = "" + dftFontHeight + "px " + font[JV.PROP_NAME];
+                    if (w >=  ctx.measureText(val).width || dftFontHeight < 6) {
+                        ctx.fillText(val, 0, 0);
+                        break;
+                    }
+                }
+            }
+            ctx.restore();
+        }
+        function private_drawCellText(cell, fonts, controls) {
+            if (cell[JV.PROP_VALUE]) {
+                var values = ("" + cell[JV.PROP_VALUE]).split('|');
+                var font = fonts[cell[JV.PROP_FONT]];
+                var control = controls[cell[JV.PROP_CONTROL]];
+                var height = cell[JV.PROP_AREA][JV.PROP_BOTTOM] - cell[JV.PROP_AREA][JV.PROP_TOP];
+                var area = [cell[JV.PROP_AREA][JV.PROP_LEFT] + me.offsetX, cell[JV.PROP_AREA][JV.PROP_TOP] + me.offsetY, cell[JV.PROP_AREA][JV.PROP_RIGHT] + me.offsetX, cell[JV.PROP_AREA][JV.PROP_BOTTOM] + me.offsetY];
+                for (var i = 0; i < values.length; i++) {
+                    area[JV.IDX_TOP] = cell[JV.PROP_AREA][JV.PROP_TOP] + i * (height / values.length) + me.offsetY;
+                    area[JV.IDX_BOTTOM] = cell[JV.PROP_AREA][JV.PROP_TOP] + (i + 1) * (height / values.length) + me.offsetY;
+                    private_drawText(values[i], area, font, control);
+                }
+            }
+        }
+        function private_drawLine(cell, ctx, style, styleBorderDest, startP, destP, mergedBand, styles) {
+            ctx.beginPath();
+            var destStyle = style;
+            if (mergedBand) {
+                if (mergedBand[styleBorderDest] == cell[JV.PROP_AREA][styleBorderDest]) {
+                    destStyle = styles[mergedBand[JV.PROP_STYLE][JV.PROP_ID]];
+                }
+            }
+            ctx.moveTo(cell[JV.PROP_AREA][startP[0]] + me.offsetX, cell[JV.PROP_AREA][startP[1]] + me.offsetY);
+            if (destStyle[styleBorderDest] && destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT] != 0) {
+                ctx.lineWidth = 1.0 * destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT];
+                ctx.strokeStyle = destStyle[styleBorderDest][JV.PROP_COLOR];
+                ctx.lineTo(cell[JV.PROP_AREA][destP[0]] + me.offsetX, cell[JV.PROP_AREA][destP[1]] + me.offsetY);
+            }
+            ctx.stroke();
+        }
+        function private_drawCell(cell, fonts, styles, controls, mergedBand) {
+            ctx.save();
+            ctx.translate(0.5,0.5);
+            var style = styles[cell[JV.PROP_STYLE]];
+            if (style) {
+                private_drawLine(cell, ctx, style, JV.PROP_TOP, [JV.PROP_LEFT, JV.PROP_TOP],[JV.PROP_RIGHT, JV.PROP_TOP], mergedBand, styles);
+                private_drawLine(cell, ctx, style, JV.PROP_RIGHT, [JV.PROP_RIGHT, JV.PROP_TOP],[JV.PROP_RIGHT, JV.PROP_BOTTOM], mergedBand, styles);
+                private_drawLine(cell, ctx, style, JV.PROP_BOTTOM, [JV.PROP_RIGHT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_BOTTOM], mergedBand, styles);
+                private_drawLine(cell, ctx, style, JV.PROP_LEFT, [JV.PROP_LEFT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_TOP], mergedBand, styles);
+            }
+            private_drawCellText(cell, fonts, controls);
+            ctx.restore();
+        }
+
+        for(var p=1;p<50;p++){
+            pageIdx=p;
+            if (pageObj && pageObj.items.length > 0 && canvas && pageObj.items.length >= pageIdx) {
+                var page = pageObj.items[pageIdx - 1],
+                    fonts = pageObj[JV.NODE_FONT_COLLECTION],
+                    styles = pageObj[JV.NODE_STYLE_COLLECTION],
+                    controls = pageObj[JV.NODE_CONTROL_COLLECTION],
+                    mergedBand = pageObj[JV.BAND_PROP_MERGE_BAND];
+                for (var j = 0; j < page.cells.length; j++) {
+                    var cell = page.cells[j];
+                    private_drawCell(cell, fonts, styles, controls, mergedBand);
+                }
+            }
+            ctx.addPage();
+        }
+
+        fs.writeFile('report.pdf', canvas.toBuffer());
+    },
+    drawPageBorder: function(rptTpl, canvas, resolution) {
+        var me = this;
+        var size = rptTpl[JV.NODE_PAGE_INFO].slice(0);
+        size[0] = Math.round(resolution[0] * size[0]);
+        size[1] = Math.round(resolution[0] * size[1]);
+
+        var ctx = canvas.getContext("2d");
+        ctx.save();
+        ctx.beginPath();
+        ctx.translate(0.5,0.5);
+        ctx.lineWidth = 1;
+        ctx.moveTo(me.offsetX, me.offsetY);
+        ctx.lineTo(size[0] + me.offsetX, me.offsetY);
+        ctx.lineTo(size[0] + me.offsetX, size[1] + me.offsetY);
+        ctx.lineTo(me.offsetX, size[1] + me.offsetY);
+        ctx.lineTo(me.offsetX, me.offsetY);
+        ctx.stroke();
+        ctx.restore();
+
+        ctx.fillStyle="black";
+        ctx.fillRect(size[0] + me.offsetX,10 + me.offsetY,10,size[1]);
+        ctx.fillRect(10 + me.offsetX,size[1] + me.offsetY,size[0],10);
+    }
+}
+
+
+let rpt_oj = reportO.reportObj;
+
+
+
+JpcCanvasOutput.drawToCanvas(rpt_oj,canvas,1);

+ 59 - 0
modules/reports/util/pdfkit_test.js

@@ -0,0 +1,59 @@
+/**
+ * Created by chen on 2017/7/28.
+ */
+
+
+var pdf = require('pdfkit');
+var fs = require('fs');
+var doc = new pdf({autoFirstPage: false});
+var text = '测试,he';
+
+doc.pipe(fs.createWriteStream('测试.pdf'));
+doc.font('simsunB.ttf');
+
+for(var p=0;p<50;p++){
+    doc.addPage({size:[1200,900]});
+
+    doc.rect(30,113,76,609).lineWidth(0.5).strokeColor('black').stroke();
+    doc.text('报表报表报表',42,717,{ height: 100, width: 500,align: 'left'});
+
+
+   /* let width = 70;
+    let height=20;
+    let j = 100;
+    let sum = 0;
+    for(i=0;i<400;i++){
+        if(i%15==0){
+            j+=height;
+            sum = 0;
+        }
+        sum =sum+width;
+        let  x = sum;
+        let y  = j;
+        doc.rect(x,y,width,height).lineWidth(0.5).strokeColor('black').stroke();
+      /!*  doc.lineWidth(1.5);
+        doc.moveTo(x,y).lineTo(x,y+height);
+        doc.lineTo(x+width,y+height);
+        doc.lineTo(x+width,y);
+        doc.lineTo(x,y)
+        doc.strokeColor('black').stroke();*!/
+
+
+        doc.fontSize(12);
+        doc.text(text,x,5+y,{
+            height: height,
+            width: width,
+            align: 'right'});
+
+        // doc.text('报表文件',100,100);
+    }*/
+    doc.save();
+  /*  doc.fontSize(20);
+    doc.rotate(-20,{origin:[400, 105]})
+    doc.text('报表报表报表',300,110,{ height: 100, width: 500,align: 'left'});*/
+    doc.restore();
+}
+
+
+
+doc.end();

+ 144 - 17
modules/reports/util/rpt_excel_util.js

@@ -7,6 +7,7 @@ let JSZip = require("jszip");
 let strUtil = require('../../../public/stringUtil');
 let jpcCmnHelper = require('../rpt_component/helper/jpc_helper_common');
 let DPI = jpcCmnHelper.getScreenDPI()[0];
+let fsUtil = require('../../../public/fsUtil');
 const dftHeadXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
 
 function writeContentTypes(sheets, isSinglePage) {
@@ -331,6 +332,7 @@ function writeSheets(pageData, paperSize, sharedStrList, stylesObj, isSinglePage
 function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
     let rst = [], xPos = [], yPos = [], yMultiPos = [], headerStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
     let cacheBorderCell = {};
+    let currentPageMergePos = null;
     let private_pre_analyze_pos = function(){
         let cell, pos;
         let self_analyze_sheet_pos = function (theShtData, theXPos, theYPos) {
@@ -446,22 +448,22 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
         borderLineWidths.push(border[JV.PROP_TOP][JV.PROP_LINE_WEIGHT]);
         borderLineWidths.push(border[JV.PROP_BOTTOM][JV.PROP_LINE_WEIGHT]);
         if (sheetBorder[JV.PROP_LEFT] && sheetBorder[JV.PROP_LEFT][JV.PROP_LINE_WEIGHT]) {
-            sheetBorderLineWidths.push(private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_LEFT));
+            sheetBorderLineWidths.push(private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_LEFT, true));
         } else {
             sheetBorderLineWidths.push(0);
         }
         if (sheetBorder[JV.PROP_RIGHT] && sheetBorder[JV.PROP_RIGHT][JV.PROP_LINE_WEIGHT]) {
-            sheetBorderLineWidths.push(private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_RIGHT));
+            sheetBorderLineWidths.push(private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_RIGHT, true));
         } else {
             sheetBorderLineWidths.push(0);
         }
         if (sheetBorder[JV.PROP_TOP] && sheetBorder[JV.PROP_TOP][JV.PROP_LINE_WEIGHT]) {
-            sheetBorderLineWidths.push(private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_TOP));
+            sheetBorderLineWidths.push(private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_TOP, false));
         } else {
             sheetBorderLineWidths.push(0);
         }
         if (sheetBorder[JV.PROP_BOTTOM] && sheetBorder[JV.PROP_BOTTOM][JV.PROP_LINE_WEIGHT]) {
-            sheetBorderLineWidths.push(private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_BOTTOM));
+            sheetBorderLineWidths.push(private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_BOTTOM, false));
         } else {
             sheetBorderLineWidths.push(0);
         }
@@ -473,14 +475,45 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
         }
         return rst;
     };
-    let private_chkAndGetMergeLine = function(cell, sheetBorder, borderStr) {
+    let private_chkAndGetMergeLine = function(cell, sheetBorder, borderStr, needFurtherChk) {
         let rst = 0, mergeBorder = pageData[JV.BAND_PROP_MERGE_BAND];
-        if (sheetBorder[borderStr] && sheetBorder[borderStr][JV.PROP_LINE_WEIGHT] != undefined) {
+        if (sheetBorder[borderStr] && sheetBorder[borderStr][JV.PROP_LINE_WEIGHT] !== undefined) {
             rst = sheetBorder[borderStr][JV.PROP_LINE_WEIGHT];
         }
-        if (cell[JV.PROP_AREA][borderStr] == mergeBorder[borderStr]) {
-            let destStyle = pageData[JV.NODE_STYLE_COLLECTION][mergeBorder[JV.PROP_STYLE][JV.PROP_ID]];
-            rst = destStyle[borderStr][JV.PROP_LINE_WEIGHT];
+        if (currentPageMergePos) {
+            let side = currentPageMergePos[borderStr];
+            if (side.indexOf(cell[JV.PROP_AREA][borderStr]) >= 0) {
+                if (needFurtherChk) {
+                    let topSide = currentPageMergePos[JV.PROP_TOP];
+                    let bottomSide = currentPageMergePos[JV.PROP_BOTTOM];
+                    for (let i = 0; i < topSide.length; i++) {
+                        if (cell[JV.PROP_AREA][JV.PROP_TOP] >= topSide[i]) {
+                            if (cell[JV.PROP_AREA][JV.PROP_BOTTOM] <= bottomSide[i]) {
+                                let destStyle = pageData[JV.NODE_STYLE_COLLECTION][mergeBorder[JV.PROP_STYLE][JV.PROP_ID]];
+                                rst = destStyle[borderStr][JV.PROP_LINE_WEIGHT];
+                                break;
+                            }
+                        } else {
+                            break;
+                        }
+                    }
+                } else {
+                    let destStyle = pageData[JV.NODE_STYLE_COLLECTION][mergeBorder[JV.PROP_STYLE][JV.PROP_ID]];
+                    rst = destStyle[borderStr][JV.PROP_LINE_WEIGHT];
+                }
+            }
+        } else {
+            if (cell[JV.PROP_AREA][borderStr] === mergeBorder[borderStr]) {
+                let destStyle = pageData[JV.NODE_STYLE_COLLECTION][mergeBorder[JV.PROP_STYLE][JV.PROP_ID]];
+                if (needFurtherChk) {
+                    if (cell[JV.PROP_AREA][JV.PROP_TOP] >= mergeBorder[JV.PROP_TOP] &&
+                        cell[JV.PROP_AREA][JV.PROP_BOTTOM] <= mergeBorder[JV.PROP_BOTTOM]) {
+                        rst = destStyle[borderStr][JV.PROP_LINE_WEIGHT];
+                    }
+                } else {
+                    rst = destStyle[borderStr][JV.PROP_LINE_WEIGHT];
+                }
+            }
         }
         return parseInt(rst);
     };
@@ -503,10 +536,10 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
         }
         let sheetBorder = pageData[JV.NODE_STYLE_COLLECTION][cell.style];
         let mergedBorder = private_getIniBorder();
-        mergedBorder[JV.PROP_LEFT][JV.PROP_LINE_WEIGHT] = private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_LEFT);
-        mergedBorder[JV.PROP_RIGHT][JV.PROP_LINE_WEIGHT] = private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_RIGHT);
-        mergedBorder[JV.PROP_TOP][JV.PROP_LINE_WEIGHT] = private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_TOP);
-        mergedBorder[JV.PROP_BOTTOM][JV.PROP_LINE_WEIGHT] = private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_BOTTOM);
+        mergedBorder[JV.PROP_LEFT][JV.PROP_LINE_WEIGHT] = private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_LEFT, true);
+        mergedBorder[JV.PROP_RIGHT][JV.PROP_LINE_WEIGHT] = private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_RIGHT, true);
+        mergedBorder[JV.PROP_TOP][JV.PROP_LINE_WEIGHT] = private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_TOP, false);
+        mergedBorder[JV.PROP_BOTTOM][JV.PROP_LINE_WEIGHT] = private_chkAndGetMergeLine(cell, sheetBorder, JV.PROP_BOTTOM, false);
         for (let i = 0; i < stylesObj.borders.length; i++) {
             let border = stylesObj.borders[i];
             if (private_checkBorder(cell, border, mergedBorder)) {
@@ -723,12 +756,14 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
         private_cacheMergeBandBorderIdxs();
         if (sheetData) {
             //current sheet data
+            currentPageMergePos = sheetData[JV.PAGE_SPECIAL_MERGE_POS];
             self_setDataEx(sheetData, yPos, 0);
         } else {
             //total data in one sheet
             let cnt = 0;
             for (let i = 0; i < pageData.items.length; i++) {
                 let shtItemData = pageData.items[i];
+                currentPageMergePos = shtItemData[JV.PAGE_SPECIAL_MERGE_POS];
                 let tmpPos = yMultiPos[i];
                 cellIdx = 0;
                 self_setDataEx(shtItemData, tmpPos, cnt);
@@ -758,15 +793,30 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
     if (paperSizeIdx >= 0) {
         pStr = 'paperSize="' + JV.PAGES_SIZE_IDX[paperSizeIdx] + '"';
     }
-    let orientationStr = (pageData[JV.NODE_PAGE_INFO][0] > pageData[JV.NODE_PAGE_INFO][1])?'landscape':'portrait';
+    let orientationStr = (pageData[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE][0] > pageData[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE][1])?'landscape':'portrait';
     rst.push('<pageSetup ' + pStr + ' fitToWidth="0" fitToHeight="0" orientation="' + orientationStr + '" />');
     rst.push('<headerFooter alignWithMargins="0"/>');
     rst.push('</worksheet>');
     return rst;
 }
 
+function mergeProperties(orgObj, newObj) {
+    let orgPropArr = [], newPropArr = [];
+    for (let p in orgObj) {
+        orgPropArr.push(p);
+    }
+    for (let p in newObj) {
+        newPropArr.push(p);
+    }
+    for (let i = 0; i < newPropArr.length; i++) {
+        if (orgPropArr.indexOf(newPropArr[i]) < 0) {
+            orgObj[newPropArr[i]] = newObj[newPropArr[i]];
+        }
+    }
+}
+
 module.exports = {
-    exportExcel: function (pageData, paperSize, fName, options, callback) {
+    exportExcel: function (pageData, paperSize, fName, options, custSheetNames, callback) {
         let rptOptions = ({singlePage: false, fileName: 'report'});
         if (options === 'true') {
             rptOptions.singlePage = true;
@@ -776,8 +826,14 @@ module.exports = {
         if (isSinglePage) {
             sheets.push({sheetName: '全部页'});
         } else {
-            for (let i = 0; i < pageData.items.length; i++) {
-                sheets.push({sheetName: '第' + (i + 1) + '页'});
+            if (custSheetNames && custSheetNames.length === pageData.items.length) {
+                for (let i = 0; i < pageData.items.length; i++) {
+                    sheets.push({sheetName: custSheetNames[i]});
+                }
+            } else {
+                for (let i = 0; i < pageData.items.length; i++) {
+                    sheets.push({sheetName: '第' + (i + 1) + '页'});
+                }
             }
         }
         //1.
@@ -849,5 +905,76 @@ module.exports = {
             //return zip.generateNodeStream({type:'nodebuffer',streamFiles:true});
             return zip;
         }
+    },
+
+    exportExcelInOneBook: function (pageDataArray, paperSize, fName, callback) {
+        let me = this, newPageData = {};
+        //1. 重新编排一下数据,把一份报表的pageData合并到一起作为一个Sheet输出(需要重新调整数据纵向坐标),多份报表数据就形成多个Sheet
+        //   -- 简单来说,就是重新包装数据
+        try {
+            // 1.1 newPageData外围属性
+            let newContrl = {}, newFont = {}, newStyle = {};
+            for (let i = 0; i < pageDataArray.length; i++) {
+                mergeProperties(newContrl, pageDataArray[i][JV.NODE_CONTROL_COLLECTION]);
+                mergeProperties(newFont, pageDataArray[i][JV.NODE_FONT_COLLECTION]);
+                mergeProperties(newStyle, pageDataArray[i][JV.NODE_STYLE_COLLECTION]);
+            }
+            newPageData[JV.NODE_CONTROL_COLLECTION] = newContrl;
+            newPageData[JV.NODE_FONT_COLLECTION] = newFont;
+            newPageData[JV.NODE_STYLE_COLLECTION] = newStyle;
+            newPageData[JV.NODE_PAGE_INFO] = pageDataArray[0][JV.NODE_PAGE_INFO];
+            newPageData[JV.BAND_PROP_MERGE_BAND] = pageDataArray[0][JV.BAND_PROP_MERGE_BAND];
+
+            // 1.2 重新设置pageDataArray的各个cell的Top/Bottom坐标
+            let sheetNames = [], newPagePos = [];
+            for (let i = 0; i < pageDataArray.length; i++) {
+                let offsetY = 0;
+                let mergeBand = {};
+                mergeBand[JV.PROP_LEFT] = [];
+                mergeBand[JV.PROP_RIGHT] = [];
+                mergeBand[JV.PROP_TOP] = [];
+                mergeBand[JV.PROP_BOTTOM] = [];
+                newPagePos.push(mergeBand);
+                mergeBand[JV.PROP_LEFT].push(pageDataArray[i][JV.BAND_PROP_MERGE_BAND][JV.PROP_LEFT]);
+                mergeBand[JV.PROP_RIGHT].push(pageDataArray[i][JV.BAND_PROP_MERGE_BAND][JV.PROP_RIGHT]);
+                sheetNames.push(pageDataArray[i][JV.NODE_PAGE_INFO][JV.NODE_MAIN_INFO_RPT_NAME]);
+
+                for (let j = 0; j < pageDataArray[i].items.length; j++) {
+                    let maxY = 0, minY = 100000;
+                    mergeBand[JV.PROP_TOP].push(pageDataArray[i][JV.BAND_PROP_MERGE_BAND][JV.PROP_TOP] + offsetY);
+                    mergeBand[JV.PROP_BOTTOM].push(pageDataArray[i][JV.BAND_PROP_MERGE_BAND][JV.PROP_BOTTOM] + offsetY);
+                    for (let k = 0; k < pageDataArray[i].items[j].cells.length; k++) {
+                        if (maxY < pageDataArray[i].items[j].cells[k][JV.PROP_AREA][JV.PROP_BOTTOM]) {
+                            maxY = pageDataArray[i].items[j].cells[k][JV.PROP_AREA][JV.PROP_BOTTOM];
+                        }
+                        if (minY > pageDataArray[i].items[j].cells[k][JV.PROP_AREA][JV.PROP_TOP]) {
+                            minY = pageDataArray[i].items[j].cells[k][JV.PROP_AREA][JV.PROP_TOP];
+                        }
+                        pageDataArray[i].items[j].cells[k][JV.PROP_AREA][JV.PROP_BOTTOM] += offsetY;
+                        pageDataArray[i].items[j].cells[k][JV.PROP_AREA][JV.PROP_TOP] += offsetY;
+                    }
+                    offsetY += (maxY - minY);
+                }
+            }
+            //2. newPageData的items属性
+            newPageData.items = [];
+            for (let i = 0; i < pageDataArray.length; i++) {
+                let pageItem = {};
+                pageItem[JV.PROP_PAGE_SEQ] = i + 1;
+                pageItem[JV.PROP_CELLS] = [];
+                for (let j = 0; j < pageDataArray[i].items.length; j++) {
+                    for (let k = 0; k < pageDataArray[i].items[j].cells.length; k++) {
+                        pageItem[JV.PROP_CELLS].push(pageDataArray[i].items[j].cells[k]);
+                    }
+                }
+                pageItem[JV.PAGE_SPECIAL_MERGE_POS] = newPagePos[i];
+                newPageData.items.push(pageItem);
+            }
+            //3. everything is ok, then call me
+            me.exportExcel(newPageData, paperSize, fName, 'false', sheetNames, callback);
+            fsUtil.wirteObjToFile(newPageData, 'D:/GitHome/ConstructionOperation/tmp/combinedHeader.js');
+        } catch (e) {
+            console.log(e);
+        }
     }
 }

+ 202 - 0
modules/reports/util/rpt_pdf_util.js

@@ -0,0 +1,202 @@
+/**
+ * Created by chen on 2017/8/16.
+ */
+/**
+ * Created by zhang on 2017/8/14.
+ */
+
+const prf_cons = require('./pdf_base_files/rpt_pdf_consts');
+var pdf = require('pdfkit');
+var fs = require('fs');
+let jpcCmnHelper = require('../rpt_component/helper/jpc_helper_common');
+let DPI = jpcCmnHelper.getScreenDPI()[0];
+//let JV = prf_cons.JV;
+let JV = require('../rpt_component/jpc_value_define');
+
+module.exports ={
+    export_pdf_file:export_pdf_file
+}
+
+
+function export_pdf_file (pageData, paperSize, fName, callback) {
+    let offsetX= 10;
+    let offsetY=10;
+    var doc = new pdf({autoFirstPage: false});
+    let newName = '' + (new Date()).valueOf();
+    let stream = doc.pipe(fs.createWriteStream(__dirname.slice(0, __dirname.length - 21) + '/tmp/'+newName+'.pdf'));
+    let pageObj = pageData;
+    // doc.rect(5,5,1190,890).lineWidth(1).strokeColor('black').stroke();//边框
+    let paperSizeIdx = JV.PAGES_SIZE_STR.indexOf(paperSize);
+    let size = JV.PAGES_SIZE[paperSizeIdx];
+
+    if (pageObj && pageObj.items.length > 0 ) {
+        for(let i=0;i<pageObj.items.length;i++){
+            doc.addPage({size:[size[1]*DPI,size[0]*DPI]});
+            var page = pageObj.items[i],
+                fonts = pageObj[JV.NODE_FONT_COLLECTION],
+                styles = pageObj[JV.NODE_STYLE_COLLECTION],
+                controls = pageObj[JV.NODE_CONTROL_COLLECTION],
+                mergedBand = pageObj[JV.BAND_PROP_MERGE_BAND];
+
+            for (var j = 0; j < page.cells.length; j++) {
+                var cell = page.cells[j];
+                private_drawCell(cell, fonts, styles, controls, mergedBand);
+            }
+        }
+    }
+    doc.end();
+    stream.on('finish',function () {
+        console.log(newName + ".pdf was written.");
+        callback(newName);
+    })
+
+
+    function private_drawCell(cell, fonts, styles, controls, mergedBand) {
+        doc.save();
+        //doc.translate(0.5,0.5);
+        var style = styles[cell[JV.PROP_STYLE]];
+        if (style) {
+            private_drawLine(cell, doc, style, JV.PROP_TOP, [JV.PROP_LEFT, JV.PROP_TOP],[JV.PROP_RIGHT, JV.PROP_TOP], mergedBand, styles);
+            private_drawLine(cell, doc, style, JV.PROP_RIGHT, [JV.PROP_RIGHT, JV.PROP_TOP],[JV.PROP_RIGHT, JV.PROP_BOTTOM], mergedBand, styles);
+            private_drawLine(cell, doc, style, JV.PROP_BOTTOM, [JV.PROP_RIGHT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_BOTTOM], mergedBand, styles);
+            private_drawLine(cell, doc, style, JV.PROP_LEFT, [JV.PROP_LEFT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_TOP], mergedBand, styles);
+        }
+        private_drawCellText(cell, fonts, controls);
+        doc.restore();
+
+    }
+
+    function private_drawLine(cell, doc, style, styleBorderDest, startP, destP, mergedBand, styles) {
+        //doc.beginPath();
+        var destStyle = style;
+        if (mergedBand) {
+            if (mergedBand[styleBorderDest] == cell[JV.PROP_AREA][styleBorderDest]) {
+                destStyle = styles[mergedBand[JV.PROP_STYLE][JV.PROP_ID]];
+            }
+        }
+        doc.moveTo(cell[JV.PROP_AREA][startP[0]] + offsetX, cell[JV.PROP_AREA][startP[1]] + offsetY);
+        if (destStyle[styleBorderDest] && destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT] != 0) {
+            doc.lineWidth(1.0 * destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT]);
+            doc.lineTo(cell[JV.PROP_AREA][destP[0]] + offsetX, cell[JV.PROP_AREA][destP[1]] + offsetY);
+            doc.strokeColor(destStyle[styleBorderDest][JV.PROP_COLOR]);
+        }
+        doc.stroke();
+    }
+    function private_drawCellText(cell, fonts, controls) {
+        if (cell[JV.PROP_VALUE]) {
+            var values = ("" + cell[JV.PROP_VALUE]).split('|');
+            var font = fonts[cell[JV.PROP_FONT]];
+            var control = controls[cell[JV.PROP_CONTROL]];
+            var height = cell[JV.PROP_AREA][JV.PROP_BOTTOM] - cell[JV.PROP_AREA][JV.PROP_TOP];
+            var area = [cell[JV.PROP_AREA][JV.PROP_LEFT] + offsetX, cell[JV.PROP_AREA][JV.PROP_TOP] + offsetY, cell[JV.PROP_AREA][JV.PROP_RIGHT] + offsetX, cell[JV.PROP_AREA][JV.PROP_BOTTOM] + offsetY];
+            for (var i = 0; i < values.length; i++) {
+                area[JV.IDX_TOP] = cell[JV.PROP_AREA][JV.PROP_TOP] + i * (height / values.length) + offsetY;
+                area[JV.IDX_BOTTOM] = cell[JV.PROP_AREA][JV.PROP_TOP] + (i + 1) * (height / values.length) + offsetY;
+                private_drawText(values[i], area, font, control);
+            }
+        }
+    }
+
+    function private_drawText(val, area, font, control) {
+        var dftFontHeight = 12;
+        var output = [];
+        if (font) {
+            dftFontHeight = 1 * font[JV.FONT_PROPS[1]];
+            var dftFontBold = font[JV.FONT_PROPS[3]];
+            var dftFontItalic = font[JV.FONT_PROPS[4]];
+            if (dftFontBold && dftFontBold == 'T') {
+                doc.font(__dirname+'/pdf_base_files/hwxsb.ttf');
+            }else if(dftFontItalic && dftFontItalic == 'T'){
+                doc.font(__dirname+'/pdf_base_files/Smart-italic.ttf');
+            }else {
+                doc.font(__dirname+'/pdf_base_files/Smart.ttf');
+            }
+            doc.fontSize(dftFontHeight);
+        }
+        var options={};
+        if (control) {
+            private_setupAreaH(area, control.Horizon, font.FontAngle, dftFontHeight, output,options);
+            private_setupAreaV(area, control.Vertical, font.FontAngle, dftFontHeight, output);
+        } else {
+            private_setupAreaH(area, "left", font.FontAngle, dftFontHeight, output,options);
+            private_setupAreaV(area, "bottom", font.FontAngle, dftFontHeight, output);
+        }
+        var w = area[JV.IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT] - area[JV.IDX_LEFT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+        if (font.FontAngle != "0") {
+            w = area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM] - area[JV.IDX_TOP] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+        }
+        doc.save();
+        //doc.translate(output[0], output[1]);
+        if (w >= doc.widthOfString(val)) {
+            options.width=w;
+            options.height=dftFontHeight;
+        } else {
+            while (true) {
+                dftFontHeight--;
+                doc.fontSize(dftFontHeight);
+                if (w >= doc.widthOfString(val) || dftFontHeight < 6) {
+                    options.width=w;
+                    options.height=dftFontHeight;
+                    break;
+                }
+            }
+        }
+
+        var rotateOptions;
+        if (font.FontAngle != "0") {
+            if (control){
+                rotateOptions=private_setupAreaRotateOption(area,w,control.Vertical,dftFontHeight, output);
+            }else {
+                rotateOptions=private_setupAreaRotateOption(area,w,"bottom",dftFontHeight, output);
+            }
+            doc.rotate(font.FontAngle,rotateOptions);
+        }
+        doc.text(val,output[0], output[1],options);
+        doc.restore();
+    }
+
+    function private_setupAreaH(area, type, fontAngle, dftFontHeight, outputPoint,options) {
+        var lType = type;
+        if (type != "left" && type != "right" && type != "center") lType = "left";
+        options.align=lType;
+        outputPoint[0]=1 * area[JV.IDX_LEFT]+ JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+    }
+
+    function private_setupAreaV(area, type, fontAngle, dftFontHeight, outputPoint) {
+        var lType = type;
+        if (type != "top" && type != "bottom" && type != "center") lType = "top";
+        switch (lType) {
+            case "top":
+                outputPoint[1] = 1 * area[JV.IDX_TOP] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+                break;
+            case "bottom":
+                outputPoint[1] = 1 * area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM]-dftFontHeight;
+                break;
+            case "center":
+                outputPoint[1] = 1 * area[JV.IDX_TOP] + (1 * area[JV.IDX_BOTTOM]-1 * area[JV.IDX_TOP]- dftFontHeight) / 2;
+                break;
+        }
+    }
+
+    function private_setupAreaRotateOption(area,w, type="top",dftFontHeight,outputPoint){
+        var x = (area[JV.IDX_RIGHT] - area[JV.IDX_LEFT])/2+area[JV.IDX_LEFT];
+        var y =(area[JV.IDX_BOTTOM] - area[JV.IDX_TOP])/2+ area[JV.IDX_TOP];
+        var rotateOptions = {origin:[x,y]};
+        var h = area[JV.IDX_RIGHT] - area[JV.IDX_LEFT];
+        outputPoint[0]=x-w/2+JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+        var lType = type;
+        switch (lType) {
+            case "top":
+                outputPoint[1] = y- h/2+ JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+                break;
+            case "bottom":
+                outputPoint[1] = y+ h/2-JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM]-dftFontHeight;
+                break;
+            case "center":
+                outputPoint[1] = y+dftFontHeight/2;
+                break;
+        }
+        return rotateOptions;
+    }
+
+}

+ 7 - 0
public/fsUtil.js

@@ -24,5 +24,12 @@ module.exports = {
                 console.log('Write file: ' + filePath + ' ok!');
             });
         }
+    },
+    wirteObjToFile: function(obj, filePath) {
+        if (obj) {
+            let arr = [];
+            arr.push(JSON.stringify(obj));
+            this.writeArrayToFile(arr, filePath);
+        }
     }
 }

+ 3 - 0
public/web/rpt_value_define.js

@@ -35,6 +35,7 @@ let JV = {
     NODE_MAIN_INFO: "主信息",
     NODE_MAIN_INFO_RPT_NAME: "报表名称",
     NODE_PAGE_INFO: "打印页面_信息",
+    NODE_PAGE_SIZE: "纸张宽高",
     NODE_MARGINS: "页边距",
 
     NODE_FONT_COLLECTION: "font_collection",
@@ -192,8 +193,10 @@ let JV = {
     OFFSET_IDX_BOTTOM: 3,
 
     PROP_PAGE_SEQ: "page_seq",
+    PROP_CELLS: "cells",
 
     PAGE_SELF_DEFINE: "自定义",
+    PAGE_SPECIAL_MERGE_POS: "page_merge_pos",
 
     PAGES_SIZE_STR: ["A3", "A4", "A5", "B5", "LETTER", "LEGAL", "EXECUTIVE", "16K"],
     PAGES_SIZE_IDX: [8, 9, 11, 13, 1, 5, 7, 93],