PB总结

来源:互联网 发布:java zip 加密解密 编辑:程序博客网 时间:2024/05/18 03:39

/DW的DBError事件
string          error_text
CHOOSE CASE sqlDBCode
          case 1                   error_text = '违反唯一索引!'
             case 1400          error_text = '字段不能为空!'
             case 1407          error_text = '字段不能为空!'
          case 1401          error_text = '字段太长!'
          case 1438          error_text = '数值大于列允许的最大精度!'
          case 2291          error_text = '出现非法字段!'         
          case 1031          error_text = '权限不足!'
          case 911          error_text = '注册名无效!'                  //权限专用
          case 922          error_text = '特殊字符无效!'          //权限专用        
          CASE 1017          error_text = '非法的用户名或口令,拒绝登录!'
          CASE 12154          error_text = '不能分解服务名称!'
          CASE 01005          error_text = '未给出口令或口令错误,拒绝登录!'
          CASE 01935          error_text = '注册名项输入的名称为系统关键字,禁止作为注册名使用!'
          CASE 540          error_text = '数据表或视图不存在!'
          CASE 942          error_text = '数据表或视图不存在!'
          CASE 903          error_text = '非法列名!'
          CASE 1403          error_text = '未查找到符合条件的数据!'                
          CASE -3                  error_text = '在您读入数据和存盘操作过程中,服务器中的数据已被别的用户或窗口改变,请重新读取数据后再试!'
          CASE 6                  error_text = '网络同数据库服务器的连接已经中断,请关闭应用程序然后重新打开.'
          CASE 50                  error_text = '网络同数据库服务器的连接已经中断,请关闭应用程序然后重新打开.'                
          case 1920          error_text = '用户名称与另外的用户或角色名称冲突'
          case 988          error_text = '缺少口令或其非法!'
          case 1918          error_text = '该ORACLE用户不存在!'
          case 1940          error_text = '不能放弃一个当前被连接的操作员,即当前删除的操作员正在使用!'
          CASE ELSE
                  if isnull(sqlca.sqlErrText) or sqlca.sqlErrText = '' then
                          error_text = '数据操作失败!'
                  else
                          error_text = sqlca.sqlErrText
                  end if
END CHOOSE
return MessageBox('错误',error_text,RetrYCancel!,1)        
//DBError参数
Buffer                  发生错误所在的缓冲区
Row                          发生第一笔错误的行数
SqlDBCode          数据库错误代码
SqlErrText          数据库错误信息


//MessageBox(title,text,icon,button,default)
icon参数:
information!          提示(缺省)
stopSign!                  中止
exclamation!          警告
question!                  询问
none!                          没有
button参数:
ok!                                  确定(缺省)
okCancel!                  确定,取消
yesNo!                          是,否
yesNoCancel!          是,否,取消
retryCancel!          重试,取消
abortRetryIgnore! 终止,重试,忽略


//如何在DBError event中处理多笔数据的错误
Rollback Using SQLCA;
If buffer = primary! Then
          Messagebox("error in row:" + string(row),"Code:" + string(sqldbcode) + "," + sqlerrtext)
          This.scrollToRow(row)
          return 1          //避免显示PB缺省的错误信息
end if


//数据窗口的规则检查
当用户在编辑控件中输入数据时,数据并不会立即写入数据窗口的缓冲区中,直到发生下面任何一种情况,
PowerBuilder才会把数据从编辑控件写入数据窗口的缓冲区中.
1.用户按下Enter键
2.用户按下Tab键跳到下一个字段
3.用户按下鼠标键跳到其它字段
4.运行AcceptText()函数
在完全通过4个步骤的规则检查后,才会真正把数据从编辑控件写入数据窗口缓冲区.任何一个步骤的错误
都会产生数据窗口的ItemError Event.数据窗口的数据规则检查步骤如下:
1.数据是否改变?
2.数据类型是否符合?
3.是否符合用户自定字段规则?
4.是否符合ItemChanged Event的程序?


//编辑控件函数
AcceptText():将编辑控件中的数据写入数据窗口缓冲区中.
不要在Itemchanged或ItemError event中编写Acceptext()函数,因为Acceptext()函数有可能驱动
ItemChanged或ItemError event,这将造成死循环的出现.
GetText():读取编辑控件的文字.


//每一个事件event和函数Function类似,会有参数argument和返回值return value.
ItemChanged Event返回值:
0.接受数据的值(缺省)
1.拒绝数据的值
2.拒绝数据的值并改变焦点
ItemError Event返回值:
0.拒绝数据的值,并且显示系统错误信息(缺省)
1.拒绝数据的值,但是不显示系统错误信息
2.接受数据的值
3.拒绝数据的值并改变焦点


//dw的update属性
Where 条件子句的产生方式:
1. Key Columns:比较原始数据缓冲区和当前数据库的数据时所产生的where子句条件不够严谨,所以在同
一个时间内,当很多的用户在一起使用数据库时有可能会发生将别人所更改过的数据覆盖的情况.为了
避免这样的情况发生,通常我们会将KeyColumns的方式用在单一用户或是关系表格中,所有的字段都是
Primary Key的情况.
2.Key and Updateable Columns:因为在比较原始数据缓冲区内的数据和当前数据库的数据时所产生的
where条件子句非常的严谨,所以在同一个时间内,当很多的用户一起使用数据库时,不会发生将别人所
更改过的数据覆盖的情况.因此,我们可以得到数据保存时最大的一致性.
3.Key and Modified Columns:因为在比较数据缓冲区内的数据与当前数据库的数据时所产生的where子句
条件比较有弹性(当前所要修改Modified的字段的数值),所以在同一个时间内,当很多用户一起使用数据
库时,可能会发生将别人所更改过的数据覆盖的情况.
主要字段(Key Column)的修改的方式:
1.Use Delete then Insert:这是数据窗口在主要字段(Key Column)的修改时的缺省选项,选用这种方式
修改数据时,数据会先被删除然后再重新增加一笔数据.但是在使用上要特别注意的是,如果在关系
数据库中,当设计删除为Cascade Delete时,在修改数据时候可能会导致其它不希望删除的数据被删除.
另外,在选择字段时必须要选择所有的字段,否则会没有办法再重增加一笔数据.
2.Use Update:这个选项会直接修改Key字段的数值,但是并不是所有的关系数据库(DBMS)都提供这样的
功能.


//动态数据窗口
数据窗口对象语法:
ls_syntax = sqlca.syntaxFromSql('select kind,name from tab_t','style(type=tabular)',ls_err1)
dw_1.create(ls_syntax,ls_err2)
dw_1.setTransObject(sqlca)
dw_1.retrieve()


//读取多行数据
1. 用DECLARE说明游标;(后无须检查SQLCode属性,要使用分号结束该语句。)
2. 用OPEN语句打开游标;
3. 使用FETCH语句读取一行数据;
4. 处理数据;
5. 判断是否已经读完所有数据,未读完时重复执行3~5步;
6. 使用CLOSE语句关闭游标。
int Emp_num
string Emp_name
DECLARE Emp_cur CURSOR FOR 
          SELECT employee.emp_number, employee.emp_name FROM employee;
open emp_cur;
FETCH Emp_cur INTO :Emp_num, :Emp_name ;
          if sqlca.sqlcode = -1 then
                  rollback;
                  messagebox('','')
                  return
          end if
CLOSE Emp_cursor;


//动态SQL(有四种类型)
//1.既无输入参数、也无结果集
string Mysql
Mysql = "CREATE TABLE Employee "&
          +"(emp_id integer not null,"&
          +"dept_id integer not null,"&
          +"emp_fname char(10) not null,"&
          +"emp_lname char(20) not null)"
EXECUTE IMMEDIATE :Mysql USING SQLCA;
//2.有输入参数、但没有结果集
int Emp_id_var = 56
PREPARE SQLSA FROM "DELETE FROM employee WHERE emp_id=?" ;
EXECUTE SQLSA USING :Emp_id_var ;
//3.编译时已经知道参数和结果集的列(游标或存储过程)
int Emp_id_var
String Emp_state_var = "北京",Sqlstatement
Sqlstatament = "SELECT emp_id FROM employee WHERE emp_state = ?"
DECLARE my_cursor DYNAMIC CURSOR FOR SQLSA;
PREPARE SQLSA FROM :Sqlstatement;
OPEN DYNAMIC my_cursor using :Emp_state_var;
FETCH my_cursor INTO :Emp_id_var;
          if sqlca.sqlcode = -1 then
                  rollback;
                  messagebox('','')
                  return
          end if
CLOSE my_cursor;
//或
int Emp_id_var
String Emp_state_var = "北京",proc,ls_error,ls_prompt
proc = "execute bb_pstn_complete_wp_p(?)"
DECLARE my_cursor DYNAMIC CURSOR FOR SQLSA;
PREPARE SQLSA FROM :proc;
OPEN DYNAMIC my_cursor using :Emp_state_var;
          if sqlca.sqlcode = -1 then
                  ls_error = sqlca.sqlErrText
                  rollback;
                  MessageBox('提示信息','过程执行失败!' + char(13) + ls_error)
          end if
FETCH my_cursor INTO :Emp_id_var;
          if li_flag = -1 then
                  rollback;
                  MessageBox('提示信息','过程执行失败!' + char(13) + ls_prompt)        
          end if
CLOSE my_cursor;
//4.开发程序时尚不知道参数和结果集
string Stringvar, Sqlstatement
int Intvar
Sqlstatement = "SELECT emp_id FROM employee"         
PREPARE SQLSA FROM :Sqlstatement ;
DESCRIBE SQLSA INTO SQLDA ;
DECLARE my_cursor DYNAMIC CURSOR FOR SQLSA ;
OPEN DYNAMIC my_cursor USING DESCRIPTOR SQLDA ;
FETCH my_cursor USING DESCRIPTOR SQLDA ;
//当FETCH语句执行成功时,动态描述区SQLDA中包含了结果集的第一行数据,反复执行FETCH语句即可得到
//其余数据。SQLDA.NumOutputs中包含了输出参数的个数。SQLDA.OutParmType数组中包含了各参数的数据
//例如TypeInteger!, 或 TypeString!等,使用CHOOSE CASE语句针对不同的输出参数类型调用不同的对象
//函数得到相应参数的值。
CHOOSE CASE SQLDA.OutParmType[1] 
             CASE TypeString! 
                     Stringvar = GetDynamicString(SQLDA, 1)
      CASE TypeInteger! 
              Intvar = GetDynamicNumber(SQLDA, 1)
END CHOOSE
CLOSE my_cursor;
//除DECLARE语句外,其它语句执行后都应该检查事务对象的SQLCode属性,以判断当前SQL语句的执行是否
//成功。


//得到下拉数据窗口中的显示值
ls_value = dw_1.Describe("Evaluate('LookupDisplay(column_name)',"+string(row_number)+")")

//固定数据窗口前几列的方法,例如第一列名为“id”,固定该列且后半部分从下一列开始显示:
dw_1.HSplitScroll = True
dw_1.Object.DataWindow.HorizontalScrollSplit = dw_1.object.id.Width
dw_1.Object.DataWindow.HorizontalScrollPosition2 = dw_1.object.id.Width


//打印数据窗口最后一页的方法:
string ls_pagecount
ls_PageCount = dw_1.describe("Evaluate('PageCount()',0)")
dw_1.object.datawindow.print.page.range = '" + ls_PageCount + "'"
dw_1.print()


//当编辑框得到焦点时自动选中内容:
this.selecttext(1,len(sle_1.text))


//判断数据窗口中是否存在某列
可以利用Describe("column_name.width")是否为"!"来判断;


//隐藏任务栏的方法,在OnCreate事件里利用Window API函数SetWindowLong:SetWindowLong(Application.Handle,GWL_EXSTYLE,WS_EX_TOOLWINDOW); 
PB使用时首先声明函数FUNCTION long SetWindowLong(ulong hWnd, integer nIndex, ulong dwNewLong) library "user32.dll" ALIAS FOR "SetWindowLongA",
然后调用:SetWindowLong(Handle(this),-20,128);


//如果大于本月23号,则将时间设置为下月1号,否则取当前时间
//方法1:
if day(today())>23    then
          if month(today())+1>12 then
                  this.text=left(string(today(),'yyyy-mm-dd'),5)+'01-01'
          else
                  this.text=string(date(year(today()),month(today())+1,1))
          end if
else
          this.text=string(today())
end if
//方法2:
dateld_temp = today()
if day(ld_temp) > 23 then ld_temp = date(year(RelativeDate(ld_temp, 10)), month(RelativeDate(ld_temp, 10)), 1)
sle_1.text = string(ld_temp)


//两个有用的PB内部函数
1.shRunDefltBrowser 调用缺省的浏览器,打开指定页面
版本:PBVM60.dll,PBVM80.dll,PB7我没用过,不过我想应该有。
函数声明:function long shRunDefltBrowser(string szUrl) library "pbvm60.dll"
调用方法:shRunDefltBrowser("www.pdriver.com")
2 shCenterWindow 将窗口位于屏幕中央
版本:PBVM60.dll,PBVM80.dll,PB7我没用过,不过我想应该有。
函数声明:function long shCenterWindow(long hWnd) library "pbvm60.dll"
调用方法:shCenterWindow(handle(w_about))

//允许用户修改新增加的记录,而检索出来的记录则不允许修改。
打开列的属性中的Expressions,在protect中输入条件判别式:
if(isRowNew(),0,1)


//使用Ole对象与Word等通讯时,如何避免启动多个Word等程序:
OLEObject ole_object
ole_object = CREATE OLEObject
li_ret = ole_object.ConnectToObject("","word.application")
IF li_ret <> 0 THEN
    //如果Word还没有打开,则新建。
    li_ret = ole_object.ConnectToNewObject("word.application")
    if li_ret <> 0 then
       MessageBox('OLE错误','OLE无法连接!错误号:' + string(li_ret))
       return
    end if
    ole_object.visible = true
END IF


//进展条的使用
在PowerBuilder中虽然没有这样的控件,可是在PowerBuilder所带的例子中有一用户对象
uo_progress_bar能够完成所需要求。将用户对象拷贝到用户的应用所在的库,将它放置在用户的界面中
需要出现的地方。然后在任务进展的时候,用对象的uf_set_position()函数指示当前任务的进展情况。


//在PB中调用屏幕保护的方法:
send(handle(This),274,61760,0)


//得到一个应用程序如Outlook的路径
RegistryGet("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/App Paths/MSIMN.EXE", &
          "Path",ls_outlook_path)
//Outlook的路径将保存在string型变量ls_outlook_path中。


//得到程序运行时的路径
//在global external functions声明:
Function uLong GetModuleFileNameA(long hinstModule, Ref String lpszPath, uLong cchPath) Library ″kernel32.dll″
//程序路径保存在变量ls_AppPath中
string ls_AppPath
int li_ret
ls_AppPath = Space(128)
li_ret = GetModuleFileNameA(Handle(GetApplication()),ls_apppath,128)
//要编译成可执行文件.exe才可用,否则得到的是Powerbuilder的pb60.exe或PB050.exe的路径。


//在程序中动态设定列的编辑风格为下拉数据窗口(DropDownDataWindow)
//假设所设定列为部门号"department_id",相关连的子数据窗口为"d_dddw_dep",
//显示列为部门名称"dept_name",数据列为部门号"dept_id",实现方法如下:
dw_1.Modify("department_id.DDDW.Name=d_dddw_dep ")
dw_1.Modify("department_id.DDDW.DisplayColumn='dept_name' ")
dw_1.Modify("department_id.DDDW.DataColumn='dept_id' ")
//或:
dw_1.object.department_id.dddw.name = "d_dddw_dep"    
dw_1.object.department_id.DDDW.DisplayColumn = "dept_name"
dw_1.object.department_id.DDDW.DataColumn = "dept_id"   
//注:PowerBuilder有一个小工具DWSyntax(程序名为:dwsyn60.exe),提供了获得及修改数据窗口、
//列等的各项属性值的语法,对编程非常有帮助。上述脚本在DWSyntax中都能找到。


//增量查询功能实现
//1.定义单行编辑器的用户事件ue_enchange,事件的ID为:pbm_enchange。这个事件能响应键盘的输入。
//2.在单行编辑器的ue_enchange事件中编写如下脚本:
long ll_found_row
string ls_find
ls_find = ″string(id) like ″ + ″′″ + this.text + ″%′″ //查找条件(左部分与单行编辑器文本相等)
ll_found_row = dw_1.Find(ls_find, 1, dw_name.RowCount()) //查找符合条件的行
if ll_found_row <= 0 then return
dw_1.ScrollToRow(ll_found_row) //滚动到相匹配的行
dw_1.SelectRow(0,false)
dw_1.SelectRow(ll_found_row,true) //将匹配行加亮显示


//如何在程序中对BLOB数据库进行写入
和后台数据库有关:以SQLANYWAY为例:
一般用 UPDATEBLOB 和 SELECTBLOB 两个SQL语句来实现。
建一个表TABLE1,一个字段是ID,另一个是BLOB, 
SELECTBLOB BLOB FROM TABLE1 WHERE ID='xx';
UPDATEBLOB SET BLOB = :BLB_X FROM TABLE1 WHERE ID='yy';
删除时删除ID为'mm'的记录即可,新增是先插入一条ID为'mm'的记录,然后 用UPDATEBLOB将数据写入
表内。 其他的数据库可参照手册进行,其命令与上述差别不大!


//如何取出DDDW中的Display Column的内容。
dw_1.describe("Evaluate('lookupdisplay(column_name)',1)")
//column_name=列名 ,'1'表示第一行;看看Help中的Describe


//屏蔽窗口的ALT+F4键 
//方法一:
1.在窗口的systemkey事件中增加以下代码:
IF KeyDown(KeyF4!) THEN 
    Message.Processed = TRUE 
END IF 
2.在窗口的closequery事件中增加如下代码:
Long ll_ret 
IF KeyDown(keyF4!) THEN 
     ll_ret = 1 
END IF 
return ll_ret 
//方法二:
建一实例变量,在你的关闭程序上赋一个True然后在closequery中判断该值, 如为False则Return 1


//当程序中用到了动态加入的对象,如BMP资源文件、数据窗口对象,PB编译时是扫描不到的,解决方法:
1.将此对象写入到资源文件中:
用记事本创建资源文件dw_object.pbr,写入:c:/myprogram.pbl(dw_sj)
编译时将此文件选入Resource File Name处。
2.将应用编译成PBD、DLL文件。


//如何在PB中实现延时:
subroutine Sleep(long dwMilliseconds) library "kernel32.dll"
延时1秒则调用: Sleep(1000)    //单位是毫秒。


//用下面表达式可得到记录在某组中的行号: 
Getrow()-First(Getrow() for Group 1)+1


//调用API函数步骤:
1、在适当的位置声明函数,如窗口内,Application内,UserObject内,
定义在Local External Function或Global External Function中,如播放声音的:
Function boolean sndPlaySoundA(string SoundName, uint Flags) Library "WINMM.DLL"
Function uint waveOutGetNumDevs() Library "WINMM.DLL"
也可以创建一个UserObject,集中声明常用的API及函数本地化,如定义用户对象 u_external_function:
Declare Local External Function(定义外部函数):
Function boolean sndPlaySoundA(string SoundName, uint Flags) Library "WINMM.DLL"
Function uint waveOutGetNumDevs() Library "WINMM.DLL"
Declare User Object Function(定义用户对象函数):
uf_play_sound(string as_wave_name, integer ai_option) 
函数内容如下:
//参数:as_wave_name :wav文件名 ai_option :同步或异步(1/0)
uint lui_numdevs
lui_numdevs = WaveOutGetNumDevs() 
If lui_numdevs > 0 Then 
          sndPlaySoundA(as_wave_name,ai_option)
      return 1
Else
          return -1
End If 
2、调用时在程序中定义一个实体并调用其函数:
u_external_function iu_external_function
iu_external_function = create u_external_function
iu_external_function.uf_play_sound('c:/windows/media/ding.wav',1)
试试看,如果有声卡,就会听到"叮”的一声。其它API函数也是如此处理。


//数据窗口的GRID格式下,根据实际情况控制每一行的背景
//调整detail的属性中的color的expression就可以了,如:
if(currentrow()=getrow(),rgb(255,240,194),if(mod(getrow(),2)=1, rgb(255,254,249) , rgb(247,247,239)))
//表达式中rgb(255,240,194)为黄色,rgb(255,254,249)为浅白色,rgb(247,247,239)为浅黄色。
//CurrentRow()得到数据窗口当前得到输入焦点的行的行号。
//GetRow()返回数据窗口相应带中的当前行行号。


//实现对数据窗口中的某一列/行显示为一指定颜色
//如果符合条件,则显示灰色的背景,否则白色;
本方法同样可以设置该列的字体颜色:其中"column_name"为列名。
dw_1.object.column_name.background.color = "16777215~tif(fromid='string',rgb(192,192,192),rgb(255,255,255))"
也可以是一行都变色:
dw_1.object.Datawindow.detail.color = "16777215~tif(fromid='string',rgb(192,192,192),rgb(255,255,255))"


//固定数据窗口前几列的方法,例如第一列名为"id”,固定该列且后半部分从下一列开始显示:
dw_1.HSplitScroll = True
dw_1.Object.DataWindow.HorizontalScrollSplit = dw_1.object.id.Width
dw_1.Object.DataWindow.HorizontalScrollPosition2 = dw_1.object.id.Width


//在数据窗口中如何隐藏某计算单元 
在它的properties/expression/visible属性中设置为"IF(1=2,1,0)”就可以了。


//超链接
Inet linet_base
GetContextService("Internet", linet_Base)
linet_Base.HyperlinkToURL('http://www.neusoft.com')
Destroy(linet_base)


//===========================================================================
//函数功能:返回计算表达式的值
//参数:    string     thestr      计算表达式,如 2 * (3+5)
//返回值:string     retVal      计算表达式的结果值,如 2 * (3+5)的结果值为 16
//        如果是一个不正确的表达式,则返回 false.
//===========================================================================
string retVal
datastore lds_evaluate
lds_evaluate = create datastore
lds_evaluate.create('release 8;~r~ntable()')
retVal = lds_evaluate.describe("evaluate('" + thestr + "', 1)")
destroy lds_evaluate
return retVal

 

//通过代码更改数据窗口对象的方法
string error_syntaxfromSQL, error_create
string new_sql, new_syntax
new_sql = 'SELECT emp_data.emp_id,emp_data.emp_name from emp_data ' &
          + 'WHERE emp_data.emp_salary>45000'
new_syntax = SQLCA.SyntaxFromSQL(new_sql,'Style(Type=Form)', error_syntaxfromSQL)
IF Len(error_syntaxfromSQL) > 0 THEN          // Display errors
          mle_sfs.Text = error_syntaxfromSQL
ELSE          // Generate new DataWindow
          dw_new.Create(new_syntax, error_create)
          IF Len(error_create) > 0 THEN
                  mle_create.Text = error_create
          END IF
END IF
dw_new.SetTransObject(SQLCA)
dw_new.Retrieve()


//打开动态窗口的方法:
window newarray[3]
string win[3]
int i
win[1] = "w_employee"
win[2] = "w_customer"
win[3] = "w_sales"
for i = 1 to 3
      Open(newarray[i], win[i])
next


//显示一个与Windows操作系统风格一致的About对话框。 首先声明如下外部函数: 
function int ShellAboutA(ulong al_hWnd, string as_szApp, string as_szOtherStuff, ulong hIcon) library "shell32" 
ShellAboutA(handle(parent),"关于...#摆渡人工作室","欢迎光临摆渡人工作室",0)


//如何将COLUMN的显示风格在EDIT、DDDW、DDLB之间相互切换:
(1)切换成DDDW:
dw_1.Modify("#1.dddw.Name='dddw_jg'")
dw_1.Modify("#1.dddw.DisplayColumn='name_jg'")
dw_1.Modify("#1.dddw.DataColumn='id_jg'")
(2)切换成DDLB:
dw_1.Modify("#1.ddlb.case='any'")        
dw_1.Object.#1.Values ="red~t1/white~t2"
(3)切换成EDIT:
dw_1.Modify("#1.edit.case='any'")
dw_1.Modify("#1.edit.AutoSelect='Yes'")
(4)获取当前风格:
dw_1.Describe("#1.Edit.Style")
(5)如果还不行,可能得要如下操作:
dw_1.Modify("#1.dddw.Name=''")一下;


//在dw_1中选定想要打印的几条记录
long ll_pos
dataStore lds_ds
lds_ds = create dataStore
lds_ds.dataObject = dw_1.dataObject
for ll_pos = 1 to dw_1.rowCount()
     if dw_1.IsSelected(ll_pos) then
               dw_1.RowsCopy(ll_pos,ll_pos,Primary!,lds_ds,lds_ds.rowCount()+1,Primary!)
     end if
next
lds_ds.print()


//实现在循环时可以通过点击按钮终止循环 
integer n 
//sb_interrupt 是共享变量 
sb_interrupt=false 
for n=1 to 3000 
          yield() 
          if sb_interrupt then //sb_interrupt的值在"取消”按纽的Clicked事件中修改为true
                  MessageBox("我不干了","你真坏!") 
                  sb_interrupt=false 
                  exit 
          else //其它处理,在单行编辑器中显示当前n值
                  sle_1.text = string(n)
          end if 
next


//SQL语句调用规范
INTEGER li_customer_id = 1
STRING ls_city_code = '501'
PREPARE SQLSA FROM "DELETE bb_customer_info_t WHERE city_code =? AND customer_id = ?" ;
EXECUTE SQLSA USING :ls_city_code,:li_customer_id;


//通过modify函数来同时修改多个表
1、新建一个数据窗口d_grid_dep_emp,它的Select语句为
SELECT department.dept_id, 
department.dept_name,
employee.emp_id, 
employee.emp_fname,
employee.emp_lname
FROM department, employee
WHERE employee.dept_id = department.dept_id
2、设置数据窗口d_grid_dep_emp的属性,将列的taborder改为非0值;并点击菜单Rows——>Update 
Properties,设置此数据窗口Allow Updates,Table to Update设为department,Updateable Columns为
department.dept_id,department.dept_name。
3、在窗口中更新数据窗口按钮的clicked事件编写脚本:
long ll_rtn
// 修改Department表(Department表在第2步已设置为可更新)
ll_rtn = dw_1.update(true, false)
If ll_rtn = 1 then
          //关闭对Department表的修改
          dw_1.Modify("department_dept_name.Update = 'No'")
          dw_1.Modify("department_dept_id.Update = 'No'")
          dw_1.Modify("department_dept_id.Key = 'No'")
          //设置Employee表成为新的可修改表
          dw_1.Modify("DataWindow.Table.UpdateTable = 'employee'") 
          dw_1.Modify("employee_emp_id.Update = 'Yes'")
          dw_1.Modify("employee_emp_fname.Update = 'Yes'")
          dw_1.Modify("employee_emp_lname.Update = 'Yes'")
          dw_1.Modify("employee_emp_id.Key = 'Yes'")
          //修改Employee表
          ll_rtn = dw_1.Update()
          IF ll_rtn = 1 THEN
                  COMMIT USING SQLCA;
                  dw_1.retrieve()
                  messagebox('提示信息','更新成功!')
          ELSE
                  ROLLBACK USING SQLCA;
                  MessageBox('提示信息', '更新失败!')
          END IF
          //重置修改标志 
          dw_1.Modify("department_dept_name.Update = 'Yes'")
          dw_1.Modify("department_dept_id.Update = 'Yes'")
          dw_1.Modify("department_dept_id.Key = 'Yes'")
          dw_1.Modify("DataWindow.Table.UpdateTable = 'department'")
          dw_1.Modify("employee_emp_id.Update = 'No'")
          dw_1.Modify("employee_emp_fname.Update = 'No'")
          dw_1.Modify("employee_emp_lname.Update = 'No'")
          dw_1.Modify("employee_emp_id.Key = 'No'")
ELSE
          ROLLBACK USING SQLCA;
          MessageBox('提示信息', '更新失败!')
END IF 
//可以将以上功能作成一个函数,在必要的时候调用即可。


//单击编辑框选中其中内容  
getfocus事件中书写代码:this.selecttext(1,len(this.text))。保存后运行,却得不到我们想要的
效果。想到了一个另类办法:以pbm_bnclicked为事件ID,创建单行编辑框的自定义事件ue_clicked,
代码是:this.selecttext(1,len(this.text)),
getfocus事件的代码改为:This.Post Event ue_clicked()。保存后运行,效果出来了!


//怎样得到字符串中汉字的个数 
For i = 1 to Len(aString) 
          ls_ch = Mid(aString,i,1) 
          If Asc(ls_ch) >= 128 then //是汉字 
                  li_num++ 
                  i = i+1 
          End if 
Next  
//最后,li_num就是汉字的个数了


//DW支持双击标题进行排序
String ls_old_sort,ls_column,ls_name,ls_criteria
Char lc_sort
IF Right(dwo.Name,2) = '_t' THEN     //取得是否是列标题名
          ls_column = LEFT(dwo.Name, LEN(String(dwo.Name)) - 2)
          ls_old_sort = this.Describe("Datawindow.Table.sort")
          IF ls_column = LEFT(ls_old_sort,LEN(ls_old_sort) - 2) THEN
                  lc_sort = RIGHT(ls_old_sort,1)
                  IF lc_sort = 'A' THEN
                          lc_sort = 'D'
                  ELSE
                          lc_sort = 'A'
                  END IF
                  this.SetSort(ls_column + " " + lc_sort)
          ELSE
                  ls_criteria = ls_column + " A"
                  this.SetSort(ls_criteria)
          END IF
          this.Sort()
END IF


//DW支持单击按Ctrl或Shift进行多选
int          il_last_row                  //il_last_row为实例变量,记录上次单击的行
int li_current_row          //当前单击行
int li_row                          //中间变量
//未选择就返回
if row = 0 then 
          return
else
          li_current_row = row
end if
if keydown(keyshift!) then          //按下SHIFT键
     if il_last_row = 0 then
                  this.selectRow(row,true)
                  il_last_row = li_current_row 
          else        
        this.selectRow(0,false)
        if li_current_row > il_last_row then
           for li_row = il_last_row to li_current_row
              this.selectrow(li_row,true)
           end for
        else
           for li_row = il_last_row to li_current_row step -1
              this.selectrow(li_row,true) 
           end for
        end if 
          end if
else                                                  //未按下SHIFT键
          il_last_row = li_current_row
     if keydown(keycontrol!) then           //按下CTRL键
        if this.isSelected(li_current_row) then
           this.selectrow(li_current_row,false)
        else
           this.selectrow(li_current_row,true)
        end if 
     else                                                           //无CTRL键或SHIFT键按下
        this.selectrow(0,false)
        this.selectrow(li_current_row,true)
     end if
end if


//改变DW的查询条件语句
string ls_select,ls_filter
ls_select = dw_1.getSqlSelect()
ls_select = mid(ls_select,1,pos(upper(ls_select),'FROM ')+30)
ls_filter="WHERE service_kind=" + vi_service_kind + " ORDER BY FEE_ID ASC "        
ls_select = ls_select + ls_filter
dw_1.Reset()
dw_1.SetTransObject(SQLCA)
dw_1.SetSQLSelect(ls_select)
dw_1.Retrieve()


//数据窗口的closeQuery事件:提示保存数据
dw_1.AcceptText()
IF dw_1.ModifiedCount() + dw_1.DeletedCount() > 0 THEN
          CHOOSE CASE MessageBox("操作提示","数据已经发生变化,是否保存?",Question!,YesNoCancel!,1)
                  CASE 1        
                          cb_save.TriggerEvent(clicked!)
                  CASE 2        
                          Return 0          //不做任何操作直接关闭窗口
                  CASE 3        
                          Return 1          //不会运行Close Event,维持原来的情况
          END CHOOSE
END IF


//提示:请选择要删除的记录
if dw_2.GetSelectedRow(0)= 0 then
          MessageBox("提示信息","请选择要删除的记录!")
          return
end if


//按某字段进行排序
IF dwo.name = "fee_id_t" THEN
          this.setSort("fee_id a")
          this.sort()
elseif dwo.name = "fee_position_t" then
          this.setsort("fee_position a, fee_id a")
          this.sort()
END IF


//控制DATAWINDOW里每页显示的行数
1、在Datawindow中增加一个计算域,起名为:ceil_page,此计算域必须放在Detail段中,
Expression中输入 ceiling(getrow()/25) 25表示每页打印25行,也可以是一个参数。
2、分组,选择菜单Rows/Create Group,选择ceil_page
按ceil_page分组,并选中New Page On Group Break(意思是新组开始时换页)。
3、将此计算域设为隐藏(在属性页中的expression页中在visible属性中写0)。
4、补空行:
在窗口的open事件中写如下代码: 
long li_count,li_i 
li_count=dw_1.retrieve() 
if mod(li_count,25)<>0 then
          for li_i=1 to 25 - mod(li_count,25) 
                  dw_1.insertrow(0) 
          next 
end if


//如何实现数据窗口数据的自动折行
1) 在DataWindow Painter中打开此DataWindow对象。
2) 在需设定自动折行的列上双击鼠标, 弹开此列的属性窗口。
3) 选择Position标签, 选中Autosize Height 多选框。
4) 选择Edit标签, 不选中Auto Horz Scroll多选框。
5) 单击OK按钮, 保存所做的修改。
6) 点中Detail Band (即写有Detail的灰色长带), 单击鼠标右键, 选择 Properties... 菜单项。
7) 选中Autosize Height多选框。
8) 单击OK按钮, 保存所做的修改。
9) 保存此DataWindow。
注意:连在一起的汉字(中间没有标点或空格分隔), 系统将认为是一个单词, 不会自动进行折行, 
英文也是如此……DW窗口折行如果有汉字的话就必需中间加空格才会折行,否则怎样设置都不行。例如你
如果想在第20位折行,就先判断第20位是否是个汉字,如不是就在第20位后加空格,如果是汉字就在
第19位加空格。判断是否是汉字可以用它的ASCII码是否大于127来判断。


//按条件对某行数据进行颜色区分
case(cj when is >= 90 then rgb(255,0,0) when is < 60 then rgb(0,255,0) else rgb(0,0,255)))


//PB中同时连接多个数据库,如连接SQLServer2000和Oracle8 
string ls_startupfile 
ls_startupfile='hisini.ini'
sqlca.DBMS = ProfileString(ls_startupfile, "database", "dbms", "") 
sqlca.database = ProfileString(ls_startupfile, "database", "database", "") 
sqlca.userid = ProfileString(ls_startupfile, "database", "userid", "") 
sqlca.dbpass = ProfileString(ls_startupfile, "database", "dbpass", "") 
sqlca.logid = ProfileString(ls_startupfile, "database", "logid", "") 
sqlca.logpass = ProfileString(ls_startupfile, "database", "LogPassWord", "") 
sqlca.servername = ProfileString(ls_startupfile, "database", "servername", "") 
sqlca.dbparm = ProfileString(ls_startupfile, "database", "dbparm", "") 
remote_trans= CREATE transaction 
remote_trans.DBMS = ProfileString(ls_startupfile, "Database_remote", "dbms", "") 
remote_trans.database = ProfileString(ls_startupfile, "Database_remote", "database", "") 
remote_trans.userid = ProfileString(ls_startupfile, "database_remote", "userid", "") 
remote_trans.dbpass = ProfileString(ls_startupfile, "database_remote", "dbpass", "") 
remote_trans.logid = ProfileString(ls_startupfile, "database_remote", "logid", "") 
remote_trans.logpass = ProfileString(ls_startupfile, "database_remote", "LogPassWord", "") 
remote_trans.servername = ProfileString(ls_startupfile, "database_remote", "servername", "") 
remote_trans.dbparm = ProfileString(ls_startupfile, "database_remote", "dbparm", "") 
//附hisini.ini 
[Database] 
DBMS=MSS Microsoft SQL Server 6.x 
Database=his 
UserId= 
DatabasePassword= 
ServerName=. 
LogId=sa 
Lock= 
Prompt=0 
computer='11' 
ocx= 0 
use0='之住院管理' 
cfprint='1' 
[Database_remote] 
DBMS = "O84 Oracle8/8i(8.x.4+)" 
ServerName = "oracle8" 
LogId = "dba" 
Database=zx 
UserId= 
DatabasePassword= 
Lock= 
Prompt=0 
computer='11' 
ocx= 0 
cfprint='1'


//PB6.5连接Oracle8i和9i的情况
SQLCA.DBMS = "O84 Oracle8/8i (8.x.4+)"
SQLCA.LogPass = "test"
SQLCA.ServerName = "myora"
SQLCA.LogId = "test"
SQLCA.AutoCommit = False
SQLCA.DBParm = "TableCriteria=',test,''TABLE'',''VIEW'''"


//在检索的数据行上再加上一行记录
dataWindowChild dwc
dw_service.getchild('svcid',dwc)
dwc.settransobject(sqlca)
dwc.retrieve()
dwc.insertrow(1)
dwc.setitem(1,'svcid','00')
dwc.setitem(1,'svcname','不区分')
dw_service.setTransObject(sqlca)
dw_service.Retrieve()


//数据窗口中按enter键实现tab功能(在数据窗口的Enter事件中)
send(handle(this),256,9,long(0,0))
return 1


//send用法:Send(handle,message#,lowword,long)
//This statement scrolls the window w_emp up one page:
Send(Handle(w_emp), 277, 2, 0)
//Both of the following statements click the CommandButton cb_OK:
Send(Handle(Parent), 273, 0, Handle(cb_OK))
cb_OK.TriggerEvent(Clicked!)
//minimizes the DataWindow:
Send(Handle(dw_1), 274, 61472, 0)
//maximizes the DataWindow:
Send(Handle(dw_1), 274, 61488, 0)
//returns the DataWindow to its normal, defined size:
Send(Handle(dw_1), 274, 61728, 0)


//重设数据窗口的检索语句
ls_accept_city = gs_citycode
ld_beg_date = datetime(date(em_assign_beg_date.text),time('00:00:00'))
ld_end_date = datetime(date(em_assign_end_date.text),time('23:59:59'))
ls_where = " WHERE b.assign_date >= :id_begin_date &
          AND b.assign_date <= :id_end_date &
          AND a.register_number = b.register_number &
          AND a.accept_city = :is_accept_city &
          AND a.action = 6 AND current_action = 1 AND status IN(1,-1) "
ls_sql = dw_wp.Describe("DataWindow.Table.Select")
if pos(ls_sql,'WHERE') <> 0 then
          ls_sql = mid(ls_sql,1,pos(ls_sql,'WHERE') - 1)
end if
ls_sql = 'DataWindow.Table.Select=" ' + ls_sql + ls_where + '"'
ls_err_info = dw_wp.modify(ls_sql)
if ls_err_info <> "" then
          messagebox('提示信息','查询异常,请核查' + ls_err_info)
          return
end if
af_connect()
dw_wp.settransobject(sqlca)
dw_wp.retrieve(ld_beg_date,ld_end_date,ls_accept_city)
af_disconnect()