GROUP BY Function in Progress OpenEdge - progress-4gl

I am trying to find out how to do the Progress equivalent of a "GROUP BY" function. I am trying to write a procedure that will list product inventory information for multiple locations. Right now, it is listing the product information twice; once for each location. I have tried the BREAK BY functional unsuccessfully. My current & desired output and code is below:
Current Output:
Desired Output:
DEF INPUT PARAMETER ip-um AS CHARACTER NO-UNDO.
MESSAGE
"ProdCode" + "^" +
"ProdName" + "^" +
"ProdUM" + "^" +
"GrossPkgdWeight" + "^" +
"QtyOH - LOC1" + "^" +
"QtyOH - LOC2"
SKIP.
FOR EACH product-um WHERE
product-um.gross-pkgd-weight <= 0.0000
NO-LOCK,
EACH product WHERE
product.product-key = product-um.product-key AND
product.can-be-sold = YES
NO-LOCK,
EACH inventory WHERE
inventory.product-key = product.product-key AND
inventory.qoh > 0 AND
inventory.level = 2
NO-LOCK,
EACH um WHERE
um.um-key = product-um.um-key AND
um.um = ip-um
NO-LOCK
BREAK BY product.product-code:
MESSAGE
product.product-code + "^" +
product.product-name + "^" +
um.um-code + "^" +
STRING(product-um.gross-pkgd-weight) + "^" +
IF inventory.level-key-2 = '00000001' THEN STRING(inventory.qoh) ELSE "0"
+ "^" + IF inventory.level-key-2 = '00000002' THEN STRING(inventory.qoh) ELSE "0"
SKIP.
END.

because you accumulate invesntory.qoh in dependency of inventory.level-key-2 the ACCUMULATE stmt is not realy feasible so coding the accumulation manually would be the best choise
DEFINE VARIABLE loc1 AS INTEGER NO-UNDO.
DEFINE VARIABLE loc2 AS INTEGER NO-UNDO.
FOR EACH product-um NO-LOCK
WHERE product-um.gross-pkgd-weight <= 0.0000
,
EACH product NO-LOCK
WHERE product.product-key = product-um.product-key
AND product.can-be-sold = YES
,
EACH inventory NO-LOCK
WHERE inventory.product-key = product.product-key
AND inventory.product-code = product.product-code
AND inventory.qoh > 0
AND inventory.level = 2
,
EACH um NO-LOCK
WHERE um.um-key = product-um.um-key
and um.um = ip-um
BREAK
BY product.product-code:
CASE (inventory.level-key-2):
WHEN "00000001"
THEN loc1 = loc1 + inventory.qoh.
WHEN "00000002"
THEN loc2 = loc2 + inventory.qoh.
END CASE.
IF LAST-OF(product.product-code)
THEN DO:
MESSAGE
product.product-code + "^" +
product.product-name + "^" +
um.um-code + "^" +
STRING(product-um.gross-pkgd-weight) + "^" +
STRING(loc1) + "^" +
STRING(loc2)
SKIP.
ASSIGN
loc1 = 0
loc2 = 0
.
END.
END.

BREAK BY tells the compiler to mark when the FOR EACH has come to the start or end of a break group.To detect these changes you'll need to use one of these functions to detect that change: FIRST(table.field), FIRST-OF(table.field), LAST(table.field), and LAST-OF(table.field).
Once the required function returns true, you can use the ABL supplied functions like ACCUMULATE, COUNT, TOTAL, etc. to display the desired results. Personally I find the concepts a bit hard to get my head around, so I declare some local variables and do the totals that way.

Related

simplifying a boolean expression using DeMorgans

This is the expression I need to simplify:
[{(AB)'*(BC)'} + (A'C)']'
Right now I have my answer as (AB + BC).(A' + C)
I don't think my answer is right but I'm not sure. IF someone could show steps on how to simplify that would be really appreciated, thanks!
((AB)'(BC)' + (A'C)')' = ((AB)'(BC)')'(A'C)'' ; DeMorgan
= ((AB)'' + (BC)'')(A'C) ; DeMorgan + double negation
= (AB + BC)(A'C) ; double negation
= ABA'C + BCA'C ; distribution
= BCA' ; AA'=0

QBASIC Decimal to Binary conversion

I have converted a decimal number to binary using STR$() in QBASIC. But I need a way to convert decimal number to binary without using string functions. Thanks.
My Code :
CLS
INPUT N
WHILE N <> 0
E = N MOD 2
B$ = STR$(E)
N = FIX(N / 2)
C$ = B$ + C$
WEND
PRINT "Output "; C$
END
This code sample converts a numeric value to a binary string in Basic.
PRINT "Enter value";
INPUT Temp#
Out3$ = ""
IF Temp# >= False THEN
Digits = False
DO
IF 2 ^ (Digits + 1) > Temp# THEN
EXIT DO
END IF
Digits = Digits + 1
LOOP
FOR Power = Digits TO 0 STEP -1
IF Temp# - 2 ^ Power >= False THEN
Temp# = Temp# - 2 ^ Power
Out3$ = Out3$ + "1"
ELSE
Out3$ = Out3$ + "0"
END IF
NEXT
END IF
PRINT Out3$
END
When you want to display an integer value as binary, it seems logical to me to store it in a string variable, because it's only for display. So I'm not really sure what you are trying to do here.
Maybe you were looking for LTRIM$ so you would get outputs like 11010 instead of 1 1 0 1 0 ?
You could store it in an integer value like in the code below. But, although the integer value will look the same as the string variable, it will in fact be a completely different value.
CLS
INPUT "Type a decimal number:", N
S$ = ""
I = 0
P = 1
WHILE (N <> 0)
' get right most bit and shift right
E = N AND 1
N = INT(N / 2) ' bit shift right
' format for dsplay
S$ = LTRIM$(STR$(E)) + S$
I = I + (E * P)
P = P * 10
WEND
PRINT "Binary as string="; S$
PRINT "Binary as int="; I
END

how to solve this boolean algrbra expression

I would like help simplifying this boolean algebra expression:
B*C + ~A*~B + ~A*~C => A*B*C + ~A
I need to know the steps of how to simplify it to the ABC + ~A
'*' indicates "AND"
'+' indicates "OR"
"~A" indicates "A NOT"
Any help would be appreciated!
Thank you!
For a better view, i'll skip * for conjunction, and use ' for negation.
First you shall expand the 2 term disjunctions: Expand B*C , A'*B' and A'*C'
1) (A + A')BC + A'B'(C + C') + A'(B + B')C'
now distribute the parentheses.
2) ABC + A'BC + A'B'C + A'B'C' + A'BC' + A'B'C'
the fourth term and the last term are the same, A'B'C', so ignore one of them since p + p = p or you can expand the situation for your needs (might be needed for some situations) as in p+p+p+p+....+p = p
3) So now, lets try to search for common terms. See the 2nd term and 5th term, A'BC and A'BC'. Take common parenthesis, A'B(C+C') => A'B.
Do the same for 3rd term and the 4th term, A'B'C and A'B'C'. A'B'(C+C') => A'B' since X+X' = 1.
now we have:
ABC + A'B + A'B'
4) take common parenthesis again, 2nd and 3rd term: A'(B+B')
There you have ABC + A'
BC + A'B' + A'C' => ABC + A'

Nested 'if' statement inside 'for' loop not working - MATLAB

for Temp = 1000:10:6000
cp_CO2 = ((2e-18)*Temp.^5) - ((4e-14)*Temp.^4) + ((3e-10)*Temp.^3) - ((8e-07)*Temp.^2) + (0.0013*Temp) + 0.5126;
cp_CO = ((5e-12)*Temp.^3) - ((7e-08)*Temp.^2) + (0.0003*Temp) + 0.9657;
cp_H2O = ((7e-12)*Temp.^3) - ((1e-07)*Temp.^2) + (0.0008*Temp) + 1.6083;
cp_N2 = ((-1e-18)*Temp.^5) + ((2e-14)*Temp.^4) - ((8e-11)*Temp.^3) + ((1e-07)*Temp.^2) + (0.0001*Temp) + 0.9985;
D_H = (y(1)*cp_CO2*44*(25-Temp)) + (y(2)*cp_CO*28*(25-Temp)) + (y(3)*cp_H2O*18*(25-Temp)) + (percent_air*x_final(2)*3.76*28*(25-Temp));
DELTA_H = round(D_H);
if DELTA_H == delta_h
break
end
end
The 'for' loop in my code is above, the variables delta_h, y and percent_air have been defined and calculated/input earlier. If I work on the loop as a cell and manually increase Temp then the values of D_H etc. all change. But for some reason when I try and execute the loop the 'if' statement doesn't seem to come into effect and the final values where Temp = 6000 are displayed in the workspace instead of the value of Temp where it produces a DELTA_H equal to that of delta_h. It's the first time I've used MATLAB for about 2 years (I'm a 3rd Year Mech Eng student) so please forgive me if it's a simple error to fix.
If either of the variables are floating-point, doing an exact compare like that is problematic. A <= or >= comparison might work better.

How to use Netbeans Variable Formatters?

By default when viewing watches/variables of objects in Netbeans, it shows its address instead of its value. This is quite tiresome since I have to expand the variable to see its real value (e.g. for Double, Integer, Date, etc). As it turns out, Netbeans has "Variable formatters" but there is hardly any documentation that i can find for it.
How would I go about displaying e.g. a simple Date variable in a human readable format in the Watches/Variables window? I don't fully understand the "Edit Variable Formatter" dialog.
I was able to properly do it for Double and Integer by using the following code snippet:
toString()
So the code seems to run in the context of the Double/Integer class. How would I refer to the actual variable if I need to do something more advanced such as:
return DateHelpers.formatDate(dateVariableName??, "yyyy-MM-dd");
In the variables view, you have a small $ icon (at the top left) which tooltip says :"Show variable value as toString() or formatted value".
Just click that, it will show you the "value" of those variables.
EDIT: If you want to add a variable formatter, it's very simple. On the variable formatter view, just click the "Add ..." button then:
In "Formatter Name" put the name of you formatter eg. "My Date formatter"
"Class Types" put your complete class name eg. java.util.Date
Select "Value formatted as a result of code snippet" and type the code to apply. For instance:
toString()
but if you want to manipulate the data or display some other thing you can. For instance:
toString() + " (" + getTime() + ")"
Which will display the time in human readable format plus the time as a long.
Don't forget to select the $ icon on the view to apply your formatter.
My answer won't solve the question. It will rather echo the previous answers. First, I haven't seen the $ sign in the variables-panel in NetBeans. Seems it was replaced with a context menu in current versions.
I haven't found the answer to the actual question, as of how you would reference the variable to debug, within the "Variable Formatters" Dialog. Something like "this" or "$1" isn't working definitely. Also the facility does not seem to know about Standard Java JRE classes like SimpleDateFormatter.
So when debugging Java JRE classes, I guess you have to live with what they're offering in terms of public methods.
Here's a workaround for the especially user friendly Date class, if you're stuck with a JDK below version 8 (as me). Just create a new Variable Formatter in NetBeans via
Tools > Options > Java > Variable Formatters > Add
Then in the "Class Types" editfield enter:
java.util.Date
Under "Value formatted as a result of code snippet" use one of the next snippets.
// German format - "dd.MM.yyyy hh:mm"
((getDate() < 10) ? ("0" + getDate()) : getDate()) + "." + ((getMonth() < 9) ? ("0" + (getMonth() + 1)) : (getMonth() + 1) ) + "." + (getYear() + 1900) + " " + ((getHours() < 10) ? "0" + getHours() : getHours()) + ":" + ((getMinutes() < 10) ? "0" + getMinutes() : getMinutes()) + ":" + ((getSeconds() < 10) ? "0" + getSeconds() : getSeconds())
// US format - "MM/dd/yyyy hh:mm"
((getMonth() < 9) ? ("0" + (getMonth() + 1)) : (getMonth() + 1) ) + "/" + ((getDate() < 10) ? ("0" + getDate()) : getDate()) + "/" + (getYear() + 1900) + " " + ((getHours() < 10) ? "0" + getHours() : getHours()) + ":" + ((getMinutes() < 10) ? "0" + getMinutes() : getMinutes()) + ":" + ((getSeconds() < 10) ? "0" + getSeconds() : getSeconds())
// ISO-8601 - "yyyy-MM-dd hh:mm"
(getYear() + 1900) + "-" + ((getMonth() < 9) ? ("0" + (getMonth() + 1)) : (getMonth() + 1) ) + "-" + ((getDate() < 10) ? ("0" + getDate()) : getDate()) + " " + ((getHours() < 10) ? ("0" + getHours()) : getHours()) + ":" + ((getMinutes() < 10) ? ("0" + getMinutes()) : getMinutes()) + ":" + ((getSeconds() < 10) ? ("0" + getSeconds()) : getSeconds())
The next snippet could also come in handy, when your lost in the the debug-output overkill of an instance of java.util.Calendar:
// German format - "dd.MM.yyyy hh:mm"
((get(5) < 10) ? ("0" + get(5)) : get(5)) + "." + ((get(2) < 9) ? ("0" + (get(2) + 1)) : (get(2) + 1) ) + "." + (get(1)) + " " + ((get(10) < 10) ? "0" + get(10) : get(10)) + ":" + ((get(12) < 10) ? "0" + get(12) : get(12)) + ":" + ((get(13) < 10) ? "0" + get(13) : get(13))
You can even put a much more complex code in the variable formatter, as long as you return a string. For example, if I have a class with two string members, name and surname I can paste the follwing code in the "Value formatted.." box:
String result;
if (name != null) {
result = name + " " + surname;
} else {
result = "<null>";
}
return result;
.. and for displaying as children the name and surname separately you can paste a code in the "Children displayed as.." box to return a String[], for example:
String[] results = new String[2];
results[0] = "name: " + name;
results[1] = "surname: " + surname;
return results;
This will display two nodes as children in the variables debug window with the name and surname
The variable itself can be referenced by this (at least it works in Netbeans 8.1).
So, let's say we want the identityHashCode of our Collection after its size:
"size = " +size() + " #" + System.identityHashCode(this)