I'm a progress noob, actually having problem with basic blocks.
Below the issue is in my if else statement. It works fine when its just if, then, else then, but when I want to put in more than one statement into the if portion, I have to put it in a block, so I'm using if, then do: else, then do: but these aren't working for me. Any obvious errors you can see? My error message is **Colon followed by white space terminates a statement. (199)
INPUT FROM "r:\_content\stephen\4gl apps\dpl\output.csv".
REPEAT:
ASSIGN i_cntr = (i_cntr + 1).
myRow = "".
IMPORT DELIMITER ',' myRow.
IF myRow[5] <> "" THEN DO:
/*change this to assign 2 rows - 2 creates - 2 sets of four*/
c_fname = myRow[1].
MESSAGE
c_fname SKIP
myRow[2] SKIP
myRow[3] skip
myRow[4] skip
myRow[5] SKIP
i_cntr
VIEW-AS ALERT-BOX INFO BUTTONS OK.
END./*end of if, then do:*/
ELSE IF myRow[5] = "" THEN DO:
MESSAGE
myRow[1] SKIP
myRow[2] skip
myRow[3] skip
myRow[4] skip
i_cntr
VIEW-AS ALERT-BOX INFO BUTTONS OK.
END./*end of else if, then do:*/
END./*end of repeat*/
A very simple syntax error: you need at least one space after the END-statement.
END. /*end of if, then do:*/
/* ^ Make sure there's space above here! */
And if you don't want to follow the excellent advice in Tims answer (use CASE). This is the "complete" syntax of the IF statement.
IF expression1 THEN DO:
/* Code goes here */
END.
ELSE IF expression2 THEN DO:
/* Code goes here */
END.
ELSE DO:
/* Code goes here */
END.
expressions:
A constant, field name, variable name, or expression whose value is logical (TRUE or FALSE). The expression can include comparisons, logical operators, and parentheses.
You can also leave out the DO: END. When the IF code to be executed only consists of a single statement:
IF TRUE THEN DISPLAY "TRUE".
ELSE DISPLAY "NOT TRUE".
You could also use other block-statements (such as FOR or REPEAT) but that will most likely only create code that is hard to read.
Rather than using nested IF/ELSE, you'd be better off using a CASE statement like so:
CASE varname:
WHEN "" THEN DO: /*something */ END.
WHEN "value" THEN DO: /*something */ END.
OTHERWISE DO: /*something */ END.
END CASE.
Check the docs on this statement for more details.
I figured out the issue. This wasn't caused by a coding error. Apparently Progress doesn't like comments too close to the code, which caused it to throw an error.
END. /*end of if, then do:*/ => This is ok.
END./*end of if, then do:*/ => This caused the issue comments too close to statement.
Thanks To Tim Kuehn for his response.
Related
my goal is change a function to a format where the return value of the function is treated :
For example ; treating a the function scanf()
Return value of scanf : The value EOF is returned if the end of input is reached before
either the first successful conversion or a matching failure occurs.
EOF is also returned if a read error occurs, in which case the error
indicator for the stream (see ferror(3)) is set, and errno is set to
indicate the error.
Thus
scanf("%d\n",&i);
will be change to
#define RVAL(exp) do {if ((exp) == -1) { perror (#exp); exit(1); }} while (0)
...
RVAL(scanf("%d\n",&i));
Thus I want this to be done quickly means :
so what i do is look for occurences of "scanf" and replace it with "RVAL(scanf"
but the problem is i have to add another right parentheses
Can this be done fast ? using a techniques ? or a style ? where each whenever I enter scanf(); its replaced witch rval(scanf());
If you don't have many ) in your format string you can use a regex with (scanf([^)]*)); and replace with rval(\1);
*see comment
I have the following if else statement that created by myself in order to link to the if else statement given in second part:
m=4
if m==3
disp(true)
else
disp(false)
Second part ( this code is fix cannot be change):
if (true)
A=Hello World
else
A=Bye
If using the first part code, my output will be
A=Hello World
but my desire output is
A=Bye
Anyone one have idea to edit the first part, because now my return value in first part not able to link to my second part.
If you can't change the second part's code, I'm afraid your desire cannot be fulfilled. Or rather, I'm afraid your code won't run at all, because your perenthesis, quotes, end-statement (and arguably semicolons) are not in place.
if true
A = 'Hello World';
else
A = 'Bye';
end
This code will return A = 'Hello World', no matter what, since true is always true. If-else conditions work like this:
if (*what's in here evealuates to true*)
%do stuff
else (*if what's up there does not evaluate to true*)
%do other stuff
Clearly, true will always evaluate to true. So the above if-else condition will always return A = 'Hello World'.
You don't need two if statements in order to accomplish this task. One is more than enough to perform all what you need:
m = 4;
if (m == 3)
A = 'Hello World';
else
A = 'Bye';
end
disp(A);
A few comments concerning your code:
if statements need to be closed with an end
if (true) will always pass into the statement
the disp function doesn't assign a value, its only goal is to display it in the Command Window
in order to work with text, you have to enclose it within single quotes ' (char array) or double quotes " (string), more info here
If you posted only small excerpts of your code and you need to perform those two checks sequentially, in different parts of your script, then:
m = 4;
if (m == 3)
m_equals_3 = true;
disp('M == 3');
else
m_equals_3 = false;
disp('M ~= 3');
end
% then, somewhere else...
if (m_equals_3)
A = 'Hello World';
else
A = 'Bye';
end
% ...
I guess this is a homework exercise. You should disclose that if it’s the case.
The exercise requieres you to change the workspace such that the second bit of code evaluated the else case. This can be accomplished by changing the meaning of true. In your first bit of code, make it so that
true = flase;
Or equivalently,
true = 0;
Note that this is really bad form, if you ever do something like this outside of a homework exercise that explicitly asks you to do so, you’ll get fired or maybe even shot. You’ve been warned!
By the way, I assume that the missing quote characters around the strings and the missing ends are typos?
I have a small problem which I believed I could solve simply, it turns out I'm not able to figure out.
I have following query:
SELECT custom_field
INTO v_start_of_invoice
FROM BILL
WHERE BIMA_TRACKING_ID = v_previous_BIMAtrackingID
AND BSCO_CODE_ID = 'PRPAYMENT'
AND PREP_SEQ_NUM = 0
AND ITEM_CAT_CODE_ID = 1
AND PARTITION_KEY = v_prev_partition
AND SUBPARTITION_KEY = v_prev_subpartition;
What I would like to achieve here is to give to variable v_start_of_invoice the value "0" if one or all the where condition are not met.
In simple word I don't want the script to fail but I want the variable either to be set with some value if all the where conditions are matched, otherwise I want to assign the value 0.
I'm sure there are quite a few ways but I need to check what could be the best way to achieve that.
Many Thks in advance
M.
You seem to have a misunderstanding of what the exception block actually does. First off you cannot avoid the exception. If you use "select into" the query is successful only when exactly 1 row is returned. Otherwise PLSQL will internally raise the NO_DATA_FOUND when the query returns 0 rows, and TOO_MANY_ROWS when it returns more then 1 row. The exception block tells PLSQL what to do when an error is generated. Basically the exception block tells what action to take on specific errors and whether to continue error processing or discard the error. (Check the RAISE and RAISE_APPLICATION_ERROR statements.)
Keep in mind that blocks can be nested. With this in mind and in context of a outer block the solution offered by #are is exactly what you want. The structure becomes:
Begin
.
.
.
begin
place #are's code here.
end ;
-- Continue your code here: The Error has been handled and execution continues as though the exception never happened.
.
.
.
end;
As far as the "NVL(v_start_of_invoice, 0);" it's a function that will return 0 if v_start_of_invoice is NULL and v_start_of_invoice otherwise. Note the value of INTO variables is not it the select generates an error unless you set it in the exception block.
begin
SELECT custom_field
INTO v_start_of_invoice
FROM BILL
WHERE BIMA_TRACKING_ID = v_previous_BIMAtrackingID
AND BSCO_CODE_ID = 'PRPAYMENT'
AND PREP_SEQ_NUM = 0
AND ITEM_CAT_CODE_ID = 1
AND PARTITION_KEY = v_prev_partition
AND SUBPARTITION_KEY = v_prev_subpartition;
exception WHEN NO_DATA_FOUND THEN
v_start_of_invoice := 0;
end;
I have the following code which should do a simple if-else statement using Progress ABL.
I cannot get the program to reach the ELSE statement even when the substring "UK" cannot be found. Can anyone see what I am missing:
FIND FIRST ttShipHead WHERE ttShipHead.ShipToCustCustID = "1404".
IF ttShipHead.AddrList Matches "*UK*" THEN
assign ttShipHead.CheckBox01 = (false).
ELSE
assign ttShipHead.CheckBox01 = (true).
I suggest that you add some debugging:
FIND FIRST ttShipHead WHERE ttShipHead.ShipToCustCustID = "1404" no-error.
message available( ttShipHead ).
pause.
message ttShipHead.AddrList ( ttShipHead.AddrList Matches "*UK*" ).
pause.
IF ttShipHead.AddrList Matches "*UK*" THEN
assign ttShipHead.CheckBox01 = (false).
ELSE
assign ttShipHead.CheckBox01 = (true).
message ttShipHead.Checkbox01.
pause.
This should make it clear what is going wrong.
I don't know a whole lot about ABL. But I think the syntax is
IF expression THEN DO: work. So try adding a DO: after your THEN
If there's a message on the screen about record ttshiphead not found, then it's not running the IF statement at all.
Typically FINDs have a "NO-ERROR" followed by an "IF AVAILABLE ttshiphead THEN " where required.
Your code looks correct. Maybe some small changes to make sure you have record.
FIND FIRST ttShipHead WHERE ttShipHead.ShipToCustCustID = "1404" NO-ERROR.
IF AVAILABLE ttShipHead THEN
IF ttShipHead.AddrList MATCHES "*UK*":U THEN
assign ttShipHead.CheckBox01 = (false).
ELSE
assign ttShipHead.CheckBox01 = (true).
if you want to can add and else to show if record not available.
FIND FIRST ttShipHead WHERE ttShipHead.ShipToCustCustID = "1404" NO-ERROR.
IF AVAILABLE ttShipHead THEN
IF ttShipHead.AddrList MATCHES "*UK*":U THEN
assign ttShipHead.CheckBox01 = (false).
ELSE
assign ttShipHead.CheckBox01 = (true).
ELSE
MESSAGE "NO RECORD FOUND".
When I read data into a dataset with the method hDataset:READ-XML() and the path to the file is incorrect, Progress first shows a warning message (warning nr 4065) and then an error message. I can catch (using a CATCH block) the error message, but not the warning. The user must remove the warning manually.
How can I suppress this warning?
DEFINE TEMP-TABLE tt NO-UNDO
FIELD a AS CHARACTER.
DEFINE DATASET ds FOR tt.
DO ON ERROR UNDO , LEAVE:
/* Reading non existing xml-file */
DATASET ds:READ-XML("FILE", "c:\dddw\s.xml","empty","", FALSE, "","" ).
CATCH err AS Progress.Lang.Error :
MESSAGE err:GETMESSAGE(1)
VIEW-AS ALERT-BOX INFO BUTTONS OK.
END CATCH.
END.
Generelly in Progress ABL you supress messages with adding NO-ERROR after the command/method.
hDataset:READ-XML() NO-ERROR.
After that you would normally check if ERROR-STATUS:STATUS = TRUE (an error occured), however that doesn's seem to work in this case.
This examples work:
DEFINE TEMP-TABLE tt NO-UNDO
FIELD a AS CHARACTER.
DEFINE DATASET ds FOR tt.
DEFINE VARIABLE i AS INTEGER NO-UNDO.
/* Reading non existing xml-file */
DATASET ds:READ-XML("FILE", "c:\dddw\s.xml","empty","", FALSE, "","" ) NO-ERROR.
/* This is false */
DISP ERROR-STATUS:ERROR.
/* However, ERROR-STATUS:NUM-MESSAGES shows 2 errors */
IF ERROR-STATUS:NUM-MESSAGES > 0 THEN DO:
DO i = 1 TO ERROR-STATUS:NUM-MESSAGES:
DISPLAY ERROR-STATUS:GET-MESSAGE(i) FORMAT "x(66)".
PAUSE.
END.
END.
If the file you want to read is local you can (should?) do SEARCH(path+file) first - that will return ? if the file doesn't exist.
IF SEARCH("/mydir/myfile.xml") = ? THEN DO:
MESSAGE "The file seems to be lost" VIEW-AS ALERT-BOX ERROR.
RETURN.
END.
ELSE DO:
/* Read XML etc */
END.