我的社保显示多条信息怎么该成单条8g和双条4g哪个好信息

EBS常见问题
1&&&&&&&&&&&&
中各键盘触发子所对应的“按键”
封装过程    键触发子&&&&&&
含义          对应按键
ABORT_QUERY  
Key-EXIT&&&&&&
[退出/取消]
BLOCK_MENU   Key-MENU&&&&&&
[块菜单]        F5
CLEAR_BLOCK  
Key-CLRBLK&&&&&&&&&&&&&&&&&&
[清空块]        Shift+F5
CLEAR_FORM   Key-CLRFRM&&&&
[清空FORM]       Shift+F7
CLEAR_RECORD  Key-CLRREC&&&&
[清空记录]       Shift+F4
COMMIT_FORM  
Key-COMMIT&&&&
[提交/存盘]       F10
COUNT_QUERY  
Key-CQUERY&&&&
[计算查询记录总数]   Shift+F2
CREATE_RECORD 
Key-CREREC&&&&
[插入新记录]      F6
DELETE_RECORD 
Key-DELREC&&&&
[删除记录]       Shift+F6
DOWN      Key-DOWN&&&&&&
[下滚记录]       Ctrl+l、下箭头
DUPLICATE_ITEM Key-DUP-ITEM&&
[复制域/项]       F3
DUPLICATE_RECORDKey-DUPREC&&&&
[复制记录]       F4
EDIT_TEXTITEM 
Key-EDIT&&&&&&
[打开编辑器]      Ctrl+E
ENTER     
Key-ENTER&&&&&
ENTER_QUERY  
Key-ENTQRY&&&&
[输入查询条件]     F7
EXECUTE_QUERY 
Key-EXEQRY&&&&
[执行查询]       F8
EXIT_FORM   
Key-EXIT&&&&&&
[退出/取消查询]     Ctrl+Q
HELP      Key-HELP&&&&&&
[帮助]         F1
LIST_VALUES  
Key-LISTVAL&&&
[显示值列表LOV]     F9
LOCK_RECORD  
Key-UPDREC&&&&
[Lock Record]
NEXT_BLOCK   Key-NXTBLK&&&&
[下一块]        Ctrl+Page Down
NEXT_ITEM    Key-NEXT-ITEM& [下一域/项]      
Ctrl+Tab、Tab、Enter
NEXT_KEY    Key-NXTKEY&&&&
[定位到下一个主键项]  Shift+F3
NEXT_RECORD  
Key-NXTREC&&&&
[下一条记录]      Shift+Down
NEXT_SET    Key-NXTSET&&&&
[下一个记录集]     Ctrl+&
PREVIOUS_BLOCK Key-PRVBLK&&&&
[前一块]        Ctrl+Page Up
PREVIOUS_ITEM  Key-PREV-ITEM& [前一域/项]      
Shift+Tab、Shift+Ctrl+Tab
PREVIOUS_RECORD
Key-PRVREC&&&&
[前一条记录]      Shift+Up
PRINT     
Key-PRINT&&&&&
[打印当前屏幕]     Shift+F8
SCROLL_DOWN  
Key-SCRDOWN&&&
[下翻屏]        Page Down
SCROLL_UP   
Key-SCRUP&&&&&
[上翻屏]        Page Up
UP       Key-UP     [上滚记录]       Ctrl+p、上箭头
Esc       取消
Backspace    向后删除
Ctrl+U     清除域/项
Ctrl+F1     显示有效的功能键列表
Shift+F1    发生错误时,显示错误窗口
设置块属性
导航器风格:改变记录
1、&&&&&&&&&&&&
调入Form Builder,打开一个新的FORM
2、&&&&&&&&&&&&
在表格级新建一个ON_LOGON触发器
3、&&&&&&&&&&&&
在ON_LOGON里输入以下代码:
PASS1 VARCHAR2(80); --PASS1为密码参数
LOGON('USER1','USER1'||'@'||'TNS1');
SELECT PASS INTO PASS1 FROM T_PASSWORD WHERE
USERNAME='USER2';
LOGON('USER2',PASS1||'@'||'TNS1');
1.& 在控制面板中选取 ODBC 控制源
2.& 系统 DSN
3.& 添加(D)...
4.& 选定您需要的驱动程序来安装数据源(S):Microsoft Acress Driver
5.& 完成(F)
6.& Date Source
Name:aaa(aaa就是数据源名称,也就是在应用程序中所要使用的)
7.& 选择一个mdb数据库文件(select)
8.& 高级属性:设置用户名、口令
10.&&&&&&&&&&&&
打开一个FORM
11.&&&&&&&&&&&&
文件(F)—&连接(E)
12.&&&&&&&&&&&&
13.&&&&&&&&&&&&
在parameter list中加入parameter_form=No
Add_parameter(list_id,'PSRAMETER_FORM',TEXT_PARAMETER,'NO');
Add_parameter(list_id,'ORACLE_SHUTDOWN',TEXT_PARAMETER,'YES');
现象说明:
FORM中,在做一连串大的操作时,有时希望用message来显示提示信息,但屏幕却不刷新,
解决方法:
message('信息1');
(同步屏幕显示)
message('信息2');
PL/SQL 3.3以上的版本中,UTL_FILE包允许用户通过PL/SQL读写操作系统文件。如下:
&&&&&&&&&&
file_handle utl_file.file_
&&&&&&&&&&
file_handle:=utl_file.fopen('C:\','TEST.TXT','A');&&&&&
--TEST.TXT是文件名
&&&&&&&&&&
utl_file.put_line(file_handle,'写入的信息');
&&&&&&&&&&
utl_file.fclose(file_handle);
Developer/2000中,可以用Text_IO读写操作系统文件。如下:
&&&&&&&&&&
in_file&&&&&&&&&&&&&&&&&
Text_IO.File_T
&&&&&&&&&&
out_file&&&&&
Text_IO.File_T
&&&&&&&&&&
in_file:=Text_IO.Fopen('文件名', 'R');
&&&&&&&&&&
Text_IO.Get_Line(in_file,linebuf);
&&&&&&&&&&
Text_IO.Fclose(in_file);
&&&&&&&&&&
out_file:=Text_IO.Fopen('文件名', 'W');
&&&&&&&&&&
Text_IO.Put_Line(out_file,'写入信息');
&&&&&&&&&&
Text_IO.Fclose(out_file);
--常用TEXT_IO
& out_file&
text_io.file_&&&&&&&&&&&&&&&&&&
out_file:=text_io.fopen('prn','w');&&&&&&&&&
--打开文件prn
& text_io.new_line(out_file,'
');&&&&&&&
--新建一行
& text_io.put_line(out_file,'
')&&&&&&&&&
--写入一行
text_io.fclose(out_file);&&&&&&&&&&&&&&&
--关闭文件
---文本输入输出
&& TEXT_IO
&& TEXT_IO.PACKAGE
&& TEXT_IO.FCLOSE
&& TEXT_IO.FILE_TYPE
&& TEXT_IO.FOPEN
&& TEXT_IO.IS_OPEN
&& TEXT_IO.GET_LINE
&& TEXT_IO.NEW_LINE
&& TEXT_IO.PUT
&& TEXT_IO.PUTF
&& TEXT_IO.PUT_LINE
Out_file&&&&
Text_io.file_
L&&&&&&&&&&&
Varchar2(100);
L1&&&&&&&&&&
Varchar2(100);
L2&&&&&&&&&&
Varchar2(100);
&&& Out_file
:=text_io.fopen('c:\ll\login.txt','r');
text_io.is_open(Out_file) then
text_io.get_line(Out_file,L);
text_io.get_line(Out_file,L1);
text_io.get_line(Out_file,L2);
Developer/2000中FMX默认title为:Developer/2000 Forms Runtime for Windows
在Form级触发器中添加触发WHEN-NEW-FORM-INSTANCE
3、&& 在此触发器中写如下代码:
SET_WINDOW_PROPERTY(FORMS_MDI_WINDOW,TITLE,'您的提示');
1、&& 调入Form
Builder,打开一个新的FORM
2、&& 在表格级新建一个ON_ERROR触发器
3、&& 在ON_ERROR里输入以下代码:
    error_code=40100 then message('已在第一 条记录!');
 elsif error_code=40102 then
message('您已在最后一条记录,请先输入处理此记录,然后再输入下一条记录!');
 elsif error_code=40200 then message('此项仅用于查询参考,您无法更改此项!');
 elsif error_code=40202 then message('此项必须输入!
产生错误原因:您未输入值,或您删去了原有值!');
 elsif error_code=40203 then message('值必须输入完全!
产生错误原因:该项有定长要求!');
 elsif error_code=40207 then
message('您输入的值不在有效范围之内,请输入有效范围之内的值!');
 elsif error_code=40401 then
message('您没有修改或输入任何新的记录,无须保存!');
 elsif error_code=40508 then
message('编码不能相同,不能有相同编码的记录,编码必须唯一!');
 elsif error_code=40509 then
message('严重操作错误!,您可能输入了一个空的记录,无法保存记录!');
 elsif error_code=41802 then
message('您只能在输入新的记录时使用[复制记录]键,来复制上一条记录!');
message(error_type||'_'||to_char(error_code)||':'||error_text);
raise form_trigger_
1、打开Form Builder
2、文件(F)→新建(N)→表格(F)
3、新建一个非数据块,取名为tool
4、鼠标右键→布局编辑器(E)
5、建一个列表项,名为xl(属于tool块)
6、新建一过程,内写如下的代码
PROCEDURE create_xl IS                    --动态显示学历过程
    CURSOR A IS SELECT DISTINCT(xl) FROM
t_      --建立a游标,从学历档案表取原始数据(有可能动态变化)
    CNT&&&
NUMBER;                    --记录总数变量,用于生成列表的总项数
    i&&&&&
NUMBER;                    --循环变量
    TNAME&
t_xl.name%TYPE;                --TNAME变量和t_xl表中name项具有相同的结构
    CLEAR_LIST('tool.xl');                --清空列表tool.xl(tool块上的xl项)
    SELECT COUNT(DISTINCT(name)) INTO CNT FROM
t_   --计算列表总数
    OPEN A;                        --打开游标
    FOR i IN 1..CNT LOOP                 --开始循环
        FETCH A INTO TNAME;              --取数
        EXIT WHEN A%NOTFOUND;             --退出条件
        ADD_LIST_ELEMENT('tool.xl',i,TNAME,TNAME);  --把查询出的值加入列表中(序号,实际值,显示值)
    END LOOP;                       --结束循环
    CLOSE A;                       --关闭游标
7、在Form级触发器中添加触发WHEN-NEW-FORM-INSTANCE
&& 在此触发器中写如下代码:create_
使FORM程序一启动,就调用此过程,达到动态生成下拉列表List的效果。
--学历档案表
create table t_xl(name varchar2(6));
insert into& t_xl values('小学');
insert into& t_xl values('初中');
insert into& t_xl values('职高');
insert into& t_xl values('技校');
insert into& t_xl values('高中');
insert into& t_xl values('中专');
insert into& t_xl values('大专');
insert into& t_xl values('本科');
insert into& t_xl values('研究生');
1、&& 打开Form Builder
2、&& 文件(F)→新建(N)→表格(F)
3、&& 鼠标右键→布局编辑器(E)
4、&& 文件(F)→导入(I)→图象(I)
5、&& 可调入作好的图像,以制作封面。
所支持的图像格式有:TIF、JPG、BMP、TGA、PCX、PCT、GIF、CAL、RAS、OIF、PCD等
set_item_property('按钮名称',ENABLED,PROPERTY_FALSE);
在Form级触发器中添加触发WHEN-NEW-FORM-INSTANCE
SET_APPLICATION_PROPERTY(CURSOR_STYLE,'CROSSHAIR'|'BUSY'|'HELP'|'DEFAULT'|'INSERTION');
在Form级触发器中添加触发WHEN-NEW-FORM-INSTANCE
在此触发器中写如下代码:
SET_WINDOW_PROPERTY(FORMS_MDI_WINDOW,WINDOW_STATE,MAXIMIZE);--最大化
SET_WINDOW_PROPERTY(FORMS_MDI_WINDOW,WINDOW_STATE,MINIMIZE);--最小化
在Form级触发器中添加触发WHEN-NEW-FORM-INSTANCE
SET_WINDOW_PROPERTY(FORMS_MDI_WINDOW, title,'你要写的标题');
或用以下方法
2. 对象导航器→窗口→WINDOW0(窗口的名字)→属性→标题→修改其属性
BEGIN&&&&&&&&
《PL/SQL块》;
&& Exception
&&&&&&&&&&&
when no_data_found
--没有找到数据
&&&&&&&&&&&&&&&&&&&&
《响应命令》;
&&&&&&&&&&&
when too_many_rows then&&
--返回多行,隐式光标每次只能检索一行数据
&&&&&&&&&&&&&&&&&&&&
《响应命令》;
&&&&&&&&&&&
when invalid_number
--字符向数字转换失败
&&&&&&&&&&&&&&&&&&&&
《响应命令》;
&&&&&&&&&&&
when zero_divide
then&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&
《响应命令》;
&&&&&&&&&&&
when dup_val_on_index
then&&&&&&&&
--向唯一索引中插入重复数据
&&&&&&&&&&&&&&&&&&&&
《响应命令》;
&&&&&&&&&&&
when invalid_cursor
--非法游标操作
&&&&&&&&&&&&&&&&&&&&
《响应命令》;
&&&&&&&&&&&
when value_error
then&&&&&&&&&&
--数字的,数据转换,截字符串或强制性的错误
&&&&&&&&&&&&&&&&&&&&
《响应命令》;
&&&&&&&&&&&
when others
then&&&&&&&&&&&&&&&&&&
--发生其它任何错误
&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&
--选择一:什么也不做,就当错误没发生
&&&&&&&&&&&
form_trigger_&&&&&
--选择二:挂起当前程序
对象导航器→窗口→WINDOW0(窗口的名字)→属性→模式→修改其属性
  设置窗口属性:模式=是
1. 在Form级触发器中添加触发KEY-OTHERS
2. 在此触发器中写如下代码:
3. 这样FORM程序运行后,大部分的功能键都被屏蔽(包括一些必需键,如:上箭头、下箭头、退出...),
&& 要想让这些键再恢复功能,就为这些键各自编程:
按键       触发器       代码        说明
上箭头       KEY-DOWN       DOWN;        上滚记录
下箭头       KEY-UP        UP;         下滚记录
&& Page Up       KEY-SCRUP      
SCROLL_UP;     上翻屏
&& Page Down     
KEY-SCRDOWN      SCROLL_DOWN;    下翻屏
F1         KEY-HELP       HELP;        显示帮助
F3         KEY-DUP-ITEM     DUPLICATE_ITEM;   复制项
F4         KEY-DUPREC      DUPLICATE_RECORD;  复制记录
F5         KEY-MENU       BLOCK_MENU;     块导航菜单
F6         KEY-CREREC      CREATE_RECORD;   插入记录
F7         KEY-ENTQRY      ENTER_QUERY;    输入查询条件&&&
F8         KEY-EXEQRY      EXECUTE_QUERY;   运行查询
&& F9         KEY-LISTVAL     
LIST_VALUES;    显示LOV
&& F10        
KEY-COMMIT      COMMIT;       存盘
Enter、Tab     KEY-NEXT-ITEM     NEXT_ITEM;     下一项
&& SHIFT+TAB     
KEY-PREV-ITEM     PREVIOUS_ITEM;   前一项
Ctrl+Q       KEY-EXIT       EXIT_FORM;     退出/取消查询
1、退出FORM
2、取消查询
&& if :System.Mode =
'ENTER-QUERY' then
1、SQL*Plus中
&& SQL& create table
t_photo1(photo1 long raw);
&& SQL& create table
t_photo2(photo2 long raw);
2、硬盘上c:\下有一个图象文件tmp.bmp
&& 3、打开FORM
&& 新建两个块:t_photo1、t_photo2
t_photo1块是数据库块,连接的表是数据库中的一个表t_photo1
t_photo2块也是数据库块,连接的表是数据库中的另一个表t_photo2(备份表)
t_photo1块上新建一个图象项,名为photo1,对应的是即表t_photo1中的photo1列
t_photo2块上也新建一个图象项,名为photo2,对应的是即表t_photo2中的photo2列
新建一按钮1,输入以下程序,这个按钮实现读入图象到表里,即录入图象到表里
&&&&&&&&&&&
GO_BLOCK('t_photo1');--到块1
&&&&&&&&&&&
READ_IMAGE_FILE('c:\tmp.bmp','bmp','t_photo1.photo1');
&&&&&&&&&&&
--读入外部图象文件tmp.bmp(图象类型为BMP)到t_photo1块的photo1项,也就是到了t_photo1表里
&&&&&&&&&&&
COMMIT;--存盘
新建一按钮2,输入以下程序,这个按钮实现图象的倒表(t_photo1到t_photo2)
&&&&&&&&&&&
GO_BLOCK('t_photo1');--到块1
&&&&&&&&&&&
&&&&&&&&&&&
--查询出表中的图象,这时,表中的图象到了FORM中的图象项上
&&&&&&&&&&&
WRITE_IMAGE_FILE('c:\tmp.bmp','bmp','t_photo1.photo1');
&&&&&&&&&&&
--把图象项中图象写入外部图象文件tmp.bmp
&&&&&&&&&&&
GO_BLOCK('t_photo2');--到块2
&&&&&&&&&&&
READ_IMAGE_FILE('c:\tmp.bmp','bmp','t_photo2.photo2');
&&&&&&&&&&&
--把外部图象文件tmp.bmp读入到t_photo2块的photo2项,也就是到了t_photo2表里
&&&&&&&&&&&
COMMIT;--存盘
&& 运行此程序,点击此按钮观察效果。
注释:t_photo1.photo1是正式图片表中的图象项(数据库项)(t_photo1块photo项1)
t_photo2.photo2是备份图片表中的图象项(数据库项)(t_photo2块photo项2)
1、&&&&&&&&&&
硬盘上c:\下有一个声音文件tmp.wav
2、&&&&&&&&&&
&& 新建一个块:t_sound
t_sound块上新建一个声音项,名为sound1
&& 新建一按钮1,输入以下程序
&&&&&&&&&&&
GO_ITEM('sound1');
&&&&&&&&&&&
READ_SOUND_FILE('c:\tmp.wav','wave','sound1');
&&&&&&&&&&&
PLAY_SOUND('sound1');
&& 运行此程序,点击此按钮观察效果。
1. 在Form级触发器中添加触发WHEN-TAB-PAGE-CHANGED
&& 2. 在此触发器中写如下代码:
&& DECLARE
&&&&&&&&&&&
canvas_id&&
VARCHAR2(30);&&&&&&&&&&&&&&&&&&&&&&&
--标签页ID
&&&&&&&&&&&
canvas_id := GET_CANVAS_PROPERTY('标签画布名', topmost_tab_page);
&&&&&&&&&&&
IF canvas_id='标签页1'& then go_block('块1');end
&&&&&&&&&&&
IF canvas_id='标签页2'& then go_block('块2');end
&&&&&&&&&&&
IF canvas_id='标签页3'& then go_block('块3');end
&&&&&&&&&&&
CTRL+T&& 编译文件
CTRL+R&& 运行FORM
布局编辑器
属性选项板
中,如何设置水平滚动条?
中,触发子POST-CHANGE的作用
中,触发子WHEN-VALIDATE-ITEM的作用
中,触发子POST-QUERY的作用
在 早 期FOXPRO 数 据 库 编 程 中, 经 常 用 到 宏 代 换 功 能, 但 在FORMS 中 却 没 有 此 功
能, 象"&","*" 等 在 编 程 中 经 常 用 到 的, 在FORMS 中 只 得 一 行 一 行 代 码 的 写,
但 后 来 发 现FORMS 中 也 有 类 似 功 能, 用NAME_IN()、COPY() 可 以 实 现 类 似 的 功
能。Name_in() 用 于 取 出 参 数 名 代 表 的 对 象 了 数 值, 而COPY() 把 一 个 参 数 值 传 递
给 另 一 参 数 值 表 示 的 对 象。 的 如 下 例:
FORM 结 构:
& 项 L1,L2,L3,L4,L5,L6
&& 在 作 录 入 程 序 时 要 对L1。。。L6 项
strItemName& varchar2(20);
&& for I in 1 …6 loop
& strItemName:=':b.l"||to_char(i);
& copy(null,strItemNmae);
---- 对 于NAME_IN 的 应 用 可 能 更 多 一 些, 笔 者 在 做 社 保 软 件 时, 作 保 险 缴 费
录 入 时 曾 用 它 少 写 了 许 多 代 码。 当 然 代 码 的 减 少 就 义 意 味 维 护 工 作 量 的 减
FORM结构:
& 块:YLYJ(养老应缴)
& 项:DWJTC(单位缴统筹),DWJZH(单位缴帐户),GRJF(个人缴费)
& 块:YLSJ (养老实缴)
& 项:DWJTC(单位缴统筹),DWJZH(单位缴帐户),GRJF(个人缴费)
& 块:GSYJ(工伤应缴)
& 项:DWJTC(单位缴统筹),DWJZH(单位缴帐户),GRJF(个人缴费)
& 块:GSSJ (工伤实缴)
& 项:DWJTC(单位缴统筹),DWJZH(单位缴帐户),GRJF(个人缴费)
& 块:YILYJ(医疗应缴)
& 项:DWJTC(单位缴统筹),DWJZH(单位缴帐户),GRJF(个人缴费)
& 块:YILSJ (医疗实缴)
& 项:DWJTC(单位缴统筹),DWJZH(单位缴帐户),GRJF(个人缴费)
---- 三 个 块 的 结 构 相 同, 只 是 块 名 称 不 同, 缴 费 时 时 行 的 操 作 也 一 样, 实 缴
名 项 不 能 大 于 应 缴, 不 用NAME_IN 时, 只 能 写 三 段 程 序, 但 用 了NAME_IN 后 只 用 一
段 写 一 个 函 数 就 能 达 到 目 的。 如 下:
& FUNCTION FUN_JF (PRE_BLOCK_NAME
& IN VARCHAR) RETURN BOOLEAN IS
if name_in(pre_block_name||'sj.dwjtc')
&&name_in(pre_block_name||'yj.dwjtc')&
& name_in(pre_block_name||'sj.dwjzh')
& &name_in(pre_block_name||'yj.dwjzh')
name_in(pre_block_name||'sj.grjf')
&name_in(pre_block_name||'yj.grjf')& then
message(' 实 缴 大 于 应 缴');
---- 从 上 面 的 两 个 例 子 来 看NAME_IN 和COPY 的 应 用 能 起 到 其 它 编 程 语 言 的"
宏" 代 换 功 能, 代 码 的 优 化 方 面 确 实 能 起 不 少 的 作 用, 减 少 了 程 序 源 代 码 的 维 护
Oracle产品Developer
2000中包括多种开发工具,其中在具体工作时用得最多的是Forms和Reports。Forms是一个设计表单的工具,利用它可以灵活方便地定义各种表单对象,以简化用户在运行期对相关数据库的操作(查询、插入、删除和更新等);Reports则是一个设计报表的工具,利用它可以按照用户的要求方便地生成报表。
在Oracle应用系统中,大量的具有交互性的功能是由Forms实现的。利用Forms所生成的表单模块可以彼此调用,实现业务流程的控制并完成与数据库有关的复杂操作;而由Reports所设计的报表模块往往当做最底层的功能被表单模块所调用。对于一些Oracle用户来说,独立地用好Forms或Reports是没有问题的,但他们却很少考虑如何使二者有机地结合起来,利用Forms对数据操纵的灵活性,由Forms模块向Reports模块传送大量结构化或非结构化的实时数据,减少(或避免)Reports对数据库的访问,从而高速地生成报表并保证报表数据与表单数据的一致性。本文通过实例介绍一种利用Forms的封装例程RUN_PRODUCT(
)在Forms模块中集成Reports模块的方法,利用该方法可以把Forms和Reports有机地结合起来,减少不必要的操作,提高工作效率。
RUN_PRODUCT例程
在Forms模块中调用Reports模块,最有效的方法是利用Forms的封装例程RUN_PRODUCT()。目前,很多程序开发人员在Forms模块中调用Reports模块时,或者没有采用这一例程,或者虽然采用这一例程但并没有充分利用参数表来传递表单中现成的数据,或者只是利用参数表来传递少量的文本参数(非结构化数据)作为Reports中的查询条件,报表的数据仍然要从数据库中查询得到,这样既增加了数据库服务器的负载,又增加了网络的流量,而且报表生成的速度慢,丧失了数据的实时性与一致性。因此,深入了解并熟练掌握参数表的使用方法便显得非常重要。
在使用RUN_PRODUCT( )之前要先建立参数表,并向参数表中添加参数。RUN_PRODUCT( )的使用格式如下:
RUN_PROCDUT(REPORTS, ‘report_name', SYNCHRONOUS, RUNTIME,
FILESYSTEM, pl_id, NULL);
其中各参数含义如下:
●REPORTS:说明被调模块是报表模块;
●report_name:被调模块的完整路径名;
●SYNCHRONOUS:
说明被调模块以同步的通信方式运行(被调模块退出之后主调模块才能继续执行,否则为ASYNCHRONOUS,即异步方式);
●RUNTIME:说明被调模块的执行方式为前台方式(否则为BATCH,即后台方式);
●FILESYSTEM:说明被调模块的存储位置是文件系统(否则为DATABASE,即数据库系统);
●pl_id:用户定义的参数表标识符。
使用参数表的要领
由Forms模块向Reports模块传递的数据可分为两类:一类是非结构化数据,即报表表头(表尾)的数据;另一类是结构化数据,即报表表目的二维数据。在如图1所示的报表中,学年、学期、班级编号、班级名称、专业名称、课程编号、课程名称、学分、班级人数等,属于表头数据;而学号、姓名、性别、修读性质、平时成绩、考试成绩、总评成绩、任课教师等属于表目数据。
图1 Reports模块执行情况
参数表中的参数有两种,文本参数(TEXT_PARAMETER)和数据参数(DATA_PARAMETER)。文本参数是对字符型数据的引用,数据参数是对记录组的引用。对于非结构化数据,可借文本参数将数据加入参数表(注意:文本参数只接受字符型数据,对于其他类型的数据要通过TO_CHAR(
)函数先转化为字符型数据);而对于结构化数据,则先要将数据存入记录组(RECORD_GROUP),然后借数据参数才能将数据加入到参数表中。注意:Forms模块的记录组中的各列和Reports模块中的查询(QUERY)对象的各列在名称、类型和顺序上要完全一致。这里文本参数是字符串指针,数据参数是记录组(结构数组)的指针,而参数表则是存储上述指针的指针数组。
如果RUN_PRODUCT( )的参数表中未加入与Reports模块中的查询对象同名的数据参数,则Reports
从数据库中查找与其模块中的查询对象相匹配的数据;如果RUN_PRODUCT( )
的参数表中加入了与Reports模块中的查询对象同名的数据参数,则Reports
并不从数据库中查找数据,而是以参数表中的同名数据参数所引用的记录组作为其模块中的查询对象的数据源,在这种情况下,Reports查询对象的SELECT语句所映射的数据集合是不起作用的。
实现集成的具体方法
本文例子中用Forms模块来对学生的期末成绩进行管理,Forms模块运行如图2所示。
●标以单位、班级、课程、成绩的各个块对象间存在级联的主从关系;
●各个块对象中,有的项因不需要使用人员予以关注,故将其定义为非显示项,未在画布(canvas)上显示,但这并不影响对它们的引用,例如,班级块中的班级编号(BJBH),课程块中的课程编号(KCBH)等;
●标以课程的块对象是基于视图(view)而非基于表(table)的;
●画布上显示的项并非都是基表项(块对象所基于的表或视图中的列),而是通过触发子从其他的表或视图中查询的,这也不影响对它们的引用,例如,课程块中的名称(MC)和学分(XF)等。
图2 Forms模块运行情况
程序实现的步骤如下:
在Sql*plus下创建一个与图1所示的表目一致的表(或视图)REPT_001当做Reports模块的查询对象Q_001的虚拟数据源:
CREATE TABLE REPT_001( /* 期末成绩表 */
XH VARCHAR2(9), /* 学号 */
XM VARCHAR2(10), /* 姓名 */
XB VARCHAR2(2), /* 性别 */
XDXZ VARCHAR2(4), /* 修读性质 */
PSCJ NUMBER, /* 平时成绩 */
KSCJ NUMBER, /* 考试成绩 */
ZPCJ NUMBER, /* 总评成绩 */
RKJS VARCHAR2(10) /* 任课教师 */);
注意:该表仅供Reports定义查询对象Q_001之用(仅援引其列名与类型),与整个应用系统的数据库结构无关,不需要向该表插入任何数据(保持该表为空表),不存在数据的完整性和一致性的问题。
在Reports中定义报表模块,源模块的名称为REP_001.rdf。在该模块中,定义与表目数据相关的查询对象Q_001:
SELECT XH,XM,XB,XDXZ,PSCJ,KSCJ,ZPCJ,RKJS FROM REPT_001;
再定义与表头数据相关的用户参数:
P_XN1 /* 学年学期 */
P_BJBH /* 班级编号 */
P_BJMC /* 班级名称 */
P_ZYMC /* 专业名称 */
P_KCBH /* 课程编号 */
P_KCMC /* 课程名称 */
P_XF /* 学分 */
P_BJRS /* 班级人数 */
在Reports的布局编辑器中调整美化报表的输出格式,最后生成目标模块REP_001.rep。
在Forms模块中定义&报表&按钮以实现对Reports模块REP_001.rep的调用。
为&报表&按钮定义WHENBUTTONPRESSED触发子:
PL_ID PARAMLIST;
RG_ID RECORDGROUP;
GC_XH GROUPCOLUMN;
GC_XM GROUPCOLUMN;
/* 定义用来捆绑表目数据的记录组G_001*/
RG_ID:=FIND_GROUP(‘G_001’);
IF ID_NULL(RG_ID) THEN
RG_ID:=CREATE_GROUP(‘G_001’);
/* 定义记录组内各列,注意各列的列名、类型、顺序均要和Reports模块所定义的查询对象Q_001中的各列相一致 */
GC_XH:=ADD_GROUP_COLUMN(RG_ID,‘XH’,CHAR_COLUMN);
GC_XM:=ADD_GROUP_COLUMN(RG_ID,‘XM’,CHAR_COLUMN);
DELETE_GROUP_ROW(RG_ID,ALL_ROWS);
GC_XH:=FIND_COLUMN(RG_ID,‘XH’,
CHAR_COLUMN);
GC_XM:=FIND_COLUMN(RG_ID,‘XM’,
CHAR_COLUMN);
/* 把Forms模块中的数据传送到记录组中 */
GO_BLOCK(‘CJZB’);
FIRST_RECORD;
ROW_NUM:=1;
ADD_GROUP_ROW(RG_ID,END_OF_GROUP);
SET_GROUP_CHAR_CELL(GC_XH,ROW_NUM,:CJZB.XH);
SET_GROUP_CHAR_CELL(GC_XM,ROW_NUM,:CJZB.XM);
EXIT WHEN :SYSTEM.LAST_RECORD=‘TRUE’;
LOW_NUM:=LOW_NUM+1;
NEXT_RECORD;
/* 建立参数表 */
PL_ID:=GET_PARAMETER_LIST(‘CJ_LIST’);
IF NOT ID_NULL(PL_ID) THEN
DESTROY_PARAMETER_LIST(‘CJ_LIST’);
PL_ID:=CREATE_PARAMETER_LIST(‘CJ_LIST’);
通过向参数表中加入文本参数的方式传送表头数据。其中,第1个参数是参数表标识符,第2个参数是键(参数名),应与Reports模块中定义的用户参数同名,第3个参数指定参数的种类是文本参数,第4个参数引用Forms模块的数据项
ADD_PARAMETER(PL_ID, ‘P_XN1’,
TEXT_PARAMETER,:START.XN1);
ADD_PARAMETER(PL_ID, ‘P_XN2’,
TEXT_PARAMETER,:START.XN2);
向参数表传送表目数据。其中,第1个参数是参数表标识符,第2个参数是键(参数名),应与Reports模块中定义的查询对象同名,第3个参数指定参数的种类是数据参数,第4个参数引用Forms模块的记录组
ADD_PARAMETER(PL_ID, ‘Q_001’,
DATA_PARAMETER,‘G_001’);
/* 调用报表模块REP_001 */
RUN_PRODUCT(REPORTS,‘C:\Apps\REP_001’,SYNCHRONOUS,RUNTIME,FILESYSTEM,PL_ID);
通过上述方法,借助参数表实现Forms模块对Reports模块的集成,既能快速生成报表(包括实时的业务单据的套打),又提高了系统的效率。如果巧妙地将报表标题、栏目标题、表头数据、格式线段、表目数据等均通过参数传送,并借助Reports的格式触发子和SWR包的模块(过程、函数和例外处理),还可以生成各种复杂的动态报表,免除了使用第三方工具带来的麻烦和副作用(如增加新的连接等)。
在实际的工作中,经常遇到用户要将EXCEL文件中的数据倒入到ORACLE数据库中,也经常遇到用户要将ORCLE数据库中的数据倒入到EXCEL文件中,这方面的资料并不多见(PB6的这项功能很简单,只需在DATAWINDOW控件中加入dw_1.save()这一函数就可以了),通常的做法是利用DEVELOPER
2000自带的示例进行修改来完成任务,但效果也不好,尤其是对初学者,面对示例中的OLE示例可能如入雾里,我在实际工作中利用DDE将数据倒入到EXCEL文件中,效果也不错,在这里向大家作一介绍.
所谓DDE,就是动态数据交换,相信各位并不陌生.运用DDE倒数据的先提条件是先在本机安装微软office中的EXCEL,在C:盘上建立一空的EXCEL文件如EXCEL.xls,打开该文件,然后运行自己开发的FORM文件.
下面我就我工作中遇到的实际工作遵照原意逐步进行介绍:
先用form4.5(5.0当然更可以)建立一个新FORM,在canvas上的新blok中建一个button,然后在该button中的WHEN-BUTTON-PRESSED触发子中,输入以下代码:
varchar2(8);
varchar2(8);
varchar2(8);
varchar2(8);
varchar2(8);
varchar2(8);
varchar2(8);
varchar2(8);
varchar2(8);
varchar2(8);
&&&&&&&&&&&&&
VARCHAR2(8);
ConvID&& PLS_INTEGER;
CURSOR C1 IS SELECT
A.SHIPMENT_NO,A.ARRIVAL_DATE,
B.DELIVERY_REF_1,B.DELIVERY_REF_3,
B.DELIVERY_REF_2,C.CASE_NO,C.LRCM_CODE,
C.ANN_QUANTITY,C.QUANTITY_DESCRIPTION,
C.SPARE_PART,C.TRANSFER_NUMBER,
C.TRANSFER_DATE& FROM
ACM A,ACMCONTRACT B,ACMDELIVERY_PL D,
ACMCASE_PL C
A.SHIPMENT_NO=B.SHIPMENT_NO AND
A.CONTRACT_NO=B.CONTRACT_NO AND
B.DELIVERY_REF_1=D.DELIVERY_REF_1 AND
B.DELIVERY_REF_2=D.DELIVERY_REF_2 AND
B.DELIVERY_REF_3=D.DELIVERY_REF_3 AND
D.DELIVERY_REF_1=C.DELIVERY_REF_1 AND
D.DELIVERY_REF_2=C.DELIVERY_REF_2 AND
D.DELIVERY_REF_3=C.DELIVERY_REF_3 AND
D.CASE_NO=C.CASE_NO AND C.SPARE_PART='SO' AND
C.TRANSFER_NUMBER IS NOT NULL
AND C.TRANSFER_DATE IS NOT NULL;
SHIPMENT_NO_TMP&&&&&&&&&&
ACM.SHIPMENT_NO%TYPE;
ARRIVAL_DATE_TMP&&&&&&&
&&ACM.ARRIVAL_DATE%TYPE;
DELIVERY_REF_1_TMP&&&&&&&
ACMCONTRACT.DELIVERY_REF_1%TYPE;
DELIVERY_REF_3_TMP&&&&&&&
ACMCONTRACT.DELIVERY_REF_3%TYPE;
DELIVERY_REF_2_TMP&&&&&&&
ACMCONTRACT.DELIVERY_REF_2%TYPE;
CASE_NO_TMP&&&&&&&&&&&&&&
ACMCASE_PL.CASE_NO%TYPE;
LRCM_CODE_TMP&&&&&&&&&&&&
ACMCASE_PL.LRCM_CODE%TYPE;
ANN_QUANTITY_TMP&&&&&&&&&
ACMCASE_PL.ANN_QUANTITY%TYPE;
QUANTITY_DESCRIPTION_TMP&
ACMCASE_PL.QUANTITY
&&&&&&&&&&&&&&&&&&&&&&&&&
_DESCRIPTION%TYPE;
SPARE_PART_TMP&&&&&&&&&&&
ACMCASE_PL.SPARE_PART%TYPE;
TRANSFER_NUMBER_TMP&&&&&&
ACMCASE_PL.TRANSFER
&&&&&&&&&&&&&&&&&&&&&&&&&
_NUMBER%TYPE;
TRANSFER_DATE_TMP&&&&&&&&
ACMCASE_PL.TRANSFER
&&&&&&&&&&&&&&&&&&&&&&&&&
_DATE%TYPE;
NCOUNT&&&&&&&&&&&&&&&&&&&
SELECT COUNT(*) INTO NCOUNT
FROM&& ACM A,ACMCONTRACT
B,ACMDELIVERY_PL D,
ACMCASE_PL C
A.SHIPMENT_NO=B.SHIPMENT_NO AND
A.CONTRACT_NO=B.CONTRACT_NO AND
B.DELIVERY_REF_1=D.DELIVERY_REF_1 AND
B.DELIVERY_REF_2=D.DELIVERY_REF_2 AND
B.DELIVERY_REF_3=D.DELIVERY_REF_3 AND
D.DELIVERY_REF_1=C.DELIVERY_REF_1 AND
D.DELIVERY_REF_2=C.DELIVERY_REF_2 AND
D.DELIVERY_REF_3=C.DELIVERY_REF_3 AND
D.CASE_NO=C.CASE_NO AND C.SPARE_PART='SO' AND
C.TRANSFER_NUMBER IS NOT NULL AND
C.TRANSFER_DATE IS NOT NULL;
ConvID := DDE.Initiate('EXCEL', 'C:\excel.xls');
DDE.Poke(ConvID, 'R1C1','船运号',
&&&&&&&&&&&&&
DDE.CF_TEXT, 1000);
DDE.Poke(ConvID, 'R1C2','到达日期',
&&&&&&&&&&&&&
DDE.CF_TEXT, 1000);
DDE.Poke(ConvID, 'R1C3','包装箱号',
&&&&&&&&&&&&&
DDE.CF_TEXT, 1000);
DDE.Poke(ConvID, 'R1C4','LRCM号',
&&&&&&&&&&&&&
DDE.CF_TEXT, 1000);
DDE.Poke(ConvID, 'R1C5','SO标识',
&&&&&&&&&&&&&
DDE.CF_TEXT, 1000);
DDE.Poke(ConvID, 'R1C6','移交单',
&&&&&&&&&&&&&
DDE.CF_TEXT, 1000);
DDE.Poke(ConvID, 'R1C7','移交日期',
&&&&&&&&&&&&&
DDE.CF_TEXT, 1000);
DDE.Poke(ConvID, 'R1C8','移交数量',
&&&&&&&&&&&&&
DDE.CF_TEXT, 1000);
DDE.Poke(ConvID, 'R1C9','设备材料描述',
&&&&&&&&&&&&&
DDE.CF_TEXT, 1000);
FOR i IN 1..NCOUNT
FETCH C1 INTO SHIPMENT_NO_TMP,
ARRIVAL_DATE_TMP,DELIVERY_REF_1_TMP,
DELIVERY_REF_3_TMP,DELIVERY_
REF_2_TMP,CASE_NO_TMP,
LRCM_CODE_TMP,ANN_QUANTITY_TMP,
QUANTITY_DESCRIPTION_TMP,SPARE_PART_TMP,
TRANSFER_NUMBER_TMP,TRANSFER_DATE_TMP;
EXIT WHEN C1%NOTFOUND OR C1%NOTFOUND IS NULL;
CROW:=I+1;
CCOL1:='R'||CROW||'C1';
CCOL2:='R'||CROW||'C2';
CCOL3:='R'||CROW||'C3';
CCOL4:='R'||CROW||'C4';
CCOL5:='R'||CROW||'C5';
CCOL6:='R'||CROW||'C6';
CCOL7:='R'||CROW||'C7';
CCOL8:='R'||CROW||'C8';
CCOL9:='R'||CROW||'C9';
TEMP:=ANN_QUANTITY_TMP;&&
DDE.Poke(ConvID, CCOL1, SHIPMENT_NO_TMP,
&&&&&&&&&&&&&
DDE.CF_TEXT, );
DDE.Poke(ConvID, CCOL2, TO_CHAR(ARRIVAL_DATE_TMP),
&&&&&&&&&&&&&
DDE.CF_TEXT, );
DDE.Poke(ConvID,CCOL3,DELIVERY_REF_1_TMP
&&&&&&&&&&&&&
||DELIVERY_REF_3_TMP||
&&&&&&&&&&&&DELIVERY_REF_2_TMP||
CASE_NO_TMP,&&&&&&&&&&
DDE.CF_TEXT, );
DDE.Poke(ConvID, CCOL4, LRCM_CODE_TMP, DDE.CF_TEXT,
&&&&&&&&&&
DDE.Poke(ConvID, CCOL5, SPARE_PART_TMP, DDE.CF_TEXT,
&&&&&&&&&&
DDE.Poke(ConvID, CCOL6, TRANSFER_NUMBER_TMP,
&DDE.CF_TEXT, );
DDE.Poke(ConvID, CCOL7, TO_CHAR(TRANSFER_DATE_TMP),
&DDE.CF_TEXT, );
DDE.Poke(ConvID, CCOL8, TEMP, DDE.CF_TEXT, );
DDE.Poke(ConvID, CCOL9, QUANTITY_DESCRIPTION_TMP,
&&&&&&&&&&
DDE.CF_TEXT, );
DDE.Terminate(ConvID);
在做好以上工作后, 编译运行该fmx文件,
此时确保打开excel.xls文件,用鼠标点击按钮,然后将焦点移到excel.xls文件中,你就会发现一行行数据正在被倒入到EXCEL文件中,等完成后,
将EXCEL文件保存起来就可以了.
---- 一个应用系统往往有不同的用户,比如:
一个劳资系统中,一个用户负责管理职工基本档案部分,另一个用户负责管理职工工资部分,管理职工基本档案的用户对职工档案只有查询的权限而不能有修改的权限。实现上述功能的一个简单的实现办法是:
设置两个全局变量分别记录用户名和密码,在进入系统时,两个用户分别输入不同的用户名和密码,判断用户名,使SET_MENU_PROPERTY(MENU1,ENABLED,FALSE)语句设置没有查询权限的用户不能访问菜单项'MENU1'。
在表连接查询时,常常用下列查询方法查询数据是:
SELECT& RECORDNO,NAME,AGE
WHERE 表1.RECORDNO NOT IN
&& (SELECT RECORDNO
WHERE& BIRTHDAY='710618');
笔者发现,如果表1的长度为6000条记录,表2的长度为1000条记录, 则要4分钟才能出结果。原因是使用了比较运算符 NOT
IN ,它的逻辑测试速度是最慢的。利用外连接替换NOT IN 运算符,查询时间则缩短为50秒。修改方法如下:
SELECT& RECORDNO,NAME,AGE
FROM& 表1,表2
WHERE 表1.RECORDNO=表2.RECORDNO(+)
AND& 表2.RECORDNO IS NULL
AND& 表2.BIRTHDAY(+)='710618';
在编程中很多FROM 模块需要共用一个程序单元。ORACLE FORM
4.5提出了库模块的概念。使用库模块建立共享程序单元库,既减少了磁盘占用空间,又增加程序的可维护性。使用库模块共享程序单元的过程是:点击系统菜单的file-new-liberary选项,建立一库模块,在program
units节点下增加一程序单元, 写入需共享程序的单元编码, 编译后存盘。当FORM模块需共享时,在模块的Attached
Libraries节点下连接库模块(此时屏幕会提示是否要删除路径,用户选择NO)。这样,用户便可在FORM模块中直接使用共享程序单元了。
在执行数据查询时,经常发现查询结果与预想的不同,主要原因是:
1.使用 SELECT * FROM &表名& WHERE &字段名& LIKE '%' 语句查询不出
&字段名&为NULL的字段。此时需对字段为NULL的情况另外处理。如:SELECT * FROM &表名&
WHERE &字段名& LIKE '%' OR &字段名& IS NULL
2.使用union
字段连接各表时,连接顺序不是按书写的先后顺序,而是按连接表的第一个字段排序。因此,为了使表按预想的顺序连接,需在各表中插入第一字段指定排序序号。
REPORT2.5提供了多种报表格式,但在报表中定义各种统计信息不仅繁琐而且不利于今后的维护,使用视图预先将各种统计、汇总数据准备好,可以起到事半功倍的作用,一旦数据源有所调整,只需修改后台视图,而不用再改前端程序了。
表1结构为:&
NAME& RECORENO&&
&&&&&&&&&&&&&
1&&&&&&&&&&&
&&&&&&&&&&&&&
2&&&&&&&&&&&
&&&&&&&&&&&&&&&
1. 首先建立视图对数据进行汇总:
CREATE VIEW& RYTJ (UNIT, BOY,GIRL)
AS SELECT UNIT, SUM(DECODE(SEX,'男'
,1,0)) , SUM(DECODE(SEX,'女',1,0) )
FROM& 表1;
2. 使用 ORACLE REPORT 2.5 对视图'RYTJ'建立报表。
ORACLE REPORT 2.5 没有提供加序号功能,使用下述简单方法可实现给报表自动加序号:在数据模板中,
向查询组中加入一个公式列 CF_XH NUMBER(4), 赋初值为0, 点击[EDIT] 按钮,
插入编码RETURN(:CF_CH+1)。
---- Developer/2000 不 能 实 现 同 时 多 数 据 源 的 同 时 连 接, 在 多 系 统 和 异 种
数 据 源 的 操 作 中 功 能 确 实 大 打 折 扣, 虽 然 可 以 用3GL 加ODBC 作 一DLL 应 用 能 实 现,
但 一 般 的 应 用 中 又 有 点 没 用 必 要 作 的 那 么 复 杂。 实 际 上Developer/2000 内 嵌
包TEXT_IO 为 我 们 提 供 了 一 个 更 简 单 的 方 法。 几 乎 所 有 的 数 据 库 或 数 据 库 前 端 开
发 工 具 都 提 供 文 本 文 件 的 操 作, 这 样 我 们 完 全 可 以 用 文 本 文 件 作 为 数 据 交 换 的
通 用 格 式。 下 例 是 在 保 险 业 中 的 一 应 用:( 要 用 到d2kwfile.dll 应 用)
&filename varchar2(128):=
&filenum text_io.file_
&linebuf varchar2(100);
&r_temp& temp%
&filename:=d2k_file_dialog.show
('请选择缴费工资台帐原文件','c:\','源文件(*.txt)|*.txt|');
& if filename is null then
&& raise form_trigger_
& filenum:=text_io.fopen(filename,'r');
text_io.get_line(filenum,linebuf);
TEXT_IO.PUT(linebuf);TEXT_IO.NEW_LINE;
exception when no_data_found then
v_temp.l1=substr(linebuf,1,9);
v_temp.l2:= to_number(substr(linebuf,10,5));
&&& insert
into temp(l1,l2) values (v_temp.l1,v_temp.l2);
exception when others then
&& & end_loop & &
---- 在PB 和VB 中 都 用 类 似 的 求 和 或 者 说 累 计 列, 但 在 早 期 的FORMS4。5 中 没
有 此 功 能, 对 于 多 条 记 录 的 录 入 中 需 要 进 行 求 和 时 很 不 方 便, 其 实 利 用FORM 的 触
发 子 很 容 易 实 现。 如 下 例:
&& 块:b1 项:l1,l2.l3,l4
&& 块:b2 项:l1,l2,l3,l4
&& 块b2是B1的求和块
&& 在块B1中的PRE_TEXT_ITEM中代码:
IF SUBSTR(:SYSTEM.CURRENT_ITEM,1,1) IN ('L') THEN
:GLOBAL.ITEM_PREVALUES:=NAME_IN
('B1.'||:SYSTEM.CURRENT_ITEM);
B2中的POST_TEXT_ITEM中代码:
--数据项在录入或修改前后的差值
--数据项在修改后的求合
& if substr(:system.current_item,1,1) in ('l')
:global.item_nextvalues:=name_in
('b1.'||:system.current_item);
num_cz:=nvl(to_number(:global.item_nextvalues),0)-
&nvl(to_number(:global.item_prevalues),0);
--新的和值
num_hz:=nvl(to_number(name_in('b_sum.'
||:system.current_item)),0)+num_
copy(to_char(num_hz),'b2.'||:system.current_item);
---- 通 过 前 后 两 值 的 比 较 很 容 易 的 实 现 一 个 较 通 用 的 求 和 算 法, 另 外 又 一
次 用 到NAME_IN 和 COPY , 减 少 了 代 码 量。 在 块 上 实 现 触 发 子 也 减 少 了 代 码 维 护
工 作 量。
---- 在 做 报 表 时 经 常 要 遇 到 类 似 的 报 表 有 多 张 的 情 况, 虽 然 通 过 简 单 的 拷
贝 可 以 减 少 编 程 的 工 作 量, 但 在 后 期 的 维 护 中 却 增 加 了 难 度, 一 张 表 改 完 后 又 改
另 一 张 表, 进 行 大 量 的 重 复 劳 动 不 是 每 个 程 序 员 想 做 的 工 作。 其 实 在REPORT 2。5
中 有 一 很 好 的 功 能 可 能 完 成 这 样 的 工 作。 就 是REPORT 的" 宏" 代 换。 如 下 例:
两个表:tab_temp1 (a number,b number,c number)
tab_temp2 (d number,e number,f number)
---- 作 两 张 报 表, 表 头 一 样, 但 查 询 不 一 样, 分 别 取 自 两 个 表
1.& 建 一 用 户 参 数(user parameters) p_1 类 型 CHAR 长
度 200, 缺 省 值 是 SELECT A,B,C FROM TAB_TEMP
2.&&&&&&&&&&&&&&&&&&&
建 一 查 询(QUERIES), 在 查 询 语 句 中 输 入:&P_1
3.&&&&&&&&&&&&&&&&&&&
生 成 布 局, 可 按 要 求 画 出 报 表。
---- 因 在 查 定 义 中 用 的 是&p_1 定 义, 所 以 可 以 在 运 行 时 动 态 的 给P_1 传
递 能 数 只 要 能 满 足 其 列 名 定 义 即 可, 例 可 用 如 下 语 句 代 入P_1
SELECT D A,E B,F C FROM TAB_TEMP2
---- 这 样 就 生 成 了 一 个 多 功 能 报 表, 把 编 写REPROT 工 作 从 简 单 的 布 局 编 辑
中 解 脱 出 来, 而 投 入 到 实 质 性 的 工 作SQL 语 句 的 生 成 上 去。
在运行一个FORM时往往会弹出一些报警器,但提示的并非出错信息,屏蔽这些报警器的方法是将系统变量:SYSTEM.MESSAGE_LEVEL的值设置为’25’。
在使用SELECT语句为某变量赋值时,往往会出?NO_DATA_FOUND"和"TOO_MANY_ROWS"等异常情况,使用SELECT语句分两种情况:第一种情况,判断某表中是否有符合某一条件的记录,这时使用聚组函数MAX就可以避免以上两个例外的发生。其格式:SELECTMAX(列1),MAX(列2)......INTO变量1,变量2......FROM基表WHERE条件,当没有符合条件的数据时,该语句返回空,即变量1,变量2......的值均为空,而不会出现"NO_DATA_FOUND"例外,另外使用聚组函数MAX的同时也就避免了"TOO_MANY_ROWS"例外。第二种情况,SELECT语句中含聚组函数SUM,这时如果使用了GROUPBY和HAVING子句,当没有符合条件的记录时将发生"NO_DATA_FOUND"例外,此时避免例外的办法是:去掉GROUPBY和HAVING子句,将HAVING子句的条件加到WHERE子句中。这样在使用SELECT语句时就不必再额外增加一段处理例外的代码,从而简化的代码的编写。
在FORM设计时有时需要用到主从块,在主从块录入时每当鼠标从从块移到主块准备录入一条新记录时,总是弹出一报警器,问你是否保存数据,从而影响录入速度,将该报警器去掉的方法是:在过程"CLEAR_ALL_MASTER_DETAILS"中的"CLEAR_BLOCK(ASK_COMMIT)"即清除从块时是否提交改为"CLEAR_BLOCK(DO_COMMIT)",这样从块录完数据再导航到主块录入新记录时,系统将自动提交数据,而不再出现上述提示。
(1)对于块中只用于查询并且无格式限制的项,设置为显示项。
(2)保存FORM时先断开与数据库的链接,然后在保存。以上两种方法均可减小FORM的大小,尤其是第二种方法更为明显。当硬盘空间较小,或将程序备份到软盘上时,这样作是很有意义的。
在MAINMENU中建立一个为WINDOWS属性的菜单项,这样主菜单中WINDOWS项就不再显示。
复杂的报表往往是由几部分组成,需建立多个查询,而每个查询都对应着一个布局,怎样才能使具有不同布局的报表数据显示在同一页上呢?其方法如下:第一步,首先根据实际报表格式建立第一个查询组的布局,称为布局1,然后依次再建立起其他查询组的布局,分别称为布局2,布局3......。注意:每个布局最外围的单选框不要去掉。第二步,分别为布局2,布局3......建立一个到布局1的定位(ANCHOR),即选中工具栏中的ANCHOR,鼠标单击布局2的单选框,然后按住鼠标左键并拖动鼠标到布局1的单选框上(可以选择上边﹑下边﹑左边或右边),松开鼠标按钮,按此方法再建立布局3,布局4......到布局1的定位。建立定位的作用是使布局2,布局3......相对与布局1的位置保持不变,这样就使具有不同布局的报表数据显示并打印在同一物理页上。
用RUN命令,一次只能生成一个.FMX文件,如果想生成一批.FMX文件,这样做即麻烦又费时,一个生成.FMX较快的办法是:先打开要运行的.FMB文件,如何按住SHIFT键将这些文件全部选中,在从系统菜单"文件"中选择"ADMINISTRATION"中"GENERATE"即可。
首先,必须将画布类型设置为“堆叠式”画布,其它类型的画布不能显示滚动条。将画布类型设置为“堆叠式”之后,该画布属性选项板的“物理属性”子类会出现“显示水平滚动条”与“显示垂直滚动条”两项内容,将其同时设置为“是”,则可以同时显示水平与垂直滚动条。
当使用系统缺省设置,不进行任何设定时,message信息将在FORM窗口的底部以小字显示。如果希望引起用户注意,可以将message信息显示在告警框中。例如,如果用户输入的数据类型错误,则弹出一个告警窗口,并在其中显示message信息:“输入数据类型不符”,这样,可以更加清晰地提醒用户输入有误,并允许用户及时地改正错误。
  在告警框中显示message信息,只需要创建一个警告(alert)与一个ON_ERROR触发器,由于引用的是系统错误信息,所以不需要程序员自己编写捕捉错误并弹出相关警告信息的程序,从而提供了极大的便利。
  在告警框内显示message信息的过程如下所述:
  1. 创建一个只具有一个按钮的警告“general_error_alert”。
  2. 在FORM一级创建ON_ERROR触发器,在出现错误时,将错误代码与信息显示在告警框中,程序如下:
  declare
  v_message varchar2(255);
  --将不需要显示的mesage信息屏蔽掉
  if error_code in (0,,,40350)
  --将错误代码与错误信息联系起来
  v_message:=error_type || '-' || to_char(error_code) || ':' ||
   --将错误信息显示为告警信息
  set_alert_property('general_error_alert',alert_message_text,v_message);
  v_button:=show_alert('general_error_alert');
  raise form_trigger_
&如果重复调用并打开了多个FORM,希望在点击任何一个FORM选单上的“退出”按钮时同时退出所有的FORM,需要在每一个FORM中设置一个全局变量global.quit_all,同时在选单条上加入一个“退出”按钮,并建立以下触发器:
  1.在每一个FORM上建立WHEN_NEW_FORM_INSTANCE触发器:
  :global.quit_all := 'N';
  2.在每一个FORM上建立WHEN_WINDOW_ACTIVATED触发器:
  if :global.quit_all = 'Y'
  then exit_
  3.在选单条的“退出”按钮上建立WHEN_BUTTON_PRESSED触发器:
  :global.quit_all := 'Y';
  注意,要么使用OPEN_FORM打开FORM,要么使用CALL_FORM打开FORM,不能两者混合使用,否则容易发生错误,无法一次退出所有的FORM。
由于FORM与REPORT是两项独立的产品,不可能使用全局变量传递数据,所以它们之间的数据无法共享。如果希望REPORT继承FORM中的一些数据,可以将FORM中的有关数据作为参数,以参数列表的形式传递给REPORT。
  例如,可以根据用户在FORM中的选择,在REPORT中动态生成符合查询条件的数据,方法是将FORM中的查询条件,作为参数传递给REPORT,从而在REPORT中动态生成查询结果。
  在FORM与REPORT之间传递参数的程序如下所示:
  declare
  pl_id ParamL
  —获取tmpdep的参数列表值
  pl_id := Get_Parameter_List( 'tmpdep' );
  —如果参数列表pl_id已存在,则删除它,然后重建。如果不删除当前pl_id,则无法创建参数列表,并在运行FORM时出现错误提示:参数列表已存在,无法重建
  if Not Id_Null( pl_id )
  then Destroy_Parameter_List(pl_id);
  --创建参数列表tmpdep
  pl_id:=Create_Parameter_List('tmpdep' );
  --在参数列表pl_id中加入参数w_clause,同时对w_clause赋值
  where deptno=:dept_deptno。
  Add_Parameter( pl_id,'w_clause', TEXT_Parameter, 'where
deptno=:dept.deptno');
  --运行报表,并将现有参数列表pl_id与值传递给报表report1
  run_product(reports,'C:\report\report1',synchronous,runtime,filesystem,pl_id);
当从FORM调用REPORT时,REPORT将按缺省窗口大小(420&360)显示,如果希望REPORT以满屏方式显示,需要加入如下代码:
  add_parameter(pl_id,maximize',TEXT_PARAMETER,'yes');
&当FORM调用REPORT时,首先会弹出一个参数窗口,显示所有FORM传递给REPORT的参数,待点击该窗口中的“运行”后,才运行REPORT。我们也可以不显示该参数窗口,方法是在FORM中加入如下代码:
  Add_Parameter(pl_id,'w_clause',TEXT_Parameter,'NO');
Oracle*Reports是Oracle的数据统计及图形化报表工具,它提供了六种风格的报表格式,而我们通常使用的只有其中的两种,即Tabular和Matrix,无论用哪种风格生成的报表,打印出的表格数都是动态变化的。其中Tabular风格的报表,列数固定,而行数不定;Matrix风格的报表,行数和列数均不定。那么在Oracle*Reports中如何实现报表的定长与定宽输出呢?笔者在实际开发过程中对上述两种风格的报表各总结出一种行之有效的方法,供大家参考。
对于Tabular风格的报表,可用报表触发子After Parameter Form和After
Report实现定长输出。其方法是:根据实际情况确定每页打印的行数,当最后一页的记录数少于每页打印的行数时,则用空记录补齐。在触发子After
Parameter Form插入空记录,在触发子After Report中再将空记录删除,下面举例说明。
假设有一数据基表WZDM:存放物资代码信息,其数据结构为:
要求:按定长输出物资代码表,并且每页均输出x行(x可根据实际情况而定)。
启动Oracle*Reports,建立物资代码打印报表(略),然后在报表触发子After Parameter
Form中加入以下代码:
v—jls number(2);
i number(2):=1;
Select Count(*) Into V—jls From W
If Mod(V—jls,x)〈〉0 Then
  Exit When i〉=(x-mod(v—jls,x))+1;
  Insert Into Wzdm(Wzdm,Wzmc,Xhgg,Jldw)
  Values(&&,&&,&&,&&);
  i:=i+1;
在报表触发子After Report中分别加入以下代码:
Delete From Wzdm Where Wzdm Is N
运行报表后即可输出定长的物资代码表。
说明:对于其它Tabular风格的报表,在编写上述两个触发子时只需将基表名与列名根据实际情况修改一下,并确定x的值即可。
二、对于Matrix风格的报表,可利用视图实现定长与定宽输出,其思路是:当行记录数和列记录少于实际报表的行数和列数时,均以空记录补齐。下面举例说明。
假设有一物资资金消耗去向统计月报,该表横向显示本期消耗去向,纵向显示物资类别,由于每月物资消耗去向和消耗物资均不定,所以此类报表即为一矩阵报表。该报表的数据存放在基表T—ZJXHQX中,其数据结构如下:
要求:按定长定宽输出物资资金消耗去向统计月报,并且每页均输出x行y列(行数和列数可根据实际情况而定)。
首先建一基表T—kjl,用来存放空记录,其数据结构为:
建完该数据表后,再往其中插入记录,记录数可根据实际情况而定,一般为一页所能打印的最大行数,这里假设为z条,即No的值为1,2,3…z。
建视图,其过程如下:
Create View V—TJBB As
 Select Dwmc,Lbmc,Je From T—zjxhqx
 Select Dwmc,Null,To—Number(Null) From T—zjxhqx,T—kjl
 Where No-(z-x)〉(Select Mod(Count(Distinct Lbmc)-1,x)+1 From
T—zjxhqx)
 Select Null,Lbmc,To—Number(Null) From T—zjxhqx,T—kjl
 Where No-(z-y)〉(Select Mod(Count(Distinct Dwmc)-1,y)+1 From
T—zjxhqx);
启动Oracle*Reports,建立矩阵报表查询时直接引用视图V—TJBB即可。这样运行时输出的报表每页都是x行y列,即实现了定长和定宽输出。
---- 在 早 期FOXPRO 数 据 库 编 程 中, 经 常 用 到 宏 代 换 功 能, 但 在FORMS 中 却 没
有 此 功 能, 象"&","*" 等 在 编 程 中 经 常 用 到 的, 在FORMS 中 只 得 一 行 一 行 代 码
的 写, 但 后 来 发 现FORMS 中 也 有 类 似 功 能, 用NAME_IN()、COPY() 可 以 实 现 类 似 的
功 能。Name_in() 用 于 取 出 参 数 名 代 表 的 对 象 了 数 值, 而COPY() 把 一 个 参 数 值 传
递 给 另 一 参 数 值 表 示 的 对 象。 的 如 下 例:
FORM 结 构:
项 L1,L2,L3,L4,L5,L6
在 作 录 入 程 序 时 要 对L1。。。L6 项 清 零
strItemName varchar2(20);
for I in 1 …6 loop
strItemName:=':b.l"||to_char(i);
copy(null,strItemNmae);
---- 对 于NAME_IN 的 应 用 可 能 更 多 一 些, 笔 者 在 做 社 保 软 件 时, 作 保 险 缴 费
录 入 时 曾 用 它 少 写 了 许 多 代 码。 当 然 代 码 的 减 少 就 义 意 味 维 护 工 作 量 的 减
FORM结构:
块:YLYJ(养老应缴)
项:DWJTC(单位缴统筹),DWJZH(单位缴帐户),GRJF(个人缴费)
块:YLSJ (养老实缴)
项:DWJTC(单位缴统筹),DWJZH(单位缴帐户),GRJF(个人缴费)
块:GSYJ(工伤应缴)
项:DWJTC(单位缴统筹),DWJZH(单位缴帐户),GRJF(个人缴费)
块:GSSJ (工伤实缴)
项:DWJTC(单位缴统筹),DWJZH(单位缴帐户),GRJF(个人缴费)
块:YILYJ(医疗应缴)
项:DWJTC(单位缴统筹),DWJZH(单位缴帐户),GRJF(个人缴费)
块:YILSJ (医疗实缴)
项:DWJTC(单位缴统筹),DWJZH(单位缴帐户),GRJF(个人缴费)
---- 三 个 块 的 结 构 相 同, 只 是 块 名 称 不 同, 缴 费 时 时 行 的 操 作 也 一 样, 实 缴
名 项 不 能 大 于 应 缴, 不 用NAME_IN 时, 只 能 写 三 段 程 序, 但 用 了NAME_IN 后 只 用 一
段 写 一 个 函 数 就 能 达 到 目 的。 如 下:
FUNCTION FUN_JF (PRE_BLOCK_NAME
IN VARCHAR) RETURN BOOLEAN IS
if name_in(pre_block_name||'sj.dwjtc')
&name_in(pre_block_name||'yj.dwjtc') or
name_in(pre_block_name||'sj.dwjzh')
&name_in(pre_block_name||'yj.dwjzh') or
name_in(pre_block_name||'sj.grjf')
&name_in(pre_block_name||'yj.grjf') then
message(' 实 缴 大 于 应 缴');
---- 从 上 面 的 两 个 例 子 来 看NAME_IN 和COPY 的 应 用 能 起 到 其 它 编 程 语 言 的"
宏" 代 换 功 能, 代 码 的 优 化 方 面 确 实 能 起 不 少 的 作 用, 减 少 了 程 序 源 代 码 的 维 护
---- Developer/2000 不 能 实 现 同 时 多 数 据 源 的 同 时 连 接, 在 多 系 统 和 异 种
数 据 源 的 操 作 中 功 能 确 实 大 打 折 扣, 虽 然 可 以 用3GL 加ODBC 作 一DLL 应 用 能 实 现,
但 一 般 的 应 用 中 又 有 点 没 用 必 要 作 的 那 么 复 杂。 实 际 上Developer/2000 内 嵌
包TEXT_IO 为 我 们 提 供 了 一 个 更 简 单 的 方 法。 几 乎 所 有 的 数 据 库 或 数 据 库 前 端 开
发 工 具 都 提 供 文 本 文 件 的 操 作, 这 样 我 们 完 全 可 以 用 文 本 文 件 作 为 数 据 交 换 的
通 用 格 式。 下 例 是 在 保 险 业 中 的 一 应 用:( 要 用 到d2kwfile.dll 应 用)
filename varchar2(128):=
filenum text_io.file_
linebuf varchar2(100);
r_temp temp%
filename:=d2k_file_dialog.show
('请选择缴费工资台帐原文件','c:\','源文件(*.txt)|*.txt|');
if filename is null then
raise form_trigger_
filenum:=text_io.fopen(filename,'r');
text_io.get_line(filenum,linebuf);
TEXT_IO.PUT(linebuf);TEXT_IO.NEW_LINE;
exception when no_data_found then
v_temp.l1=substr(linebuf,1,9);
v_temp.l2:= to_number(substr(linebuf,10,5));
insert into temp(l1,l2) values (v_temp.l1,v_temp.l2);
exception when others then
& & end_loop & &
---- 在PB 和VB 中 都 用 类 似 的 求 和 或 者 说 累 计 列, 但 在 早 期 的FORMS4。5 中 没 有 此
功 能, 对 于 多 条 记 录 的 录 入 中 需 要 进 行 求 和 时 很 不 方 便, 其 实 利 用FORM 的 触 发 子
很 容 易 实 现。 如 下 例:
块:b1 项:l1,l2.l3,l4
块:b2 项:l1,l2,l3,l4
块b2是B1的求和块
在块B1中的PRE_TEXT_ITEM中代码:
IF SUBSTR(:SYSTEM.CURRENT_ITEM,1,1) IN ('L') THEN
:GLOBAL.ITEM_PREVALUES:=NAME_IN
('B1.'||:SYSTEM.CURRENT_ITEM);
在块 B2中的POST_TEXT_ITEM中代码:
num_ --数据项在录入或修改前后的差值
num_ --数据项在修改后的求合
if substr(:system.current_item,1,1) in ('l') then
:global.item_nextvalues:=name_in
('b1.'||:system.current_item);
num_cz:=nvl(to_number(:global.item_nextvalues),0)-
nvl(to_number(:global.item_prevalues),0);
--新的和值
num_hz:=nvl(to_number(name_in('b_sum.'
||:system.current_item)),0)+num_
copy(to_char(num_hz),'b2.'||:system.current_item);
---- 通 过 前 后 两 值 的 比 较 很 容 易 的 实 现 一 个 较 通 用 的 求 和 算 法, 另 外 又 一 次 用
到NAME_IN 和 COPY , 减 少 了 代 码 量。 在 块 上 实 现 触 发 子 也 减 少 了 代 码 维 护 工 作
---- 在 做 报 表 时 经 常 要 遇 到 类 似 的 报 表 有 多 张 的 情 况, 虽 然 通 过 简 单 的 拷 贝 可
以 减 少 编 程 的 工 作 量, 但 在 后 期 的 维 护 中 却 增 加 了 难 度, 一 张 表 改 完 后 又 改 另 一
张 表, 进 行 大 量 的 重 复 劳 动 不 是 每 个 程 序 员 想 做 的 工 作。 其 实 在REPORT 2。5 中 有
一 很 好 的 功 能 可 能 完 成 这 样 的 工 作。 就 是REPORT 的" 宏" 代 换。 如 下 例:
两个表:tab_temp1 (a number,b number,c number)
tab_temp2 (d number,e number,f number)
---- 作 两 张 报 表, 表 头 一 样, 但 查 询 不 一 样, 分 别 取 自 两 个 表
建 一 用 户 参 数(user parameters) p_1 类 型 CHAR 长 度 200, 缺 省 值 是 SELECT
A,B,C FROM TAB_TEMP
建 一 查 询(QUERIES), 在 查 询 语 句 中 输 入:&P_1
生 成 布 局, 可 按 要 求 画 出 报 表。
---- 因 在 查 定 义 中 用 的 是&p_1 定 义, 所 以 可 以 在 运 行 时 动 态 的 给P_1 传 递
能 数 只 要 能 满 足 其 列 名 定 义 即 可, 例 可 用 如 下 语 句 代 入P_1
SELECT D A,E B,F C FROM TAB_TEMP2
---- 这 样 就 生 成 了 一 个 多 功 能 报 表, 把 编 写REPROT 工 作 从 简 单 的 布 局 编 辑 中 解
脱 出 来, 而 投 入 到 实 质 性 的 工 作SQL 语 句 的 生 成 上 去。
&1 . 引 言
---- ORACLE 关 系 数 据 库 管 理 系 统 是 目 前 世 界 上 最 流 行 的 高 性 能 数 据 库 管
理 系 统 之 一,Developer/2000 是ORACLE 公 司 推 出 的 集 成 化 软 件 开 发 和 运 行 环 境。
ORACLE *Forms 是Developer/2000 的 一 部 分, 它 是 一 种 功 能 丰 富, 用 于 构 建 应 用
的 工 具 产 品, 产 品 化 屏 幕 处 理 存 储 在 数 据 库 中 的 数 据。 在 许 多 实 际 应 用 中, 往 往
需 要 将 数 据 用 很 直 观 的 图 形 表 示 出 来。 例 如: 饼 图, 折 线 图, 直 方 图 等, 从 而 使 数
据 及 其 比 例 关 系 一 目 了 然。Developer/2000 的 另 一 工 具ORACLE *Graphics 提 供
了 丰 富 的 图 形 化 表 示 数 据 的 方 法, 它 可 以 从 各 种 数 据 源 获 得 数 据, 并 可 以
与Forms 模 块 结 合 起 来, 更 有 效 地 表 示 数 据。
---- 笔 者 曾 参 加 某 企 业 决 策 支 持 系 统 的 开 发 工 作, 通 过 在Forms 中 调
用Graphics 中 的 图 形 功 能, 使 数 据 表 示 更 为 直 观, 并 可 根 据Forms 中 数 据 的 变 化
来 动 态 地 显 示 图 形, 从 而 帮 助 决 策 人 员 进 行 数 据 分 析, 达 到 支 持 决 策 的 目 的。 下
文 是 笔 者 在 实 际 开 发 中, 完 成 动 态 显 示 图 形 功 能 制 作 过 程 中 的 一 点 体 会。
动 态 图 形 显 示 的 实 现
---- 本 例 假 设 有 一 个 产 品 销 售 数 据 表SALES, 并 含 有 销 售 时 间, 产 品 名 称, 销
售 量 三 个 字 段( 销 售 时 间 以 年 为 单 位), 其 数 据 字 典 为
字 段 名 & 字 段 长 度
&& 字 段 含 义
销 售 时 间
产 品 名 称
number(10,2)
---- 启 动Graphics, 建 立 一 个 新 的 图 形 文 件, 并 命 名 为chart.ogd。 在Queries 中
定 义SQL 查 询 语 句 以 显 示 图 形, 并 在 图 形 的 属 性 栏 中 定 义x 轴 和y 轴 所 需 显 示 的 数
据。 本 例 将 在x 轴 显 示 产 品 名 称,y 轴 显 示 各 种 产 品 的 销 售 量。
---- 启 动Forms, 建 立 一 个 新 的 Forms 应 用 文 件sale.fmb。 在 画 布CANVAS1 中 填
加 一 个List Item 控 件LIST1 , 并 在LIST1 的 属 性 中 填 充 所 要 显 示 的 时 间 值。 然 后
填 加 一 个Chart Item 控 件chart_area1, 并 调 节 好chart_area1 的 边 界 和 大 小, 以
显 示 图 形chart.ogd。
---- 在Forms 中 调 用 图 形, 必 须 与Graphics 进 行 参 数 值 的 传 递。 首 先 回
到Graphics 中, 在chart.ogd 中 设 置 如 下 结 构:
---- (1) 在 参 数 表Parameters 中 定 义 参 数。 本 例 需 传 递 时 间 参 数, 并 设 其 为
m1, 在 参 数 表 中 设 置 其 属 性
parameter m1
type number
initial value 1998
---- (2) 定 义 图 形 的 查 询 语 句。 在Queries 中 定 义"query0" 查 询, 如 下 所
select product,amount
from sales
where time=:m1
---- (3) 定 义 过 程。 在 Program Unit 中 编 写 update_chart 过 程, 完 成 图 形 随
参 数 变 化 显 示 的 功 能。
PROCEDURE update_chart IS
og_execute_query(og_get_query('query0'));
---- 完 成 以 上 工 作 后, 回 到Forms 中, 首 先 打
开orawin95\forms45\plsqllib\og.pll 文 件, 然 后 定 义 如 下 结 构:
---- (1) 在LIST1 的 属 性List elements 中 填 写 列 表 框 中 所 要 显 示 的 数 值, 然 后
设 置WHEN_LIST_CHANGED 触 发 器, 并 编 写 触 发 器 代 码, 如 下
pl := Get_Parameter_List('plist');
IF NOT Id_Null(pl) THEN
destroy_parameter_list(pl);
pl := Create_Parameter_List('plist');
add_parameter(pl,'m1',text_parameter,:blk1.list1);
og.interpret('c:\chart.ogd','chart_area1','
update_',true,pl);
---- (2) 在Forms 中 设 置WHEN_NEW_FORM_INSTANCE 触 发 器, 完 成 初 始 化 工 作, 其
程 序 如 下:
Set_Window_Property (Forms_MDI_Window,
Window_State,Maximize);
Show_Window ('sales');
set_window_property('sales',window_state,
maximize);
og.open('c:\chart.ogd','chart_area1');
---- (3) 在Forms 中 设 置POST_FORM 触 发 器, 用 来 在 程 序 结 束 时 关 闭 图
og.close('c:\chart.ogd','blk1.chart_area1');
---- 通 过 以 上 过 程, 动 态 图 形 显 示 得 以 实 现。 当 改 变 时 间 列 表 中 的 数 值 时, 图 形
随 着 时 间 的 改 变 而 变 化, 显 示 另 一 个 时 间 相 应 的 各 种 产 品 的 销 售 量 的 值。
---- 本 文 介 绍 了 一 些Developer/2000 中Forms 和Graphics 的 开 发 方 法 及 使 用 技
巧。 当 然Developer/2000 中 还 有 许 多 其 他 的 触 发 器 及 内 部 例 程, 需 要 在 实 践 中 不
断 探 索。
CREATE OR REPLACE FUNCTION CONVERT_MONEY(INPUT_NBR IN NUMBER
DEFAULT 0)
&&&&&&&RETURN&VARCHAR2&IS
INPUT_NBR_BAK&&&&&NUMBER(20);&&&&&&
NUM_CHARACTER&&&&&VARCHAR2(20)&:=&'零壹贰叁肆伍陆柒捌玖';
UNIT_CHARACTER&&&&VARCHAR2(40)&:=&'分角圆拾佰仟万拾佰仟亿拾佰仟万拾佰仟亿';
OUTPUT_STRING&&&&&VARCHAR2(100):=&'';
REMAIN_NBR&&&&&&&&NUMBER(20);
BIT_NUM&&&&&&&&&&&NUMBER(20);&&&&&&
BIT_UNIT&&&&&&&&&&VARCHAR2(2);&&&&&
BIT_INDIC&&&&&&&&&NUMBER(1)&:=0;&&&
I&&&&&&&&&&&&&&&&&NUMBER(2)&:=0;&&&
SPE_UNIT&&&&&&&&&&VARCHAR2(2):='A';
SIGN_INDIC&&&&&&&&VARCHAR2(1);&&&&&
IF&&&&&INPUT_NBR=0&THEN&RETURN&'零圆整';
ELSIF&&INPUT_NBR&0&THEN&SIGN_INDIC:='0';
&&&&&&&INPUT_NBR_BAK:=INPUT_NBR;
ELSIF&&INPUT_NBR&0&THEN&SIGN_INDIC:='1';
&&&&&&&INPUT_NBR_BAK:=-INPUT_NBR;
END&&&&IF;
&&&&REMAIN_NBR&&&&&:=&FLOOR(INPUT_NBR_BAK&/&10);&&&&&&&&&&
&&&&BIT_NUM&&&&&&&&:=&INPUT_NBR_BAK&-&REMAIN_NBR&*&10;&&&&
&&&&INPUT_NBR_BAK&&:=&REMAIN_NBR;&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&BIT_UNIT&&&&&&&:=&RTRIM(SUBSTR(UNIT_CHARACTER,&I&*&2+&1,&2));
&&&&IF&&&&BIT_NUM&&&0&THEN&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&BIT_INDIC&:=1;
&&&&&&&&&&IF&&&&I=6&&OR&I=14&&THEN&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&SPE_UNIT:='万';&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&ELSIF&(I&=7&AND&I&=9)&OR&(I&=15&AND&I&=17)&THEN&
&&&&&&&&&&&&&&&&IF&&&SPE_UNIT!='万'&THEN&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&OUTPUT_STRING:='万'||OUTPUT_STRING;
&&&&&&&&&&&&&&&&&&&&&SPE_UNIT:='万';&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&END&&IF;
&&&&&&&&&&END&&&IF;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&OUTPUT_STRING&:=&SUBSTR(NUM_CHARACTER,&BIT_NUM&*&2&+&1,&2)||BIT_UNIT||OUTPUT_STRING;
&&&&ELSE&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&IF&&&BIT_INDIC&=&1&THEN&&&&&&&&&&&&&
&&&&&&&&&&&&&&&OUTPUT_STRING&:=&'零'||OUTPUT_STRING;
&&&&&&&&&&END&&IF;
&&&&&&&&&&IF&&&&BIT_UNIT&IN&('圆','亿')&THEN&&
&&&&&&&&&&&&&&&&SPE_UNIT:=BIT_UNIT;&&&&&&&&&&&
&&&&&&&&&&&&&&&&OUTPUT_STRING&:=&BIT_UNIT||OUTPUT_STRING;
&&&&&&&&&&END&&&IF;
&&&&&&&&&&BIT_INDIC&&:=0;&&&&&&&&&&&&&&&&&&&&&
&&&&END&&&IF;
&&&&I&:=&I&+&1;
&&&&EXIT&WHEN&INPUT_NBR_BAK&=&0;
IF&&&&MOD(INPUT_NBR,10)=0&THEN&&&&&&&&&&&&&
&&&&&&OUTPUT_STRING:=OUTPUT_STRING||'整';
IF&&&&SIGN_INDIC='1'&THEN
&&&&&&OUTPUT_STRING:='负'||OUTPUT_STRING;
RETURN&OUTPUT_STRING;
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 ddr4 16g单条 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信