说句老实话,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**/
只有打印模版,和聚宝盆记账易里的销售打印模版一样的。