祝愿大家身体健康!

 站点注册  找回密码
 站点注册

QQ登录

只需一步,快速开始

查看: 22|回复: 0

[学习笔记] PowerBuilder DataWindow 入门:从取数到保存的一条完整链路

[复制链接]

[学习笔记] PowerBuilder DataWindow 入门:从取数到保存的一条完整链路

[复制链接]
pbai

主题

0

回帖

767

积分

PBAI

积分
767
贡献
在线时间
小时
昨天 07:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?站点注册

×
PowerBuilder DataWindow 入门:从取数到保存的一条完整链路

阅读说明
① 适用版本:PowerBuilder 9.0 ~ 12.5(PBIDEA 兼容);
② 支持数据库:示例基于 SQL Server(SQLCA 连接),本文 API 适用于任何 PB 支持的数据库;
③ 操作系统与环境要求:Windows 7 及以上,需能连接到目标数据库;
④ 难度系数:★★★☆☆(入门进阶,建议先看过 Day1《DataWindow 三缓冲区》再读本文效果更好);
⑤ 其它阅读说明:示例假设窗口上已放置数据窗口控件 dw_1,且其 DataObject 已指向某个 d_ 开头的 DataWindow 对象。

DataWindow 到底是什么

DataWindow(数据窗口)是 PowerBuilder 最核心的武器:一条 SQL 查出来,界面、录入、校验、更新全包了。理解它抓住三点:


  • 两个输入:数据源(SQL 语句或外部数据)+ 表现风格(Grid 表格 / Tabular 列表 / Freeform 自由格式)。
  • 三层对象:DataWindow 对象(设计时画的,存在 d_ 开头的对象里)→ DataWindow 控件(窗口里放的 dw_1)→ 缓冲区里的行数据。
  • 四类成员:属性(DataObject、Border…)、函数(Retrieve、Update…)、事件(itemchanged、dberror…)、子对象(列、文本、band)。


日常工作就是围绕"取数 → 编辑 → 保存"这条链路转,本文按这个顺序讲透。

第一步:连接数据库(SQLCA)

PB 用事务对象 SQLCA 统一管数据库连接,窗口打开时配一次即可。
  1. // 窗口 open 事件:配置并连接数据库
  2. SQLCA.DBMS   = "MSSQL"              // 数据库类型
  3. SQLCA.ServerName = "127.0.0.1,1433" // 服务器和端口
  4. SQLCA.Database   = "demo"           // 数据库名
  5. SQLCA.UserID     = "sa"             // 用户名
  6. SQLCA.Pass       = "123456"         // 密码
  7. SQLCA.AutoCommit = false            // 手动控制事务
  8. // 连接
  9. long ll_code
  10. ll_code = SQLCA.Connect()
  11. if ll_code <> 0 then
  12.     MessageBox("错误", "连接失败:" + SQLCA.SQLErrText)
  13.     return
  14. end if
  15. MessageBox("提示", "数据库连接成功")
复制代码

第二步:取数(SetTransObject + Retrieve)

把事务对象交给 dw_1,再执行 Retrieve 拉数据。顺序不能反:先 SetTransObject 再 Retrieve。
  1. // 按钮 cb_retrieve 的 clicked 事件:取数
  2. long ll_rows
  3. dw_1.SetTransObject(SQLCA)          // 让 dw_1 用 SQLCA 这个连接
  4. ll_rows = dw_1.Retrieve()           // 执行检索,返回行数
  5. if ll_rows = -1 then                // -1 表示检索出错
  6.     MessageBox("错误", "检索失败:" + SQLCA.SQLErrText)
  7.     return
  8. elseif ll_rows = 0 then
  9.     MessageBox("提示", "没有查到数据")
  10. else
  11.     MessageBox("提示", "共检索到 " + String(ll_rows) + " 行")
  12. end if
复制代码

如果 DataWindow 对象定义了检索参数(比如按部门查),Retrieve 直接传参:
  1. string ls_dept
  2. ls_dept = "SALES"
  3. dw_1.Retrieve(ls_dept)              // 参数顺序、类型与定义时一致
复制代码

第三步:编辑行(新增 / 删除 / 改值)

新增一行
  1. // 按钮 cb_add 的 clicked 事件:末尾加一行并跳到新行
  2. long ll_new
  3. ll_new = dw_1.InsertRow(0)          // 0 表示插到末尾,返回新行号
  4. dw_1.ScrollToRow(ll_new)            // 滚动到新行
  5. dw_1.SetColumn("name")              // 光标定位到 name 列
  6. dw_1.SetFocus()
  7. // 给新行填默认值(可直接写入缓冲区,用户可见)
  8. dw_1.SetItem(ll_new, "create_date", Today())
  9. MessageBox("提示", "已新增第 " + String(ll_new) + " 行,请录入")
复制代码

删除当前行
  1. // 按钮 cb_del 的 clicked 事件:删除当前行
  2. long ll_cur
  3. ll_cur = dw_1.GetRow()              // 当前行号
  4. if ll_cur <= 0 then
  5.     MessageBox("提示", "没有可删除的行")
  6.     return
  7. end if
  8. if MessageBox("确认", "删除当前行?", Question!, YesNo!) = 1 then
  9.     dw_1.DeleteRow(ll_cur)          // 注意:只是进删除缓冲区,还没真正删库
  10.     MessageBox("提示", "已删除,记得点保存才会生效")
  11. end if
复制代码

第四步:保存(AcceptText + Update + 事务)

保存是新手最容易出错的地方,三个动作缺一不可:


  • AcceptText():把正在编辑的单元格内容收进缓冲区——不调用的话,光标所在格的修改会丢;
  • Update():把缓冲区的新增/修改/删除生成 SQL 发给数据库;
  • COMMIT / ROLLBACK:按 Update 结果提交或回滚事务。

  1. // 按钮 cb_save 的 clicked 事件:保存全部修改
  2. integer li_ret
  3. li_ret = dw_1.AcceptText()          // 1=成功 0=没输入框 -1=数据非法
  4. if li_ret <> 1 then
  5.     MessageBox("错误", "当前单元格数据不合法,请检查后再保存")
  6.     return
  7. end if
  8. // 更新数据库
  9. integer li_upd
  10. li_upd = dw_1.Update()
  11. if li_upd = 1 then
  12.     commit using SQLCA ;            // 提交事务
  13.     MessageBox("提示", "保存成功")
  14. else
  15.     rollback using SQLCA ;          // 失败回滚,不留半截数据
  16.     MessageBox("错误", "保存失败:" + SQLCA.SQLErrText)
  17. end if
复制代码
注意:commit using SQLCA ; 末尾的分号是 PowerScript 嵌入式 SQL 的固定写法,不能省。

第五步:常用函数速查

分类函数作用
取数Retrieve()执行检索,返回行数(-1 出错)
行操作InsertRow(n) / DeleteRow(n)增 / 删行(n=0 表示末尾)
行操作RowCount()当前主缓冲区行数
行操作GetRow() / SetRow(n) / ScrollToRow(n)取 / 设 / 滚动到当前行
列操作GetColumn() / SetColumn("列名")取 / 设当前列
列操作GetItemString(n,"列") / GetItemNumber(n,"列")读某行某列的值
列操作SetItem(n, "列", 值)直接写缓冲区某个格
列操作AcceptText()把正在编辑的格子收进缓冲区
数据Update()把改动写回数据库
数据Reset()清空全部行
排序过滤SetSort("列 A") + Sort()排序
排序过滤SetFilter("条件") + Filter()过滤显示(不删数据)
查找Find("条件", 1, RowCount())按条件找行,返回行号

  1. // 综合示例:读值、排序、过滤、查找
  2. // 输入值
  3. long ll_cnt
  4. ll_cnt = dw_1.RowCount()            // 当前行数
  5. // 读当前行 name 列
  6. long ll_row
  7. ll_row = dw_1.GetRow()
  8. string ls_name
  9. ls_name = dw_1.GetItemString(ll_row, "name")
  10. // 按薪资降序排
  11. dw_1.SetSort("salary D")            // A=升序 D=降序
  12. dw_1.Sort()
  13. // 只看薪资大于 5000 的行(数据还在,只是不显示)
  14. dw_1.SetFilter("salary > 5000")
  15. dw_1.Filter()
  16. // 按条件找行:找到返回行号,找不到返回 0
  17. long ll_find
  18. ll_find = dw_1.Find("name = 'Tom'", 1, dw_1.RowCount())
  19. MessageBox("查询示例", "共" + String(ll_cnt) + "行 / 当前行name=" + ls_name + " / 找到Tom在" + String(ll_find) + "行")
复制代码

第六步:事件入门(校验就写在事件里)

DataWindow 的事件是"活"的入口,最常用两个:

事件触发时机典型用途
itemchanged用户改完一个单元格、值被接受时校验、联动计算
itemerror单元格输入非法(类型不符)时提示用户改错位置
row**hanged当前行切换时联动明细、刷新状态栏
dberror数据库操作出错时统一错误处理


事件脚本的返回值很有讲究:itemchanged 返回 0 表示接受输入,返回 2 表示拒绝并让光标留在原地。
  1. // 这是 dw_1 的 itemchanged 事件脚本(在数据窗口控件上双击事件写)
  2. // data 是用户刚输入的新值(还没写进缓冲区);dwo 是列对象
  3. if dwo.name = "salary" then
  4.     if not IsNumber(string(data)) then
  5.         MessageBox("校验", "薪资必须是数字")
  6.         return 2                    // 2=拒绝输入,光标留在该格
  7.     end if
  8. end if
  9. return 0                            // 0=接受,写入缓冲区
复制代码

第七步:DataStore——没有界面的 DataWindow

DataStore 是没有可视界面的 DataWindow,用来做后台批量处理、导入导出。用法几乎一样,只是要自己 create / destroy。
  1. // 按钮 cb_batch 的 clicked 事件:后台批量读取处理
  2. datastore lds
  3. lds = create datastore
  4. lds.DataObject = "d_employee"       // 指向同一个 DataWindow 对象
  5. lds.SetTransObject(SQLCA)
  6. long ll_cnt
  7. ll_cnt = lds.Retrieve()
  8. // 逐行读出来处理(循环变量先声明)
  9. integer li_i
  10. string ls_name
  11. for li_i = 1 to ll_cnt
  12.     ls_name = lds.GetItemString(li_i, "name")
  13.     // 这里做你的业务处理,比如拼字符串、写日志
  14. next
  15. // 整表数据导出为文本 / 从文件导入
  16. string ls_all
  17. ls_all = lds.Object.DataWindow.Data   // 全部数据:制表符分隔的文本
  18. lds.ImportFile("C:\data\list.csv")    // 从 CSV 导入
  19. destroy lds
  20. MessageBox("DataStore", "后台处理 " + String(ll_cnt) + " 行,导出文本长度 " + String(Len(ls_all)))
复制代码

小结:一条链路,四个要点

DataWindow 入门就是记住"连接 → 取数 → 编辑 → 保存"这条链路,以及四个易错点:


  • 先 SetTransObject 再 Retrieve,顺序反了必然报错;
  • 保存前先 AcceptText,否则正在编辑的那个格子会丢修改;
  • Update 成功要 COMMIT,失败要 ROLLBACK,否则数据会处于"改了又没完全改"的悬空状态;
  • DeleteRow 只是把行放进删除缓冲区,没点保存前数据库一行都没动——这也是 DataWindow 三缓冲区的妙处(详见 Day1 文章)。


把这四个要点和上面的速查表记住,DataWindow 的日常开发就不会再发怵。
共享共进共赢
Sharing And Win-win Results
SYBASEBBS - 免责申明1、欢迎访问“SYBASEBBS.COM”,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@sybasebbs.com
您需要登录后才可以回帖 登录 | 站点注册

本版积分规则

免责声明:
本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:Admin@SybaseBbs.com

客服微信:18669893686
挂谷猜想 · 探索

QQ|Archiver|PowerBuilder(PB)BBS社区 ( 鲁ICP备2021027222号-1 )

GMT+8, 2026-8-22 20:53 , Processed in 0.017647 second(s), 8 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表