PBDataWindow38个技巧.docx
《PBDataWindow38个技巧.docx》由会员分享,可在线阅读,更多相关《PBDataWindow38个技巧.docx(14页珍藏版)》请在冰豆网上搜索。
PBDataWindow38个技巧
PBDataWindow38个技巧
1使DataWindow列只能追加不能修改
如何使DataWindow中的数据只能追加新记录而不能修改,利用Column的Protect属性可以很方便的做到这一点,方法如下:
将每一列的Protect属性设置为:
If(IsRowNew(),0,1))
在PowerScript中可以动态修改Protect属性:
dw_1.Modify("column_name_here.Protect='1~tIf(IsRowNew(),0,1)'")
这样,DataWindow中只有新追加的记录可修改,而其他记录是只读的。
2如何在DataWindow中实现列的自动折行
我们在PowerBuilder应用程序的开发过程中,使用DataWindow时,经常会遇
到某列的数据太长,不能同时全部显示的情况.若采用自动水平滚动,操作起
来又不够简便.下面介绍一种方法,实现列数据多行显示,即实现列数据的自
动折行.具体步骤如下:
1)在DataWindowPainter中打开此DataWindow.
2)在需设定自动折行的列上双击鼠标,弹开此列的属性窗口.
3)选择Position标签,选中AutosizeHeight多选框.
4)选择Edit标签,不选中AutoHorzScroll多选框.
5)单击OK按钮,保存所做的修改.
6)点中DetailBand(即写有Detail的灰色长带),单击鼠标右键,选择
Properties...菜单项.
7)选中AutosizeHeight多选框.
8)单击OK按钮,保存所做的修改.
9)保存此DataWindow.
注意:
连在一起的汉字(中间没有标点或空格分隔),系统将认为是一个单词,不
会自动进行折行.
3在数据窗口中实现动画
要实现动画,必须要有定时器,在数据窗口中已经有了一个定时器,双击数据窗口将弹出的对话框,在TimerInterval中定义大于零的值就有定时器(可以精确到毫秒),有了这个定时器就可以实现动画了。
比如要改变某字段的背景颜色,可设
ackgound.color=RGB(Integer(Right(string(now(),'hhmmssf'),1))*256/10,Integer(Right(string(now(),'hhmmssf'),1))*256/10,0)
当然,您不仅可以改变背景颜色,而且可以改变字体等等任何属性,使他可以动起来!
4使数据窗口中的被选中行具有更好的外观
大家都知道,在选择数据窗口中的某一行时,如果使用pb提供的选择函数SelectRow(),那么的外观真是不能恭维,单调而古板的蓝色背景,可能和您的漂亮而生动的应用程序格格不入。
有没有办法改变呢?
当然有啰,请听我慢慢道来。
改变某一行的背景比较简单,改变每一列的背景属性(backgroundcolor)即可,可要根据鼠标选择情况自动改变,并可以返回被选中的行可能还需要一定的技巧。
下面分单行选择和多行选择分辨说明。
单行选择
单行选择比较简单,我们只要将所有字段的背景色的表达式改为:
if(GetRow()=CurrentRow(),RGB(255,126,0),RGB(0,0,0))
其中第一个颜色为被选中的颜色,第二个颜色未被选中的颜色。
然后用GetRow()代替GetSelectedRow()函数来得到被选中的行。
多行选择
多行选择比较复杂,如果单纯依靠改变数据窗口的属性没法实现,我们必须使用数据窗口属性和代码结合起来才能实现
首先,改变数据窗口的SQL语句,增加一个计算字段:
0asflag,Select语句改为:
Selectcol1,col2,1asflagfromtablenamewhere.....,
当返回数据窗口painter时,您就会发现多了一个字段flag,我们就是利用这个字段保存行被选中的信息。
其次,修改各个字段的背景颜色属性,设置为:
if(flag=1,RGB(255,126,0),RGB(255,255,255))
第三:
在数据窗口控件中,增加对clicked事件的处理,代码如下:
ifrow<1thenreturn//setredraw(false)
ifthis.object.flag[row]=1then//如果该行被选中,撤销选择,否则选中该行
this.Object.flag[row]=0
else
this.Object.flag[row]=1
endif
setredraw(true)
您还可以定制本选中行的字体,文本属性等等。
原理相同,不再赘述。
5将日期型字段初始化为当天的日期
使用ColumnSpecifications对话框来设置数据的初始值是一个比较好又比较通用的方法。
为了将日期型字段初始化为当天的日期,只要设置初始化值为today,而不是today()即可。
同样设置初始值为NUll,可以使用null,而不是null()。
6在DataWindow中调整列顺序
在Gird风格的DataWindow中,列的排列顺序是按照你选择Column的顺序排列的,并且不能改变.要改变列的顺序则必须重新制作DataWindow.
最近我发现一个办法可以改变列的顺序:
在DataWindow画板中打开要修改的DataWindow,然后按'Preview'按钮切换到预览模式下,选择要移动的列标题并拖动到预定位置,然后返回DataWindow画板,存盘即可.
7Retrieve时不清除原有Datawindow数据
当你调用Retrieve函数,PowerBuilder自动清除原有DataWindow然后Retrieve数据。
在DatawindowRetrieveStart事件中,使用Return2,这样PowerBuilder不会清除原有数据而是追加新数据。
8美化DataWindow的显示效果
使DataWindow的单双行显示颜色不同,不仅仅可以使你的应用程序更显专业性,并使数据的可读性增强。
先调出你需要改动的DataWindow,在Detailband按下右键选择Properties,选择Tab页中的Expressions,在color属性中输入下面内容:
(注意是在Detail明细显示段按右键,而不是在Column上)IF(MOD(GETROW(),2)=0,RGB(192,192,192),RGB(255,255,255))马上Preview一下,看一看效果如何。
9用Line建立漂亮的GridDataWindow的技巧
虽然PowerBuilder有Grid风格的DataWindow,但不够灵活,如果想打印一张边框粗线条或双线,内框为细线条的表格直接使用Grid风格的DataWindow就不能实现。
因此许多人都用Tabular风格的DataWindow,然后自己用Line来实现Grid。
在调整线条位置是一个即伤脑筋又伤眼睛的事件,而一旦需要调整行高,所有工作都得重来,试一试用下面方法,会大大减轻你的工作量:
在verticallines,改变它的属性,在ExpressionsTab上,y1行上输入0,y2行上输入rowheight()-1在horizontallines,设置y1和y2=rowheight()-5这样PowerBuilder会自动调整线的坐标,你只需要设置横线的长度和x1,x2的坐标即可。
马上Preview一下,看一看效果!
你再也不需要因为行的高度发生改变而重新调整线条位置。
10如何创建一个报表,如下形式
QuantityRunningTotal
5,0005,000
2,5007,500
3,00010,500
12,00022,500
对于RunningTotal列,我们可使用计算列:
CumulativeSum(Quantityforall),即可达到逐渐递增求和的功能。
11数据窗口的数据送缓冲区之前确认的四个步骤判断数据类型是否正确。
如不正确则触发ItemError事件。
判断数据是否符合有效性规则。
如不符合有效性规则,同样触发ItemError事件。
判断是否有数据被改动。
判断数据是否通过ItemChanged事件,如果数据和ItemChanged相斥,将触发ItemError事件。
12如何在DataWindow中用数据类型为Datetime的列为条件进行查找
1.当要查找的日期条件是一常数时使用如下表达式:
ls_Find="datetime_col
=DateTime('1/1/1999')"
2.当要查找的日期条件是一个变量时使用如下的表达式:
ls_Find="datetime_col=DateTime('"+ls_Date+"')"
3.当要查找的日期条件是一个DateTime数据类型时使用如下表达式:
ls_Find="datetime_col=DateTime('"+String(ldt_DateTime)+"')"
13设置数据窗口Boolean型属性的三种方法
PowerBuilder提供了三种方法设置数据窗口的布尔型属性,分别是True/False,1/0,'Yes'/'No'。
例如:
dw_1.Object.address.Visible=0dw_1.Object.address.Visible=Falsedw_1.Object.address.Visible='No'
PowerBuilder在处理上以字符串的形式保存属性,而不考虑属性值是布尔型、长整型或是字符型。
为了进一步理解,可以导出一个数据窗口并查看它的原码,可以发现即使是列的颜色属性它也是使用带双引
号的数字来表达。
14如何在DataWindow中快速删除多行
在开发过程中可能经常有要进行多行删除的操作,一般都使用循环语句进行操作:
FORll_RowOn=1TOdw_1.RowCount()dw_1.DeleteRow(ll_RowOn)NEXT
一个快速的删除方法是把要删除的行从主缓冲区中移到删除缓冲区中。
例如,删除缓冲区中所有的行:
dw_1.RowsMove(dw_1,1,dw_1.RowCount,Primary!
dw_1,1,Delete!
)
不过不要忘了过滤的行在不同的缓冲区中。
15如何在DataWindow的SQL语法中不使用SELECTDISTINCT实现删除重复的行
起先对你要显示唯一值的列进行排序:
"cityA",然后增加如下过滤字符串:
"city<>city[-1]orGetRow()=1"
16如何在分组形式的DataWindow中分别显示各组的行号
当我们为Datawindow的每一行显示行号时,可以简单的放一个表达式为GetRow()计算列。
但是对于分组的Datawindow,要分别显示各组的行号,则应使用表达式为
GetRow()-First(GetRow()forGroup1)+1的计算列。
17如何改变列的字体颜色,提醒用户此列已做修改
在列的Color属性中,输入如下表达式
IF(column_name<>column_name.Original,RGB(255,0,0),RGB(0,0,0))。
在这个条件中,如果此列已改变,则显示红色字体,否则显示黑色字体。
这个表达式主要用column_name<>column_name.Original比较当前列的值和原始列的值是否相同来达到判断的目的。
18在数据窗口中移走行,但不是去做过滤或删除操作
RowsDiscard()函数可做到这一点,它在数据窗口中执行移除工作,但被移走的行它不可被删除或做任何修改性的保存。
19如何在多行显示的DataWindow中的FooterBand中显示当前数据的首行和最后行的行号
我们先看两个计算列的表达式:
IF(GetRow()=First(GetRow()FORPage),1,0)//1为当前页的第一行
IF(GetRow()<>1ANDGetRow()=Last(GetRow()FORPage),1,0)//1为当前页的最后一行
由上面可知,在FooterBand中设置如下计算列表达式:
'Rows'+String(First(GetRow()FORPage))+'to'+String(Last(GetRow()FORPage))+'aredisplayed'。
即可达到这项功能。
20使可编辑的数据窗口只读
有时,你可能需要将一个用于编程的数据窗口用作显示目的,可以有以下几种方法来实现这一要求:
1.建立两个数据窗口,一个用于编辑,一个用于显示
2.将数据窗口中的全部对象的taborder设置为0.
3.也可以将数据窗口中的列的protect属性设为On或Off,但你不能使用protect属性进行编辑操作
4.数据窗口有一个将datawindow设为只读的属性(readonly),使用它最方便。
21数据窗口检查重复行
dw_1.SetSort("user_idA")
dw_1.Sort()
dw_1.SetFilter("user_id=user_id[-1]")
dw_1.Filter()
ifdw_1.RowCount()>0then
Messagebox("注意","用户编码重复.")
endif
dw_1.SetFilter("")
dw_1.Filter()
22如何在分组形式的DataWindow中分别显示各组的行号
----当我们为Datawindow的每一行显示行号时,可以简单的放一个表达式为GetRow()
----计算列。
但是对于分组的Datawindow,要分别显示各组的行号,则应使用表达式为
GetRow()-First(GetRow()forGroup1)+1的计算列。
23如何能让数据窗口的某几列在其他列横拉时固定不动
////////////////////////////////////////////////////////////////
// 功能说明:
用于冻结左边的滚动栏
// 变更记录:
变更或版本更新的时候
//
////////////////////////////////////////////////////////////////
inti
ifpane=1then
i=integer(this.object.datawindow.horizontalscrollposition2)
ifi<1orisnull(i)thenreturn
ifscrollpos>0then
this.object.datawindow.horizontalScrollPosition=0
endif
else
i=integer(this.Object.DataWindow.HorizontalScrollSplit)
ifi<1orisnull(i)thenreturn
ifi>scrollposthen
this.object.datawindow.horizontalScrollPosition2=i
endif
endif
24在数据窗口中如果要使其中一列的属性为只读,也就是不允许用户修改,那么只需简单地将这一列的TableOrder设置成0就可。
然而,在有些情况下
需要对这一列的某些行修改,而某些行不能修改,这就要用到这一列的protect属性了。
打开列的属性中的Expressions,在protect中输入条件判别
式。
例如:
允许用户修改新增加的记录,而检索出来的记录则不允许修改。
条件判别式可以写成如下:
if(isRowNew(),0,1)
在PowerScript中可以动态修改Protect属性:
dw_1.Modify("column_name_here.Protect='1~tIf(IsRowNew(),0,1)'")
这样,DataWindow中只有新追加的记录可修改,而其他记录是只读的。
25控制DATAWINDOW里每页显示的行数
1、在Datawindow中增加一个计算域,起名为:
ceil_page,此计算域必须放在Detail段中,
Expression中输入ceiling(getrow()/25)25表示每页打印25行,也可以是一个参数。
2、分组,选择菜单RowsCreateGroup,选择ceil_page
按ceil_page分组,并选中NewPageOnGroupBreak(意思是新组开始时换页)。
3、将此计算域设为隐藏(在属性页中的expression页中在visible属性中写0)。
4、补空行:
在窗口的open事件中写如下代码:
longli_count,li_i
li_count=dw_1.retrieve()
ifmod(li_count,25)<>0then
forli_i=1to25-mod(li_count,25)
dw_1.insertrow(0)
next
endif
26数据窗口的closeQuery事件:
提示保存数据
dw_1.AcceptText()
IFdw_1.ModifiedCount()+dw_1.DeletedCount()>0THEN
CHOOSECASEMessageBox("操作提示","数据已经发生变化,是否保存?
",Question!
YesNoCancel!
1)
CASE1
cb_save.TriggerEvent(clicked!
)
CASE2
Return0//不做任何操作直接关闭窗口
CASE3
Return1//不会运行CloseEvent,维持原来的情况
ENDCHOOSE
ENDIF
27Getchild函数主要被用来得到一个数据窗口的子数据窗口
该函数在两种情况下可以使用,1、取出数据窗口对象的下拉式数据窗口;
2、取出复合风格(composite)数据窗口对象里所嵌入的子数据窗口对象。
语法:
integerdwcontrol.GetChild(stringname,REFDataWindowChild
dwchildvariable)
例子1 这段程序取出一个composite数据窗口对象的两个子数据窗口,并对他们进行过滤,和排序的操作。
/*dw_dy是连接一个composite数据窗口对象的一个数据窗口控件。
dw_1、dw_2分别是嵌套的数据窗口的NAME*/
Stringls_filter
DataWindowChilddwc_czrw,dwc_czx//定义子数据窗口变量
dw_dy.Settransobject(sqlca)
dw_dy.Retrieve()
dw_dy.GetChild("dw_2",dwc_czrw)
dw_dy.Getchild("dw_1",dwc_czx)
ls_filter="czrw_bh='"+dw_3.GetItemString(dw_3.GetRow(),"czrw_bh")+"'"//过滤条件
dwc_czrw.SetFilter(ls_filter)
dwc_czrw.Filter()
ls_filter="czx_rwbh='"+dw_3.GetItemString(dw_3.GetRow(),"czrw_bh")+"'"
dwc_czx.SetSort("czx_sxA")
dwc_czx.Sort()
dwc_czx.SetFilter(ls_filter)
dwc_czx.filter()
当然也可以通过数据共享(ShareData)等方式操作子数据窗口中的数据。
访问复合数据窗口对象.方法:
dw_dy.object.dw_1.object.对象
例子2 下拉数据窗口动态过滤
在数据窗口dw_1的ItemFocusChanged事件中写入如下脚本:
Integerrtncode
Stringls_nowFld,ls_deptid,ls_sql
DataWindowChildfld_child
rtncode=dw_1.GetChild("Unit_id",fld_child)//获得Unit_id字段名下拉数据窗口的句柄
Ifrtncode=-1ThenMessageBox("错误!
","不是下拉数据窗口!
")
fld_child.SetTransObject(SQLCA)//设置事务对象
ls_sql=Lower(fld_child.GetSQLSelect())//获得DDDW的SQL语句
//去除Sql语句中的Where条件子句,如原Sql语句中须有Where条件子句,此处则需进行较
//复杂的处理,应视具体情况而定。
ifPos(ls_sql,"where")>0thenls_sql=Left(ls_sql,Pos(ls_sql,"where"))
//重新设置Sql语句中的Where条件子句
ls_deptid=dw_1.Object.dept_id[GetRow()]//取得当前dept_id选定值
ls_sql=ls_sql+"Wheredept_id='"+Trim(ls_deptid)+"'"
//重新设置Sql语句
fld_child.SetSQLSelect(ls_sql)
fld_child.Retrieve()//取得满足条件的数据
28从数据窗口中获取数据
单条:
假设我们要读取dept_id字段的第一笔数据,可以用下列方式表示∶li_id=dw_1.object.dept_id[1]
假设我们要读取第一行中第二个字段的数据,可以用下列方式表示∶ls_name=dw_1.object.DATA[1,2]
假设我们要读取dept_id字段的所有数据,可以用下列方式表示∶li_array=dw_1.object.dept_id.CURRENT
假设我们要读取过滤缓冲区(filterbuffer)内dept_id字段的第一笔数据,可以用下列方式表示∶li_id=dw_1.object.dept_id.Filter
[1]