Special Tips for List Items in Oracle D2k
In this section, I shall discuss some special tips and techniques offered by Forms with respect to lists and list items.
Populating List Items Dynamically in Oracle D2kList items appear as either drop-down list boxes, T-lists, or combo boxes in Forms. Mostly, list items have static values as their elements, created during design time. However, there arises a need to populate a list item with elements based on runtime criteria or from a database table. For example, one might populate a drop-down list box with all the state codes from a look-up table named STATE_TAB. This can be done either using a query or adding elements one by one at runtime. This way of populating list items programmatically without hard-coding their values at design time is what is termed dynamically populating list items.
This technique involves populating the list with a query or without a query. I will discuss populating by means of a query because it is very powerful and efficient.
One elegant way to populate list items dynamically is to use programmatically created records groups. This record group should have a two-column structure, both being of character data type. The first column should correspond to the label of the list item, and the second column, to the corresponding value.
Tip
The record group has to be created programmatically. However, it can either query or nonquery as long as it follows the two-column structure mentioned here.
Never try to populate a list item using a query directly. Always create and populate a query record group, and use this record group to do the job.
The code performs these tasks:
Create the record group using CREATE_GROUP_FROM_QUERY.
Populate the record group using POPULATE_GROUP or POPULATE_GROUP_FROM_QUERY.
Populate the list item using POPULATE_LIST.
The sample code is given here:
DECLARE
rg_list_id recordgroup;
rg_name VARCHAR2 (20) := 'RG_LIST';
ret_code NUMBER;
--The following holds a SELECT query from which the list elements are derived.
v_select VARCHAR2 (300);
BEGIN
v_select := 'SELECT state_code, state_code FROM state_tab ORDER BY 2';
rg_list_id := FIND_GROUP (rg_name);
IF NOT ID_NULL (rg_list_id)
THEN
DELETE_GROUP (rg_list_id);
END IF;
rg_list_id := CREATE_GROUP_FROM_QUERY (rg_name, v_select);
ret_code := POPULATE_GROUP (rg_list_id);
POPULATE_LIST ('LIST_ITEM', 'RG_LIST');
DELETE_GROUP (rg_list_id);
END;
Tip
Use a form procedure, passing the input query and list item name as parameters.
A nonquery record group can also be used instead of a query record group, provided that it is created programmatically using CREATE_GROUP and populated using POPULATE_GROUP or POPULATE_GROUP_WITH_QUERY.
Populating a List Item with Date and Number Values in Oracle D2kSometimes, it might be necessary to populate NUMBER and DATE columns as list item element values. Because list items always retain character values only, for both the label and value, it is necessary to perform conversion to VARCHAR2 from NUMBER and DATE.
As an illustration, consider a drop-down list box showing all departments in an organization. You can assume that the DEPT table has the following structure:
CREATE TABLE DEPT
(ID NUMBER(6) PRIMARY KEY,
NAME VARCHAR2(30) NOT NULl);
The label column has its values derived from the NAME column. The value corresponding to each NAME is derived from the ID column and should be stored in the list item as a character value. This requires the use of TO_CHAR. Therefore, the query text in the preceding example changes to
v_select := 'SELECT name, TO_CHAR(id) FROM dept ORDER BY 1';
After populating the list, the value can be accessed by doing a reconversion to NUMBER using the TO_NUMBER function. The following shows how to access the ith element from the list discussed in the preceding example:
DECLARE
v_id NUMBER;
v_id_char VARCHAR2 (6);
item_id item;
BEGIN
item_id := FIND_ITEM ('LIST_ITEM');
IF ID_NULL (item_id)
THEN
MESSAGE ('Invalid List');
RAISE form_trigger_failure;
END IF;
FOR i IN 1 .. GET_LIST_ELEMENT_COUNT (item_id)
LOOP
v_id_char := GET_LIST_ELEMENT_VALUE (item_id, i);
v_id := TO_NUMBER (v_id);
END LOOP;
END;
Tip
Use conversion functions TO_CHAR, TO_DATE, and TO_NUMBER.
On input to the list, use TO_CHAR for both date and numeric values that correspond to the Value column of the list.
On output from the list, use TO_DATE and TO_NUMBER, respectively, for date and numeric values.
Use these in the SELECT column list, which is used to populate the list.
Adding Items to the Beginning of a List in D2kHow many of you are aware of the fact that in Forms, you can add elements to the beginning of an already populated list item without repopulating it? This seems trivial at first thought but is a very powerful and flexible technique to be used in many demanding situations.
Use ADD_LIST_ELEMENT and specify the constant 1 for the element index. This displaces all the existing elements to one position below and makes room for the new element with index number 1. Do not specify the constant 0 instead of 1.
The code you will use is as follows:
ADD_LIST_ELEMENT(list_id, 1, <label>, <value>);
Adding Items in the Middle and to the End of a List in D2kSo far, I have discussed how to add elements dynamically to an empty list, how to access noncharacter list elements, and how to add to the beginning of an existing list. Now I will present a simple method to insert elements in the middle of an existing list and to append elements to the end of an existing list.
Use ADD_LIST_ELEMENT and specify the index number of the new element as
current element index + 1
where current element is the element after which the new element should be added. This displaces all the remaining elements to one position below and makes room for the new element.
To add to the end of the list, specify the constant returned by GET_LIST_ELEMENT_COUNT, which gives the number of existing elements, and then specify the index of the new element as the value of this constant incremented by 1.
The following is the code for this:
DECLARE
cnt NUMBER := 0;
BEGIN
cnt := GET_LIST_ELEMENT_COUNT(list_id);
ADD_LIST_ELEMENT(list_id, (cnt+1), <label>, <value>);
END;
In this example, you take the count of the list elements and increment it by 1. This value serves as the index for the new list element to be added. This works even when the list is wholly empty, because you initialize the count to zero before incrementing it by 1. Therefore, it adds the first element in case of an empty list.
Simulating a Drill-Down and Drill-Up LOV Using T-Lists in D2kLOV is the Forms acronym for List of Values. It functions in a manner similar to a pick list of choices. Drill-down LOV refers to descending through the LOV to its sublevels, starting from a highlighted element in the LOV.
Drill-down LOVs are very useful for tables involving recursive and/or parent-child relationships. Examples of such relationships are those involving a department and its employees, a manager and employees, or a company and its hierarchical representation.
In each of these cases, a foreign key is involved that is either self-referential or parent- referential. For example, the department-employee relationship involves a parent-referential foreign key from the Department table (the parent table). The manager-employees relationship is self-referential, with the primary and foreign keys being selected from the same table. Also, the information is hierarchical. The company information is another example of a hierarchical representation.
LOVs are a commonly required feature of any application involving this kind of look-ups. The features of LOVs supported by Forms are limited in the sense that
There is no way to do multiselection from an LOV.
There is no way to drill down an LOV into its sublevels.
There is no way to add new rows to the look-up table using an LOV.
Out of these limitations, the most required functionality in case of parent-child relationships, especially tree-oriented, is the drill-down.
Drill-down functionality can be incorporated in an LOV directly using a Forms-provided LOV or using list items. This section discusses the implementation details of building a drill-down LOV using list items. The same method can be followed when using a Forms-supplied LOV.
You will use a T-list and dynamically populate it using a record group. The drill-down is achieved by dynamic replacement of the same record group query again and again till there is no further drill-down. Double-clicking a parent element will show this parent element and all its children one level below. The user "drills down" the LOV to reach a deeper level. The operation is repeatable until leaf elements are reached. The string '- Parent' is appended to the parent element label to identify it as the parent. This element is always the first element of the list, irrespective of whether it has children.
Double-clicking a parent element will show its parent and all its children, that is, one level above. The user "drills up" the LOV to reach a higher level. The operation is repeatable until the root element is reached. Once at the root, the original list is restored; that is, all EMPNOs that exist as MGRs. The string '- Parent' is still appended to the parent element label until the initial list is restored.
The same T-list and the same record group are reused for the drill-down and drill-up operations.
The selection of an element is done by pressing Shift and double-clicking on the element. The normal double-clicking being reserved for drill-down, the Shift+double-click is used as an alternative for selecting an element from the LOV.
Create a block, BLOCK2, having an item named LOV in it. The properties for the block are set as follows: Database Data Block property set to No, Number Of Records Displayed set to 1, Insert Allowed set to Yes, and Update Allowed set to Yes. The properties for the LOV item are as follows: Subclass Information property set to PC_TLIST (property class).
The property class PC_TLIST.
Tip
Remember to create a NULL list element; that is, both the label and its value are NULL. NULL means a null value, not the string 'NULL'.
The EMP table is used to project the hierarchical relationship between manager (MGR column) and employees (EMPNO column). Assume that the EMP table has the following structure:
CREATE TABLE EMP
(EMPNO NUMBER(10) PRIMARY KEY,
ENAME VARCHAR2(30) NOT NULL,
MGR NUMBER(10) REFERENCES EMP (EMPNO),
HIREDATE DATE,
SAL NUMBER(11,2),
JOB VARCHAR2(20),
DEPTNO NUMBER);
The LOV functions the following way. At first, all the employees at the parent level are displayed. The query for doing this follows:
SELECT ename, TO_CHAR(empno) empno FROM emp WHERE
empno IN (SELECT mgr FROM emp a)
This SELECT statement also guarantees that the first-level EMPNO is selected.
A dynamic record group, 'RG_'||'LOV', is created from the preceding query and then populated and repopulated using rows returned by the query. The T-list is populated using this record group. You use a generic procedure for this step. The procedure is named p_populate_list:
PROCEDURE p_populate_list (item_name_in VARCHAR2,
query_in VARCHAR2,
o_retcd OUT NUMBER)
IS
rg_id recordgroup;
retcd NUMBER;
rg_name VARCHAR2 (100);
item_id item;
BEGIN
item_id := FIND_ITEM (item_name_in);
IF ID_NULL (item_id)
THEN
o_retcd := -1;
retrun;
END IF;
rg_name :=
'RG_'
|| SUBSTR (item_name_in,
INSTR (item_name_in, '.', 1) + 1,
LENGTH (item_name_in));
rg_id := FIND_GROUP (rg_name);
IF NOT ID_NULL (rg_id)
THEN
DELETE_GROUP (rg_id);
END IF;
rg_id := CREATE_GROUP_FROM_QUERY (rg_name, query_in);
retcd := POPULATE_GROUP (rg_id);
IF (retcd <> 0)
THEN
o_retcd := retcd;
RETURN;
END IF;
POPULATE_LIST (item_name_in, rg_id);
IF NOT FORM_SUCCESS
THEN
o_retcd := -2;
END IF;
o_retcd := 0;
END;
The appropriate trigger for calling the p_populate_list procedure is WHEN-NEW-FORM-INSTANCE:
WHEN-NEW-FORM-INSTANCE
DECLARE
query_in VARCHAR2 (32767) := 'SELECT ename, TO_CHAR(empno) empno
FROM emp
WHERE empno IN (SELECT mgr FROM emp)';
retcd NUMBER;
BEGIN
p_populate_list ('
block2.lov ', query_in, retcd);
IF (retcd <> 0)
THEN
MESSAGE (' err:could NOT populate list item.');
RAISE form_trigger_failure;
END IF;
END;
The right place for the drill-down code is the WHEN-LIST-ACTIVATED trigger:
DECLARE
query_in VARCHAR2 (32767);
item_name VARCHAR2 (100) := NAME_IN ('SYSTEM.TRIGGER_ITEM');
retcd NUMBER;
current_rows_mgr NUMBER;
current_rows_empno NUMBER;
BEGIN
query_in :=
'select LPAD(ename, ((LEVEL-1)*4+LENGTH(ename)), '''')||
DECODE(TO_CHAR(empno), '
|| NAME_IN (item_name)
|| ', ''- Parent'', NULL) ename, TO_CHAR(empno) '
|| ' FROM emp '
|| 'WHERE empno = '
|| TO_NUMBER (NAME_IN (item_name))
|| 'or mgr = '
|| TO_NUMBER (NAME_IN (item_name))
|| ' START WITH empno = '
|| TO_NUMBER (NAME_IN (item_name))
|| 'CONNECT BY PRIOR empno = mgr';
p_populate_list (item_name, query_in, retcd);
END;
The WHEN-LIST-ACTIVATED trigger is modified as follows (the following listing shows the complete code) to accomplish both drill-down and drill-up:
WHEN-LIST-ACTIVATED
DECLARE
query_in VARCHAR2 (32767);
item_name VARCHAR2 (100) := NAME_IN ('SYSTEM.TRIGGER_ITEM');
retcd NUMBER;
current_rows_mgr NUMBER;
current_rows_empno NUMBER;
BEGIN
IF INSTR (GET_LIST_ELEMENT_LABEL (item_name, 1), 'Parent', 1) = 0
THEN
-- if current element is in the initial list
query_in :=
'SELECT LPAD(ename, ((LEVEL-1)*4+LENGTH(ename)), '''') ||
DECODE(TO_CHAR(empno), '
|| NAME_IN (item_name)
|| ',''- Parent'',NULL) ename, TO_CHAR(empno)'
|| 'FROM emp '
|| 'WHERE empno = '
|| TO_NUMBER (NAME_IN (item_name))
|| 'or mgr = '
|| TO_NUMBER (NAME_IN (item_name))
|| 'START WITH empno = '
|| TO_NUMBER (NAME_IN (item_name))
|| 'CONNECT BY PRIOR empno = mgr ';
ELSIF INSTR (GET_LIST_ELEMENT_LABEL (item_name, 1), 'Parent', 1) > 0
AND (TO_NUMBER (GET_LIST_ELEMENT_VALUE (item_name, 1)) !=
TO_NUMBER (NAME_IN (item_name)))
THEN
-- if current is a child of a parent
query_in :=
'SELECT LPAD(ename, ((LEVEL-1)*4+LENGTH(ename)), '''') ||
DECODE(TO_CHAR(empno), '
|| NAME_IN (item_name)
|| ', ''- Parent'',NULL) ename, TO_CHAR(empno)'
|| 'FROM emp '
|| 'WHERE empno = '
|| TO_NUMBER (NAME_IN (item_name))
|| 'or mgr = '
|| TO_NUMBER (NAME_IN (item_name))
|| 'START WITH empno = '
|| TO_NUMBER (NAME_IN (item_name))
|| 'CONNECT BY PRIOR empno = mgr ';
ELSIF INSTR (GET_LIST_ELEMENT_LABEL (item_name, 1), 'Parent', 1) > 0
AND (TO_NUMBER (GET_LIST_ELEMENT_VALUE (item_name, 1)) =
TO_NUMBER (NAME_IN (item_name)))
THEN
-- if current element is a parent
BEGIN
current_rows_empno := TO_NUMBER (NAME_IN (item_name));
MESSAGE (TO_CHAR (current_rows_empno), acknowledge);
SELECT mgr
INTO current_rows_mgr
FROM emp
WHERE empno = current_rows_empno;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
NULL;
END;
IF current_rows_mgr IS NOT NULL
THEN
query_in :=
'SELECT LPAD(ename, ((LEVEL-1)*4+LENGTH(ename)), '''') ||
DECODE(TO_CHAR(empno), '
|| TO_CHAR (current_rows_mgr)
|| ', ''- Parent'', NULL) ename, TO_CHAR(empno) '
|| 'FROM emp '
|| 'WHERE empno = '
|| current_rows_mgr
|| 'or mgr = '
|| current_rows_mgr
|| 'START WITH empno = '
|| current_rows_mgr
|| 'CONNECT BY PRIOR empno = mgr ';
ELSE
query_in := 'SELECT ename, TO_CHAR(empno) empno FROM emp WHERE
empno IN (SELECT mgr FROM emp)';
END IF;
END IF;
p_populate_list (item_name, query_in, retcd);
END;
Simulating the Find Feature of List of ValuesThe Find feature of LOVs enables you to enlarge or reduce the LOV list as the user types in characters of the LOV element value. This feature can be simulated using COMBO BOX and T-LIST type list items in Forms 4.5. Although it doesn't use the exact mechanism offered by LOVs, the method described here imitates the same functionality. You will assume that the list to be displayed is SITE_NAME, based on the SITE_TAB table. The SITE_TAB table has the following structure:
SITE_NO NUMBER(6) NOT NULL,
SITE_NAME VARCHAR2(20) NOT NULL.
Follow these steps:
Create a combo box–type list item. Name it LIST_ITEM_COMBO. The trick lies in using a combo box so that as the user types in characters, the resulting list can be populated with a record group, which is created dynamically, based on user input. A WHEN-LIST-CHANGED trigger would suffice for this.
Create a T-list–type list item below LIST_ITEM_COMBO. Name it LIST_DEST_ITEM. This holds the destination list based on the characters the user types in LIST_ITEM_COMBO.
Create a WHEN-LIST-CHANGED trigger for LIST_ITEM_COMBO as follows:
DECLARE
rg_list_id recordgroup;
ret_code NUMBER;
BEGIN
rg_list_id := FIND_GROUP ('RG_LIST');
IF NOT ID_NULL (rg_list_id)
THEN
DELETE_GROUP (rg_list_id);
END IF;
rg_list_id :=
CREATE_GROUP_FROM_QUERY (
'RG_LIST',
'SELECT site_name, site_name
FROM site_tab
WHERE site_name LIKE '
|| ''''
|| :list_item_combo
|| '%'
|| '''');
ret_code := POPULATE_GROUP (rg_list_id);
POPULATE_LIST ('LIST_DEST_ITEM', 'RG_LIST');
DELETE_GROUP (rg_list_id);
END;
See also: http://www.foxinfotech.in/2013/03/shifting-listitem-values-from12-oracle-forms.html
- Creating Dynamic LOV in Oracle D2k Forms
Dynamic Lov is a good idea for the form where too many Lov requirement is there with different recor ...
- Creating Timer in Oracle D2k / Forms 6i and Displaying a Clock
Creating Timer in Oracle D2k / Forms 6i and Displaying a Clock This is about timer in D2k An externa ...
- Creating Object Library OLB in Oracle D2k Form
With following steps you can create Object Library (OLB) in Oracle D2k Forms.Step - 1Create a form i ...
- DISPLAY_ITEM built-in in Oracle D2k Forms
DISPLAY_ITEM built-in in Oracle D2k Forms DescriptionMaintained for backward compatibility only. For ...
- CHECKBOX_CHECKED built-in in Oracle D2k Forms
CHECKBOX_CHECKED built-in in Oracle D2k Forms DescriptionA call to the CHECKBOX_CHECKED function ret ...
- Obtaining Query Count Without executing a Query in Oracle D2k
Obtaining Query Count Without executing a Query in Oracle D2k Obtaining a count of records that will ...
- Using Call_Form in Oracle D2k
Using Call_Form in Oracle D2k CALL_FORM examples/* Example 1:** Call a form in query-only mode.*/BEG ...
- Using GET_APPLICATION_PROPERTY in Oracle D2k Forms
Using GET_APPLICATION_PROPERTY in Oracle D2k Forms DescriptionReturns information about the current ...
- Pre-Query trigger in Oracle D2k / Oracle Forms
Pre-Query trigger in Oracle D2k / Oracle Forms DescriptionFires during Execute Query or Count Query ...
随机推荐
- 锋利的JQuery(一)
释义: Ajax:Asynchronous Javascript And XML,异步的Javascript和XML 其它库: Prototype:最早 Dojo:学习曲线陡 YUI:比较丰富 Ext ...
- shell 条件测试语句三种方法
1.test -f file 2.[ -f file ] 3.[[ -f file ]] [ -f file1 -a -f file2]逻辑与[ -f file1 -o -f file2]逻辑或 [ ...
- 鸟哥的linux私房菜学习记录之开机流程、模块管理与Loader
- selenium+phantomJS学习使用记录
背景知识: phantomjs是一个基于webkit的没有界面的浏览器,所以运行起来比完整的浏览器要高效. selenium是一个测试web应用的工具,目前是2.42.1版本,和1版的区别在于2.0+ ...
- webservice cxf error:org.apache.cxf.interceptor.Fault: Unmarshalling Error: 意外的元素 (uri:"", local:"ca
服务器端webservice接口 需要定义@WebParam,如: public ReturnDTO cardBatchSyn(@WebParam(name = "cardBatchSynM ...
- Oracle 行迁移和行链接
一.行迁移 1.1.行迁移概念 当一个行上的更新操作(原来的数据存在且没有减少)导致当前的数据不能在容纳在当前块,我们需要进行行迁移.一个行迁移意味着整行数据将会移动,仅仅保留的是一个转移地址.因此整 ...
- Centos6.5和Centos7 php环境搭建如何实现呢
首先我们先查看下centos的版本信息 代码如下: #适用于所有的linux lsb_release -a#或者cat /etc/redhat-release#又或者rpm -q centos-rel ...
- php中引用和赋值的区别主要在哪里
php中引用和赋值的区别 <pphp 的引用允许用两个变量来指向同一个内容. 相当于他们可以是 不同的名字,却可以指向 同一个 物理空间. 赋值,它实际上意味着把右边表达式的值赋给左边的运算数. ...
- 集合(Collection)使用笔记
Collections.unmodifiableCollection这个可以得到一个集合的镜像,它的返回结果不可直接被改变,否则会提示 java.lang.UnsupportedOperationEx ...
- asp.net dropdownlist和listbox
if (!IsPostBack) { //页面初次加载时执行这里的内容 DataSet ds = new DataSet(); //数据集 ds.Tables.Add("stu") ...