PB常用程序汇总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_MACHINESOFTWAREMicrosoftWindowsCurrentVersionApp PathsMSIMN.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:windowsmediading.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


//在数据窗口中如何隐藏某计算单元 
在它的propertiesexpressionvisible属性中设置为"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、分组,选择菜单RowsCreate 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()


//常用API函数例解
1.如何使PB窗口总在最上层(Always On Top) 
通过SetWindowPos函数把窗口的显示层次修改为HWND—TOPMOST,就可使指定窗口永远不会被其它窗口覆
盖,该函数声明为: 
Function Long SetWindowPos(Long hwnd,Long ord,Long x,Long y,Long dx,Long dy,Long uflag) Library ″user32″ 
参数1为要顶层显示的窗口句柄,参数2指定显示的层次,参数7为附加选项,其余参数指定窗口位置和
大小,均可忽略。在窗口的Open或Activate事件中加入如下函数调用: 
SetWindowPos(Handle(This),-1,0,0,0,0,3) 
参数2取-1表示在最顶层显示窗口,取1表示在最底层显示;最后一个参数若取1,表示窗口大小保持不
变,取2表示保持位置不变,因此,取3(=1+2)表示大小和位置均保持不变,取0表示将窗口的大小和
位置改变为指定值。

2.在PB中如何获得光盘盘符 
通过GetDriveType函数可以获取驱动器(如:软驱、硬盘、光驱、网络映射驱动器等)的信息,该函数
声明为:
Function Uint GetDriveTypeA(String drive) Library ″kernel32.dll″ 
参数为一个盘符(如"C:"),返回值:1表示未知,2表示软驱,3表示本地硬盘,4表示网络驱动器,
5表示光驱。因此如下代码可以获得光盘的盘符: 
For i=Asc(′D′) to Asc(′Z′) 
//列举所有可能的CDROM驱动器 
  If GetDriveTypeA(Char(i)+″:″)=5 Then 
//若找到CDROM 
MessageBox(″CDROM″,Char(i)+″:″) 
//显示光盘盘符 
Exit //退出列举 
  End If
Next

3.在PB中如何获取目录信息 
⑴获取当前目录。通过GetCurrentDirectory函数可以获取当前目录,该函数声明为: 
Function Ulong GetCurrentDirectoryA(Ulong buflen, ref String dir) Library ″kernel32.dll″ 
参数2为接收当前目录的字符缓冲区,前面必须加ref表示地址引用;参数1用来指定字符缓冲区的长度。
调用过程为:
String curdir 
curdir=Space(256) 
//为字符缓冲区开辟内存空间 
GetCurrentDirectoryA(256,curdir) 
MessageBox(″Current Directory″,curdir) 
⑵获取Windows及系统目录。要用到GetWindowsDirectory和GetSystemDirectory两个函数,须作如下声明: 
Function Uint GetWindowsDirectoryA(ref String dir,Uint buflen) Library ″kernel32.dll″ 
Function Uint GetSystemDirectoryA(ref String dir,Uint buflen) Library ″kernel32.dll″

4.在PB中如何注销当前用户、关闭计算机、重启计算机 
通过ExitWindowsEx函数可实现这三个功能,首先作如下声明: 
Function Long ExitWindowsEx(Long uflag,Long nouse) Library ″user32.dll″ 
参数2保留不用,可取0;参数1取0可以注销当前用户,取1可以关闭计算机,取2可以重启计算机,其值
再加4表示强制结束"未响应"的进程。

5.控制由Run运行的程序(简称Run程序) 
在PB程序设计中,可以用Run()来运行一些程序。比如用户按了F1,就运行一个chm文件。但Run程序无法
与PB主程序协调工作,若用户按了多次F1,就会启动Run程序的多个实例,主程序退出时,Run程序依然
运行。可以用如下函数来使它们协调工作: 
Function Ulong FindWindowA(Ulong classname, String windowname) Library ″user32.dll″ 
Function Long SetParent(Long childwin,Long parentwin) Library ″user32.dll″ 
⑴使Run程序只运行一个实例 
handle=FindWindowA(nul,wtitle) 
//查找Run程序是否已经运行,wtitle为Run程序的标题 
IF handle〉0 Then Return 
//若已经在运行就返回 
Run(″C:Program FilesJointJoint.chm″) 
//否则运行Run程序 
⑵PB主程序退出时,Run程序也关闭 
handle=FindWindowA(nul,wtitle) 
SetParent(handle,Handle(w—main)) 
//使Run程序窗口成为PB主程序的子窗口

6.映射网络驱动器 
若要在程序中把远程主机的资源映射到本地驱动器,可以用如下函数: 
Function long WNetAddConnectionA(String path,string pwd,String drv) Library ″mpr.dll″ 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当进行PB(PowerBuilder)程序的数据库升级时,需要考虑以下几个方面: 1. 数据库备份:在进行数据库升级之前,务必要对当前的数据库进行备份,以防在升级过程中出现意外情况导致数据丢失或损坏。备份操作应该在升级之前进行,确保数据的安全性。 2. 升级计划:在进行PB程序的数据库升级之前,应该制定一个详细的升级计划。这个计划应包括升级所需的步骤、时间安排、资源分配等内容,以确保升级过程的顺利进行。同时,还需要确定升级后的数据库版本以及与PB程序的兼容性。 3. 数据库脚本的更新:升级数据库可能涉及到表结构、视图、存储过程等的更改。在进行升级之前,需要先编写好对应的数据库脚本,并确保这些脚本能够顺利地执行。这些脚本应该包括对数据库结构的修改、数据迁移等操作。 4. PB程序的修改:根据数据库升级后的变化,可能需要对PB程序进行相应的修改。例如,对于表结构的更改,可能需要更新相关的数据窗口、数据访问逻辑等。在对PB程序进行修改时,需要确保修改的正确性,并进行严格的测试,以保证升级后的程序能够正常运行。 5. 测试和验证:在进行PB程序的数据库升级之后,需要对升级后的数据库和程序进行全面的测试和验证。测试应该涵盖各个方面,包括数据的完整性、查询功能、报表生成等。只有通过了相关的测试,才能确认升级过程的成功,并将新版本的PB程序投入使用。 综上所述,进行PB程序的数据库升级需要进行备份、制定升级计划、更新数据库脚本、修改PB程序,并进行完整的测试和验证。这样才能确保升级过程的顺利进行,并能够保证升级后的数据库和程序的稳定性和可用性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值