以前打印相信很多人因为A4打印两个报告头大过,M要把一堆报告既有A4的也有A5的还有微生物的,可能输出Page还不那么严谨。要么换页不对叠加了、要么多空白页、中间夹杂A4报告就更加头大。也有的人为了打印页码的共几页而头大。
借助新设计的优势,一举解决痛点问题:
多输出PAGE导致空白页的协议优化
A4打印两个的协议约定
文本背景的协议约定
PDF的协议约定
页码的约定
约定封装
/*** 控制打印用A4打印两个的模式,业务只需要确保第一个或第二个元素是该元素即可达到A4打印两个的效果* @param A4Last 如果打印包含A4纸的话是把A4往后移还是不打乱顺序的合并A4前后的A5打印* @return*/public static PrintElement A4Double(boolean A4Last) {PrintElement ret = new PrintElement();ret.PrintType = "A4DOUBLE";if(A4Last==true){ret.PrintFlag="Last";}return ret;}/*** 输出页码元素** @param x x坐标(*必填)* @param y y坐标(*必填)* @param format 格式串,给空为:第{curnum}页,共{allnum}页 其他自己控制占位符* @param font 字体* @param fontSize 字体大小* @param fontStyle 字体样式* @param alignment 字体靠齐方向 Center:居中 Right:靠右 Justified或者空:靠左* @param color 颜色,html颜色 red #ffffff这种* @param colorBK 背景颜色,html颜色 red #ffffff这种,正常不给* @param angle 旋转角度,角度数字* @return*/public static PrintElement DrawPageNum(int x, int y, String format, String font, Integer fontSize, String fontStyle, PrintAlignment alignment, String color, String colorBK, String angle) {PrintElement ret = new PrintElement();ret.PrintX = String.valueOf(x);ret.PrintY = String.valueOf(y);//默认值if (format == null || format.isEmpty()) {format = "第{curnum}页,共{allnum}页";}ret.PrintText = format;ret.PrintFont = font;if (fontSize == null) {fontSize = 9;}ret.PrintFontSize = String.valueOf(fontSize);ret.PrintFontStyle = fontStyle;if (color == null) {color = "";}ret.PrintColor = color;if (colorBK != null && !colorBK.isEmpty()) {ret.PrintColor = ret.PrintColor + "^" + colorBK;}if (alignment != null) {ret.PrintAlignment = alignment.toString();}ret.Angle = String.valueOf(angle);ret.PrintType = "PAGENUM";return ret;}/*** 画标签** @param x x坐标(*必填)* @param y y坐标(*必填)* @param drawStr 要绘制的文本(*必填)* @param font 字体* @param fontSize 字体大小* @param fontStyle 字体样式* @param alignment 字体靠齐方向 Center:居中 Right:靠右 Justified或者空:靠左* @param color 颜色,html颜色 red #ffffff这种* @param colorBK 背景颜色,html颜色 red #ffffff这种,正常不给* @param angle 旋转角度,角度数字* @return*/public static PrintElement DrawLabel(int x, int y, String drawStr, String font, Integer fontSize, String fontStyle, PrintAlignment alignment, String color, String colorBK, String angle) {PrintElement ret = new PrintElement();ret.PrintX = String.valueOf(x);ret.PrintY = String.valueOf(y);ret.PrintText = drawStr;ret.PrintFont = font;if (fontSize == null) {fontSize = 9;}ret.PrintFontSize = String.valueOf(fontSize);ret.PrintFontStyle = fontStyle;if (color == null) {color = "";}ret.PrintColor = color;if (colorBK != null && !colorBK.isEmpty()) {ret.PrintColor = ret.PrintColor + "^" + colorBK;}if (alignment != null) {ret.PrintAlignment = alignment.toString();}ret.Angle = String.valueOf(angle);ret.PrintType = "Label";return ret;}/*** PDF文件的ftp或http全路径。用英文逗号分隔两个A5PDF路径打印会自动合并为一个A4。一个A5路径后跟个英文逗号,会把PDF转A4纸打印.单独调用打印。** @param httpOrFtpPath pdf文件的下载路径* @return*/public static PrintElement DrawFile(String httpOrFtpPath) {PrintElement ret = new PrintElement();ret.DataField = httpOrFtpPath;ret.PrintType = "FILE";return ret;}/*** PDF文件的ftp或http全路径。用英文逗号分隔两个A5PDF路径打印会自动合并为一个A4。一个A5路径后跟个英文逗号,会把PDF转A4纸打印,会把PDF每页提取成大图当一页打印** @param httpOrFtpPath pdf文件的下载路径* @return*/public static PrintElement DrawPDF(String httpOrFtpPath) {PrintElement ret = new PrintElement();ret.DataField = httpOrFtpPath;ret.PrintType = "PDF";return ret;}
实现A4Double和忽略空PAGE
/*** 构造函数,在这里就把切页处理好,避免老模式分页逻辑太复杂,简化后续操作** @param elementList* @return 返回页数,打印页的时候下标从0开始*/public int JRTPrintDrawInit(List<DrawElement> elementList) {if (elementList != null && elementList.size() > 0) {List<DrawElement> onePage = new ArrayList<>();for (DrawElement ele : elementList) {//控制打印机的元素不用管if (ele.PrintType.contains("PRINTER")) {continue;}//控制打印PDF的元素不用管if (ele.PrintType.contains("FILE")) {AllPDFFile.add(ele);continue;}//A4打印两个的模式if (ele.PrintType.contains("A4DOUBLE")) {//A4打印两个A5模式isA4Double=true;if(ele.PrintFlag.equals("Last")){//A4移到最后isA4ToLast=true;}continue;}//按照页切割if (ele.PrintType.equals("PAGE") || ele.PrintType.equals("PDF")) {//剔除空白页,让业务可以不那么容易出空白页if (onePage.size() > 0) {allPageData.add(onePage);//存每页纸张的判断if(pageMaxPrintY>587) {pagePaper.add("A4");}else{pagePaper.add("A5");}pageMaxPrintY=0;}onePage = new ArrayList<>();}//打印PDF文件的元素元素if (ele.PrintType.equals("PDF")) {JRTPrintDraw.FileService fileService = new JRTPrintDraw.FileService();InputStream stream = null;try {//从文件服务里面下载文件if (ele.PrintImageFile == "1") {stream = fileService.DownloadStream(ele.DataField, true);} else {stream = fileService.DownloadStream(ele.DataField, false);}if (stream != null) {List<BufferedImage> images = JRTPrintDraw.PDFUtil.GetPDFImage(stream);stream.close();if (images != null && images.size() > 0) {for (BufferedImage img : images) {DrawElement graph = new DrawElement();graph.PrintX = String.valueOf(0);graph.PrintY = String.valueOf(0);graph.DataField = ImgToBase64(img);graph.PrintWidth = String.valueOf(img.getWidth() / 5);graph.PrintHeight = String.valueOf(img.getHeight() / 5);graph.PrintType = "Graph";graph.PrintFlag = "D";onePage.add(graph);//剔除空白页,让业务可以不那么容易出空白页if (onePage.size() > 0) {allPageData.add(onePage);//存每页纸张的判断if(img.getHeight() / 5>587) {pagePaper.add("A4");}else{pagePaper.add("A5");}pageMaxPrintY=0;}onePage = new ArrayList<>();}}}} catch (Exception ex) {StringWriter stringWriter = new StringWriter();ex.printStackTrace(new PrintWriter(stringWriter));WriteLog(stringWriter.toString());}continue;}//得到最大的Y坐标DealMaxY(ele);//不是分页元素才加if (!ele.PrintType.equals("PAGE")) {onePage.add(ele);}}if (onePage.size() > 0) {allPageData.add(onePage);//存每页纸张的判断if(pageMaxPrintY>587) {pagePaper.add("A4");}else{pagePaper.add("A5");}pageMaxPrintY=0;}}//A4打印两个的处理逻辑if(isA4Double==true){DealA4Double();}//设置打印的页面for(List<DrawElement> onePage:allPageData) {printPageData.add(onePage);}return allPageData.size();}/*** 处理A4打印两个*/private void DealA4Double(){//存处理的A4打印两个页List<List<DrawElement>> allA4DoublePape = new ArrayList<>();//临时放A4后移的页List<List<DrawElement>> a4LastPageTmp = new ArrayList<>();int index=-1;//当前添加A5到一页的数量int addA5Num=0;//合并一页用的临时数组List<DrawElement> mergePageTmp=new ArrayList<>();for(List<DrawElement> onePage:allPageData){index++;String paper=pagePaper.get(index);//A4页处理if(paper.equals("A4")){//中间的A4后移if(isA4ToLast==true){a4LastPageTmp.add(onePage);}else{//如果有合并的页就终止if(mergePageTmp.size()>0) {//合并满一页开始新的一页allA4DoublePape.add(mergePageTmp);mergePageTmp = new ArrayList<>();addA5Num = 0;}allA4DoublePape.add(onePage);}}//A5页处理else{addA5Num++;//上半页if(addA5Num==1){MergePage(mergePageTmp,onePage,false);}//下半页else if(addA5Num==2){MergePage(mergePageTmp,onePage,true);//如果有合并的页就终止if(mergePageTmp.size()>0) {//合并满一页开始新的一页allA4DoublePape.add(mergePageTmp);mergePageTmp = new ArrayList<>();addA5Num = 0;}}}}//如果有合并的页就终止if(mergePageTmp.size()>0) {//合并满一页开始新的一页allA4DoublePape.add(mergePageTmp);mergePageTmp = null;addA5Num = 0;}//后移的A4合并进主数据if(a4LastPageTmp.size()>0){for(List<DrawElement> onePage:a4LastPageTmp){allA4DoublePape.add(onePage);}}//替换主数据allPageData=allA4DoublePape;allA4DoublePape=null;a4LastPageTmp=null;}/*** 合并页数据* @param mergeTmp 合并的临时数据* @param addPage 要并入的页* @param addY 是否添加y,是就是A4下面*/private void MergePage(List<DrawElement> mergeTmp,List<DrawElement> addPage,boolean addY){//不添加Y的话就原封不动的转移if(addY==false){if(addPage!=null&&addPage.size()>0){for(DrawElement ele:addPage){mergeTmp.add(ele);}}}//A4下半页偏移Y坐标else{if(addPage!=null&&addPage.size()>0){for(DrawElement ele:addPage){ele.PrintY=String.valueOf(DrawConvert.ToInt32(ele.PrintY)+583);//线的终点的Y坐标if(ele.PrintType.equals("ILineN")){ele.PrintHeight=String.valueOf(DrawConvert.ToInt32(ele.PrintHeight)+583);}//多边形的Y坐标if(ele.PrintType.equals("Poly")){String [] arr=ele.PrintText.split("\\^");String polyStr = "";for(String s:arr){String [] arr1=s.split("@");if (polyStr.isEmpty()) {polyStr = arr1[0] + "@" + String.valueOf(DrawConvert.ToInt32(arr[1])+583);} else {polyStr += "^" + arr1[0] + "@" + String.valueOf(DrawConvert.ToInt32(arr[1])+583);}}ele.PrintText=polyStr;}mergeTmp.add(ele);}}}}
打印示例代码
import JRT.Core.Dto.OutParam;
import JRT.Core.Dto.OutValue;
import JRT.Core.Dto.PrintElement;
import JRT.Core.Util.PrintDrawProtocol;
import JRTBLLBase.BaseHttpHandlerNoSession;
import JRTBLLBase.Helper;import java.awt.*;
import java.util.ArrayList;
import java.util.List;/*** 输出符合打印元素绘制协议的打印元素数据,来供打印执行层打印*/
public class PrintBarCodeTest extends BaseHttpHandlerNoSession {/*** 按传入的RowID输出符合打印元素绘制协议的数据来实现打印控制* @param RowID 业务主键* @param P1* @param P2* @param P3* @param P4* @param P5* @param P6* @param P7* @param P8* @param P9* @param P10* @param P11* @param P12* @param P13* @param Session* @param Output* @return*/public String GetData(String RowID, String P1, String P2, String P3, String P4, String P5, String P6, String P7, String P8, String P9, String P10, String P11, String P12, String P13, OutValue Session, OutValue Output) throws Exception{List<PrintElement> retList=new ArrayList<>();//标志A4打印两个retList.add(PrintDrawProtocol.A4Double(true));//打印PDF文件//retList.add(PrintDrawProtocol.DrawFile("http://localhost:8080/JRTWeb/FileService/test.pdf"));retList.add(PrintDrawProtocol.DrawPDF("http://localhost:8080/JRTWeb/FileService/test.pdf"));//换页retList.add(PrintDrawProtocol.ChangePage());//换页retList.add(PrintDrawProtocol.ChangePage());//换页retList.add(PrintDrawProtocol.ChangePage());//页码retList.add(PrintDrawProtocol.DrawPageNum(720,10,"","宋体",12,"", null,"","#fda632","0"));//画logoretList.add(PrintDrawProtocol.DrawLabel(420,10,"http的logn图","宋体",22,"", null,"","#fda632","0"));retList.add(PrintDrawProtocol.DrawGraph(420,30,64,64,"http://localhost:8080/JRTWeb/FileService/logo.png",false,null));retList.add(PrintDrawProtocol.DrawLabel(420,150,"ftp的logn图","宋体",12,"", null,"","#fda632","0"));//retList.add(PrintDrawProtocol.DrawGraph(420,180,64,64,"ftp://zlz:zlz@127.0.0.1:21/ftp.png",false,null));//画一个文本retList.add(PrintDrawProtocol.DrawLabel(20,20,"zhanglianzhu","宋体",12,"", null,"","#ff5252","0"));//画一个条码retList.add(PrintDrawProtocol.DrawBarCode(20,50,"0947809",true,5,30,"","宋体",12,"",null,"","0"));//换一根横线retList.add(PrintDrawProtocol.DrawLine(20,70,70,70,1,"",""));//换一根竖线retList.add(PrintDrawProtocol.DrawLine(50,10,50,470,1,"",""));//绘制一个条码retList.add(PrintDrawProtocol.DrawQRCode(20,90,"jbase",90,90));//绘制一个条码retList.add(PrintDrawProtocol.DrawLabel(20,210,"jbase打印支持","宋体",12,"",null,"","","0"));//绘制一个条码retList.add(PrintDrawProtocol.DrawLabel(20,230,"20231118 22:49","宋体",12,"",null,"","","0"));//画一个点retList.add(PrintDrawProtocol.DrawPoint(20,270,10,10,"o",""));retList.add(PrintDrawProtocol.DrawPoint(100,270,10,10,"[]",""));retList.add(PrintDrawProtocol.DrawPoint(200,270,10,10,"<>",""));//画多边形List<Point> pointList=new ArrayList<>();Point p1=new Point();p1.x=10;p1.y=300;pointList.add(p1);Point p2=new Point();p2.x=100;p2.y=310;pointList.add(p2);Point p3=new Point();p3.x=50;p3.y=360;pointList.add(p3);retList.add(PrintDrawProtocol.DrawPoly(pointList,""));//画复选框retList.add(PrintDrawProtocol.DrawCheckBox(10,400,true,30,30));//画单选框retList.add(PrintDrawProtocol.DrawRadio(60,400,true,30,30));//画复选框retList.add(PrintDrawProtocol.DrawCheckBox(110,400,false,30,30));//画单选框retList.add(PrintDrawProtocol.DrawRadio(160,400,false,30,30));//绘制一个条码retList.add(PrintDrawProtocol.DrawLabel(20,1010,"页尾","宋体",12,"",null,"","","0"));retList.add(PrintDrawProtocol.DrawLabel(20,900,"A4纸张打印","宋体",12,"", null,"","","0"));//换一根横线retList.add(PrintDrawProtocol.DrawLine(20,1025,700,1025,1,"",""));//换页retList.add(PrintDrawProtocol.ChangePage());//页码retList.add(PrintDrawProtocol.DrawPageNum(520,10,"","宋体",12,"", null,"","#fda632","0"));//画logoretList.add(PrintDrawProtocol.DrawLabel(420,10,"logn图","宋体",12,"", null,"","","0"));retList.add(PrintDrawProtocol.DrawGraph(420,20,64,64,"http://localhost:8080/JRTWeb/FileService/logo.png",false,null));//画一个文本retList.add(PrintDrawProtocol.DrawLabel(10,10,"这是打印的第二页","宋体",12,"", null,"","","0"));//画一个条码retList.add(PrintDrawProtocol.DrawBarCode(10,50,"0947809",true,5,30,"","宋体",12,"",null,"","0"));//换一根横线retList.add(PrintDrawProtocol.DrawLine(10,70,70,70,1,"",""));//换一根竖线retList.add(PrintDrawProtocol.DrawLine(50,10,50,470,1,"",""));//绘制一个条码retList.add(PrintDrawProtocol.DrawQRCode(10,90,"jbase",90,90));//绘制一个条码retList.add(PrintDrawProtocol.DrawLabel(10,210,"jbase打印支持","宋体",12,"",null,"","","0"));//绘制一个条码retList.add(PrintDrawProtocol.DrawLabel(10,230,"20231119","宋体",12,"",null,"","","0"));retList.add(PrintDrawProtocol.DrawLabel(20,500,"A5纸张打印","宋体",12,"", null,"","","0"));//画一根横线retList.add(PrintDrawProtocol.DrawLine(20,525,700,525,1,"",""));//换页retList.add(PrintDrawProtocol.ChangePage());//页码retList.add(PrintDrawProtocol.DrawPageNum(520,10,"","宋体",12,"", null,"","#fda632","0"));//画logoretList.add(PrintDrawProtocol.DrawLabel(420,10,"logn图","宋体",12,"", null,"","","0"));retList.add(PrintDrawProtocol.DrawGraph(420,20,64,64,"http://localhost:8080/JRTWeb/FileService/logo.png",false,null));//画一个文本retList.add(PrintDrawProtocol.DrawLabel(10,10,"这是打印的第三页","宋体",12,"", null,"","","0"));//画一个条码retList.add(PrintDrawProtocol.DrawBarCode(10,50,"0947809",true,5,30,"","宋体",12,"",null,"","0"));//换一根横线retList.add(PrintDrawProtocol.DrawLine(10,70,70,70,1,"",""));//换一根竖线retList.add(PrintDrawProtocol.DrawLine(50,10,50,470,1,"",""));//绘制一个条码retList.add(PrintDrawProtocol.DrawQRCode(10,90,"jbase",90,90));//绘制一个条码retList.add(PrintDrawProtocol.DrawLabel(10,210,"jbase打印支持","宋体",12,"",null,"","","0"));//绘制一个条码retList.add(PrintDrawProtocol.DrawLabel(10,230,"20231119","宋体",12,"",null,"","","0"));retList.add(PrintDrawProtocol.DrawLabel(20,500,"A5纸张打印","宋体",12,"", null,"","","0"));//画一根横线retList.add(PrintDrawProtocol.DrawLine(20,525,700,525,1,"",""));//换页retList.add(PrintDrawProtocol.ChangePage());//页码retList.add(PrintDrawProtocol.DrawPageNum(520,10,"","宋体",12,"", null,"","#fda632","0"));//画logoretList.add(PrintDrawProtocol.DrawLabel(420,10,"logn图","宋体",12,"", null,"","","0"));retList.add(PrintDrawProtocol.DrawGraph(420,20,64,64,"http://localhost:8080/JRTWeb/FileService/logo.png",false,null));//画一个文本retList.add(PrintDrawProtocol.DrawLabel(10,10,"这是打印的第四页","宋体",12,"", null,"","","0"));//画一个条码retList.add(PrintDrawProtocol.DrawBarCode(10,50,"0947809",true,5,30,"","宋体",12,"",null,"","0"));//换一根横线retList.add(PrintDrawProtocol.DrawLine(10,70,70,70,1,"",""));//换一根竖线retList.add(PrintDrawProtocol.DrawLine(50,10,50,470,1,"",""));//绘制一个条码retList.add(PrintDrawProtocol.DrawQRCode(10,90,"jbase",90,90));//绘制一个条码retList.add(PrintDrawProtocol.DrawLabel(10,210,"jbase打印支持","宋体",12,"",null,"","","0"));//绘制一个条码retList.add(PrintDrawProtocol.DrawLabel(10,230,"20231206","宋体",12,"",null,"","","0"));retList.add(PrintDrawProtocol.DrawLabel(20,500,"A5纸张打印","宋体",12,"", null,"","","0"));//画一根横线retList.add(PrintDrawProtocol.DrawLine(20,525,700,525,1,"",""));//先包一个打印元素绘制协议数据生成的工具类来解决元素约束问题,工具类实现了调用工具类得到标签,条码,文本等return Helper.Object2Json(retList);}
}
让独立的A4后移
不扰乱顺序
这样就能极大的简化业务的打印控制逻辑,方便得到高效稳定的打印效果,后面有时间将解决绘制表格的痛点问题来给Web提供强大的客户端支持,这是一次没有历史代码干扰的全新设计,也是对老效果的全面超越 哈哈