说句老实话,ReportX是非常好的控件。可惜作者宣传的不是那么到位。觉得有些可惜了。
接触ReportX很长时间了,这次聚宝盆记账易就是用的ReportX控件来打印的,有些人喜欢奇奇怪怪的模版,就让他们自己去设计吧。写这个软件的时候各种赶工期,打印也没那么仔细测试。后来有人反映说分页打印有点问题。今天干脆整理了下,打印这个分离成小例子发上来。
先上打印预览效果吧,效果如下。
主文件
io.open(); import win.ui; import reportX; import reportX.design; import console; //import com.activeX; import com.lite; /*DSG{{*/ mainForm = win.form(text="prinx 打印小例子";right=763;bottom=565;parent=...) mainForm.add( button={cls="button";text="打印预览";left=554;top=523;right=641;bottom=554;z=2}; button2={cls="button";text="填充数据";left=447;top=525;right=534;bottom=556;z=3}; button3={cls="button";text="直接打印";left=656;top=522;right=743;bottom=553;z=4}; custom={cls="custom";text="custom";left=8;top=6;right=746;bottom=503;autosize=1;center=1;edge=1;transparent=1;z=1}; 替换={cls="button";text="替换";left=300;top=527;right=375;bottom=557;z=5} ) /*}}*/ prinx = reportX(mainForm.custom); //调用prinx报表方法 prinx.openReport( io.fullpath("/Example/通用销售单.rpxe")); var data = /**{shop_phone="15671404230";user_endtime="2020-03-28 11:33:20";p_dabt="0.00";p_order_no="XS20191005101025";status=3;shop_type_name="通用基础店铺记账";shop_type_id=2;p_discountMoney="0.00";uuid="JS5CC74F819AC71495797";p_operator="邓继松";user_group_text="店铺超级店长";id=2;tableData='商品全名,单位,数量,单价,金额合计,备注\r\n新商品3,条,1,20.00,20.00,\r\n看1,件,1,20.00,20.00,\r\n这里是测试自动完成,,1,30.00,30.00,\r\n呜呜,dd,1,28.00,28.00,\r\n看看全名是什么,台,1,30.00,30.00,\r\n这里瞎写,个,1,150.00,150.00,\r\n家电就安静地,,1,20.00,20.00,\r\n这个是最后一次,,1,60.00,60.00,\r\n新商品,,1,50.00,50.00,\r\n看看新商品,支,1,60.00,60.00,\r\n金拇指老人机,台,1,180.00,180.00,';p_time="2019-10-05 10:22:53";p_actual_pay="648.00";user_name="邓继松";appid=10002;io_path="通用销售单";shop_name="劲松电脑通讯";p_payable="648.00";shop_city="松滋市王家桥镇麻水社区85号";user_avatarurl="http://image.jvbaopeng.com/shop/20190526/df9ea2295.jpg";endtime=1585366400}**/; data = eval(data) mainForm.button.oncommand = function(id,event){ prinx.printPreview() } mainForm.button3.oncommand = function(id,event){ prinx.printSheet(false) //打印文件,是否显示打印设置对话框 } //插入当行 var addline = function(n,temptab){ prinx.setCellValue(1,n,temptab[1] ); //行号 prinx.setCellValue(2,n,temptab[2] ); //商品 prinx.setCellValue(5,n,temptab[3] ); //单位 prinx.setCellValue(6,n,temptab[4] ); //数量 prinx.setCellValue(7,n,temptab[5] ); prinx.setCellValue(8,n,temptab[6] ); prinx.setCellValue(9,n,temptab[7] ); } mainForm.button2.oncommand = function(id,event){ var tableda = ..string.splitEx(data.tableData); //默认按行拆分 var alltab = {}; var temptab = {}; //临时数组 //把数据整理规范下 if(..string.indexOf(tableda[1],"操作")){ //把表格里有操作字样的删掉 for(k,v in tableda){ temptab = ..string.splitEx(v,","); ..table.pop(temptab,1); } } for(k,v in tableda){ temptab = ..string.splitEx(v,","); if(k==1){ ..table.insert(temptab,"NO"); }else { ..table.insert(temptab,k-1); } ..table.push(alltab,temptab); } var htab = table.remove(alltab,1); //移除第一行数组用作打印标题 console.dump(alltab); var p_remarks =""; if(data[["p_remarks"]]){ p_remarks = data.p_remarks ; } var con =prinx.rowCount; //模版总行数 //再判断一张纸能不能打下 var tabN = con - 9 ; //减去7行是头尾8行,还有一行是表头,一行是合计,共减去10行,就是模版里能打表内容的 var dtatN = #alltab ; //所有商品的行数 var num = 0 ; //商品数量 var pay_num = 0 ; //总金额 var pano = ..math.ceil(dtatN/tabN); //取分页,看共有几页 //先把表头表尾填充清楚 //先填充表头 prinx.setCellValue(1,1,data.shop_name++"销售单"); prinx.setCellValue(3,3,data.p_order_no); prinx.setCellValue(3,2,data.p_user_name); prinx.setCellValue(6,2,data.p_phone); prinx.setCellValue(6,3,data.p_operator); prinx.setCellValue(9,3,data.p_time); prinx.setCellValue(9,2,data.p_address); addline(4,htab) ; //表头数据 //填表尾巴,按行高算 prinx.setCellValue(1,con,"地址:"++ data.shop_city); prinx.setCellValue(8,con,"电话:"++ data.shop_phone); prinx.setCellValue(1,(con-2),"备注:"++ p_remarks); prinx.setCellValue(1,(con-3),"应付金额(元):"++ data.p_payable); prinx.setCellValue(4,(con-3),"优惠金额(元):"++ data.p_discountMoney); prinx.setCellValue(8,(con-3),"实付金额(元):"++ data.p_payable++" 欠款:"++data.p_dabt); //多的几页就复制页面过来 for(MN=2;pano;1){ prinx.appendRow(1); //先添加一行 prinx.copyCell(1,1,10,con) //复制原版内容 prinx.paste(1,con*(MN-1)+1,true) //粘帖为新的模版 } //锁定填充快点 prinx._object.InvalidatePaint(); var LRow = 0; //正式打印行数 for(M=1;pano;1){ //每次正式打印行数等于当商品数量减去表格可打印行数*页码大于0则打印表整行,否则为余数 LRow = (dtatN-tabN*M > 0) ? tabN :dtatN%tabN; //每一页把每一页的数量和金额都清零 num = 0; pay_num = 0; for(i=1;LRow;1){ //行 temptab = alltab[i+(M-1)*tabN]; addline(4+i+(M-1)*con,temptab); //列 num += tonumber(temptab[4],10); pay_num += tonumber(temptab[6],10); //填充表尾 prinx.setCellValue(1,(con-4)+con*(M-1),"合计"); prinx.setCellValue(6,(con-4)+con*(M-1),num); prinx.setCellValue(8,(con-4)+con*(M-1),..string.format("%.2f",pay_num)); //有多页就显示分页 if(tabN<dtatN){ prinx.setCellValue(9,(con-4)+con*(M-1),"第"++M++"页/共"++pano++"页"); } } } prinx._object.ValidatePaint(); } mainForm.替换.oncommand = function(id,event){ prinx.replace(1,17,10,17,false,false,"定","三国杀交付给交付给"); } mainForm.show() win.loopMessage();
aardio自带的reportX好像有点小问题,缺几个函数和一个函数错误了,我这把小修改的放上来吧。
import access; import com.lite; import util.metaProperty; class reportX{ ctor(winform){ var ocx = ..com.lite(_reportOcxPath) ocx.createEmbed(winform,"{A5DA6E97-1D4C-4708-B705-84A45716B4DD}") this = winform._embedObject; this._ocx = ocx; }; newReport = function(aColCount,aRowCount){ return this._object.NewReport(aColCount,aRowCount); } openReport = function(aFileName){ return this._object.OpenReport(..io.fullpath(aFileName)); } saveReport = function(aFileName){ return this._object.SaveReport(..io.fullpath(aFileName)); } openString = function(aReport,aCompression){ return this._object.OpenString (aReport,aCompression); } saveString = function(aCompression){ return this._object.SaveString(aCompression); } printSetup = function(){ return this._object.PrintSetup(); } printPreview = function(){ return this._object.PrintPreview(); } printSheet = function(aDialog){ return this._object.PrintSheet(aDialog); } replace = function(aCol1,aRow1,aCol2,aRow2, aCaseSensitive,aWholeWords,aFindString,aReplaceString){ return this._object.Replace(aCol1,aRow1,aCol2,aRow2, aCaseSensitive,aWholeWords,aFindString,aReplaceString); } setCellSelectColor = function(aColor1,aColor2){ return this._object.SetCellSelectColor(aColor1,aColor2); } validatePaint = function(){ return this._object.ValidatePaint(); } setCellBackColor = function(aCol,aRow,aBackColor){ return this._object.SetCellBackColor(aCol,aRow,aBackColor); } setCellFontColor = function(aCol,aRow,aBackColor){ return this._object.SetCellFontColor(aCol,aRow,aBackColor); } setCellFontStyle = function(aCol,aRow,aFontStyle,aStyleBool){ return this._object.SetCellFontStyle(aCol,aRow,aFontStyle,aStyleBool); } setCellExpression = function(aCol,aRow,aExpression){ return this._object.SetCellExpression(aCol,aRow,aExpression); } appendCol = function(aCount){ return this._object.AppendCol(aCount); } appendRow = function(aCount){ return this._object.AppendRow(aCount); } copyCell = function(aCol1,aRow1,aCol2,aRow2){ return this._object.CopyCell(aCol1,aRow1,aCol2,aRow2); } paste = function(aCol,aRow,asize){ return this._object.Paste(aCol,aRow,asize); } clearCell = function(aCol1,aRow1,aCol2,aRow2){ return this._object.AppendRow(aCol1,aRow1,aCol2,aRow2); } clearData = function(aCol1,aRow1,aCol2,aRow2){ return this._object.ClearData(aCol1,aRow1,aCol2,aRow2); } getInputCell = function(){ return this._object.GetInputCell(); } getSelectCell = function(){ return this._object.GetSelectCell(); } setSelectCell = function(aCol1,aRow1,aCol2,aRow2){ return this._object.SetSelectCell(aCol1,aRow1,aCol2,aRow2); } mergeCell = function(aCol1,aRow1,aCol2,aRow2){ return this._object.MergeCell(aCol1,aRow1,aCol2,aRow2); } mergeSelected = function(){ return this.mergeCell(this.getSelectCell()); } setFrozenCol = function(aFrozenStart,aFrozenEnd){ return this._object.SetFrozenCol(aFrozenStart,aFrozenEnd); } setFrozenRow = function(aFrozenStart,aFrozenEnd){ return this._object.SetFrozenRow(aFrozenStart,aFrozenEnd); } setFrozenRow = function(aFrozenStart,aFrozenEnd){ return this._object.SetFrozenRow(aFrozenStart,aFrozenEnd); } getCellValue = function(aCol,aRow){ return this._object.GetCellValue(aCol,aRow); } setCellValue = function(aCol,aRow,aValue){ return this._object.SetCellValue(aCol,aRow,aValue); } setCellFormat = function(aCol,aRow,aFormatType,aFormatText){ return this._object.SetCellFormat(aCol,aRow,aFormatType,aFormatText); } setCellControl = function(aCol,aRow,aControlType){ return this._object.SetCellControl(aCol,aRow,aControlType); } exportExcel = function(aFileName,aDisplayValue,aSheetName){ return this._object.ExportExcel(..io.fullpath(aFileName),aSheetName : "Sheet1",aDisplayValue); } importExcel = function(aFileName,aOleText){ if(aOleText===null) aOleText = true; var db,err = ..access( aFileName, {["Extended Properties"] = "Excel 8.0;HDR=No";}) if(!db) return null,err; for(tbName,tbType,tbObj in db.eachTableObject() ){ if( ( tbType=="TABLE") && ( tbName[#tbName]=='$'# ) ){ var tb = db.getTable("SELECT COUNT(*) AS c FROM [%s]",tbName); if(tb){ this.newReport(tbObj.Columns.count,tb[1].c) var row = 0; for(rs in db.each("SELECT * FROM ["+tbName+"]") ){ row = row + 1; for( i=1;rs.Fields.Count ){ this.setCellValue(i,row,rs(i-1).value); } } db.close(); return true; } } } db.close(); } importExcelOle = function(aFileName,aOleText,aCol1,aRow1,aCol2,aRow2){ if(aOleText===null) aOleText = true; if( (aCol1 === null) || (aRow1 === null) || (aCol2 === null) || (aRow2 === null) ){ var db,err = ..access( aFileName, {["Extended Properties"] = "Excel 8.0;HDR=No";}) if(!db) return null,err; for(tbName,tbType,tbObj in db.eachTableObject() ){ if( ( tbType=="TABLE") && ( tbName[#tbName]=='$'# ) ){ var tb = db.getTable("SELECT COUNT(*) AS c FROM [%s]",tbName); var columns = tbObj.Columns.count; if(tb){ db.close() return this._object.ImportExcelOle(..io.fullpath(aFileName),1,1,columns,tb[1].c,aOleText); } } } db.close() } return this._object.ImportExcelOle(..io.fullpath(aFileName),aCol1,aRow1,aCol2,aRow2,aOleText); } openDatabaseGuide = function(){ return this._object.OpenDatabaseGuide(); } setTopPoleText = function(aIndex,aText) { return this._object.SetPoleText(0,aIndex,aText); } setLeftPoleText = function(aIndex,aText) { return this._object.SetPoleText(1,aIndex,aText); } openQuery = function(){ return this._object.OpenQuery(); } lockUpdate = function(proc){ this._object.InvalidatePaint(); proc(); this._object.ValidatePaint(); } setCellBorder = function(aCol,aRow,aBorderType, aBorderWidth,aBorderStyle){ this._object.SetCellBorder(aCol,aRow,aBorderType, aBorderWidth,aBorderStyle); } editCellScript = function(aCol,aRow){ this._object.EditCellScript(aCol,aRow); } addCellPicture = function(aCol,aRow,aFileName,aStretch){ this._object.AddCellPicture(aCol,aRow,..io.fullpath(aFileName),aStretch); } delCellPicture = function(aCol,aRow){ this._object.DelCellPicture(aCol,aRow); } addChartSeries = function(aChartName,aSeriesType,aSeriesSignText,aSeriesDataText,aSeriesCell){ return this._object.AddChartSeries(aChartName,aSeriesType,aSeriesSignText,aSeriesDataText,aSeriesCell); } @_metaProperty; } namespace reportX{ _reportOcxPath = ..fsys.getSpecial( 0x1c /*_CSIDL_LOCAL_APPDATA*/ ,"aardio/std/ReportX.ocx"); if(!..io.exist(_reportOcxPath)){ ..string.save(_reportOcxPath,$"~\lib\reportX\.dll\ReportX.ocx" ) } _metaProperty = ..util.metaProperty( connectionString = { _get = function(){ return owner._object.ConnectionString; } _set = function( v ){ owner._object.ConnectionString = v; } }; executeScript = { _get = function(){ return owner._object.ExecuteScript; } _set = function( v ){ owner._object.ExecuteScript = v; } }; printBackColor = { _get = function(){ return owner._object.PrintBackColor; } _set = function( v ){ owner._object.PrintBackColor = v; } }; printBorders = { _get = function(){ return owner._object.PrintBorders; } _set = function( v ){ owner._object.PrintBorders = v; } }; colCount = { _get = function(){ return owner._object.ColCount; } _set = function( v ){ owner._object.ColCount = v; } }; rowCount = { _get = function(){ return owner._object.RowCount; } _set = function( v ){ owner._object.RowCount = v; } }; saved = { _get = function(){ return owner._object.Saved; } }; ) } /**intellisense() reportX = reportX报表控件 reportX(__/*窗口对象*/) = 创建reportX报表控件 reportX() = !prinx. !prinx.connectionString = 数据库连接串 !prinx.executeScript = 单元格改变时是否自动执行脚本 !prinx.openDatabaseGuide() = 打开数据库连接向导 !prinx.newReport(.(列数,行数) = 新建报表 !prinx.openReport(.(报表文件路径) = 打开报表 !prinx.saveReport(.(报表文件路径) = 存储报表 !prinx.openString(.(报表字符串,是否压缩) = 从字符串载入报表 !prinx.saveString(.(是否压缩) = 保存到字符串 !prinx.printSetup = 打印设置 !prinx.printPreview = 打印预览 !prinx.printSheet = 直接打印 !prinx.saved = 是否保存 !prinx.colCount = 列总数 !prinx.rowCount = 行总数 !prinx.addChartSeries(.(图表名,类型,样式,数据,单元格) = 添加图表内容\n详见帮助文档 !prinx.setCellFontStyle(.(列数,行数,样式类型,是否设置) = 参数@3可选字体类型如下:\n0:粗体;1:斜体;2:下滑线;3:删除线 !prinx.setCellExpression(.(列数,行数,公式) = 设置单元格公式。\n支持标准函数+、-、*、/、\整除、%取余、^乘方、\nPI、Abs、Sqrt、Ln、Exp、Sin、Cos、Tg、ArcTan、\nFac阶乘、(左扩号、)右扩号\n支持自定义函数Sum(aCol1,aRow1、aCol2、aRow2)、\nAverage(aCol1,aRow1、aCol2、aRow2)、Max(aCol1,aRow1、aCol2、aRow2)、\nMin(aCol1,aRow1、aCol2、aRow2)、Stdev(aCol1,aRow1、aCol2、aRow2) !prinx.mergeSelected() = 合并选中单元格 !prinx.setTopPoleText(列,__/*标题*/) = 设置列标题 !prinx.setLeftPoleText(行,__/*标题*/) = 设置行标题 !prinx.setFrozenCol(.(起始列,结束列) = 设置冻结列 !prinx.setFrozenRow(.(起始行,结束行) = 设置冻结行 !prinx.setSelectCell(起始行,起始列,结束行,结束列) = 设置选区 !prinx.getSelectCell() = 返回选区 !prinx.getCellValue(.(列,行) = 返回指定单元格的值 !prinx.editCellScript(.(列,行) = 插入脚本 !prinx.addCellPicture(.(列,行,图像路径,是否拉伸) = 添加图像 !prinx.delCellPicture(.(列,行) = 删除图像 !prinx.setCellBackColor(.(列,行,背景色) = 设置单元格背景色 !prinx.setCellFontColor(.(列,行,字体颜色) = 设置单元格字体颜色 !prinx.setCellFontStyle(.(列,行,字体样式,是否设置) = 设置字体样式(0:粗体;1:斜体;2:下滑线;3:删除线) !prinx.setCellExpression(.(列,行,公式) = 设置公式 !prinx.setCellBorder(.(列,行,边框类型,宽度,样式) = 边框类型\n 0:四周 1:左边 2:上边 3:右边 4:下边 5:斜线 6:反斜线\n\n边框样式\n 0:实线;1:虚线;2:点;3:点虚线;4点点虚线 !prinx.setCellControl(.(列号,行号,输入控制) = 输入控制\n0:无\n1:字母\n2:自然数\n3:整数\n4:字母数字\n5:字母数字\n6:实数 !prinx.setCellFormat(列号,行号,1,"0.00") = 输入1234.5 显示1234.50 !prinx.setCellFormat(列号,行号,1,"##,###.00") = 输入1234.5 显示1,234.50 !prinx.setCellFormat(列号,行号,1,"0.00%") = 输入1234.5 显示1234.50% !prinx.setCellFormat(列号,行号,2,"3") = 输入1234.5 显示1230 !prinx.setCellFormat(列号,行号,3,"yyyy-MM-dd") = 输入1-01-01 显示2001-01-01 !prinx.setCellFormat(列号,行号,3 "yyyy'年'MM'月'dd'日'") = 输入1-01-01 显示2001年01月01日 !prinx.setCellFormat(列号,行号,3 "yyyy-MMM-dd DDD") = 输入1-01-01 显示2001-一月-01 星期一 !prinx.setCellFormat(列号,行号,4,"hh:mm:ss") = 输入1:01:01 显示01:01:01 !prinx.setCellFormat(列号,行号,4,"hh'时'mm'分'ss'秒'") = 输入1:01:01 显示01时01分01秒 !prinx.setCellFormat(列号,行号,4, "h:mm:ss AM/PM") = 输入1:01:01 显示1:01:01 AM !prinx.setCellValue(.(aCol,aRow,aValue) = 修改单元格的值(列,行,内容) !prinx.importExcel(.(文件路径,仅导入文本) = 导入excel表格,xls格式 !prinx.importExcelOle(.(文件路径,仅导入文本,列1,行1,列2,行2) = 导入excel表格,\n指定行列参数可省略 !prinx.exportExcel(.(文件路径,按显示值输出) = 导出excel表格,xls格式 !prinx.lockUpdate = @.lockUpdate( function(){ \n __/*暂停刷新并执行这里的代码*/\n }\n) !prinx.OnBeginPrintDoc = @.OnBeginPrintDoc = function(printer,title,titleChange){ __/*开始打印时执行,参数说明 printer:打印机句柄 Title:打印文档名 */ } !prinx.OnButtonClick = @.OnButtonClick = function(aCol,aRow,aNameText,scriptText){ __/*单击按钮类型单元格时执行,参数说明 aCol:列号 aRow:行号 aNameText:单元格按钮文本 aScriptText:单元格按钮脚本 */ } !prinx.OnCellChanged = @.OnCellChanged = function(aCol,aRow,aCellValue ){ __/*单元格的值改变后时执行,参数说明 aCol:列号 aRow:行号 aCellValue:单元格的值 */ } !prinx.OnCellChanging = @.OnCellChanging = function(aCol,aRow,aCellValue ){ __/*单元格的值正在改变时执行,参数说明 aCol:列号 aRow:行号 aCellValue:单元格的值 */ } !prinx.OnCellLDblClick = @.OnCellLDblClick = function(aCol,aRow ){ __/*鼠标左键双击单元格时执行,参数说明 aCol:列号 aRow:行号 */ } !prinx.OnCellLDown = @.OnCellLDown = function(aCol,aRow ){ __/*鼠标左键在单元格上落下时执行,参数说明 aCol:列号 aRow:行号 */ } !prinx.OnCellLUp = @.OnCellLUp = function(aCol,aRow ){ __/*鼠标左键在单元格上抬起时执行,参数说明 aCol:列号 aRow:行号 */ } !prinx.OnCellRDown = @.OnCellRDown = function(aCol,aRow,aScreenX,aScreenY ){ __/*鼠标右键下落时执行,参数说明 aCol:列号 aRow:行号 aScreenX:在屏幕上的横坐标 aScreenY:在屏幕上的纵坐标 */ } !prinx.OnError = @.OnSelectChange = function(aMessage ){ __/*发生错误时执行,参数说明 aMessage:错误信息*/ } !prinx.OnInputChange = @.OnInputChange = function(aCol,aRow ){ __/*输入单元格改变时执行,参数说明 aCol:列号 aRow:行号*/ } !prinx.OnKeyPress = @.OnKeyPress = function(keyCode){ __/*按键时执行,参数说明 keyCode:按键*/ } end intellisense**/
只有打印模版,和聚宝盆记账易里的销售打印模版一样的。