APEX 4.1 Shuttle Null on Right - oracle-apex

APEX version: 4.1.1.00.23
I have a shuttle that populates the right site based on what is chosen from a select list. Whenever an item is picked from the select list, the correct item or items are populated on the right panel, but there is always a null that is added. How do I get ride of the null?
Shuttle name: P51_Shuttle
Select list name: P51_Analyst
Here is my code:
HTML Header:
<script type="text/javascript">
function LoadRightPane()
{
var objDQAnalyst = document.getElementById("P51_DQ_ANALYST");
var ajaxRequest = new htmldb_Get(null,&APP_ID.,'APPLICATION_PROCESS=get_DQAttributes',0);
ajaxRequest.add('P51_DQ_ANALYST',objDQAnalyst.value);
ajaxResult = ajaxRequest.get();
//alert(ajaxResult);
if(ajaxResult)
{
var shuttleRight = document.getElementById("P51_SHUTTLE_RIGHT");
shuttleRight.options.length = 0;
var attrArray = ajaxResult.split("~colsep~");
for(var i=0; i < attrArray.length; i++) {
shuttleRight.options[i] = new Option(attrArray[i], attrArray[i]);
}
}
else
{
shuttleRight.options.length = 0;
}
ajaxRequest = null;
}
function moveitem(item) {
return;
s_left = document.getElementById("P51_SHUTTLE_TO_LEFT");
db.transaction(function(tx){
tx.executeSql('select distinct DQ_ATTRIBUTE from DQ_MANUAL_EDIT where DQ_ANALYST = ?',[item],function(tx,results)
{
for (var i=0; i < s_left.options.length;i++)
{
if (results.value == s_left.options[i].value)
{
s_left.options[i].selected = true;
g_Shuttlep_v15.move();
}
}
});
});
}
</script>
Page HTML Body Attribute:
onLoad="Javascript:LoadRightPane();"
Applicaiton/Page process called (get_DQAttributes)
DECLARE
L_RETURN VARCHAR2(2000):= NULL ;
BEGIN
BEGIN
FOR rec IN (
select distinct dq_attribute
from DQ_MANUAL_EDIT
where dq_analyst = :P51_DQ_ANALYST
)
LOOP
L_RETURN := L_RETURN || rec.dq_attribute || '~colsep~' ;
END LOOP;
end;
htp.prn(L_RETURN);
END;

Your ajax process always returns something suffixed with ~colsep~
When you run a string like that in firebug:
"test1~colsep~".split("~colsep~")
The result will be an array with 2 elements:
["test1", ""]
So your NULL element originates from that. To fix this just adjust the ajax process to trim the last separator with RTRIM.
DECLARE
L_RETURN VARCHAR2(2000):= NULL ;
BEGIN
FOR rec IN ( select distinct dq_attribute
from DQ_MANUAL_EDIT
where dq_analyst = :P51_DQ_ANALYST)
LOOP
L_RETURN := L_RETURN || rec.dq_attribute || '~colsep~' ;
END LOOP;
l_return := rtrim(l_return, '~colsep~');
htp.prn(L_RETURN);
END;

Everything about Tom's answer is correct. I had to make one modification to the line
l_return := rtrim(l_return, '~colsep~');
When running that code, the last two letters would be removed. And if I had multiple items in the shuttle, the first item would be fine, but the second one would be cut off.
For example:
Using the code: l_return := rtrim(l_return, '~colsep~');
the right panel of the shuttle would look like this
Score
Da
But the actual text should be
Score
Data
So I used the 'substr' function and now it is working
l_return := substr(l_return,0,(length(l_return)-8));
Here is the whole code
DECLARE
L_RETURN VARCHAR2(2000):= NULL ;
BEGIN
FOR rec IN ( select distinct dq_attribute
from DQ_MANUAL_EDIT
where dq_analyst = :P51_DQ_ANALYST)
LOOP
L_RETURN := L_RETURN || rec.dq_attribute || '~colsep~' ;
END LOOP;
L_RETURN := substr(l_return,0,(length(l_return)-8));
htp.prn(L_RETURN);
END;
Thank you Tom for getting my mental ball rolling!!!

Related

How to edit list elements in kotlin or add to second list?

I tried to edit a list in-place but wasn't able to get it working. Now trying to edit individual elements and add them to a second list. However the second list remains null and does not get updated. Any help would be appreciated.
var localFiles: MutableList<String> = File(localPath).list().toMutableList()
var localFileDates: MutableList<String>? = null
val iterateLocal = localFileDates?.listIterator()
for (item in localFiles) {
var date = item.takeLast(10).take(6)
if (date.matches("[0-9]+".toRegex()) and (date.length == 6) and (date != null) and (date != "null")) {
iterateLocal?.add(item.takeLast(10).take(6))
}
}
println(networkFiles) // prints correct outpu
println(localFileDates) // prints null
You need init localFileDates variable:
var localFileDates = MutableList()
var localFiles: MutableList<String> = File(localPath).list().toMutableList()
var localFileDates = MutableList<String>()
val iterateLocal = localFileDates?.listIterator()
for (item in localFiles) {
var date = item.takeLast(10).take(6)
if (date.matches("[0-9]+".toRegex()) and (date.length == 6) and (date != null) and (date != "null")) {
iterateLocal?.add(item.takeLast(10).take(6))
}
}
println(networkFiles) // prints correct outpu
println(localFileDates) // prints correct
It is better to use map{..} function to create a copy of the list with updated values.
val localFiles = File(localPath).list()?.toMutableList() ?: listOf()
val localFileDates = localFiles.mapNotNull { item ->
val date = item.takeLast(10).take(6)
if (date.matches("[0-9]{6}".toRegex()) {
date
} else {
null
}
}
println(localFiles)
println(localFileDates)
I use the mapNotNull{..} function calls the block for every element of the list and builds the new list only from non-null values.
You do not need var in your code, explicit type names can be omitted too.
The condition can be simplified - no need for the null check, the regular expression filters our the data == "null" case, the length check can be included into the regex too. The date variable can be re-used too.
A more idiomatic (and readable) way:
val localFileDates = File(localPath).list().map { it.takeLast(10).take(6) }.filter {
it.matches("[0-9]+".toRegex()) && (it.length == 6) && (it != "null")
}
Also I suggest you create a named function for takeLast(10).take(6) and the condition to make it clear what is the intent of these lines of code.

IRC String comparison is always true

I'm trying to simply compare a line in a text file to today's date.
The line I want help with always seems to evaluate true for my code.
Any examples?
My code:
set %lines $lines(test.txt)
set %date $adate
while (%i <= %lines)
set %read $read(test.txt, n, %i)
if( %date isin %read ){ ; <-- Line in question
do things
}
}
You have a few errors.
Your while loop is missing an open bracket. (And closing at the end)
while (%i <= %lines) {
You must have a space between () { } and the rest of the lines
if<space>(
)<space> {
if ( %date isin %read ) {
I took the liberty of suggesting another version.
Code:
var %filename = test.txt
var %lines = $lines(%filename)
var %currentDate = $adate
var %i = 1
while (%i <= %lines) {
var %line = $read(%filename, n, %i)
if (%currentDate isin %line) {
# do things
# Should uncomment the break in case you want to stop after a match
#break
}
inc %i
}
I am sorry if I didn't understand, but what is the reason for a complex script just to check if there is a date format in a line of a text file?
There is no reason to set a variable %read to store the line of the loop in question, when you can do an IF condition after the loop:
var %x = 1
while (%x <= $lines(test.txt)) {
if ($adate isin $read(test.txt,n,%x)) {
;do things
}
inc %x
}

Append a value at the end of a row of a text file through Siebel escript

My requirement is as follows.
In step 1 my business service will read the records from a text file.
In step 2 they create a record based on the values.
In step 3 it has to append a Success/Failure message at the end of the corresponding record.
Text file will contain multiple records, each field is delimited with '|'. So my requirement is to append Success/Failure after the last value of the record.
Please help.
May be you can have a look at this code.
This code reads data from a Excel Sheet and creates record in Siebel BC. You can implement this as part of a BS. You can also extend this and add logic to include Success or Failure message in each record.
if (MethodName == "ImportRecords")
{
var i =2;
var ExcelApp = COMCreateObject("Excel.Application");
ExcelApp.Workbooks.Open("C:\\***\\***\\Desktop\\LoadTest.xlsx");
ExcelApp.Visible = false;
var oBOLdVal = TheApplication().GetBusObject("Dummy BO");
var oBCLdVal = oBOLdVal.GetBusComp("Dummy BC");
while(ExcelApp.ActiveSheet.Cells(i,1).Value!= null)
{
var A= ExcelApp.ActiveSheet.Cells(i,1).Value;
var B= ExcelApp.ActiveSheet.Cells(i,2).Value;
var C= ExcelApp.ActiveSheet.Cells(i,3).Value;
var D= ExcelApp.ActiveSheet.Cells(i,4).Value;
var E= ExcelApp.ActiveSheet.Cells(i,5).Value;
with(oBCLdVal)
{
ActivateField("A");
ActivateField("B");
ActivateField("C");
ActivateField("D");
ActivateField("E");
ClearToQuery();
InvokeMethod("SetAdminMode","TRUE");
NewRecord(NewAfter);
SetFieldValue("A",A);
SetFieldValue("B",B);
SetFieldValue("C",C);
SetFieldValue("D",D);
SetFieldValue("E",E);
SetFieldValue("Status","Success");
WriteRecord();
} i=i+1;
} ExcelApp.Quit();
ExcelApp = null;
oBOLdVal = null;
oBCLdVal = null;
TheApplication().RaiseErrorText("Load Success");
return(CancelOperation);
}
Hope this helps!

Delphi - ValueListEditor not adding new row

I have a procedure which needs to read data from an ini file with the following format:
'Prices', [integer], [data to be read]
The data read consists of two pieces of information split by a '/' symbol. The data is split successfully when I call my procedure below.
I have a TValueListEditor (called ledtPrices) placed on the form and would like to add the values from the ini file to the List Editor. If I call ledtPrices.InsertRow via a button click, the values I enter into to add to the row are added and the list editor is refreshed.
However, when I call the same function from my RefreshPList procedure, the values are not added as new rows (the list editor is blank). I have tested my code with ShowMessage dialogues to ensure each part of the procedure is functioning when it should. My code is as follows:
procedure RefreshPList;
var
l: TValueListEditor;
xFile: TINIFile;
temprow, tl, tp: string;
tempr: TStringList;
i: integer;
begin
i := 0;
l := frmSettings.ledtPrices;
try
tempr := TStringList.Create;
tempr.StrictDelimiter := True;
tempr.Delimiter := '/';
xFile := TIniFIle.Create('C:\MData.ini');
try
temprow := xFile.ReadString('Prices', '0', 'xx');
if temprow = 'xx' then
ShowMessage('no prices saved')
else
begin
repeat
temprow := xFile.ReadString('Prices', IntToStr(i), 'xx');
if temprow <> 'xx' then
begin
tempr.DelimitedText := temprow;
tl := tempr[0];
tp := tempr[1];
l.InsertRow(tl,tp,true);
//ShowMessage(tl);
Inc(i);
end
else
ShowMessage('End of list');
until (temprow = 'xx');
//l.Refresh;
end;
finally
xFile.Free;
end;
LastLine := i;
finally
tempr.Free;
end;
end;
LastLine is a global integer value to be used later. I'm trying to add, remove and edit data within the list editor, without editing the cells directly. The procedure to add new data to the ini file has been written and runs successfully.
UPDATE
I've come to realise that any procedure that I create which tries to edit a components values does not edit the components values. Am I missing something simple here?
For example, I created a memo on the form and created a procedure which adds the contents of an array to the memo.lines. This procedure did not execute when called from a buttonclick. However, if I copy the contents of the procedure directly into the buttonclick and execute it, it works.
The procedures are called from buttonclick commands. The form is created from a mainform. The components all sit within a pagecontrol tabsheet.
A quick test application (XE5, VCL Forms) cannot reproduce the problem.
I start with a new blank application, drop a TValueListEditor and a TButton on the form, and use the Object Inspector to add two key/value combinations:
Key Value
--- -----
A Aaaaaaa
C Ccccccc
In the TButton.OnClick event, I use the following code:
procedure TForm1.Button1Click(Sender: TObject);
var
NewKey, NewValue: string;
begin
NewKey := 'B';
NewValue := 'Bbbbbbb';
ValueListEditor1.InsertRow(NewKey, NewValue, True);
end;
I run the application:
I click Button1, and the code successfully adds the new item at the end (bottom) of the TValueListEditor.
I change the last parameter to InsertRow to False, and it inserts it at the start (top) of the TValueListEditor.
This indicates that either you're not getting the values you expect from your ini file, or the code that inserts the new row isn't executing.
Here's the full code of the test app I created:
Unit1.dfm
object Form4: TForm1
Left = 0
Top = 0
Caption = 'Form4'
ClientHeight = 178
ClientWidth = 447
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object ValueListEditor1: TValueListEditor
Left = 40
Top = 16
Width = 306
Height = 137
Strings.Strings = (
'A=Aaaaaaa'
'C=Ccccccc')
TabOrder = 0
end
object Button1: TButton
Left = 352
Top = 16
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 1
OnClick = Button1Click
end
end
Unit1.pas
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Grids, Vcl.ValEdit;
type
TForm1 = class(TForm)
ValueListEditor1: TValueListEditor;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
NewKey, NewValue: string;
begin
NewKey := 'B';
NewValue := 'Bbbbbbb';
ValueListEditor1.InsertRow(NewKey, NewValue, True);
end;
end.

Overhead of an If statement inside cursor loop vs a cursor select

suppose I have a procedure that takes in a siteId and empId
which makes the primary key (siteId emp.site_id%TYPE, empId emp.emp_id%TYPE)
and I'm trying to create an xml clob, I have method called createParent() which creates a parent node, another method called put_child_node, which takes in a parentNode, child element name, and child element value, however the name and the attribute are taken from a join on two tables. see code:
DECLARE
cursor has_emp_attribute
select 1
from emp_attribute
where site_id = siteId
and emp_id = empId; <-- quick select
cursor get_emp_attributes
select an.name, ea.attribute_value
from attribute_name an, emp_attribute ea
where an.attribute_id = ea.attribute_id
and ea.site_id = siteId
and ea.emp_id = empId;
hasAttribute boolean;
parentNode xmldom.domnode;
BEGIN
hasAttribute := false
for has_emp_attribute_rec in has_emp_attribute
loop
hasAttribute := true;
parentNode = createParentNode();
exit;
end loop;
if (hasAttribute) then
for get_emp_rec in get_emp_attributes
loop
put_child_node(parentNode, get_emp_rec.name, get_emp_rec.attribute_value);
end loop;
end if;
END;
If instead I used an if statement to check if we have records inside the second cursor, and create the parentNode in there would this be a better solutions:
cursor get_emp_attributes
select an.name, ea.attribute_value
from attribute_name an, emp_attribute ea
where an.attribute_id = ea.attribute_id
and ea.site_id = siteId
and ea.emp_id = empId;
hasAttribute boolean;
parentNode xmldom.domnode
BEGIN
hasAttribute := false
for get_emp_rec in get_emp_attributes
loop
if(hasAttribute = false) then
parentNode := createParentNode();
hasAttribute := true;
end if;
put_child_node(parentNode, get_emp_rec.name, get_emp_rec.attribute_value);
end loop;
END;
IF you are creating only one child node in one call than second way is efficient because of less number of cursor and loop. Just make sure that your cursor query fetches the child node for that particular parent.