Frame only displaying last record in table - progress-4gl

Hopefully this will be my last question for a while. I know there isn't much to be said about Progress's UI capability, but I'm having what seems to be a really strange problem with displaying in a frame.
Here is some pseudo code to help you understand the problem:
DEF TEMP-TABLE tMainTable.
DEF TEMP-TABLE tPage LIKE tMainTable.
DEF VAR iCursor AS INT.
/* SOME INPUT DETECTION */
/* Moving the cursor */
FIND FIRST tMainTable WHERE tMainTable.UniqueId EQ iCursor.
DO i = 1 TO iMaxPageSize:
CREATE tPage.
BUFFER-COPY tMainTable TO tPage.
END.
/* DISPLAY */
FOR EACH tPage:
DISPLAY tPage.iNumber tPage.Name.
END.
These are the basics of the program. Now the desired output, would have the FRAME displaying these to end right under the last entry. Currently, using the default FRAME, it scales to the bottom of the terminal screen.
Though, when I instantiate a FRAME and interchange all of the logical available options, I can get it to size to where I want it, but can't get it to display the entries in seperate lines. What it looks like it's doing instead, is displaying each entry on the same line, overwriting the last one, as it always shows the last record in the TEMP-TABLE.
I tried instantiating the FRAME "WITH iMaxPageSize DOWN", with no effect. After reading a little deeper on this particular option, it looks like it's only available for displaying multiple fields in a table, and not certain fields of multiple tables.
Hope this made sense, I really need help with this.

Figured it out, took me a cumulative of 8 hours of reading, and trial-and-error coding.
FOR EACH tPage WITH 6 DOWN:
Was all I needed.
It still bugs me that when I instantiated a FRAME, I could only ever get it to display one record despite using it in a FOR EACH.

you need to do something like this - the FIND / DO combination isn't doing what you think it is.
DEF TEMP-TABLE tMainTable.
DEF TEMP-TABLE tPage LIKE tMainTable.
DEF VAR iCursor AS INT.
DEF VAR i AS INT.
i = 0.
FOR EACH tMainTable
WHERE tMainTable.UniqueId EQ iCursor
NO-LOCK:
i = i + 1.
IF i > maxpagesize THEN
LEAVE.
CREATE tPage.
BUFFER-COPY tMainTable TO tPage.
END.
/* DISPLAY */
FOR EACH tPage:
DISPLAY tPage.iNumber tPage.Name
WITH DOWN.
END.

Related

Cimplicity Screen - one object/button that is dependent on hundreds of points

So I have created a huge screen that essentially just shows the robot status for every robot in this factory (individually)… At the very end of the project, they decided they want one object on the screen that blinks if any of the 300 robots fault. I am trying to think of a way to make this work. Maybe a global script of some kind? Problem is, I do not do much scripting in Cimplicity, so any help is appreciated.
All the points that are currently used on this screen (to indicate a fault) have very similar names… as in, the beginning is the same… so I was thinking of a script that could maybe recognize if a bit is high based on PART of it's string name characteristic. The end will change a little each time, but I am sure there is a way to only look for part of a string and negate the rest. If the end has to be hard coded, that's fine.
You can use a Python script in Cimplicity.
I will not go into detail on the use of python in Cimplicity, which is well described in the documentation indicated above.
Here's an example of what can be done... note that I don't have a way to test it and, of course, this will work if the name of your robots in the declaration follows the format Robot_1, Robot_2, Robot_3 ... Robot_10 ... Robot_300 and it also depends on the Name and the Type of the fault variable... as you didn't define it, I imagine it can be an integer, with ZERO indicating no error. But if you use something other than that, you can easily change it.
import cimplicity
(...)
OneRobotWithFault = False
# Here you get the values and check for fault
for i in range(0, 300):
pointName = f'MyFactory.Robot_{i}.FaultCode'
robotFaultCode = cimplicity.point_get(pointName)
if robotFaultCode > 0:
OneRobotWithFault = True
break
# Set the status to the variable "WeHaveRobotWithFault"
cimplicity.point_set("WeHaveRobotWithFault", OneRobotWithFault)

How to change a cell value periodically in libreoffice calc?

The title says it all...
For example, if I want to have a cell which displays the current time and auto updates minute by minute (well, I think we call that a clock), how do I do it?
Is there a simple function implemented already or should I create a macro and assign it to a specific event?
EDIT: Following the provided answer by #Jim K, I want to be more clear about what I want. The "clock" example above was here to make it simple to understand, but what I really want is in the title: a cell value which changes periodically, be it a string, a number, a date...
First enter =NOW() in a cell, and format the number by going to Format -> Cells.
Next, this Basic macro (from here) recalculates every minute. Go to Tools -> Customize and assign it to the Open Document event.
Sub RecalculatePeriodically
Const secs = 60
On Error Goto ErrorHandler
Do While True
Wait(1000 * secs)
ThisComponent.calculateAll()
Loop
ErrorHandler:
'Document was probably closed
End Sub
However, this crashes when exiting LibreOffice. So instead, use the following threaded Python macro (like here). Assign keep_recalculating_thread to the Open Document event.
import time
from threading import Thread
import uno
def keep_recalculating_thread(action_event=None):
t = Thread(target = keep_recalculating)
t.start()
def keep_recalculating():
oDoc = XSCRIPTCONTEXT.getDocument()
while hasattr(oDoc, 'calculateAll'):
oDoc.calculateAll()
time.sleep(60)
g_exportedScripts = keep_recalculating_thread,
Another idea is at https://ask.libreoffice.org/en/question/5327/how-can-i-run-a-macro-at-regular-time-interval/, although it requires linking to another file which seems cumbersome.
EDIT:
Maybe you are looking for something like this? Test it by starting with a blank spreadsheet and entering 1 in cell A1.
def keep_changing_cell(action_event=None):
t = Thread(target = keep_changing_thread)
t.start()
def keep_changing_thread():
oDoc = XSCRIPTCONTEXT.getDocument()
oSheet = oDoc.CurrentController.ActiveSheet
COLUMN_A = 0
FIRST_ROW = 0
oCell = oSheet.getCellByPosition(COLUMN_A, FIRST_ROW)
while hasattr(oDoc, 'calculateAll'):
oCell.setValue(oCell.getValue() + 1)
time.sleep(2)
tl;dr
Is there a simple function implemented already
No.
From LibreOffice and fairly recent:
(I don't know a 'clock' property applying to cells.)
There are simple ways to obtain the time, for example given suitable formatting, with date:
=NOW()
or Ctrl+;
Or, for example, without date:
=MOD(NOW(),1)
The first and last will update, but only when the sheet is recalculated.
For a cell that ticks away (eg second by second) I believe you will need a script.

Debugging a for loop in matlab

I've been looking throught the documentation, but can't seem to find the bit I want.
I have a for loop and I would like to be able to view every value in the for loop.
for example here is a part of my code:
for d = 1 : nb
%for loop performs blade by blade averaging and produces a column vector
for cc = navg : length(atbmat);
atb2 = (sum(atbmat((cc-(navg-1):cc),d)))/navg;
atbvec2(:,cc) = atb2;
end
%assigns column vector 'atbvec2' to the correct column of the matrix 'atbmat2'
atbmat2(d,1:length(atbvec2)) = atbvec2;
end
I would like to view every value of atb2. I'm a python user(new to MATLAB) and would normally use a simple print statement to find this.
I'm sure there is a way to do it, but I can't quite find how.
Thankyou in advance.
you can use disp in Matlab to print to the screen but you might want to use sprintf first to format it nicely. However for debugging you're better off using a break point and then inspect the variable in the workspace browser graphically. To me, this is one of Matlab's best features.
Have a look at the "Examine Values" section of this article
The simplest way to view it everywhere is to change this line:
atb2 = (sum(atbmat((cc-(navg-1):cc),d)))/navg;
Into this, without semicolon:
atb2 = (sum(atbmat((cc-(navg-1):cc),d)))/navg
That being said, given the nature of your calculation, you could get the information you need as well by simply storing every value of abt2 and observing them afterwards. This may be done in atbmat2 already?
If you want to look at each value at the time it happens, consider setting a breakpoint or conditional breakpoint after the line where abt2 is assigned.

Requesting member of node_element results in "undefined"

I'm using Opa for a school project in which there has to be some synchronization of a textfield between several users. The easy way to solve this, is to transmit the complete field whenever there is a change performed by one of the users. The better way is of course to only transmit the changes.
My idea was to use the caret position in the textfield. As a user types, one can get the last typed character based on the caret position (simply the character before the caret). A DOM element has an easy-to-use field for this called selectionStart. I have this small Javascript for this:
document.getElementById('content').selectionStart
which correctly returns 5 if the caret stands at the fifth character in the field. In Opa, I cannot use selectionStart on either a DOM or a dom_element so I thought I'd write a small plugin. The result is this:
##extern-type dom_element
##register jsGetCaretPosition: dom_element -> int
##args(node)
{
return node.selectionStart;
}
This compiles with the opp-builder without any problem and when I put this small line of code in my Opa script:
#pos = %%caret.jsGetCaretPosition%%(Dom.of_selection(Dom.select_id("content")));
that also compiles without problems. However, when I run the script, it always returns "undefined" and I have no idea what I'm doing wrong. I've looked in the API and Dom.of_selection(Dom.select_id("content")) looked like the correct way to get the corresponding dom_element typed data to give to the plugin. The fact that the plugin returns "undefined" seems to suggest that the selected element does not know the member "selectionStart" eventhough my testcode in Javascript suggest otherwise. Anyone can help?
In Opa dom_element are the results of jQuery selection (i.e. an array of dom nodes). So if I well understood your program you should write something like node[0].selectionStart instead of node.selectionStart.
Moreover you should take care of empty selection and selection which doesn't contains textarea node (without selectionStart property). Perhaps the right code is tmp == undefined ? -1 : tmp = node[0].selectionStart == undefined ? -1 : tmp

Data Processing, how to approach

I have the following Problem, given this XML Datastructure:
<level1>
<level2ElementTypeA></level2ElementTypeA>
<level2ElementTypeB>
<level3ElementTypeA>String1Ineed<level3ElementTypeB>
</level2ElementTypeB>
...
<level2ElementTypeC>
<level3ElementTypeB attribute1>
<level4ElementTypeA>String2Ineed<level4ElementTypeA>
<level3ElementTypeB>
<level2ElementTypeC>
...
<level2ElementTypeD></level2ElementTypeD>
</level1>
<level1>...</level1>
I need to create an Entity which contain: String1Ineed and String2Ineed.
So every time I came across a level3ElementTypeB with a certain value in attribute1, I have my String2Ineed. The ugly part is how to obtain String1Ineed, which is located in the first element of type level2ElementTypeB above the current level2ElementTypeC.
My 'imperative' solution looks like that that I always keep an variable with the last value of String1Ineed and if I hit criteria for String2Ineed, I simply use that. If we look at this from a plain collection processing point of view. How would you model the backtracking logic between String1Ineed and String2Ineed? Using the State Monad?
Isn't this what XPATH is for? You can find String2Ineed and then change the axis to search back for String1Ineed.