Pb从入坑到放弃(三)数据窗口

写在前面

数据窗口是Pb的一个特色控件,有了数据窗口对于pb来说可谓如虎添翼。

对数据库中的数据操作,几乎都可以在数据窗口中完成。

使用数据窗口可以简单检索数据、以图形化的方式显示数据、绘制功能强大的数据统计报表。

一、 数据窗口画板

数据窗口画板由Design, Preview, Control List, Data, Properties和 Column Specification 6个试窗构成

数据窗口画板

1.1 Design 视窗

Design 是一个非常重要的视窗 ,使用菜单 Design→Options 来改变 Design 窗口的外观

1.1.1 General tab页设置

General

Snap to Grid:选中该属性时,在数据窗口中的部件自动和网格对齐, 建议都选中

Show Grid:是否显示网格。

-- 未选中 -- 选中后
未选中 选中后

Show Ruler:显示标尺。

-- 未选中 -- 选中
未选中标尺 选中标尺

X, Y:网格之间的间距,单位是数据窗口属性中设置的单位

Show Edges:是否显示边框。主要针对字段、标签、文本等而言

Retrieve on Preview:是否在预览时检索

1.1.2 Generation tab页设置

Generation

Presentation Style:在该下拉列表框中可以选择要设置哪种类型的数据窗口。下面的
其他操作都是针对选中的那种类型的数据窗口而言的。
Background Color:设置数据窗口的背景颜色。
Text 组框: border 可以设置 text 部件的边框类型, color 可以设置文本的颜色。
Columns 组框: border 可以设置字段的边框类型, color 可以设置字段中文字的颜

1.1.3 Prefixes tab页设置

设置数据窗口中放置部件时命名的默认前缀

Prefixes

1.2 Preview 视窗

可以预览数据窗口的外观,并显示相应表中对应的数据

在该窗口中可以进行各种数据操作,包括数据过滤、数据排序、增加数据、删除数据、检索数据、查找数据以及翻页等

这些操作都可以在鼠标右键弹出菜单中完成

1.2.1 查找数据
--呼出菜单 -- 查找内容
image-20230702152859447 image-20230702153243006
1.2.2 翻页
-- 呼出菜单 --呼出菜单
image-20230702153416310 image-20230702153432362
  • first page(翻到第一页)
  • prior page(前一页)
  • next page(下一页)
  • last page(最后一页)
1.2.3 增加、删除数据

在数据窗口中增加或者删除数据,得首先设置数据窗口相应的属性,

允许修改的字段Tab Order 值不能为 0

-- --
image-20230702153817872 image-20230702153937111

1.3 Control List 视窗

Control List 是数据窗口中所有的部件构成的一个列表

image-20230702154224282

1.4 Data 视窗

显示的是数据窗口对象中的数据,很多操作和 Preview 视窗中的都相同 .

该视窗侧重于对应表中各个字段的取值,而 Preview 视窗侧重于数据窗口对象的显示效果

image-20230702154503043

1.5 Properties 视窗

属性视窗显示的是当前选中对象的属性,可以对这些属性进行修改

Properties 视窗

1.6 Column Specification 视窗

是一个比较重要的视窗,在该视窗中可以增加、删除、修改列的初始值、检验表达式或者校验信息

校验信息

举个栗子:

假设 empno的位数是 10,如果位数不正确,则应该提醒用户。

Validation Expression列为字段 empno输入校验表达式:
len(empno) = 10
Validation message 中输入:'员工编号必须为 10 位! '
当程序运行时,会自动校验用户输入的内容是否位数为 10 位,否则显示输入的信息

二、数据窗口的数据源

Pb提供的 Quick Select(快速选择类型)、 SQL Select( SQL 选择类型)、 Query(查询类型)、 External
(外部类型) 和 Stored Procedure(存储过程类型) 5种数据源

2.1 Quick Select 数据源

快捷数据源,是经常使用的一种数据源,可以快速地创建数据窗口 。

使用这种数据源,只能从一个数据表或者视图中选取数据

需要从多个数据表中选取数据而且还想使用这种数据源时,只能创建对应的视图

-- --
image-20230702161151928 image-20230702161616327

2.2 SQL Select 数据源

选择这种数据源时,SQL语句设计是图形化的,也可以手工输入SQL语句

-- ①选择数据源 --②选择表
image-20230702162238916 image-20230702162329169
--③ 选择字段 -- SQL语法和图形化切换
image-20230702162635260 image-20230702162841887
-- ④ 定义检索条件
image-20230702163453988 image-20230702163614029

2.3 Query 数据源

PB可以将特定的 SQL 语句保存为 Query 对象, 不同的 Query 数据源的数据窗口都可以使用这些已经保存
Query对象来作为数据源,增强了 SQL 语句的重用性

--① 新建Query数据源对象 --② 使用Query 数据源
新建数据源对象  使用 数据源

2.4 External 数据源

是一种比较特殊的数据源,可以弥补其他四种数据源的不足

当和不存在于数据库中的数据打交道或者要利用数据窗口的某些特性但不进行数据处理时,这两种情况下都可以使用 External 数据源的数据窗口

--① 指定数据源 -- ② 设置数据类型及长度
指定数据源 设置数据类型及长度

2.5 Stored Procedure(存储过程)

可以直接使用数据库中已经创建好的存储过程作为数据源

SQL 语句无需网上传送,可以减少网络通信量及网上传输 SQL 语句的时间, 所以执行效率比其他数据源的数据窗口要高

-- ① 选择数据源 --② 选择数据库中创建好的存储过程
image-20230702165806412 存储过程

2.6 Web Service 数据源

这是PB 11.5 以后新加的数据源

--① 选择Web Service 数据源 --②输入WebService的WSDL文件的地址
选择webservice wsdl地址
--③ 选择WebService接口 --④ 选择WebService 接口方法
选择WebService接口 WebService 接口方法

三、数据窗口显示样式

3.1 Grid 显示样式

数据窗口布局整齐,但不能灵活地安排字段、标签、表头的布局

字段横向排列在 detail band 中,标签横向排列在 header band 中,和字段相对应,字段和字段之
间有网格线分隔,类似于电子表格 。

如下图所示

Grid 显示样式

3.2 Tabular 显示样式

字段、标签的布局和 Grid 显示样式的数据窗口相同,都是横向排列的,但是字段之间没有网格线分隔。

字段和标签的布局可以随意调整,在 header band 中的标签可以随意拖放到 detail band 中,

detail band 中的字段也可以拖放到 header band 中

Tabular 显示样式

3.3 Group 显示样式

数据窗口可以指定按那个(或那些)字段进行分组,可以用指定的分组条件将数据分组显示,并且允许为每组指定一些计算。

例如:要显示各部门员工的薪资数据,可以按部门分组

-- ①按部门分组 -- ②分组后数据
image-20230706081121250 image-20230706081216960

3.4 Freedom 显示样式

这种显示样式的数据窗口布局也很灵活,可以随意安排字段和标签的位置

-- ① 选择Freeform -- ②录入表单信息
image-20230706081444933 image-20230706082146853

3.5 Label 显示样式

如果用户想要生成邮件标签,可以使用 Label 显示样式的数据窗口来实现

在向导的指引下,可以设定标签的一些参数。

可以指定标签的大小,包括三方面的设定: Label 本身的大小、Label 之间的边框、 Label 的布局顺序。

在 Label 组框中,参数“ Across”指横向显示的标签数目, “ Down”表示一页中竖向显示的标签数目

-- --
image-20230706082846458 image-20230706082946035
image-20230706083005580 image-20230706083027102

最终效果

3.6 N-up 显示样式

可以在同一页上显示多列相同字段的一种特殊的显示样式 .

可以设置每行重复显示字段的次数 ,默认是2

这里我们每行显示2列员工编号和员工姓名

-- ① 选择N-up样式 -- ②设置每行显示列数
image-20230706142754440 image-20230706142918266

最终显示效果

3.7 CrossTab 显示样式

通过CrossTab 显示样式我们可以制作出下图所示的交叉报表

--① 选择CrossTab 显示样式 --② 设置行分类、列分类
image-20230706144921837 image-20230706145207746

最终显示效果

交叉报表

3.8 Graph 显示样式

Graph 显示样式 可以显示饼图、柱状图、折线图等

Graph 显示样式的数据窗口时,三个主要参数是

  • Category 显示在横向坐标轴上的字段
  • Values 显示在纵向坐标轴上的字段
  • Series 横向坐标轴上同组比较时的分组标准
-- ① 选择Graph 样式 -- ② 选择横向、纵向坐标
image-20230706151325074 image-20230706151600488
--③ 选择图表样式及设置标题
image-20230706151909292

我们这里选择柱状图显示,一共又17种样式可以选择,感兴趣的小伙伴可以都试试

柱状图

3.9 Composite 显示样式

这种样式的数据窗口可以将多种类型的、多个逻辑上毫不相关的数据窗口放置到一起,是一种比较灵活的

我们把前面制作好的柱状图和表格放到一起

-- ① 选择Composite 显示样式 -- ② 选择要展示的报表
image-20230706170353099 image-20230706170534859

最终显示效果

混合图表

3.10 RichText 显示样式

这种样式的数据窗口使数据库中的数据和文字可以在一起排版,可以方便地将数据库中的数据和文字内容一起形成文
档、报告 。

-- ① 选择RichText 显示样式 -- ② 选择文字处理工具
image-20230706171641052 image-20230706171834285

最终显示效果

文字处理

3.11 OLE 2.0 显示样式

OLE 对象链接和嵌入 。使用它可以将其他软件的功能引入到 PB开发的应用程序中

使用这种显示样式的数据窗口,可以借鉴其他软件的强大功能,弥补 PB在某些专业性较强领域中的不足或空白

-- ① 选择OLE 样式 -- ② 设置分组
image-20230707221130369 image-20230707221243781

引入pdf功能

3.12 TreeView 显示样式

该样式可以按照树形结构显示数据,我们以empdept表为例,以dept_name 字段进行分组

-- ① 选择TreeView 样式 -- ② 选择dept_name分组
选择TreeView样式 image-20230708171958910

最终效果

根据部门分组显示员工信息

四、数据窗口对象介绍

数据窗口用带( Band)将其分隔成四部分 ,一个标准的报表一般由题头、数据、页脚、总计四部分构成,分别对应数据窗口的 Header, Detail,
Summary 和 Footer 四部分

数据窗口四部分

描述
Header 出现在每页的顶端,用于显示标题和列的题头。
放置表头、报表日期等一些能够方便查阅的内容, 即使这部分字段的 Tab Order 值不为 0、 DisplayOnly 属性为 False 也不允许用户编辑,并且也只能显示多条记录中的一条
Detail 包含了数据窗口对象的主体,显示了各行的数据和相关的标签。
放置数据、表格,程序运行时,数据窗口自动处理该区域,根据数据库中的数据显示一条或者多条数据
Summary 出现在每页的底端,用来显示文本和页号
放置页内小计、页号等页脚方面的内容
Footer 出现在 DataWindow 对象的最后一页,用来为整个数据窗口对象显示总计和总和
放置总计、制表人等需要在表格最后放置的内容

五、数据窗口常用函数

函数 参数 说明
dw_1.insertrow(row) row 设置插入位置
成功时返回插入成功的行号,失败返回-1
insertrow(0) 表示在最后一行插入一行
插入空行
dw_1.deleterow(row) row 要删除的行号
成功时返回1,失败时返回-1
deleterow(0) 代表删除当前行
删除行
dw_1.retrieve() dw_1.retrieve(参数1,参数2,参数3...) 检索数据
dw_1.update(accept,resetflag) accept:默认为true,执行之前调用
resetflag:默认为true,数据窗口自动重置更新标志
成功返回1,失败返回-1
修改或更新操作
dw_1.setsort(format) format: A 升序,D降序
成功时返回1,失败时返回-1
设置排序
dw_1.sort() 成功是返回1,失败时返回-1 按照当前数据窗口 的排序规则进行排 序
dw_1.setfilter(format) format:是字符串,可以使用字段名或字段号定义
成功时返回1,失败时返回-1
例1:dw_1.setfilter("sal> 5000 and age < 10000")
例2:dw_1.setfilter(#3>5000)
例3:dw_1.setfilter("")
设置数据窗口的过 滤条件
dw_1.filter() 对数据窗口进行过 滤
dw_1.reset() 成功返回1,失败返回-1 清除数据窗口的所 有数据
dw_1.scroll(number) number:滚动的行数
参数为正数的时候向下滚动,为负数时向上滚动
成功返回控件第一行显示的数据行号,失败时返回-1
设置滚动的行数
dw_1.scrolltorow(row) row 指定的行号
成功返回1,失败返回-1
滚动到指定行
dw_1.scrollpriorpage() 滚动到上一页
dw_1.ScrollNextPage() 滚动到下一页
dw_1.scrollpriorrow() 滚动到上一行
dw_1.scrollnextrow() 滚动到下一行
dw_1.getrow() 没有当前行时返回0,失败返回-1,成功返回当前行号 获得当前行的行号
dw_1.getcolumn() 没有当前列时返回0,失败返回-1,成功返回当前列的 列号 获取当前列的列号
dw_1.setrow(row) row 指定的行号
成功返回1,失败返回-1
设置当前行
dw_1.setcolumn(column) coumn 列号或列名
成功返回1,失败返回-1

例:设置当前列为第5列
dw_1.setcolumn(5)

例:设置当前列为age列
dw_1.setcolumn("age")
设置当前列
dw_1.setrowfocusindicator(f,x,y) f 用于指示当前行的可视化图标
x x坐标
y y坐标
成功返回1,失败返回-1

例:设置手形图标
dw_1.setrowfocusindicator(Hand!)

例2:设置图片控件p_arrow为指示图标
dw_1.setrowfocusindicator(p_arrow)
设置用于指示当前 行的可视化图标
dw_1.rowcount() 无数据时返回0,失败返回-1 获得数据窗口总行 数
dw_1.modifiedcount() 返回被修改但未更新的数据行数
无数据时返回0,失 败返回-1
获得数据窗口中被 修改,但未更新的 数据行数。(不包 括新插入的行)
dw_1.deletedcount() 无数据时返回0,失败返回-1 获得数据窗口中做 了删除标记,未做 update操作的数 据行数
dw_1.filteredcount() 无数据时返回0,失败返回-1 获得被过滤掉的数 据行数
dw_1.accepttext() 将还在编辑中的数 据,传送到数据窗 口控件
dw_1.gettext() 获得编辑控件中的 文本
dw_1.settext(text) 成功返回1,失败返回-1 设置编辑控件中的 文本
dw_1.GetItemDate (row,column,dwbuffer,originalvalue) row 指定数据行的行号
column: 指定的数据列
dwbuffer: 指定读取数据的缓冲区
originalvalue 为true时,返回原始缓冲区的值,为 false时返回当前值

例:取数据窗口dw_1第3行first_day字段的日期型变量 dw_1.getitemdate(3,"first_day")
获取指定字段的日 期型变量
dw_1.GetItemDateTime(row,column,dwbuffer,originalvalue) row: 指定数据行的行号
column: 指定的数据列
dwbuffer 指定读取数据的缓冲区
originalvalue 为true时,返回原始缓冲区的值,为 false时返回当前值
获取指定字段的日 期时间型变量
dw_1.GetItemTime(row,column,dwbuffer,originalvalue) row 指定数据行的行号
column: 指定的数据列
dwbuffer 指定读取数据的缓冲区
originalvalue 为true时,返回原始缓冲区的值,为 false时返回当前值
获取指定字段的时 间型变量
dw_1.GetItemString(row,column,dwbuffer,originalvalue) row 指定数据行的行号
column: 指定的数据列
dwbuffer 指定读取数据的缓冲区
originalvalue 为true时,返回原始缓冲区的值,为 false时返回当前值
获得指定字段的字 符串变量
dw_1.GetItemNumber(row,column,dwbuffer,originalvalue) row 指定数据行的行号
column: 指定的数据列
dwbuffer: 指定读取数据的缓冲区
originalvalue 为true时,返回原始缓冲区的值,为 false时返回当前值
获得指定字段的数 值型变量
dw_1.GetItemDecimal(row,column,dwbuffer,originalvalue) row 指定数据行的行号
column: 指定的数据列
dwbuffer 指定读取数据的缓冲区
originalvalue 为true时,返回原始缓冲区的值,为 false时返回当前值
获得指定字段的小 数型变量
dw_1.sharedata(dwsecondary) 成功返回1,失败返回-1 数据窗口控件数据 共享,保持同步更 新
dw_1.sharedataoff() 成功返回1,失败返回-1 关闭数据窗口之间 的共享关系
dw_1.print() 成 功返回1,失败返回-1 打印数据窗口
dw_1.printcancel() 成功返回1,失败返回-1 取消数据窗口的打 印
dw_1.getitemstatus (row,colum,dwbuffer) row: 指定数据的行号
column: 指定的数据列
dwbuffer: 指定读取数据的缓冲区,默认为主缓冲区, 返回一个dwitemstatus枚举变量

例:取数据窗口dw_1第5行work字段在filter缓冲区的 状态 l_status l_status = dw_1.getitemstatus(5,'work',filter!)
获取指定字段的状 态
dw_1.setitemstatus (row,colum,dwbuffer,status) row: 指定数据的行号
column: 指定的数据列
dwbuffer :指定读取数据的缓冲区,默认为主缓冲区, 返回一个dwitemstatus枚举变量 status 枚举变量

例:设置数据窗口dw_1第5行party字段在主缓冲区的 状态为notmodified
l_status l_status = dw_1.setitemstatus(5,'salary',primary!,notmodified!)
设置指定字段的状 态
dw_1.setitem(row,column,value) row: 指定的行
column :指定的列
value: 赋值的内容
为指定字段赋值
dw_1.getvalidate(column) column 定义检验规则的字段(序号或字段名)。返回 指定字段的有效性检验规则 获取当前某些字段 的有效性检验规则
dw_1.setvalidate(column,rule) column 定义检验规则的字段(序号或字段名) rule 新的有效性检验规则
成功返回1,失败返回-1
设置当前某些字段 的有效性检验规则

六、数据窗口使用技巧

6.1 数据窗口的增删改查

6.1.1 将编辑的数据放到主缓冲区
dw_1.accepttext()
6.1.2 增加一行数据
dw_1.insertrow(0)
6.1.3 删除一行数据
dw_1.deleterow(row)
6.1.4 更新数据
dw_1.update()
  • 在使用update() 函数将修改的数据保存到数据库中时,必须要设置数据窗口的修改属性。

  • 数据窗口只能修改一个数据表

  • 当增加、删除或者重新选择了字段时, PB将数据窗口的修改属性置为不允许,这时也应该进行手工设置

单项 Rows→Update Properties 进行修改属性的设置

修改属性设置

  • Allow Updates : 选中该选项,才允许继续进行其他属性的设定
  • Table to Update :要被更新的表
  • Where Clause for Update/Delete
选项 说明
Key Columns 单用户应用程序或者用户都以加锁方式访问数据库时可以选中该选项
只使用在“ Unique Key Column(s)”列表框中指定的惟一列进行数据更新
Key and Updateable Columns 默认的修改方式
用主键列和可以修改的列来创建 where 子句
Key and Modified<br/>Columns 上面两种方法的折中
用主键和数据发生了变化的列来产生 where 子句
  • Key Modification
选项 说明
Use Delete then Insert 先删除原有主键值,然后再使用新的主键值插入一个完整的行
Use Update 通过Update语句修改数据
  • Updatable Columns : 需要修改的列
  • Unique Key Column(s) : 唯一能够确定一行的列
6.1.5 查找数据
dw_1.settransobject(sqlca)
dw_1.retrieve()

6.2 数据窗口更新多个表

思路: 动态修改数据窗口的Update属性

举个栗子: dw_1数据窗口中包含两张表的字段,emp(员工信息表),dept(部门表)

select dept.deptno,dept.dname,
emp.empno,emp.ename
from emp,dept
where emp.deptno = dept.deptno

在创建数据窗口时设置为 dept 表可修改

Int li_update
li_update = dw_1.Update(True,False) //接受最后一个字段内容,并且不清除行修改标志
// 如果对 Department 表的修改成功,下一步就要修改另一个表 Employee
If li_update = 1 Then
    //首先,关掉对 dept 表的修改
    dw_1.ModIfy('dept_dname.Update = "No"')
    dw_1.ModIfy('dept_deptno.Update = "No"')
    dw_1.ModIfy('dept_deptno.Key = "No"')
    //使 emp 表成为新的可修改表
    dw_1.dwModIfy('DataWindow.Table.UpdateTable = ~'emp~' ')
    dw_1.ModIfy('emp_empno.Update = "Yes"')
    dw_1.ModIfy('emp_ename.Update = "Yes"')
    dw_1.ModIfy('emp_empno.Key = 'Yes' ' )
    //然后修改 Employee 表
    li_update = dw_1.Update()
    If li_update = 1 Then
    Commit Using SQLCA;
Else
    MessageBox("修改错误! ", "数据修改错误,错误代码"&
    + String(SQLCA.SqlDBCode) + "~r~n 错误原因: "+ SQLCA.SqlErrText)
    Rollback Using SQLCA;
    End If
    //恢复数据窗口开始时的属性,以便下一次用户单击“保存”按钮时
    //程序能够正确执行
    dw_1.ModIfy('dept_dname.Update = "Yes"')
    dw_1.ModIfy('dept_deptno.Update = "Yes"')
    dw_1.ModIfy('dept_deptno.Key = "Yes"')
    dw_1.ModIfy('DataWindow.Table.UpdateTable = ~'dept~' ')
    dw_1.ModIfy('emp_empno.Update = "No" ')
    dw_1.ModIfy('emp_ename.Update = "No" ')
    dw_1.ModIfy('emp_empno.Key = "No" ')
Else
    MessageBox('部门表更新失败,回滚更改为部门')
    Rollback Using SQLCA;
End If

6.3 设置字段只读

① 方法一

将tab order 设置为0

② 方法二

dw_1.modify("cname.tabsequence = 0 ")  

③ 方法三

dw_1.modify( "meno.edit.displayonly=yes")

④ 方法四

dw_1.modify("code_course.protect= 1")

6.4 切换数据窗口数据源

dw_1.dataobject = "数据窗口名"

6.5 隐藏数据窗口刷新过程

dw_1.setredraw(false) //不刷新
dw_1.setredraw(true) //刷新

6.6 数据窗口共享数据

dw_2.sharedata(dw_1)

6.7 数据窗口SQL中传递 in 的参数

select emp.empno,emp.ename,emp.job,emp.mgr,emp.hiredate,emp.sal,emp.comm  from emp where emp.empno in (传入的参数)
//在传给数据窗口时,in中的内容必须是数组类型
string[] arr_in
arr_in[1]='7369'
arr_in[2]='7499'
arr_in[3]='7521'
dw_1.retrieve(ls_in)

6.8 获取当前数据窗口的sql

dw_1.getsqlselect()

6.9 设置当前数据窗口的sql

dw_1.setsqlselect(sql)

6.10 调用子数据窗口

integer rtncode
datawindowchild dwc_child
rtncode = dw_1.getchild("主窗口字段", dwc_child)
if rtncode = 1 then
	messagebox('',dwc_child.getitemstring(1,'子窗口字段'))
else
	messagebox('提示','未获取到子数据窗口!')
end if

6.11 判断数据窗口是否被修改

//判断数据窗口是否修改,建议写在closequery事件中
if dw_1.modifiedcount() + dw_1.deletedcount() > 0 then
	messagebox('提示','数据窗口已经修改,是否保存?')
else
	messagebox('提示','数据窗口没有修改,正常退出')
end if

6.12 数据窗口重置

dw_1.reset()

6.13 数据窗口重新分组

//重新分组,在我们处理过滤和排序后,如果是分组窗口可能会破坏分组规则
//所以我们要进行重新分组,重新分组一般都是在filter()或sort()后面
dw_1.groupcalc()

6.14 获得数据窗口的状态

//(可选状态:datamodified! new! newmodified! notmodified!)
//当第一次使用retrieve()函数从数据库中读取数据时,所有在数据窗口缓冲区的记录与字段都是属于
NotModified!状态。
//当时数据被修改过后,被修改过的记录状态标志与字段状态标志都会被改成DataModified!
//当增加一笔数据时,增加数据的字段状态标志为NotModified!,记录状态标志为New!.
//当我们在增加的字段中填上数据后,字段状态标志为DataModified!记录状态标志为NewModified!
if dw_1.getitemStatus(1,dw_1.deletedcount(),primary!) = datamodified! then
	messagebox('1:已修改数据','datamodified!')
elseif dw_1.getitemStatus(1,dw_1.deletedcount(),primary!) = new! then
	messagebox('2:已增加数据','new!')
elseif dw_1.getitemStatus(1,dw_1.deletedcount(),primary!) = newmodified! then
	messagebox('3:已填写数据','newmodified!')
elseif dw_1.getitemStatus(1,dw_1.deletedcount(),primary!) = notmodified! then
	messagebox('4:未修改数据','notmodified!')
end if

6.15 设置数据窗口状态

//(可选状态:datamodified! new! newmodified! notmodified!)
dw_1.setitemstatus(1,dw_1.deletedcount(),primary!,notmodified!)

6.16 查找数据窗口中第一个被选中的行

dw_1.getselectedrow(0)

6.17 数据窗口查找(find)

//dw_1.find(查找条件表达式,开始行, 结束行), 如果表达式成立,那么就返回符合条件的行号
dw_1.find('id=8',1,10)

6.18 数据窗口过滤

① 列名过滤

dw_1.setfilter("isnull(列名)")
dw_1.filter()

②条件过滤

dw_1.setfilter("列名='" + 列值 + "'")
dw_1.filter()

③ 清除过滤

//方法一
dw_1.setfilter('')
dw_1.filter()
//方法二
dw_1.setfilter('1=1')

④ sql语句过滤

sql = 'select * from 表名 where isnull(字段名 , ''空'') = ''空'' ' ;

6.19 数据窗口分页

增加一个计算列
计算列必须放在detail段
expression中输入:ceiling(getrow()/20) 这里表示每页20条数据

这里20还可以用全局函数取代,这样可以允许用户任意设置每页多少行。

定义分组,选择菜单rows->create group...

按计算列字段分组,并一定将check box-->new page on group break选中

将此计算列设为不可视

然后添加以下按钮,完成分页功能

①首页

dw_1.scrolltorow(0)
dw_1.setrow(0)

② 上一页

dw_1.scrollpriorpage()

③ 下一页

dw_1.scrollnextpage()

④ 最后一页

dw_1.scrolltorow(dw_1.rowcount())
dw_1.setrow(dw_1.rowcount())

6.20 数据窗口排序

① 正序排列

dw_1.setsort("列名 a")
dw_1.sort()

② 倒序排列

dw_1.setsort("列名 d")
dw_1.sort()

③ 双击排序

string ls_old_sort, ls_column
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
		this.setsort(ls_column + " a")
	end if
	this.sort()
end if

6.21 数据窗口获取焦点

dw_1.setfocus()
dw_1.setrow("数据行号")
dw_1.setcolumn("字段名")

6.22 数据窗口行相关

① 行处理

dw_1.rowcount() //获取总行
dw_1.getrow() //获取当前行
dw_1.setrow(1) //设置当前行
dw_1.scrolltorow() //滚动到目标行
dw_1.selectrow(1, true) //将第一行变成选中状态
dw_1.isselected(1) //检查第一行是否被选择

② 点击高亮显示

Ⅰ 在数据窗口的click事件中,写入以下代码

if row > 0 then
    this.selectrow(0,false)
    this.selectrow(row,true)
end if

Ⅱ在数据窗口rowfocuschanged事件中,写入以下代码

if currentrow > 0 then
    selectRow(0, false)
    selectRow(currentrow, true)
    scrolltorow( currentrow )
end if

③ 隔行变色

Ⅰ 打开数据窗口
Ⅱ. 右键 detail
Ⅲ. 找到右侧 color 属性右侧的小图标
Ⅳ. 在表达式中输入以下代码

if ( mod( getrow() , 2) = 1 , rgb(255,255,255) , rgb(235,255,235) )

④ 自增行

Ⅰ. 添加计算列, page n of n
Ⅱ. 选择 getrow()

⑤ 设置每页打印行数

Ⅰ. 添加计算列 page n of n ,输入公式: ceiling(getrow()/20)
Ⅱ. 选择菜单 rows->create group ,创建分组,选择刚才创建的公式列page_1

Ⅲ. 创建完分组后,选择右侧属性, new page on group break 打上勾即可
Ⅳ. 如果需要最后一页不足补空行

long ll_pagerow = 6 //每页打印行数
long ll_count, ll_row
ll_count = dw_1.retrieve()
//取得现有报表的总行数
ll_count = ll_pagerow - mod(ll_count, ll_pagerow)
if ll_count < ll_pagerow then
    for ll_row = 1 to ll_count
        dw_print.insertrow(0) //补足空行
    next
end if

⑥ 移动行

//移动行
//(primary!主缓冲区 delete!删除缓冲区 filter!过滤缓冲区)
//dw_name.rowsmove(开始行,结束行,缓冲区,要移动到的另一窗口名,在哪一行前面插入,插入哪个缓冲区)
//rowsmove还可以在同一数据窗口的不同缓冲区进行移动行
//如:从删除缓冲区移动行到主缓冲区实现恢复功能:
dw_1.deleterow(1) //删除第1行
dw_1.rowsmove(1,dw_1.deletedcount(),delete!,dw_1,1,primary!) //恢复第1行

⑦ 复制行

//复制行(primary!主缓冲区 delete!删除缓冲区 filter!过滤缓冲区)
//dw_name.rowscopy(开始行,结束行,缓冲区,要复制到的另一窗口名,在哪一行前面插入,插入哪个缓冲区)
//rowscopy( )--基本用法和移动行差不多
dw_1.deleterow(1) //删除第1行
dw_1.rowscopy(1,dw_1.deletedcount(),delete!,dw_1,1,primary!) //复制第1行

6.23 列处理

① 获得数据窗口所有的列名

integer li_index
for li_index = 1 to integer(dw_1.object.datawindow.column.count)
	messagebox(string(li_index),dw_1.describe("#" + string(li_index) + ".name"))
next

② 获得字段对应的dbname

integer li_index
for li_index = 1 to integer(dw_1.object.datawindow.column.count)
	messagebox(string(li_index),dw_1.describe("#" + string(li_index) +".dbname"))
next

③ 复制列

dw_1.object.字段名.primary = dw_1.object.字段名.primary

④ 获取显示列

describe('DataWindow.Table.GridColumns')

6.24 数据窗口中实现复选框

① 在数据窗口的sql中,添加多选框字段

'0' as checkbox

② 设置字段的 edit 属性为 checkbox ,并勾选3d look

③ 设置(data value for on = 1),设置(data value for off = 0)

④ 再dw_1数据窗口的click事件中写

if dwo.name = "checkbox" then
	if dw_1.rowcount() = 0 then
	else
        if dw_1.object.checkbox[1] = "1" then
            for row = 1 to dw_1.rowcount()
                dw_1.object.checkbox[row] = "0"
            next
        else
            for row = 1 to dw_1.rowcount()
                dw_1.object.checkbox[row] = "1"
            next
		end if
	end if
end if

⑤ 判断是否选中

long i
if dw_1.rowcount() = 0 then return 0
for i = 1 to dw_1.rowcount()
    if dw_1.getitiemstring(i, "checkbox") = '1' then
        messagebox('提示信息',‘第’+string(i)+'行被选中')
    end if
next

6.25 数据窗口转datastore

datastore lds_data
lds_data = create datastore
//给实例化后的datastore变量关联数据窗口对象
lds_data.dataobject = 'd_data'
//给数据存储对象指定事务对象
lds_data.settransobject(sqlca)
    
//接下来就和操作普通数据窗口一样了
long ll_row
ll_row = lds_data.insertrow(0)
lds_data.object.name[ll_row] = '张三'

6.26 动态数据窗口

① 数据窗口赋值与取值

//1 赋值
dw.setitem(行, '列名称', 值)
dw.object.列名[行号] = 值
    
//2 取值
dw_1.object.字段名[行数] //直接取值
dw_1.object.字段名.text //文本框
dw_1.GetItemString(行数,列名) //字符串
dw_1.GetItemNumber(行数,列名) //数值
dw_1.GetItemDate(行数,列名) //日期
dw_1.GetItemDateTime(行数,列名) //日期时间
dw_1.GetItemDecimal(行数,列名) //小数

② 通过describe 获取数据窗口中的各种属性

dw_1.Describe("#1.name")  //获取字段名称  title
dw_1.Describe("title.ColType")  //获取字段类型  char(100)
dw_1.Describe("title.background.color") // 获取字段背景颜色 536870912
dw_1.Describe("title.background.mode") //获取字段背景模式 1
dw_1.Describe("title.edit.Autohscroll") //获取字段是否允许自动横向滚动 yes
dw_1.Describe("title.key")  //获取字段是否为主键 no
dw_1.Describe("title.protect") //获取字段中的数据保护 0
dw_1.Describe("title.SlideLeft") //获取字段的滑动属性(当左面空白时是否向左滑动)  no
dw_1.Describe("title.slideup") //获取字段的滑动属性(当上面出现空白时是否向上滑动) no
dw_1.Describe("title.tabsequence") // 获取字段的TabOrder值    15
dw_1.Describe("title.update")  //获取字段是否可以修改 yes
dw_1.Describe("title.validation") // 获取字段的校验规则
dw_1.Describe("title.expression") // 获取字段的表达式
dw_1.Describe("Evaluate('LookupDisplay(sex)',1)")  // 获取显示值的属性
    

③ 通过modify 修改数据窗口中的各种属性

dw_1.modify("title.background.mode='1'")  // 修改字段背景模式
dw_1.modify("title.background.color = '0'") //修改字段背景颜色
dw_1.modify("title.criteria.dialog = yessex.criteria.override_edit =yes")  //修改检索规则
dw_1.modify("title.edit.required = yes") //修改字段为必须输入
dw_1.modify("title.format = 'yyyy-mm-dd'")  // 修改字段显示格式为日期格式
dw_1.modify("title.key = yes") // 修改字段为主键
dw_1.modify("title.protect ='1~tif(isrownew(),0,1)'")  //修改字段的保护属性

④ 程序运行中动态创建数据窗口

方法Ⅰ

string str_dwsyntax,str_lag
//获得数据窗口1的语法
str_dwsyntax=dw_1.object.datawindow.syntax
//根据数据窗口1的语法动态生成数据窗口2的语法
dw_2.create(str_dwsyntax)
//对数据窗口2的内容作局部修改
str_lag="stu_id_t.font.height='-12' stu_id_t.font.face='楷体_GB2312'"
//字体变12号字体,由宋体改为楷体
dw_2.modify(str_lag)
dw_2.settransobject(sqlca)
dw_2.retrieve()

方法Ⅱ

在程序中使用系统函数LibraryExport()得到某个已经存在的数据窗口对象的源代码

方法Ⅲ

在PB开发环境的库管理画笔(Library Painter)中使用移出功能(右键→Export)将某个数据窗口对象的语法保存到文本文件中

方法Ⅳ

//连接默认事务sqlca
sqlca.dbms = "O84 Oracle8/8i (8.x.4+)"
SQLCA.LogPass = '数据库密码'
SQLCA.ServerName = ‘服务器IP’
SQLCA.LogId = '数据库用户名'
SQLCA.AutoCommit = False
SQLCA.DBParm = "PBCatalogOwner='hb_zh'"
sqlca.autocommit = false
sqlca.dbparm = ""
connect using sqlca;
string dw_sql,dw_style
string dw_syntax,dw_syntax_error,dw_create_error
//设置数据窗口sql
dw_sql = "select * from 表名"
//设置数据窗口风格
dw_style = "style(type=grid)"
//构造sql数据源
dw_syntax = sqlca.syntaxfromsql(dw_sql, dw_style, dw_syntax_error)
//判断sql数据源是否有错误
if len(dw_syntax_error) > 0 then
	messagebox("提示", "构造sql数据源错误: " + dw_syntax_error)
	return
end if
//通过sql数据源创建dw_1数据窗口
dw_1.create(dw_syntax,dw_create_error)
//判断dw_1数据窗口在创建中是否有错误
if len(dw_create_error) > 0 then
	messagebox("提示", "创建数据窗口错误: " + dw_create_error)
	return
end if
//检索数据
dw_1.settransobject(sqlca)
dw_1.retrieve()

以上用到的SyntaxFromSQL()函数和Create() 函数具体说明如下

动态数据窗口1

Create函数

6.27 数据窗口导入导出

① 数据窗口导入

//dw_1.importfile(导入的文件类型, 文件名, 文件的开始行 , 文件的结束行, 文件的开始列, 文件的结束列, 数据窗口的开始列 )
//因为导出的数据窗口都有标题,所以我们这边从第2行开始导入
dw_1.importfile(text!,'1.txt',2,10,1,10,1) //导入txt文件
dw_1.importfile(excel!,'1.xls',2,10,1,10,1) //导入xls文件
dw_1.importfile(excel!,'1.xlsx',2,10,1,10,1)//导入xlsl文件
dw_1.importfile(csv!,'1.csv',2,10,1,10,1)//导入csv文件

② 数据窗口导出

//dw_name.saveas(名字可含路径,另存为的类型,是否显示列标题)
dw_1.saveas("1.txt",text!,true) //另存为txt文件
dw_1.saveas("1.xls",excel!,true) //另存为xls文件
dw_1.saveas("1.xlsx",excel!,true) //另存为xlsl文件
dw_1.saveas("1.csv",csv!,true) //另存为csv文件

6.28 数据窗口快捷键

//1、新建事件
//事件名 keydown
//event ID pbm_dwnkey(选择这个就可以了,其他参数它会自己设置)

//2、在此事件中,写入以下代码
if key = KeyEnter! then Send(Handle(this),256,9,0)

6.29 设置datawindow的当前行指示图标

//在datawindow中建立一个计算列,expression为'',并将该计算列移动为datawindow的第一个列,在
//datawindow控件的rowfocuschanged事件中写入代码:
SetRowFocusIndicator(hand!) //小手指样式
setrowfucsindicator(p_1) //自定义图片样式

6.30 打印datawindow的内容到文件中

//数据窗口打印出pdf
dw_1.object.datawindow.print.filename ="c:/temp.pdf"
dw_1.print()

6.31 将Grid风格改成自由格式

在DW的editsource中将processing=1的1改为0

6.32 数据窗口自动调整大小

在数据窗所在窗口的Resize事件下编写代码

Resize(dw_datamon,this.Workspacewidth()-50,this.Workspaceheight()-50)

6.33 一个报表中要有一个计算域,是几个NUM型列相加,加的时候几个列中有一为空就加不出来

方法Ⅰ

设置此数据列的初使值为0.0。但必需在数据窗口对象中设,即选菜单Rows中的Column Specifications……选项,在Initial Value列中写上0.0即可

方法Ⅱ

计算列公式采用如下:

 // A + B + C
if(isnull(A), 0,A) + if(isnull(B), 0,B) + if(isnull(C), 0,C)  

6.34 动态生成的报表中怎么修改各个带区的宽度、位置?

// 改变detail区的高度:
dw_1.Modify("DataWindow.detail.Height=200")

6.35 动态生成的报表中增加文本(标题),或对标题栏的文本进行修改

//对标题栏文本的更改(文本名为dept_name_t)
dw_1.modify("dept_name_t.text = '单位名称'")

6.36 动态生成的报表中动态增加计算列

string ls_modrow
dw_1.Modify("DataWindow.summary.Height=64")
ls_modrow = 'Create compute(band=summary font.charset="0" font.face="MS Sans Serif" font.family="2" font.height="-8" font.pitch="2" font.weight="400" background.mode="1" background.color="536870912" color="0" x="9" y="4" height="52" width="297" format="[general]" expression="count(dept_id for all)" alignment="1" border="0" crosstab.repeat=no )~r~n'
dw_1.modify( ls_modrow )

6.37 动态修改grid数据窗口中网格线是否可见,并在detail区增加加一条线

dw_1.Modify("DataWindow.Grid.Lines='1' ")
dw_1.Modify("DataWindow.detail.Height=332")
ls_line = 'Create line(band=detail background.mode="2" background.color="16777215" pen.style="0" pen.width="5" pen.color="0" x1="37" y1="320" x2="1458" y2="316" )~r~n'
dw_1.modify( ls_line )

6.38数据窗口中添加一计算域,统计一下性别为男的记录数

//添加一个计算列
sum( if( stu_sex ='男', 1, 0 )) 

6.39 数据窗口中数据自动折行

在PowerBuilder应用程序的开发过程中, 使用DataWindow时, 经常会遇到某列的数据太长, 不能同时全部显示的情况. 若采用自动水平滚动, 操作起来又不够简便,那么我们将如何实现列数据多行显示, 即实现列数据的自动折行呢?

① 在DataWindow Painter中打开此DataWindow对象

②在需设定自动折行的列上双击鼠标, 弹开此列的属性窗口

③ 选择Position标签, 选中Autosize Height 多选框

④ 选择Edit标签, 不选中Auto Horz Scroll多选框

⑤ 单击OK按钮, 保存所做的修改

⑥ 点中Detail Band (即写有Detail的灰色长带), 单击鼠标右键, 选择Properties... 菜单项
⑦ 选中Autosize Height多选框
⑧ 单击OK按钮, 保存所做的修改
⑨ 保存此DataWindow

注意:连在一起的汉字(中间没有标点或空格分隔), 系统将认为是一个单词, 不会自动进行折行, 英文也是如此……DW窗口折行如果有汉字的话就必需中间加空格才会折行,否则怎样设置都不行。例如你如果想在第20位折行,就先判断第20位是否是个汉字,如不是就在第20位后加空格,如果是汉字就在第19位加空格。判断是否是汉字可以用它的ASCII码是否大于127来判断

6.40 连续页数打印多个数据窗

① 建立一个全局变量

 integer g_int_page=0

② 建立一个全局函数f_setpage()

 return g_int_page

③ 在数据窗口对象中加入一计算域gs_pagenum

 //利用全局涵数来传递全局变量
page() + f_setpage()

④ 在每一个数据窗口控件的printend事件中改变全局变量的值,以使计算域的值发生变化

g_int_page=dw_1.getitemnumber(dw_1.rowcount(),"gs_pagenum")

⑤ 当所有窗口打印完毕后将全局变量恢复

g_int_page=0

6.41 动态实现打印不固定的数据列

做一个程序,其中的一个功能是:

例如:数据库。雇员(序号,姓名,年龄,性别,出生年月,学历,职务,工资,等等)。

客户要求在程序的运行中进行选择(对表的项任意选),然后打印出来。

如选择姓名,年龄,出生。则打印姓名,年龄,出生。

又如选择姓名,工资。则打印姓名,工资。我不知道如何去实现

方法Ⅰ

建数据窗口对象时,选用Grid风格(Grid风格数据窗口的字段宽度可以随意拖动,如同Excel),不需要打印的字段可以随时将其宽度拖动为零

方法Ⅱ

用列表框显示出所有的列,可以多选高亮列。通过Modify函数动态定义选中列的位置,宽度以及是否可见等属性

posted @ 2023-07-10 09:06  程序员晓凡  阅读(946)  评论(4编辑  收藏  举报