2011年9月3日
从理论上说,工薪个税是分段计算的,但那样做在实际工作中很麻烦,所以就用速算扣除数计算法。
比如某人某月的工资是6000元,在扣除了费用2000元以后,应纳税所得是4000元,分段算是500*5%+1500*10+2000*15=475元。
为了方便,用速算扣除法计算是(6000-2000)*15%-125=475元,其中的500元税率应该是5%,但用速算法计算时,是以15%算,所以要减除多算的10%,就是500*10%=50元;其中的1500元税率应该是10%,但用速算法,是以15%算,所以要减除多算的5%,就是1500*5%=75元;剩下的2000元不论用什么方法算,税率都是15%,所以扣除数为0,这样速算扣除数就是50+75+0=125元
备注:速算扣除数是指在采用超额累进税率征税的情况下,根据超额累进税率表中划分的应纳税所得额级距和税率,先用全额累进方法计算出税额,再减去用超额累进方法计算的应征税额以后的差额。当超额累进税率表中的级距和税率确定以后,各级速算扣除数也固定不变,成为计算应纳税额时的常数。
2011最新个税计算公式excel:
=LOOKUP(A1-3500,{-3500;0;1500;4500;9000;35000;55000;80000},{0;0.03;0.1;0.2;0.25;0.3;0.35;0.45}*(A1-3500)-{0;0;105;555;1005;2755;5505;13505})
=MAX((A1-3500)*5%*{0.6,2,4,5,6,7,9}-{0,105,555,1005,2755,5505,13505},)
=MAX((A1-3500)*5%*{0.6,2,4,5,6,7,9}-{0,21,111,201,551,1101,2701}*5,)
=MAX((A1*5%-175)*{0.6,2,4,5,6,7,9}-{0,21,111,201,551,1101,2701}*5,)
=5*MAX((A1%-30)*{1,2,4,5,6,7,9}-5*{0,3,21,39,109,219,539},)
个人所得税税率表一(工资、薪金所得适用)(9月1日起执行):
|
级数 |
全月应纳税所得额 |
税率 |
速算扣除数(元) |
|
1 |
全月应纳税额不超过1500元 |
税率为3% |
0 |
|
2 |
全月应纳税额超过1500元至4500元 |
税率为10% |
105 |
|
3 |
全月应纳税额超过4500元至9000元 |
税率为20% |
555 |
|
4 |
全月应纳税额超过9000元至35000元 |
税率为25% |
1005 |
|
5 |
全月应纳税额超过35000元至55000元 |
税率为30% |
2755 |
|
6 |
全月应纳税额超过55000元至80000元 |
税率为35% |
5505 |
|
7 |
全月应纳税额超过80000元 |
税率为45% |
13505 |
2010年6月16日
pb函数库之打印函数
Print()
功能以当前字体在打开的打印作业中打印一行或多行文本。
语法Print(printjobnumber,{tab1,}string{,tab2})
参数printjobnumber:用PrintOpen()函数打开的打印作业号tab1:Integer类型,可选项,指定文本开始打印的位置,在开始打印字符串之前将打印光标移动到该位置,从打印区的左边界开始计算,以千分之一英寸为单位。如果打印光标已经位于指定位置、或打印光标已经超过了指定位置、或省略了该参数,那么,Print()函数从打印光标的当前位置开始打印string:string类型,指定要打印的字符串。如果字符串中包括回车换行字符(~r~n),那么该字符串将被分成多行输出,但是,除第一行之外,其它行忽略tab1参数指定的起始打印位置tab2:Integer类型,可选项,指定字符串打印结束后打印光标移动到的位置,从打印区的左边界开始计算,以千分之一英寸为单位。如果打印光标已经超过了指定位置,那么Print()函数忽略该参数,打印光标位于已打印字符串的尾部。如果省略了该参数,Print()函数把打印光标移动到下一行的起始位置。返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果任何参数的值为NULL,Print()函数返回NULL。用法在打印作业中,PowerBuilder使用打印光标来跟踪打印位置。打印光标保存了即将打印区域左上角的坐标。使用Print()函数打印文本后,PowerBuilder自动更新打印光标。PowerBuilder使用行距来决定打印出的两行文本之间的距离,行距与字符的高度成比例,缺省的行距是字符高度的1.2倍。使用PrintSetSpacing()函数可以改变行距。当Print()函数在下一行打印输出时,它把打印光标的x坐标设置为0、y坐标增加当前行距指示的数值。由于每打印一行时Print()函数都自动调整打印光标的y坐标位置,因此,该函数会自动处理分页,因此,应用程序没有必要调用PrintPage()函数进行分页。打印区由纸张的物理尺寸和边界空白决定,PrintSend()函数能够发送具体打印机的ESC控制序列,使用这个函数可以改变边界空白的大小。另外,在打印开始之前,使用PrintDefineFont()和PrintSetFont()函数可以改变Print()使用的字体。
PrintBitmap()
功能在打印区域的指定位置打印位图。
语法PrintBitmap ( printjobnumber, bitmap, x, y, width, height )
参数printjobnumber:用PrintOpen()函数打开的打印作业号bitmap:string类型,指定要打印的位图文件的文件名x:integer类型,指定位图起始打印位置的x坐标,以千分之一英寸为单位y:integer类型,指定位图起始打印位置的y坐标,以千分之一英寸为单位width:integer类型,指定位图的打印宽度,以千分之一英寸为单位。如果该参数的值指定为0,那么按图像的原始宽度打印height:integer类型,指定位图的打印高度,以千分之一英寸为单位。如果该参数的值指定为0,那么按图像的原始高度打印返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果任何参数的值为NULL,PrintBitmap()函数返回NULL。用法执行PrintBitmap()函数后,打印光标的位置不变,依然停留在执行该函数前的位置上。
PrintCancel()
功能取消用PrintOpen()函数启动的打印作业。
语法PrintCancel ( printjobnumber )
参数printjobnumber:要取消的打印作业的作业号返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果参数printjobnumber的值为NULL,PrintCancel()函数返回NULL。用法PrintCancel()函数取消指定的打印作业,删除相应的打印池文件,关闭打印作业,所以,应用程序执行了PrintCancel()函数之后,不需要再执行PrintClose()函数关闭打印作业了。
PrintClose()
功能关闭打印作业并把打印页面发送到打印机上。
语法PrintClose ( printjobnumber )
参数printjobnumber:要关闭的打印作业的作业号返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果参数printjobnumber的值为NULL,PrintClose()函数返回NULL。用法应用程序使用PrintOpen()函数启动打印作业后,必须使用PrintClose()在完成打印任务后关闭打印作业,或根据需要使用PrintCancel()函数取消打印作业。
PrintDataWindow()
功能打印数据窗口控件的内容,用该函数可以在一个打印作业中打印多个数据窗口控件的内容,每个都从新的一页开始打印。
语法PrintDataWindow ( printjobnumber, dwcontrol )
参数printjobnumber:用PrintOpen()函数打开的打印作业号dwcontrol:要打印其内容的数据窗口控件名或子数据窗口控件名返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果参数printjobnumber的值为NULL,PrintDataWindow()函数返回NULL。用法应用程序通过多次执行PrintDataWindow()函数可以在一个打印作业中一次打印多个数据窗口的内容,并且每个数据窗口都从新的一页开始打印。当数据窗口的表现风格为RichTextEdit时,数据窗口中的每一行都在新的一页上开始打印。需要注意的是,PrintDataWindow()函数在打印数据窗口时使用数据窗口本身定义的字体以及风格,使用PrintDefineFont()和PrintSetFont()函数为当前作业定义的字体不起作用。
PrintDefineFont()
功能定义打印作业使用的字体,对每个打印作业PowerBuilder支持八种字体。
语法PrintDefineFont(printjobnumber,fontnumber,facename,height,weight,fontpitch,fontfamily, italic,underline)
参数printjobnumber:用PrintOpen()函数打开的打印作业号fontnumber:指定赋给当前定义字体的编号,有效值在1到8之间 facename:string类型,指定字体名称,该字体应该是你的打印机支持的字体,比如"宋体"height:Integer类型,使用正值指定字体的高度,以千分之一英寸为单位;使用负值指定字体点数,比如,-18代表18点。一般来说,使用点数更精确些weight:指定字体的磅数,正常字体为400磅,粗体为700磅fontpitch:FontPitch枚举类型,指定字体标准。有效取值为:Default! - 缺省值;Fixed! - 固定形式;Variable! - 可变形式fontfamily:FontFamily枚举类型,指定字体系列。有效取值为:AnyFont!、Decorative!、Modern!、Roman!、Script!、Swiss!italic:boolean类型,指定是否使用斜体样式。有效取值为:TRUE - 使用斜体样式;FALSE - 不使用斜体样式。缺省值为FALSEunderline:boolean类型,指定是否加下划线。有效取值为:TRUE - 加下划线;FALSE - 不加下划线。缺省值为FALSE返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果任何参数的值为NULL,PrintDefineFont()函数返回NULL。用法在一个打印作业中,应用程序能够最多同时定义8种字体。当应用程序需要使用更多的字体时,可以在使用了某个字体号输出内容后使用PrintDefineFont()函数将该字体号对应的字体更换为其它字体。
PrintLine()
功能在当前打印页上绘出指定厚度的一条线。
语法PrintLine ( printjobnumber, x1, y1, x2, y2, thickness )
参数printjobnumber:用PrintOpen()函数打开的打印作业号x1:integer类型,指定直线起点的x坐标,以千分之一英寸为单位y1:integer类型,指定直线起点的y坐标,以千分之一英寸为单位x2:integer类型,指定直线终点的x坐标,以千分之一英寸为单位y2:integer类型,指定直线终点的y坐标,以千分之一英寸为单位thickness:integer类型,指定直线的厚度,以千分之一英寸为单位返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果任何参数的值为NULL,PrintLine()函数返回NULL。用法应用程序执行了PrintLine()函数后,该函数并不改变打印光标的位置。
PrintOpen()
功能启动打印作业并返回作业号。
语法PrintOpen ( { jobname } )
参数jobname:string类型,可选项,指定要打开打印作业的名称,该名称将显示在打印管理器窗口中返回值Long。函数执行成功时返回打印作业号,发生错误时返回-1。如果任何参数的值为NULL,PrintOpen()函数返回NULL。用法应用程序执行PrintOpen()函数后,启动新的打印作业并走纸到下一页,同时将打印机缺省字体设置为该打印作业的字体。打印光标的位置位于打印区的左上角。其它同组的打印函数使用PrintOpen()函数返回的作业号来标识作业。需要注意的是,使用PrintOpen()函数打开打印作业、使用同组的其它函数完成打印任务后,必须使用PrintClose()关闭打印作业,或根据需要使用PrintCancel()函数取消打印作业。
*PrintOval()*功能在指定位置以指定线宽绘制椭圆或圆。
语法PrintOval ( printjobnumber, x, y, width, height, thickness )
参数printjobnumber:用PrintOpen()函数打开的打印作业号x:integer类型,指定椭圆或圆外形框左上角的x坐标,以千分之一英寸为单位y:integer类型,指定椭圆或圆外形框左上角的y坐标,以千分之一英寸为单位width:integer类型,指定椭圆或圆外形框的宽度,以千分之一英寸为单位height:integer类型,指定椭圆或圆外形框的高度,以千分之一英寸为单位thickness:integer类型,指定椭圆或圆外边线的厚度,以千分之一英寸为单位返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果任何参数的值为NULL,PrintOval()函数返回NULL。用法应用程序执行了PrintOval()函数后,该函数并不改变打印光标的位置。PrintOval()函数绘出的椭圆或圆是实心的,也就是说,执行该函数后,椭圆或圆下面的文字或图像将完全被覆盖。如果想在椭圆或圆中输出文字或图形,那么应用程序应该首先绘制椭圆或圆,然后使用其它函数在椭圆或圆中输出文字或图形。
PrintPage()
功能将当前页发送给打印机或打印池并在当前打印作业中启动一个新的打印页。
语法PrintPage ( printjobnumber )
参数printjobnumber:用PrintOpen()函数打开的打印作业号返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果任何参数的值为NULL,PrintPage()函数返回NULL。
PrintRect()
功能在指定位置以指定线宽打印矩形。
语法PrintRect ( printjobnumber, x, y, width, height, thickness )
参数printjobnumber:用PrintOpen()函数打开的打印作业号x:integer类型,指定矩形左上角的x坐标,以千分之一英寸为单位y:integer类型,指定矩形左上角的y坐标,以千分之一英寸为单位width:integer类型,指定矩形的宽度,以千分之一英寸为单位height:integer类型,指定矩形的高度,以千分之一英寸为单位thickness:integer类型,指定矩形边线的厚度,以千分之一英寸为单位返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果任何参数的值为NULL,PrintRect()函数返回NULL。用法应用程序执行了PrintRect()函数后,该函数并不改变打印光标的位置。PrintRect()函数绘出实心的矩形,也就是说,执行该函数后,矩形下面的文字或图像将完全被覆盖。如果想在矩形中输出文字或图形,那么应用程序应该首先绘制矩形,然后使用其它函数在矩形中输出文字或图形。
PrintRoundRect()
功能在指定位置以指定线宽打印圆角矩形。
语法PrintRoundRect(printjobnumber,x,y,width,height,xradius,yradius,thickness)
参数printjobnumber:用PrintOpen()函数打开的打印作业号x:integer类型,指定圆角矩形左上角的x坐标,以千分之一英寸为单位y:integer类型,指定圆角矩形左上角的y坐标,以千分之一英寸为单位width:integer类型,指定圆角矩形的宽度,以千分之一英寸为单位height:integer类型,指定圆角矩形的高度,以千分之一英寸为单位xradius:integer类型,指定圆角矩形圆角部分的x半径,以千分之一英寸为单位yradius:integer类型,指定圆角矩形圆角部分的y半径,以千分之一英寸为单位thickness:integer类型,指定圆角矩形边线的厚度,以千分之一英寸为单位返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果任何参数的值为NULL,PrintRoundRect()函数返回NULL。用法应用程序执行了PrintRoundRect()函数后,该函数并不改变打印光标的位置。PrintRoundRect()函数绘出实心的圆角矩形,也就是说,执行该函数后,圆角矩形下面的文字或图像将完全被覆盖。如果想在圆角矩形中输出文字或图形,那么应用程序应该首先绘制圆角矩形,然后使用其它函数在圆角矩形中输出文字或图形。
PrintScreen()
功能在打印作业中打印屏幕图像。
语法PrintScreen ( printjobnumber, x, y {, width, height } )
参数printjobnumber:用PrintOpen()函数打开的打印作业号x:integer类型,指定要打印屏幕图像左上角在打印页上的x坐标,以千分之一英寸为单位y:integer类型,指定要打印屏幕图像左上角在打印页上的y坐标,以千分之一英寸为单位width:integer类型,可选项,指定屏幕图像的打印宽度,以千分之一英寸为单位。如果省略了该参数,那么PowerBuilder按屏幕的原始宽度打印屏幕图像。如果指定了该参数,必须同时指定height参数height:integer类型,可选项,指定屏幕图像的打印高度,以千分之一英寸为单位。如果省略了该参数,那么PowerBuilder按屏幕的原始高度打印屏幕图像返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果任何参数的值为NULL,PrintScreen()函数返回NULL。
PrintSend()
功能直接向打印机发送任意字符串,通常用于发送打印机的控制代码。
语法PrintSend ( printjobnumber, string {, zerochar } )
参数printjobnumber:用PrintOpen()函数打开的打印作业号string:string类型,指定发送到打印机的字符串。在该字符串中,使用非打印字符的ASCII码值表示非打印字符zerochar:integer类型,可选项,指定在string参数中用于表示数值0的ASCII码值。有效取值在1到255之间返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果任何参数的值为NULL,PrintSend()函数返回NULL。用法应用程序使用PrintSend()函数可以直接向打印机发送控制序列(换码序列),比如,设置打印文字的浓淡、打印页的四周空白等。不同类型的打印机使用不同的控制序列,你需要翻一翻你的打印机手册。由于PowerBuilder使用数值0(即ASCII码为0的字符)结束每个字符串,因此,如果打印控制序列中包含了数值0,应用程序需要使用其它字符在参数string中替代数值0,并用zerochar参数指明这个替代字符。一般来说,应该选择一个打印机控制序列中不使用的字符作为0值字符的替代字符。通常情况下,按下述次序组织打印作业:1. 使用PrintOpen()函数打开打印作业2. 使用PrintSend()函数设置打印机特性,比如打印方向、四周空白等3. 使用PrintDefineFont()和PrintSetFont()函数设置该打印作业使用的字体4. 使用该组的其它函数打印输出文字或图形5. 执行PrintClose()函数关闭打印作业
PrintSetFont()
功能设置当前打印作业使用的字体。
语法PrintSetFont ( printjobnumber, fontnumber )
参数printjobnumber:用PrintOpen()函数打开的打印作业号fontnumber:指定该打印作业使用字体的字体编号,该编号与PrintDefineFont()函数中定义的编号应该对应,字体编号的有效取值在1到8之间,0表示使用打印机的缺省字体返回值Integer。函数执行成功时返回当前字体的高度,发生错误时返回-1。如果任何参数的值为NULL,PrintSetFont()函数返回NULL。
PrintSetSpacing()
功能设置行间距因子,打印函数将使用该因子来决定行间距。
语法PrintSetSpacing ( printjobnumber, spacingfactor )
参数printjobnumber:用PrintOpen()函数打开的打印作业号spacingfactor:指定行间距因子,用字符高度的倍数表示,缺省值为1.2返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果任何参数的值为NULL,PrintSetSpacing()函数返回NULL。用法在PowerBuilder应用程序中,行间距与字符的高度成正比,缺省值为字符高度的1.2倍。当Print组函数生成新行时,系统自动把打印光标的x坐标位置设置为0,y坐标位置在原有基础上增加当前行距值。使用PrintSetSpacing()函数可以改变当前打印作业的行距。
PrintSetup()
功能打开打印机设置对话框。
语法PrintSetup ( )
返回值Integer。函数执行成功时返回1,发生错误时返回-1。如果任何参数的值为NULL,PrintSetup()函数返回NULL。用法当系统中安装了多种打印机时,在Windows 95中PrintSetup()函数打开如图2-1所示的对话框,单击"Setup"按钮设置打印机各种特性。如果系统中只有一个打印机,则直接打开该打印机的打印设置对话框。需要注意的是,在Windows95和Windows NT 3.51以后的版本中,使用PrintSetup()函数设置的打印机设置只对当前应用起作用,并不影响其它应用的打印机设置。对Windows 3.1来说,使用PrintSetup()函数设置的打印机设置影响系统中的所有应用。
PrintText()
功能在指定位置打印一行文本。
语法PrintText ( printjobnumber, string, x, y {, fontnumber } )
参数printjobnumber:用PrintOpen()函数打开的打印作业号string:string类型,指定要打印的文本x:integer类型,指定文本开始打印位置的x坐标,以千分之一英寸为单位y:integer类型,指定文本开始打印位置的y坐标,以千分之一英寸为单位fontnumber:可选参数,指定打印文本使用的字体号,该编号由PrintDefineFont()函数确定。省略该参数时,以打印作业的当前字体打印文本返回值Integer。函数执行成功时返回文本打印后打印光标的x位置,即参数x的值加上打印文本的宽度。发生错误时返回-1。如果任何参数的值为NULL,PrintText()函数返回NULL。
PrintWidth()
功能确定一个字符串在指定打印作业中按当前字体所占的宽度,以千分之一英寸为单位。
语法PrintWidth ( printjobnumber, string )
参数printjobnumber:用PrintOpen()函数打开的打印作业号string:string类型,指定要决定其打印宽度的字符串返回值Integer。函数执行成功时返回按当前字体计算的字符串打印宽度,以千分之一英寸为单位,发生错误时返回-1。如果任何参数的值为NULL,PrintWidth()函数返回NULL。
PrintX()
功能返回打印光标的x坐标位置。
语法PrintX ( printjobnumber )
参数printjobnumber:用PrintOpen()函数打开的打印作业号返回值Integer。函数执行成功时返回打印光标的x坐标位置,以千分之一英寸为单位,发生错误时返回-1。如果任何参数的值为NULL,PrintX()函数返回NULL。
PrintY()
功能返回打印光标的y坐标位置。
语法PrintY ( printjobnumber )
参数printjobnumber:用PrintOpen()函数打开的打印作业号返回值Integer。函数执行成功时返回打印光标的y坐标位置,以千分之一英寸为单位,发生错误时返回-1。如果任何参数的值为NULL,PrintY()函数返回NULL。
PB 函数库-数据类型检查与转换函数
Asc()
功能得到字符串第一个字符的ASCII码整数值。
语法Asc ( string )
参数string:要得到第一个字符ASCII值的字符串返回值Integer。函数执行成功时返回string参数第一个字符的ASCII值,如果string参数的值为NULL,则Asc()函数返回NULL。
Char()
功能将字符串的第一个字符、Blob变量的第一个值、或一个整数转换成字符。
语法Char ( n )
参数n:字符串、Blob变量或整数,也可以是包含上述类型数据的Any类型变量返回值Char。返回参数n的第一个字符。如果n参数的值为NULL,则Char()函数返回NULL。
Dec()
功能将字符串或Blob值转换成Decimal类型的值。
语法Dec ( stringorblob )
参数stringorblob:string类型变量或Blob类型变量。Blob类型变量时,把该变量第一个值转换为Decimal类型的值,其余部分被忽略。stringorblob参数也可以是包含上述类型数据的Any类型变量返回值Decimal。函数执行成功时返回相应的Decimal类型值。如果stringorblob参数中的值不是有效的PowerScript数字或数据类型不兼容,那么Dec()函数返回0。如果stringorblob参数的值为NULL,则Dec()函数返回NULL。
Double()
功能将字符串或Blob值转换成Double类型的值。
语法Double(stringorblob)
参数stringorblob:string类型变量或Blob类型变量。Blob类型变量时,把该变量第一个值转换为Double类型的值,其余部分被忽略。stringorblob参数也可以是包含上述类型数据的Any类型变量返回值Double。函数执行成功时返回相应的Double类型值。如果stringorblob参数中的值不是有效的PowerScript数字或数据类型不兼容,那么Double()函数返回0。如果stringorblob参数的值为NULL,则Double()函数返回NULL。
Integer()
功能 将字符串或Blob值转换成Integer类型的值。
语法Integer ( stringorblob )
参数stringorblob:string类型变量或Blob类型变量。Blob类型变量时,把该变量第一个值转换为Integer类型的值,其余部分被忽略。stringorblob参数也可以是包含上述类型数据的Any类型变量返回值Integer。函数执行成功时返回相应的Integer类型值。如果stringorblob参数中的值不是有效的PowerScript数字或数据类型不兼容,那么Integer()函数返回0。如果stringorblob参数的值为NULL,则Integer()函数返回NULL。
Long()
功能将其它类型的数据转换为Long类型的值。该函数有两种语法格式:
语法一、将两个无符号整数组合成一个长整数值;
语法二、将字符串或Blob值转换成Long类型的值。下面分别予以介绍:
语法一、将两个无符号整数组合成一个长整数值
语法Long ( lowword, highword )
参数lowword:UnsignedInteger类型,指定长整数中的低位值highword:UnsignedInteger类型,指定长整数中的高位值返回值Long。函数执行成功时返回由低位值和高位值组合后的长整数值,发生错误时返回-1。如果任何参数的值为NULL,则Long()函数返回NULL。
语法二、将字符串或Blob值转换成Long类型的值
语法Long ( stringorblob )
参数stringorblob:string类型变量或Blob类型变量。Blob类型变量时,把该变量第一个值转换为Long类型的值,其余部分被忽略。stringorblob参数也可以是包含上述类型数据的Any类型变量返回值Long。函数执行成功时返回相应的Long类型值。如果stringorblob参数中的值不是有效的PowerScript数字或数据类型不兼容,那么Long()函数返回0。如果stringorblob参数的值为NULL,则Long()函数返回NULL。
Real()
功能将字符串或Blob值转换成Real类型的值。
语法Real ( stringorblob )
参数stringorblob:string类型变量或Blob类型变量。当该参数是Blob类型变量时,把该变量第一个值转换为Real类型的值,其余部分被忽略。stringorblob参数也可以是包含上述类型数据的Any类型变量返回值Real。函数执行成功时返回相应的Real类型值。如果stringorblob参数中的值不是有效的PowerScript数字或数据类型不兼容,那么Real()函数返回0。如果stringorblob参数的值为NULL,则Real()函数返回NULL。
*Date()*功能 将其它类型的数据转换为Date类型的数据。该函数有三种语法格式:
语法一、将DateTime类型或第一个值是DateTime或Date的Blob值转换成Date类型的值;
语法二、将其值是个有效日期的字符串转换成Date类型的值;
语法三、将三个整数组合成一个日期。下面分别予以介绍:
语法一、将DateTime类型或第一个值是DateTime或Date的Blob值转换成Date类型的值
语法Date ( datetime )
参数datetime:DateTime类型的值或第一个值是DateTime或Date的Blob类型的值。当该参数是Blob类型变量时,把该变量第一个值转换为Date类型的值,其余部分被忽略。datetime参数也可以是包含上述类型数据的Any类型变量返回值Date。函数执行成功时返回相应的Date类型值。如果datetime参数中的值不是有效的PowerScript日期或数据类型不兼容,那么Date()函数返回1900-01-01。如果datetime参数的值为NULL,则Date()函数返回NULL。
语法二、将其值是个有效日期的字符串转换成Date类型的值
语法Date ( string )
参数string:string类型,其值包括一个有效的以字符串形式表示的日期(比如January 1, 1998或12-31-99),string参数也可以是包含字符串类型数据的Any类型变量返回值Date。函数执行成功时返回相应的Date类型值。如果string参数中的值不是有效的PowerScript日期或数据类型不兼容,那么Date()函数返回1900-01-01。如果string参数的值为NULL,则Date()函数返回NULL。
语法三、将三个表示年、月、日的整数组合成一个日期
语法Date ( year, month, day )
参数year:integer类型,指定日期中的年份,用四位数字表示,从0到9999month:integer类型,指定日期中的月份,用一位或两位数字表示,从1到12day:integer类型,指定日期中的号数,用一位或两位数字表示,从1到31返回值Date。函数执行成功时返回由year、month、day三个参数确定的日期。如果这三个参数中任何一个参数使用了无效值(比如月份指定为14),则Date()函数返回1900-01-01。如果任何参数的值为NULL,则Date()函数返回NULL。
DateTime()
功能 将其它类型的数据转换为DateTime类型的数据。该函数有两种语法格式:语法一、把日期和时间值组合成DateTime类型的值;语法二、将Blob类型的值转换成DateTime类型的值。下面分别予以介绍:
语法一、把日期和时间值组合成DateTime类型的值
语法DateTime ( date {, time } )
参数date:Date类型的日期值time:可选参数,Time类型的时间值,省略该参数时,PowerBuilder把时间设置为午夜(00:00:00.000000)。当指定该参数时,可以仅仅指定小时值返回值DateTime。函数执行成功时返回日期和时间组合而成的DateTime类型的值。如果任何参数的值为NULL,则DateTime()函数返回NULL。
语法二、将Blob类型的值转换成DateTime类型的值
语法DateTime ( blob )
参数blob:Blob类型变量,把该变量第一个值转换为DateTime类型的值,其余部分被忽略。blob参数也可以是包含blob类型数据的Any类型变量返回值DateTime。函数执行成功时返回相应的DateTime类型值。如果blob参数的值为NULL,则DateTime()函数返回NULL。
IsDate()
功能检测指定的字符串是否包含有效的日期。
语法IsDate ( datevalue )
参数datevalue:string类型,指定要检测的字符串返回值Boolean。如果datevalue包含了有效的日期,则IsDate()函数返回TRUE,否则返回FALSE。如果datevalue参数的值为NULL,则IsDate()函数返回NULL。
IsNull()
功能测试变量或表达式的值是否是NULL。
语法IsNull ( any )
参数any:要测试的变量或表达式返回值Boolean:如果any的值为NULL,函数返回TRUE,否则函数返回FALSE。
IsNumber()
功能测试字符串是否是有效的数值。
语法IsNumber ( string )
参数string:string类型,要测试的字符串返回值Boolean:如果string的值为有效的PowerScript数字,函数返回TRUE,否则函数返回FALSE。如果string参数的值为NULL,则IsNumber()函数返回NULL。
IsTime()
功能测试字符串的值是否是有效的时间。
语法IsTime ( timevalue )
参数timevalue:string类型,要测试的字符串返回值Boolean:如果timevalue的值为有效的时间,函数返回TRUE,否则函数返回FALSE。如果timevalue 参数的值为NULL,则IsTime()函数返回NULL。
String()
功能按指定格式将数据转换成字符串。String()可以把Date、DateTime、数值类型、Time、String类型的数据转换成指定格式的字符串。
语法String(data,{format})
参数data:指定要转换格式的数据,其数据类型可以是Date、DateTime、数值类型、Time、String,也可以是包含上述类型数据的Any类型变量format:可选项,string类型,其值指定数据格式。如果data参数的类型为string,则必须指定format参数返回值String。函数执行成功时返回以字符串方式表示的指定数据,如果data参数的数据类型与format参数指定的格式不匹配、format参数指定的格式无效、或data参数不是前面提到的适宜数据类型时,String()函数返回空字符串("")。
用法:
format是个用掩码表示的字符串,对data参数为数值类型的情况来说,格式为:正数格式;负数格式;零的显示格式;空的显示格式除第一部分必须提供外,其它部分可以省略。数值型显示格式中使用两个掩码字符:#和0,其中,使用#代表0~9之间的任意数字,0代表每个零都要显示。另外,货币符号($或¥)、百分号(%)、小数点(.)、逗号(,)等字符也可以出现在格式字符串中,但是,除小数点(.)、逗号(,)能够出现在格式字符#和0之间外,其它字符只能放置在格式串的前面或后面,例如,###,###$###是个错误的格式串,¥###,###,###是个正确的格式串。省略format参数时,String()函数使用PowerBuilder缺省格式。注意,如果显示格式有多个部分,各部分之间的分号(;)不能省略。其它字符也可以出现在显示格式字符串中(只能放在格式串的开头和末尾),但它们没有特殊意义,系统只是照原样显示。例如,用显示格式字符串"收入##"格式化数值12时,显示结果为"收入12"。对data参数为字符串(String)类型的情况来说,format参数的语法格式为:正常字符串格式;空值时格式在"正常字符串格式"中,@代表字符串中的任意字符,除此之外的任何字符照原样显示,例如,如果定义了下面的格式:(@@)@@@@-@@@@则字符串0166767593显示为:(01)6676-7593对data参数为日期(Date)类型的情况来说,format参数的语法格式为:正常日期格式;日期为空值时的格式日期格式中格式字符意义如下:d棗开头不带0的日数(如8)dd棗开头带0的日数(如08)ddd棗星期的英文缩写(如Mon、Tue)dddd棗星期的英文全称(如Monday、Tuesday)m棗开头不带0的月份(如8)mm棗开头带0的月份(如08)mmm棗月份的英文缩写(如Jan、Feb)mmmm棗月份的英文全称(如January、February)yy棗两位数字表示的年份(如97)yyyy棗四位数字表示的年份(如1997)另外,还可以使用下面的关键字作为日期的显示格式:[General] Windows系统中定义的短日期格式[LongDate] Windows系统中定义的长日期格式[ShortDate] Windows系统中定义的短日期格式对data参数为时间(Time)类型的情况来说,语法格式为:正常时间格式;时间为空值时的格式时间格式中格式字符意义如下:h开头不带0的小时(比如6)hh棗开头带0的小时(比如06)m棗开头不带0的分钟(比如6)mm棗开头带0的分钟(比如06)s棗开头不带0的秒(比如6)ss棗开头带0的秒(比如06)f棗开头不带0的微秒,可以指定1~6个f,每个f代表一部分微秒AM/PM棗用AM/PM显示上、下午时间,12小时制am/pm棗用am/pm显示上、下午时间,12小时制A/P棗用A/P显示上、下午时间,12小时制a/p棗用a/p显示上、下午时间,12小时制另外,显示格式中还可以使用关键字[Time],它表示按当前Windows系统定义的格式显示时间。对data参数为日期时间(DateTime)类型的情况来说,语法格式为:正常日期时间格式;日期时间为空值时的格式日期时间类型使用的掩码就是把日期掩码和时间掩码结合起来即可。
Time()
功能 把其它类型的数据转换为Time类型的值。该函数有三种语法格式:语法一、将DateTime类型或第一个值是DateTime或Time的Blob值转换成Time类型的值;语法二、将其值是个有效时间的字符串转换成Time类型的值;语法三、将表示时、分、秒、以及微秒的整数组合成一个时间值。下面分别予以介绍:
语法一、将DateTime类型或第一个值是DateTime或Time的Blob值转换成Time类型的值
语法Time ( datetime )
参数datetime:DateTime类型的值或第一个值是DateTime或Time的Blob类型的值。当该参数是Blob类型变量时,把该变量第一个值转换为Time类型的值,其余部分被忽略。datetime参数也可以是包含上述类型数据的Any类型变量返回值Time。函数执行成功时返回相应的Time类型值。如果datetime参数中的值不是有效的PowerScript时间或数据类型不兼容,那么Time()函数返回00:00:00.000000。如果datetime参数的值为NULL,则Time()函数返回NULL。
语法二、将其值是个有效时间的字符串转换成Time类型的值
语法Time ( string )
参数string:string类型,其值包括一个有效的以字符串形式表示的时间(比如9am或10:25),string参数也可以是包含时间类型数据的Any类型变量返回值Time。函数执行成功时返回相应的Time类型值。如果string参数中的值不是有效的PowerScript时间或数据类型不兼容,那么Time()函数返回00:00:00.000000。如果string参数的值为NULL,则Time()函数返回NULL。
语法三、将表示时、分、秒、以及微秒的整数组合成一个时间值
语法Time ( hour, minute, second {, microsecond } )
参数hour:integer类型,指定时间中的小时,从0到23minute:integer类型,指定时间中的分钟,从0到59second:integer类型,指定时间中的秒,从0到59microsecond:integer类型,可选项,指定时间中的微秒,从0到32767返回值Time。函数执行成功时返回由hour、minute、second、microsecond 四个参数确定的时间。如果这四个参数中任何一个参数使用了无效值(比如小时指定为44),则Time()函数返回NULL。
1. 前言
Power Builder是Powersoft公司推出的基于客户机/服务器体系结构的强有力的专业开发工具,自问世以来深受开发人员的好评。Data Window是Power Builder中获取专利技术的控件,它对数据处理的方法相当简洁,能处理各种显示格式,进行报表打印,对复杂的报表同样处理自如。Data Window是对数据库中的数据进行操作的窗口,它包括数据窗口控件和数据窗口对象两部分,通过它不但可以对数据库的表进行查询、检索,而且还可以进行数据的插入、删除和更新,定义数据的显示格式和编辑风格,定义数据的检条件、过滤条件、有效性规则等。因此Data Window是一个支持数据操作的封装性很好的对象。
一般用户对数据的操作和管理均在Data Window中进行,通过Data Window,用户可以自由灵活地操作和处理数据,而作为Power Builder应用的开发人员则很有必要了解Data Window是如何操作和管理数据的,深入了解Data Window对数据的底层更新机制,全面理解Data Window的技术精华,从而灵活、有效地开发Power Builder应用程序。所以,研究Power Builder的底层数据管理与更新机制具有重大的理论价值和现实意义。
2. Data Window控件管理数据的原理
在Data Window中可以处理用户对数据的增加、删除、修改等请求,那么在Data Window中数据是如何管理的呢?
当光标在Data Window中移动时,Power Builder就在光标所在的当前工作单元上放置了一个编辑控件。
编辑控件中的内容为文本,文本还没有被Data Window控件所接受,在文本中输入的数据还没有成为Data Window缓冲区中的数据,只是编辑控件中的一串字符。当用户改变了编辑控件中的内容,按回车键或Tab等离开该单元时,Power Builder将处理编辑控件中的字符,判断其是否成为有效数据。若有效则接收,把它写入Data Window当前缓冲区的当前行当前列;若无效则被拒绝,不进行写入操作。那么,Power Builder处理Data Window控件单元的文本的过程是怎样的呢?当Data Window中某一列的文本被接收,且光标移开后,将顺序发生下面的事件。
2.1 Power Builder把编辑控件中的文本转换成对应列的数据类型 的数据,若输入的数据不能转换成对应列的数据类型,就触发Item Error错误。
2.2 若转换成功,Power Builder就会用该列的有效性规则对转换 后的数据进行有效性检查。如果有效性检查失败,也会触发Item Error事件。
2.3 若数据通过了有效性检查就会触发Item Change事件,如果该 事件返回值为1,则Power Builder会拒绝该数据,并且不允许光标从该单元上移开。在这种 情况下也会触发Item Error事件。
2.4 Item Changed事件接收了输入的数据后,将触发Item Focus C hanged事件,数据就会作为一项存入Data Window的数据缓冲区中。
前一阶段完成后进入下一阶段。若某阶段未通过则跳过下面的阶段直接显示出错信息。四个阶段全完成后Power Builde自动把编辑控件中的数据放入数据窗口的响应项上,同时存入主缓冲区。编辑控件中的数据可以通过Data Window控件的对象函数Get Text()得到。
3. Data Window对象更新数据的原理
当在Data Window中对数据做了修改后,可以使用Update函数把上次执行Update或Retrieve函数以来在Data Window中进行的所有插入、修改、删除等操作都提交给数据库。
那么Power Builder的底层又是如何对数据库进行更新的呢,要了解它就必须了解Data Window中的四个缓冲区以及当前数据存储时各个缓冲区中状态的转变情况。
3.1 Data Window的四个缓冲区
在每一个Data Window对象中都有4个二维表作为数据缓冲区,用来存储查询到的数据,用户在Data Window中对数据处理系统内部的操作实际上都是将数据在几个缓冲区中进行修改和移动,最后,在用户提交数据库时,系统根据4个缓冲区中的信息,形成SQL的Insert、update、Delete等语句。
这四个缓冲区是:
当从数据库中读取数据时,所有数据会放在Primary Buffer中,并且会复制一份到Original Buffer中,在数据窗口中,我们只能看到Primary Buffer内的数据,任何数据的处理也都是针对主缓冲区中的数据做处理。但是要记住,不管我们对缓冲区中的数据做何种处理,除非运行Update函数,否则,缓冲区内任何数据的改变,对于后端数据库是没有任何影响的。
Primary Buffer的记录行数通过数据窗口控件的对象函数Rowcount()得到;Delete Buffer的记录行数通过数据窗口控件的对象函数Deleted Count()得到;Filter Buffer的记录行数通过数据窗口的控件对象函数Filter Count()得到。利用数据窗口控件的对象函数Set Filter()可以动态地改变过滤条件,然后使用数据窗口控件的对象函数filter更新主缓冲区和过滤缓冲区中的数据。
而Original Buffer由Power Builder内部维护,Power Builder所提供的所有函数都无法改变它的值。不过通过Power Builder所提供的Get Item系列函数可以读出Data Window最初从数据库中检索到的值。通过这些函数可以编程实现所谓"undo"功能。
3.2 Data Window数据项的状态值
在数据窗口控件的主缓冲区,过滤缓冲区和删除缓冲区中,每一行和每一行中的列都有一个编辑状态标志,这个标志表示了相应行是否是新增加的行、相应列的数据是否被修改。在更新数据库时,Power Builder通过查看Data Window缓冲区中每一行的状态值来决定产生什么类型的SQL语句。可以用Get Item Status函数和Set Item Status 对这些状态值进行操纵,缓冲区有四个状态值,其中有两个用于行。
当往Data Window中插入一行时,新插入行的状态为New!,该行中所有列的状态都为Not Modified !,当该行中某列的数据发生变化时,该列状态为Data Modified!。若Data Window中某一列设置了默认值,新插入一行时,该列状态也为Not Modified!,至少要对它做一次修改,该列的状态才会变成该列状态为Data Modified!
3.3 Data Window数据的操作
当调用Update函数时,Power Builder根据当前缓冲区和过滤缓冲区中的各行状态产生响应的Insert或Update语句。当行状态为New Modified!时,Power Builder将产生一个Insert语句,当行状态为Data Modified!时,Power Builder将产生一个Update语句。若某列在Data Window维护的可更新列名单上,或者该列为Data Modified!时,Power Builder将更新此列。对Insert语句来说,Power Builder将对所有列进行插入操作,因此,Insert语句将包括所有的列,如果该列没有赋值,Power Builder将会插入一个空值,若数据库不允许该列为空,则会产生数据库错误。
在Data Window中用Delete Row()函数删除的行将移到删除缓冲区中。当使用Update语句向数据库提交Data Window中的数据时,对Data Window删除缓冲区中的所有行都产生一个SQL Delete语句。然而若在Delete Row()被调用前某行的状态为New!,或New Modified!,对该行将不产生Delete语句。
4.四个缓冲区在编程中的应用
有时需要人为改变行和列的状态,其目的是为了阻止Power builder某些默认行为的发生。例如,如果事先已经从一个数据窗口拷贝某行到另一个数据窗口中,当用户对所拷贝的行又做了修改,需要将修改后的行覆盖另一数据窗口中的同一行时就应该对该行发一个Update语句,而不是Insert语句。 可以利用Set Item Statsus函数在程序中改变数据窗口行和列的状态信息,利用Get Item S tatus来获得某行某列的状态信息。
Set Item Statsus函数可以将某一列的状态从Data Modified!改变为Not Modified!,或从N ot Modified!变为Data Modified!,而对于行状态来说情况就要复杂的多。
当把某行状态改成Not Modified!或New!时,将把该行所有列的状态都设为Not Modified!。但若不能直接将一种状态改变为另一种状态,可以间接完成。例如,如果要把某行状态从New!改为Not Modified!可以先把该行状态改为Data Modified!,然后再从Data Modified!状态改为NotModified!。要复位整个数据窗口的修改状态,请使用数据窗口控件的Reset Update()对象函数。该函数除New!状态之外,将其它状态均修改为Not Modified!。
另外,当使用Reset函数和Retrieve函数以及改变数据对象属性时,系统将重置这几个缓冲区。例如当用户插入一个新行时,程序往往要在新插入行中的某一列中插入一个缺省的数据值,但此时用户并没有对数据做任何修改。在用户要关闭这一窗口时,如果在Close Query事件中用Modified Count函数查看数据是否修改,得到的结果是有所改变。因此,此时用户将得到一个提示信息:"是否保存所做的修改?"这样的结果是很不好的,因为用户原本没有向DataWindow中输入任何数据,但是程序却提示用户是否做保存操作。若用户选择了做保存操作,系统将形成SQL Insert语句提交数据库,原本应是空记录的行,也成了有记录的行,同时若碰上某些字段不能为空的却因没输入数据而提交了,保存操作后就插入了NULL,因此会导致数据的有效性出错。但是这一情况可以通过编程得到完美的解决:用Set Item Stats us函数将该行的状态改为New!即当新行插入并设置了缺省值以后该行的状态值为New!亦即无数据改变,因此不再提示做数据保存操作。其具体实现情况如下面代码所示:
//在数据窗口dw-1中插入一个新行
longrow1
row1=dw1Insert Row(dw1,Getrow())
dw1Set Item(row1,"discountpic",0,10)
//设置行状态为New!让程序只有在用户输入了数据时,才提示保存操作。
dw1Set Item Status(row1,0,primary!,New!)
//下面是用代码修改行列状态的例子。
该例代码将数据窗口主缓冲区第五行Salay列的状态置为Not Modified!dw1Set Item Statsus(5,"Salary",Primary!, Not Modified!)
下面的代码将数据窗口主缓冲区第五行empstatus列的状态设为Date Modified!
dw1Set Item Status(5,"empstatus",Primary,Data Modified!)
5.结束语
数据窗口在处理数据时很有特色,它在客户机的本地内存中开辟了四个缓冲区:主缓冲区、删除缓冲区、过滤缓冲区及原始缓冲区。从数据库中检索到数据后,数据窗口根据不同情况把数据放到不同的缓冲区中。四个缓冲区各司其职,相互协作完成数据的增、删、改等操作,最后把结果提交给数据库管理系统。
2010年6月1日
一、处理SQL语句
1、缓冲SQL语句
在应用程序中有时需要反复调用同一组SQL语句,在这种情况下,可以通过在应用中为这些SQL建立缓冲
区来提高执行性能。
在缺省情况下,SQL语句的缓冲区是关闭的,可以通过如下语句打开:
SQLCACHE=n n表示装入缓冲区SQL语句数量(缺省为0)
例如:
dw_1.SetTransObject(sqlca)
SQLCA.dbParm = "SQLCache = 0"
dw_1.retrieve()
如果将上例的 "SQLCache = 0" 改为 "SQLCache = 25", 此句的执行效率将提高五分之一左右。
但应注意缓冲区的大小,否则也将影响程序执行的性能。注:此方法对用 ODBC 和 ORACLE 连接的数据
库非常有效。
2、捆绑变量
请看下例:
SQLCA.DBPARM = "DISABLEBIND=1"
INSERT INTO DA_DH valueS("1","河南0")
INSERT INTO DA_DH valueS("2","河南1")
INSERT INTO DA_DH valueS("3","河南2")
INSERT INTO DA_DH valueS("4","河南3")
INSERT INTO DA_DH valueS("5","河南4")
INSERT INTO DA_DH valueS("6","河南5")
这里未使用捆绑变量,在插入是 PB 将重新处理每个带有 新值的SQL语句。如果将上例改为:
SQLCA.DBPARM = "DISABLEBIND=0"
INSERT INTO DA_DH valueS("1","河南0")
INSERT INTO DA_DH valueS("2","河南1")
INSERT INTO DA_DH valueS("3","河南2")
INSERT INTO DA_DH valueS("4","河南3")
INSERT INTO DA_DH valueS("5","河南4")
INSERT INTO DA_DH valueS("6","河南5")
则系统将把 INSERT 语句按如下格式进行处理:
INSERT INTO DA_DH valueS(?,?)
其中 "?" 称为占位符。系统性能将有所增强。
3、用数据窗口代替 SQL 语句
通常,为了获得某些数据,采用数据窗口和 SQL 语句都是可行的,但是PB 对数据窗口和 SQL 语
句采用不同的处理机制,因此,具有不同的效率。例:为里检索电话档案中的用户名,可以利用 SQL
语句,将所有的数据检索到一个多行编辑中,也可以检索到一个数据窗口中。如果使用第一种方法:
首先定义一个游标:
DECLARE CUR CURSOR FOR
SELECT "DA_DH"."HM"
FROM "DA_DH";
然后可以:
STRING stxt[],st
int li
open cur
do li = li + 1
fetch cur
into :stxt[li] ;
st=st+stxt[li] + "~r~n"
loop while stxt[li]<>""
close cur;
mle_1.txt = st
也可以使用第二种方法:
dw_1.settransobject(sqlca)
dw_1.retrieve()
利用 POWERBUILDER PROFILER 工具进行检查,对比两种方法所需时间如下
方法 所需时间 (百分之一秒)
SQL 语句 100.9857
数据窗口 49.0133
由于数据窗口或DATASTORE 使用了标准的内嵌的代码,而不是有开发人员进行全部编码,同时编
译执行的速度比解释执行的速度快的多,因此在开发过程中应尽量使用数据窗口和DATASTORE.. 即
使是必须用 SQL 语句的时候,也应该尽量将它们定义为存储过程(特别是在多用户的环境中),以
提高应用程序的性能.
二、数据窗口的编程和执行
数据窗口是PB最值得被称道的, 其具有如下特点:
1、多种显示方式.
2、多种编辑方式.
3、使用方法简单.
4、具有多种报表形式.
5、可实现屏幕滚动.
6、可实现数据的有效性校验.
7、执行性能显著提高.
8、编程工作变少.
9、可以在数据窗口内部实现数据哭的更新.
下面, 我将介绍一些用于提高数据窗口性能的技术.
1、减少连接数据库的次数
连库操作是非常影响执行速度的操作. 因此在程序中,一旦与数据库连接后就应当尽量保持与数据
库的连接, 减少连接数据库的次数.PowerBuilder 提供里两个函数来建立数据窗口与事务对象的连接:
SetTrans()
SetTransObject()
在程序中应当尽量使用 SetTransObject(), 因为SetTrans() 函数在每次调用 Retrieve(),
Update() 等函数之后, 都要执行数据库的连接和断开操作.
2、下拉数据窗口与表的连接
对于数据库服务器来说, 表的连接操作是一项非常大的开销, 而 PowerBuilder 提供的下拉数据
窗口在某些情况下可以代替表的连接操作.
例如, 为了在数据窗口上显示用户的电话号码和姓名:如果用表的连接的方法, 数据窗口对应的
SQL 语句应是这样的:
SELECT "DA_DH"."DHHM","DA_HTH"."DWM"
FROM "DA_HTH", "DA_DH"
WHERE ("DA_HTH"."DHHM"="DA_DH"."DHHM")
同样的程序可用下拉数据窗口来完成, 这里不再具体介绍.但是, 应当注意, 以上两种方法究竟哪
一种数据更快, 与表的结构, 表的数量, 连接的方法等均有关系, 应当具体分析.
3、共享数据
在一个应用程序中, 某些数据需要频繁的使用, 如果在每次使用时都从数据库中进行检索, 则需
占用大量的服务器资源和网络资源. 为了减少开销, 可以在客户端对这些数据只进行一次检索, 然后
允许其它任务共享这些数据.
例如, 如果有两个数据窗口, 都需要从第三方表中检索出用户的电话号码, 且此列用下拉数据窗
口给出. 如果每次都对电话号码进行检索, 则性能较低. 因此, 可以单独建立一个关于电话号码的数
据窗口. 在每次打开窗口时, 首先将电话号码检索到此数据窗口中, 然后另外两个数据窗口中关于电
话号码的下拉数据窗口可以共享此数据窗口中的数据.
在窗口的 Open 事件中编写如下程序:
dw_1.settransobject(sqlca)
dw_2.settransobject(sqlca)
dw_3.settransobject(sqlca)
// 检索 dw_1
dw_1.retrieve()
// 使 DW_2 的下拉数据窗口共享 DW_1
datawindowchild child1
dw_2.getchild('dhhm',child1)
child1.settransobject(sqlca)
dw_1.sharedata(child1)
// 使 DW_2 的下拉数据窗口共享 DW_1
datawindowchild child2
dw_3.getchild('dhhm',child2)
child2.settransobject(sqlca)
dw_1.sharedata(child1)
使用这种方法, 避免了各个数据窗口间物理的拷贝数据, 因此减少了空间上的开销,提高了应用程
序的综合性能.
4、数据窗口间数据的拷贝
如果需要在数据窗口间共享数据, 应当尽量使用 ShareData() 函数, 但是,ShareData() 函数并
不是物理地在数据窗口间拷贝数据, 如果在显示数据的同时, 还要对数据进行操作, 则需要进行数据
的拷贝.
例如, 要求将 DW_1 中选定的行拷贝到 DW_2 中:
在窗口的 OPEN 事件中编程:
dw_1.settransobject(sqlca)
dw_2.settransobject(sqlca)
dw_1.retrieve()
在数据窗口 DW_1 的 rowfocuschanged 事件中编写下列程序:
long lr
lr = dw_1.selectrow(0,false)
lr = dw_1.getrow()
lr = dw_1.selectrow(lr,true)
要完成从 DW_1 到 DW_2 的拷贝工作, 有两种方法:
第一种:在按钮 "拷贝" 的 CLICKED 事件中编程
long lr
lr = dw_1.getselectedrow(0)
dw_1.rowscopy(lr,lr,primary!,dw_2,100,primary!)
执行程序, 利用 POWERBUILDER PROFILER 得出所需时间为 1.7034(百分之一秒)
第二种:在按钮 "拷贝" 的 CLICKED 事件中编程
dw_2.object.data = da_1.object.data.selected
执行程序, 利用 POWERBUILDER PROFILER 得出所需时间为 0.8062(百分之一秒)
5、数据窗口属性的访问和修改
A、数据窗口属性的访问
在程序中访问数据窗口的属性有下列几种方法:
A1、采用点表达式访问
A2、应用多个独立的 Describe() 函数访问
A3、只使用一个 Describe() 函数, 采用复合参数访问多个属性
上面三中方法, 通常第一种方法最慢, 第三种方法最快.
例如:
在窗口的 OPEN 事件中
DW_1.Settransobject(SQLCA)
DW_1.Retrieve()
第一种方法:
在检索按钮的 CLICKED 事件中编程.
string dx, dy, dh, dw
dx = dw_1.object.da_dh.x
dy = dw_1.object.da_dh.y
dx = dw_1.object.da_dh.height
dy = dw_1.object.da_dh.width
st_1.text =dx+","+dy+","+dh+","+dw
第二种方法:
string dx, dy, dh, dw
dx=dw_1.describe("da_dh.x")
dx=dw_1.describe("da_dh.y")
dx=dw_1.describe("da_dh.height")
dx=dw_1.describe("da_dh.width")
st_1.text =dx+","+dy+","+dh+","+dw
第三种方法:
string dx, dy, dh, dw
st_1.text=dw_1.describe("da_dh.x" + "a_dh.y" + "da_dh.height" + "da_dh.width")
实验证明, 第三种方法的速度是最快的. 但是程序的可读性最差.
B. 数据窗口属性的修改
在程序中修改数据窗口的属性有下列几种方法:
A1. 采用点表达式修改
A2. 应用多个独立的 Modify() 函数访问
A3. 只使用一个 Modify() 函数, 采用复合参数访问多个属性
上面三中方法, 通常第一种方法最慢, 第三种方法最快.
例如:
在窗口的 OPEN 事件中
DW_1.Settransobject(SQLCA)
DW_1.Retrieve()
第一种方法:
在检索按钮的 CLICKED 事件中编程.
DW_1.SETREDRAW(FALSE)
dw_1.object.da_dh.x = 18
dw_1.object.da_dh.y = 16
dw_1.object.da_dh.height = 100
dw_1.object.da_dh.width = 200
DW_1.setredraw(true)
st_1.text =dx+","+dy+","+dh+","+dw
第二种方法:
DW_1.SETREDRAW(FALSE)
dw_1.modify("da_dh.x = 18")
dw_1.modify("da_dh.y = 16")
dw_1.modify("da_dh.height = 100")
dw_1.modify("da_dh.width = 200")
dw_1.setredraw(true)
第三种方法:
dw_1.modify("da_dh.x=18" + "da_dh.y=16" + "da_dh.height=100" + "da_dh.width=200")
实验证明, 第三种方法的速度是最快的. 但是程序的可读性最差.
注意, 在方法一和方法二中, 都使用的 setredraw() 函数以减少屏幕的重绘, 否则, 执行速度将
严重下降.
6、数据窗口中数据的访问
在程序中, 经常会需要动态的修改数据窗口中的数据. 对此, PB提供了多种方法, 各种方法在性
能上会有一些差异.
A、数据窗口中数据的访问
目的: 将数据窗口中的电话号码存放在一个数组中.
请比较下面两中方法.
方法一:
string da_dh[]
long ll,i
ll = dw_1.rowcount()
for i = ll to 1 stet -1
da_dh[i] = dw_1.getitemstring(i,"dhhm")
next
方法二:
string da_dh[]
da_dh[] = dw_1.object.dhhm.current
测试发现, 第二种方法比第一种方法快将近一倍. 数据量越大这种差异越明显.
B、数据窗口中数据的修改
目的: 修改数据窗口中的电话号码列的值.
请比较下面两中方法.
方法一:
dw_1.setitem(i,"dhhm",l_name)
方法二:
dw_1.object.name[i] = l_name
测试发现, 第二种方法比第一种方法快将近一倍. 数据量越大这种差异越明显.
7、数据窗口事件对性能的影响
对于数据窗口控制中经常发生的事件, 应当尽量减少其中的程序代码.特别是如下事件:
a、 itemchanged
b、 editchanged
c、 itemfocuschanged
d、 pbm_dwnkey
e、 rowfocuschanged
f、 retrieverow
在这些事件中的任何处理程序, 都会降低应用程序的处理速度. 所以应当尽量减少这些事件中的
处理程序, 必要时, 可以考虑只将重要的代码放在这些事件中, 而将剩余的代码放在一个传递的事件
中.
例如,如果需要用到数据窗口的 Rowfocuschanged 事件,可以为数据窗口定义一用户事件
"UE_RE", 而在数据窗口的 ROWFOCUSCHANGED 事件中写如下代码:
Parent.postevent("ue_re")
在 UE_RE 事件中再编写相应的程序代码,如:
string code
dw_1.selectrow(0,false)
dw_1.selectrow(rownum,true)
code = getitemstring(dw_1,rownum,"dhhm")
dw_2.retrieve(code)
另外,为了获得当前行号,应尽量使用数据窗口的 Currentrow 变量,而少用 GETROW() 函数
8、数据窗口的列名称与列编号
对数据窗口的某列进行访问, 可以采用该列的名称, 也可以使用该列的编号,
例如:采用列编号:
dw_1.object.data[ll_row,2]
dw_1.getitemstring(3,2)
采用列名称表示某列:
dw_1.object.article_text[ll_row]
dw_1.getitemstring(3,"dhhm")
dw_1.setitem(3,"date",1999-03-31)
对于以上两种方法, 如果只进行一次查询, 在速度上并没有太大的区别,如过需要循环访问数据窗口上的某一列, 则速度上的差异就表现的比较明显,才用第一种方法要快, 但是程序的可读性比较差。
但是, 在使用函数时(如 GETITEM() 和 setitem() ), 执行速度往往没有很大差别。
9、计算域
数据窗口的计算域会对数据的操作性能产生影响。 如果数据窗口中包含许多复杂的计算域,将严重影响数据窗口的执行速度。
多个DW进行update
//菜鸟代码
dw_1.Update()
dw_2.Update()
初级代码
IF dw_1.Update() = 1 And dw_2.Update() = 1 THEN
COMMIT;
ELSE
ROLLBACK;
END IF
中级代码
IF dw_1.Update() = 1 THEN
IF dw_2.Update() = 1 THEN
COMMIT;
ELSE
MessageBox("提示","喝多了!")
ROLLBACK;
END IF
ELSE
MessageBox("提示","喝多了!")
ROLLBACK;
END IF
高级代码
IF dw_1.Update() = 1 THEN
IF dw_2.Update() = 1 THEN
COMMIT;
ELSE
ROLLBACK;
MessageBox("提示","少喝点!")
END IF
ELSE
ROLLBACK;
MessageBox("提示","少喝点!")
END IF
专家级代码
IF dw_1.Update(True,False) = 1 THEN
IF dw_2.Update(True,False) = 1 THEN
dw_1.ResetUpdate()
dw_2.ResetUpdate()
COMMIT;
ELSE
ROLLBACK;
MessageBox("提示","没喝高啊!")
END IF
ELSE
ROLLBACK;
MessageBox("提示","没喝高啊!")
END IF
多个DW进行update,有时会不能全部成功update 用事务处理时,多个DW进行update后,再COMMIT.偶然会发现前面几个DW update成功,但后面的表失败时,好像执行了COMMIT,不会rollback.
正确的写法如下:
if dw_1.update(true, false)= 1 and dw_2.update(true, false)=1 ...then
commit;
dw_1.resetUpdate();
dw_2.resetUpdate();
else
rollback;
end if
2008年7月25日
2008年6月24日
//财务从一套帐到另一套帐
use master
go
select * from syslogins
use cwbase14
go
select * from sysusers
//
use master
go
sp_configure "allow updates",1
go
reconfigure with override
go
use cwbase14
go
update sysusers set suid = 129,name = 'lc0149999' where suid = 57
go
sp_configuer "allow updates",0
go
reconfigure with override
go
//设置数据库状态
sp_dboption cwbase1 , "select into/bulkcopy", true
go
2008年6月22日
2008年6月19日
2008年6月5日
2008年5月27日
2006年3月25日
熟悉Windows编程的人员都知道,Windows的API为程序员提供了大量的消息,约有200多个。在PowerBuilder中,系统将每个Windows消息作为事件传递给程序员处理,并且为大多数普通的事件提供了缺省处理。
PowerBuilder在语句描绘器中为每一个标准的控件设定了一些常用事件,一般的编程人员基于这些事件就基本可以完成常见的操作。如果我们遇到事件的处理需要另外截获Windo ws的消息,我们可以在语句描绘器菜单的"Declare|UserEvent..."中加入一个新的事件,同时指出您所希望对应的Windows消息。
Windows API的消息一般以两到三个字符的标识开始,这个标识标明了该消息的来源或对象。例如:pbm_active实际上对应的是WM_ACTIVATE,WM说明该消息是一窗口消息。其它的消息前缀包括:
*BM 按钮消息
*BN 按钮通知消息
*CB 通用对话框消息
*CBN 通用对话框通知消息
*DM 对话框消息
*EM 编辑器控件消息
*EN 编辑器控件通知消息
*LB 列表框消息
*LBN 列表框通知消息
*MM 多媒体消息
*SBN 卷滚条通知消息
此外还有一个DDE消息,DDE消息从技术上来说属于窗口消息,但在这里我们把它们分离出来,因为PowerBuilder并不完全支持全部的DDE消息。
消息一般告诉某个对象(如按钮)去执行一些动作。通知消息一般由某个控件发出,它通知应用程序某些事件在其上发生了。WaiteGroup的《Windows API编程字典》详细描述了这200多个消息的具体含义。这些消息,我们在PowerBuilder中也可以用Send(handle,message_no,word,long)函数发出。
所有的PowerBuilder自动映射的事件名都以"Pbm"为前缀,例如,BM_GETCHECK变成了pbm _bmgetcheck。通过向定义用户事件对话框中增加事件,程序员可以在需要的时候截获这些消息。
PowerBuilder还有另一类消息是标准的Windows API所不提供的消息。这类消息以"dw" 或"dwn"开头,如pbm_dwnretrieveend。这些是与数据窗口有关的消息和通知消息,因为数据窗口不是标准窗口对象,它们有它们自己的事件。
下面我们解释一下PowerBuilder中以pbm开头的内部映射事件的含义。限于篇幅,我们不能全部介绍,只能按类举一些主要例子,其余的事件类推。
单选或多选按钮消息(前缀:pbm_bm)
getcheck 单选按钮或多选按钮是否被选
getstate 按钮是否加亮
setcheck 将无线按钮或确认框的选中状态改为未选中状态,反
之亦然
setstate 加亮或不加亮按钮
change 改变按钮的风格,例如,改为单选按钮或组合框
单选或多选按钮通知消息(前缀:pbm_bn)
clicked 按钮控件被点中
disable 使按钮控件无效
double-clicked 按钮控件被双点
dragdrop 一个对象被放到按钮控件
dragenter 一个对象被拖到按钮控件
dragleave 一个对象被拖离按钮控件
dragover 一个对象被拖经按钮控件
hilite 按钮控件被加亮
paint 按钮控件被绘制
setfocus 按钮控件获得聚焦
unhilite 按钮控件不被加亮
通用对话框消息(前缀:pbm_cb)
addstring 将字符串加到通用对话框
deletestring 从通用对话框删除一个字符串
dir 加一个目录列表到通用对话框
findstring 搜索以一组字符开头的字符串
findstringexact 搜索与所提供的字符完全匹配的字符串
getcount 列表框中的项数
getcursel 当前被选项的数目
getdroppedcontrolset 列表框在屏幕上的坐标位置
geteditsel 编辑器控件中被选字符的范围
getextendedui 缺省或扩展的用户界面
getitemdata 重画的列表框中的4字节(32位)项
getitemheight 列表框中某一项的高度
getlbtext 列表框中的文本
getlbtextlen 列表框中文本的长度
insertstring 向列表框中增加新的字符串或4字节项
limittext 限制能被输入到列表框中的字符数
resetcontent 删除列表框中所有元素
selectstring 搜索匹配的字符串并显示
setcursel 在列表框中选择并显示一项
seteditsel 在列表框的编辑区域中选择一块文本
setextendedu 设置缺省或扩展的用户界面
setitemdata 在列表框中设定4字节(32位)项
setitemheight 设置列表框中项的高度
showdropdown 转换(显示或隐藏)列表框中拖放区域
通用对话框通知消息(前缀:pbm_cbn)
dblclk 用户在列表中某一项上双点
dragdrop 一个对象被放到通用对话框控件上
dragenter 一个对象被拖到通用对话框控件上
dragleave 一个对象被拖离通用对话框控件
dragover 一个对象被拖经通用对话框控件
dropdown 列表框的下放区域即将被显示
editchange 编辑器控件中的文本发生变化
editupdate 列表框编辑器控件中的文本即将被改变
errspace 列表框满,不能再向其中加入项
killfocus 通用列表框失去聚焦
selchange 列表框中被选文本被改变
selendcancel 用户按下了"取消"按钮
selendok 用户按下了"确认"按钮
setfocus 通用对话控件拥有聚焦
数据窗口消息(前缀:pbm_dw)
closedropdown 关闭下拉式数据窗口
scrollend 在数据窗口中卷滚到最后一行
scrollhome 在数据窗口中卷滚到第一行
scrolllineend 卷滚到当前行的行尾(水平方向)
scrolllinehome 卷滚到当前行的行首(水平方向)
数据窗口通知消息(前缀:pbm_dwn)
backtabout 即将通过Shift+Tab组合键离开该控件
changing 控件即将被改变
dropdown 下拉式列表框的下拉部分即将可见
graphcreate 即将创建图形
itemchangefocus 数据窗口控件中当前项的聚焦改变
itemvalidationerror 对当前项的修改引起了一个合法性检查错误
key 有键被按下。使用KeyDown()处理键盘值
lbuttondown 鼠标左键被按下
lbuttonup 鼠标左键被松开
mbuttonclk 鼠标中键点击
mbuttondbclk 鼠标中键双击
mousemove 鼠标移动
printmarginchange 打印边界被改变
processenter 回车键被按下
rowchange 数据窗口中聚焦从一行转向另一行
tabdownout 用户在数据窗口最后一行按了下箭头键
tabout 用户在数据窗口的最后一行/列中按了tab键
tabupout 用户在数据窗口第一行中按了上箭头键
动态数据交换(DDE)消息(前缀:pbm_dde)
ddeack 收到一个DDE消息
ddeinitiate 开始一个DDE会话
ddeterminate 终止一个DDE会话
编辑器控件消息(前缀:bm_em)
canundo 编辑器控件是否能撤消上一次修改
emptyundobuffer 清空由Windows管理的取消操作的缓冲区
fmtlines 在多行编辑器控件的行尾增加或删除回车换行
getfirstvisibleline 返回编辑器控件中可见的第一行的行号
gethandle 获得编辑器控件使用的内存句柄
getline 从编辑器控件中复制一行到内存中的一个缓冲区
getlinecount 返回多行编辑器控件的行数
getmodify 文本是否被用户修改
getrect 返回控件的长方形域
getsel 返回被选文本的起始位置
limittext 限制用户键入的文本长度
linefromchar 返回被选文本的行号
lineindex 返回编辑器控件中被选行第一个字符在编辑串中的位置
linelength 返回编辑器控件中被选行中的字符数
linescroll 水平或垂直卷滚编辑器控件
replacesel 从剪贴板或从键盘上用新文本替换被选文本
sethandle 设置编辑器控件的句柄指向内存中的一个缓冲区
setmodify 设置编辑器控件的modified标志
setpasswordchar 设置用户输入任何文本时显示的字符,在输入密码时的显示
setrect 设置/重置编辑器控件所在的长方形区域,编辑器控件中的文本被重画。
setrectnp 除了不重画文本,大致与setrect相同
setsel 选择字符
settabstops 在多行编辑器控件中设置tabstops
setwordbreak 设置新的词拆分函数
setwordbreakproc 设置新的词拆分过程
undo 撤消最近的编辑操作
编辑控件通知消息(前缀:pbm_en)
change 编辑器控件中的文本发生改变
errspace 编辑器控件内存缓冲区溢出
hscroll 用户点中上水平卷滚条
maxtext 用户试图输入比允许更多的文本
update 编辑器控件即将显示用户的修改
vscroll 用户点中了垂直卷滚条
转枫叶飘零的BLOG
SendMessage API函数在PowerBuilder中应用
一、引言
在Powerbulider巧妙地调用API函数SendMessage,可以完成Pb中的一些用常规的方法而很难实
现的功能,特将对该api函数在Powerbuilder中的使用,例举几个方面的运用,以期起到抛砖引玉的效果(以下代码完全可以使用PowerBuilder中的Send函数替代SendMessage 这个Api函数,因起稿比较匆忙,代码未经测试)
二、函数说明
SendMessage函数说明:
说明
调用一个窗口的窗口函数,将一条消息发给那个窗口。除非消息处理完毕,否则该函数不会返回。SendMessageBynum, SendMessageByString是该函数的"类型安全"声明形式
返回值
Long,由具体的消息决定
参数表
参数 类型及说明
hwnd Long,要接收消息的那个窗口的句柄
wMsg Long,消息的标识符
wParam Long,具体取决于消息
lParam Any,具体取决于消息
Powerbuilder中已使用函数Send函数对其进行了封装
函数原形:Send ( handle, message#, lowword, long )
Send函数说明:
说明
调用一个窗口的窗口函数,将一条消息发给那个窗口。除非消息处理完毕,否则该函数不会返回。
返回值
Long,由具体的消息决定
参数表
参数 类型及说明
handle Long,要接收消息的那个窗口的句柄
message# Long,消息的标识符
lowword Long,具体取决于消息
long long,具体取决于消息
3、 应用举例
定义外部函数引用声明:
funcation long SendMessage (long hwnd As Long,long wMsg , long wParam,long lParam) Library "user32.dll" Alias for "SendMessageA"
funcation long ReleaseCapture() Library "user32.dll"
定义实例变量:
Constant long LB_ITEMFROMPOINT = 425
Constant long HTCAPTION = 2
Constant long WM_NCLBUTTONDOWN = 161
Constant long EM_GETLINE = 404
Constant long EM_GETLINECOUNT = 399
Constant long EM_GETLINECOUNT = 186
Constant long EM_GETLINE = 196
Constant long TVM_SETITEMHEIGHT = 4379
Constant long EM_LINESCROLL = 182
Constant long EM_LIMITTEXT=197
1、列表框中鼠标移动时检测位置项
Powerscript:
在列表框的自定义事件ue_mousemove(pbm_mousemove)中写入如下代码:
pos = unitstopixels(parent.pointerx(),XUnitsToPixels!)+ unitstopixels(parent.pointery(),yUnitsToPixels!) * 65536
idx = SendMessage(handle(this), LB_ITEMFROMPOINT, 0, pos) If idx < 65536 Then sle_1.Text = lb_1.text(idx)
2、在列表框中查找匹配的项目
Powerscript:
窗口的open事件:
lb_1.AddItem ("软件")
lb_1.AddItem("电脑游戏")
lb_1.AddItem("电视机")
lb_1.AddItem("电视台")
lb_1.AddItem("电脑")
lb_1.AddItem("电脑游戏软件")
singlelineedit控件的modified事件:
long li_index
li_index= SendMessage(handle(this), EM_GETLINECOUNT, -1, sle_1.text)
lb_1.selectitem(li_index)
3、为ListBox添加水平滚动条
Powerscript:
窗口的open事件:
lb_1.AddItem("软件")
lb_1.AddItem("电脑游戏")
lb_1.AddItem("电视机")
lb_1.AddItem("电视台")
lb_1.AddItem("电脑")
lb_1.AddItem("电脑游戏软件")
SendMessage (handle(this), EM_GETLINE, 250, 0)
4、实现拖动无标题栏窗体
Powerscript:
在窗口的自定义事件ue_lbuttondown(pbm_lbuttondown)
long ReturnVal
x = ReleaseCapture()
ReturnVal = SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0)
5、获取多行文本框行数
Powerscript:
Commandbutton的clicked事件
Messagebox("", SendMessage(handle(mle_1), EM_GETLINECOUNT, 0, 0))
6、设置树型列表控件标题行高度
Powerscript:
tv_1的constructor事件:
SendMessage(handle(tv_1), TVM_SETITEMHEIGHT, 60, 0)
7、突破Powerbuilder中的多行文本框32k的限制
Powerscript:
SendMessage(handle(mle_1), EM_LIMITTEXT, 65534, 0)
8、用程序代码控制文本框的滚行与滚列
Powerscript:
SendMessage(handle(sle_1), EM_LINESCROLL, 0, 1)//下卷一行
SendMessage(handle(sle_1), EM_LINESCROLL, 0, -1)//上卷一行
SendMessage(handle(sle_1), EM_LINESCROLL, 1, 0)//右卷一列
SendMessage(handle(sle_1), EM_LINESCROLL, -1, 0)//左卷一列
三、结束语
在编写Powerbuilder应用时,应该充分调用相关的api函数来扩充pb的一些不足。