- APEX –开发
-
-
- 理解WorkSpace、Application
-
WorkSpace:工作空间,一个WorkSpace对应Oracle数据库的一个Schema,形象的理解我们可以认为它就是一个工程,这个工程里面有很多的子项目Application.在与EBS的集成开发中,我们认为每个Application可以类似于EBS中的一个Form,该Form里包含多个窗口.
本文有些截图是基于Oracle Application Express 4.2.5版本。在APEX中的页面布局、各种OBJECT的属性控制都是可以通过配置来解决的,对于这种声明式的开发(不需要编译)它需要的是少量的Coding,主要是偏向于pl/sal编程.
Oracle Application Express可以创建Database Applications,Websheet Applications,Packaged Application
本文对应的开发都是Database Application.
-
-
- Application授权登录机制
-
每个Application都可以为其设置安全认证,创建Application的时候会让你三选一。
后期创建好后我们是可以对其登录机制进行修改。具体的APEX自带的授权登录机制有7种。
在目前的开发中我们可以选择Application Express Accounts与HTTP Header Variable. 前者必须输入APEX用户名密码才可登录,后者
-
-
- Page0
-
Page0是该Application的一个全局页,比如某些全局变量,全局常量都可以在该页去设置,为了方便管理我们把不同类型的变量放在不同的区域,这些区域是不显示在界面上的类似于HTML的HIDDEN.
-
-
- 待定
-
Application Express 提供了 20 个主题。每个主题由定义应用程序外观的组件模板组成。Oracle Application Express 4.0 提供的这些现代化主题都符合 XHTML 和 CSS 标准。XHTML 页面可移植性更强、呈现时间更短。在项目上开发的使用的是APEX4.1.1版本,在网页布局这块比较郁闷,创建Region的Column属性是在某个 Body内是全局的,在APEX4.2.5版本中,就变得相当的Easy,可以对子子….区域的重新布局,其子子区域都会有对应的Grid Layout可以配置。
-
-
- 页面区域展现
-
APEX的页面在选定主题后,其页面的布局与CSS基本上已确定,基本上符合DIV+CSS来布局,然后把某几个常用的DIV【Body1、Body2、Body3、Postion1、Position2、Position3、Position4】放开给Developer开发使用。其中Body区域在HTML中是以<TABLE></TABLE>展现,Position区域在HTML中是以<DIV></DIV>展现
其中我们常用的区域为红色标记的区域。
实例创建区域的布局如图:
如何实现以上布局呢?在这里首先还是得明白HTML中的基本元素<TABLE><TR><TD></TD></TR></TABLE>及这些元素附带的一些属性.
上图相信对TABLE能一目了然了。那这些HTML的标签是如何对应APEX中的配置呢?请看下图来自APEX的Grid Layout的配置
Start New Grid:意为着当前的Object是否采用新的网格布局,即是否采用一个新的<TABLE>展现,不基于上一个<TABLE>的布局展现(比如可以重新定义列数,…)
Start New Row:意为着当前的Object是否换行显示,即<TR></TR>展现
Column:意为着当前的Object是在该<TABLE>的当前行的第几列<TD></TD>展现.
那么像上面布局图中的
Search3的区域布局配置为:
Newsearch1的区域布局配置为:
Newsearch3的区域布局配置为:
同理要实现更复杂的布局基于上述原则也是实现起来比较简单的。配配就OK了
-
-
- 标题待定
-
-
- APEX控件
APEX作为一个强大的快速开发工具,当然少不了一些常用的控件,下拉框Commbox,值列表Lov,文本框Text,日历DataPick,报表Report,…。这些控件的基本使用可参考
我们知道控件都是可以有很多属性、事件、校验、Dynamic Action。
其中Dynamic Action是可以做很多操作的,比较重要的是执行pl/sql时类似于Ajax的无刷新
控件属性:
- Form Element Width:控件的宽度
- Horizontal / Vertical Alignment:控件的显示位置还有Label显示位置。
- Value Required:是否必输入。
- Condition Type:控件显示的条件,只有满足了才显示。
- Read Only Condition Type,:控件只读的条件,只有满足了才只读。
- Default value:设置控件的默认值。
- Format Mask:控件值的格式掩码
事件:
事件定义也是有属性可配置的:
- Condition Type:执行事件的前提条件
- True Actions:事件发生后,对应控件的校验条件为真时执行的动作。
- False Actions:事件发生后,对应控件的校验条件为假时执行的动作。
- WHEN Condition:事件发生后,执行相应的动作的判断条件。
校验属性:
- When Button Pressed :触发校验的Button
- Condition Type:触发校验的前提条件
- Condition Expression:校验表达式
- Validation:执行相应的校验
- Error message display location:错误信息显示方式
- Associated Item:错误信息关联到指定的Object
下面做个具体的实例使用这些属性、事件、校验
- 点击Button: Search2 Btn时校验 X_Text1值是否为空,满足校验的前提条件是jjl_test表中存在记录user_id=’123’;
- 当页面加载完,DatePick:Data init值赋值为当前日期
- 当X_text2值不为空时,Region:new search2隐藏,否则显示
最终效果图:
Step By Step操作
- 创建一个页面命名为Page2
- Pl/sql apps登录创建table:jjl_test(user_id varchar2(50),resp_id varchar2(50),resp_appl_id varchar2(50),login_name varchar2(50),login_count number,login_date date); insert into jjl_test values(‘123’,’’,’’,’’,’’);
- 在Page2中创建六个html region,对应的Parent Regionn选择Page Template Body(1)
- Search1,search2,search3 属于同一个TABLE,属性Column依次为1,2,2. 属性Start New Grid依次为Yes,No,No. 属性Start New Row依次为Yes,No,Yes.
- New Search1,new search2,new search3 属于同一个TABLE,属性Column依次为1,2,3. 属性Start New Grid依次为Yes,No,No. 属性Start New Row依次为Yes,No,No.
- 在search1中创建TextField:P1_X_TEXT,P2_X_TEXT,search2中创建Button :SEARCH2_BTN,search3中创建DatePick:DATA,new search2中创建子区域:newsearch_subpage1,new_search3_subpage2,new_search3_subpage3, 属于同一个TABLE,属性Column依次为1,2,1. 属性Start New Grid依次为Yes,No,No. 属性Start New Row依次为Yes,No,Yes
- P1_X_TEXT鼠标右键创建相应的Validation:
Name:X_TEXT1 IS NOT NULL
When Button Pressed:SEARCH2_BTN.
Condition Type:Exists(SQL query returns at least one row)
Condition Expression 1:select 1 from jjl_test jt where jt.user_id=’123’;
Validation Type:Function Returning Boolean
Validatoin Expression:begin if :P1_X_TEXT is not null then return true; end if; return false;end;
Error message:X_TEXT1 can’t be null;
- P2_X_TEXT鼠标右键创建相应的Dynamic Actions:
Name:Dynamic_action1;
Conditon Type:Always;
When Event:Change
When Selection Type:Item(s)
When Item(s):P2_X_TEXT
When Condition:is not null
True Actions:Hide Region(new search2)
False Actions:Show Region(new search2);
- 创建PageLoad型的Dynamic Action
Name:page_load_set_date;
Condition Type:Dynamic Actoin Not conditional
When Event:Page Load
When Condition No Condition
True Actions:Set Value
Set Value/Settings/Set Type:SQL Statement
Set Value/Settings/SQL Statement:select sysdate from dual;
Set Value/Affected Elements/Selection Type:Item(s)
Set Value/Affected Elements/Item(s):DATA
-
- Report常用增删改
通常在APEX中对于记录的增删改是通过链接到新的页面去实现单条数据的更改。本节主要介绍如何在一个Tabular Form中不链接实现多行数据的增删改和客户化逻辑。APEX的Tablular Form开发类似于EBS Form开发,也是基于视图去开发。
下面实例开发一个Form,当更改用户的class_name与login_name时,更新用户的login_name,然后在另一张表校验class_name是否存在,若不存在报错,若存在则把当前勾选的记录插入另一张表jjl_test3
- 数据库中先创建APEX页面的Tabular Form的View,同时创建一个APEX页面并创建Tabular Form
- create table jjl_class(class_id number,class_name varchar2(50));
create or replace view jjl_class_test2 as
SELECT jt.user_id,
jt.resp_id,
jt.resp_appl_id,
jt.login_name,
jc.class_name
FROM jjl_test2 jt, jjl_class jc
WHERE jc.class_id = jt.class_id;
- 配置页面Tabular Form数据源
- 创建一个RegionButton:Apply Change
- 为Apply Change创建Process:
- 运行效果如图:
当class_name不存在于jjl_class表中时
当输入的class name存在时,运行的效果与结果如图:
把BBB更改为DDD
点击Apply Change后
真是麻雀虽小,五脏俱全,上传下载在Apex里的实现是非常easy.下面的例子实现
文件上至数据库
-- Create table
1、create table JJL_FILE
(
id NUMBER,
file_nmae VARCHAR2(50),
file_memetype VARCHAR2(50),
file_blob BLOB,
file_comments VARCHAR2(200),
file_charset VARCHAR2(20),
last_update_date DATE)
2、创建Page:updown load file,在该page中创建html区域:upload file
由于数据文件是上传至数据库表,需要在页面上传文件之前,可以在加载完head后去表里 Fetch Row from jjl_file,然后在页面上创建相应的hidden项与表jjl_file中相字段相应。就像在pl/sql中要往表里插一行记录时,可以先定义该表的Rowtype类型的变量,然后再做赋值与Commit;
创建相应的region item,type:hidden分别为p_file_id,p_file_name,p_file_charset,p_file_memetype
创建processes:fetch row from jjl_file;
上图中的table name要大写.
双击之前hidden项,配置每项的Source属性,保持与jjl_file的列名一致。如P_FILE_ID对应JJL_FILE中的ID。
4、在区域upload file中创建File Browse项,具体配置如下:
以上都对应数据库中的表jjl_file相应的字段。
5、创建区域button:upload file
6、为region item:FILE_BLOB创建Validation:点击UPLOAD_FILE按钮时验证FILE_BLOB不能为空.
7、SubmitPage后执行如下Processes: Process Row of JJL_FILE,配置如下图
运行效果如图:
上传APEX技术开发文档.doc 7.5M
Pl/sql中查看保存结果:
下载文件的实例:
创建一个interactive report名为downlaod file,配置其Sourceo:
SELECT jf.id,
jf.file_nmae,
jf.file_memetype,
jf.last_update_date,
dbms_lob.getlength(jf.file_blob) file_size,
dbms_lob.getlength(jf.file_blob) download
FROM jjl_file jf
创建OK后双击report:download file,配置列download为blob如图:
运行效果如图:
下面做一个页面Report数据的下载链接
- Classic Report 的下载链接配置
在Report的Attribute里做如下配置
运行效果如图:
- Interactiive Report的下载链接配置
URL: /f?p=<app_id>:<page_id>:<session_id>:<format>
app_id is the application id
page_id is the page id
session_id is the session id
<format> : CSV or HTMLD
创建Interactive report region下的一个Display Only项,Settings配置如下:
运行效果如图:
-
-
- Wait for
-
-
- 使用CSS与JS
在做相对比较复杂或比较个性化的APEX页面时还是需要用到一些JavaScript脚本和CSS。
下面做一个用JavaScript给Report表格中列赋值.效果如图:
创建Report,构建相应的列的HTML标签
设置每列的显示方式
创建page_item_button
为page_item_button创建Dynamic Action执行Set Value动作
Set Value/Settings/Set Type:Javascript Expression
Set Value/Settings/Javascript Expression:
再做一个使用CSS来控制页面中元素的显示,由于之前项目上有些Report需要显示很多列,导致把页面拉得很宽,而在APEX4.1.1版本中没有相应的CSS模板,因此需要自己来控制Report的显示。
如上图给Region加滚动条,并为滚动条赋上相应的颜色、控制滚动条的显示形状。
开发步骤:
- 首先在Page页面HTML Header and Body Attribute属性中定义CSS
<style type="text/css">
.css1{width: 752px; height: 380px; -ms-overflow-x: scroll; -ms-scrollbar-3dlight-color: rgb(235, 235, 228); -ms-scrollbar-shadow-color: rgb(179, 221, 247); -ms-scrollbar-highlight-color: rgb(179, 221, 247); -ms-scrollbar-darkshadow-color: rgb(235, 235, 228); -ms-scrollbar-arrow-color: rgb(0, 0, 0); -ms-scrollbar-track-color: rgb(244, 244, 240); ms-scrollbar-face-color: rgb(179, 221, 247);}
</style>
- 在Page页属性JavaScript:Excute When Page Loads
document.getElementById("t20BreadCrumbsLeft").className = "css1";
- Coding截图
当然上述只是一个很简单的例子来介绍如何去使用CSS控制APEX对象.
在APEX4.2.5版本中已经有带滚动条的模板可选择了,但依然还是有缺陷,Report header Row不能固定,它会随滚动条向下滚动而被覆盖
Application Express3.0之后支持HTML5 Chart 与Flash Chart,支持2D/3D的柱状图、水平条形图、饼图和圆环图、折线图、K线图、计量表、甘特图。(这几个图表插件Buy from AnyChart)
下面实例step by step 发柱状和饼图。
准备工作:创建一个Application,在新的Application中创建一个页面Page1
在新的Page1中创建一个HTML区域 命名为new search1(序列号50)。Pl/sql登录往table:jjl_test里插入值:
- 在区域new search1中右键选择 Create Sub Region,弹出的页面中选择 Chart,点击Next,选择ChartType:Column/3D Column,Chart Rendering:HTML5 Chart
- 定义需要创建的Chart:Display Attributes,如图
上图中的 Color Scheme:是Chart的显示颜色主题,也可支持自设颜色。
Show Grid:Y-axis 设置Y轴显示网络
Show ints: 设置当鼠标移动到柱状图上时是否显示提示信息。
Show Labels:设置Chart的柱状条下是否显示名称
Show Values: 设置是否显示柱状条的值
- 点击Next 设置Source,即该Chart的数据源。数据源的SQL有两种写法,第一种是直接赋SQL。
SELECT NULL url,
to_char(jt.login_date, 'MON RRRR') label ,
SUM(decode(jt.login_name, 'admin', jt.login_count, 0)) "admin",
SUM(decode(jt.login_name, 'developer', jt.login_count, 0)) "developer",
SUM(decode(jt.login_name, 'end user', jt.login_count, 0)) "end user",
SUM(decode(jt.login_name, 'super admin', jt.login_count, 0)) "super admin"
FROM jjl_test jt
GROUP BY to_char(jt.login_date, 'MON RRRR')
配置图表的Source的SQL,第一列为URL,即点击柱状条的一个链接,第二列为2)里的Show Labels的Label值.后面的SQL例为2)里的Show Values的Value
第二种写一个pl/sql表达式
CREATE or REPLACE function login_data_fn
l_qry VARCHAR2(32767);
BEGIN
l_qry := 'SELECT null, to_char(jt.login_date, 'MON RRRR') label ';
--Loop through the login_name and add a sum(decode...) column with column alias
FOR r1 IN (SELECT DISTINCT login_name FROM jjl_test)
LOOP
l_qry := l_qry || 'sum(decode(jt.login_name,''' || r1.login_nmae ||
''', jt.login_count,0)) ' || r1. login_nmae || ',';
END LOOP;
--Trim off trailing comma
l_qry := rtrim(l_qry, ',');
--Append the rest of the query
l_qry := l_qry || 'FROM jjl_test jt GROUP BY to_char(jt.login_date, ''' ||'MON RRRR'||''')';
RETURN l_qry;
END login_data_fn;
运行效果图:
当配置Source为某一个月的时候,运行效果如下图:
当在第一个3D柱状图表中再配置一个Source:
运行效果如图:
同理 饼图制作也如上述一致,只是配置Chart Type为Pie/3D Pie,配置Source的时候SQL赋值为:
运行效果图
-
-
- PDF、Word、Excel报表开发
-
与EBS的报表开发一样,也是基于xml+layout,简单的举个例子即可
创建xml Data
创建layout,
Xml 绑定布局文件rtf
在page中创建button:Print
Action:Download Printable Report Query
Report Query:testquery
运行效果如图: