Message Statements in a Closed Loop

I created a brand new database and typed up a new procedure and I get the same results. Anybody who’s interested in checking it out can download it from Dropbox - File Deleted

If I let the code in the HeartRateStanding field call the procedure, the record I just filled out seems to be replaced by a new record, containing only the next day’s date in the mdate field, and a 1 in the Comment field. Then it adds a completely empty record, and then another record with the same information as the one two records up.

If I delete the code from the field, and run a procedure from the Action menu, that calls the .CheckEntry procedure, it runs correctly.

If I simply put the code from .CheckEntry into the code box for that field, I get the same erroneous results that I do if I call it from that code box.

Initiating it from the Action menu works correctly, but triggering it with data entry does not.

Have a closer look at what’s happening Dave - in my case, the procedure deletes the active record before adding a couple of new ones - does yours do that also?

The other oddity is that, when the procedure has finished, the data sheet does not appear to be active:

It should look like this:

Screen Shot 2020-07-02 at 4.41.26 pm

I’m sorry, moving to a different record in the code triggered by data entry isn’t allowed. Panorama hasn’t yet finished dealing with the current record, it’s in a state where you can’t hop off somewhere else quite yet.

You could get around this restriction by using a timer. Here’s one way it could be done – I tested this code and it appears to work exactly as you want. This works because there is a slight delay before the code in the timer runs. The delay is just a few milliseconds, but it’s enough to allow Panorama to wrap up what it needs to do with the current record.

;       .CheckEntry     29 June 2020

    ;Comment = "0"

starttimer supernow(),"repeat",1,"code","farcallwithin "+quoted(info("databasename"))+","+quoted(info("procedurename"))+",extrastuff"
return

extrastuff:
let NewDate = mDate + 1

If info("EOF")
    AddRecord
    Comment = "1"
Else
    DownRecord
    Comment = "2"
EndIf

mDate = NewDate
Field mDate
Field Systolic

    ;stop

If you press the tab key, I’m not sure what will happen here. Probably it would be a good idea to put tabForward: and tabBackward: labels in the code and handle the tab key differently, without moving to a different record.

It’s usually not such a great idea to try to re-work the user interface of Panorama this way.

‘Not allowed’ meaning causes an error? If so, what error?

If I modify the code to assign a value to a field in the current record, as in:

;       .CheckEntry     29 June 2020
Comment = "0"
let NewDate = mDate + 1
If info("EOF")
    AddRecord
Else
    DownRecord
EndIf

mDate = NewDate
Field mDate
Field Systolic

then the procedure works exactly as one would expect from the code. If I remove that assignment, the procedure deletes the current record and adds two more. Why?

Meaning it doesn’t work.

But it does work, as stated in my post of 2 July. With the Comment = "0" statement in place, it works perfectly.

Not for me. I pasted the code you posted above into your database, and I got this.

I’ve changed it a little - see what happens with this version:

Yep. That works.

For the record, the new code is.

;       .CheckEntry     6 July 2020


Comment = "0"


let NewDate = mDate + 1

If info("EOF")
    AddRecord
    Comment = Comment + "1"
Else
    DownRecord
    Comment = Comment + "2"
EndIf

mDate = NewDate
Field mDate
Field Systolic
    
save

You’re the Man here Dave - any idea why it works?

The answer I expect lies somewhere in the details of the code Jim has written to handle code that is triggered by data entry. It could be a side effect of one of those details.

The way that procedure code interacts with the system is much more complicated than you imagine. Fortunately most of the time Panorama hides the details from you, but in some situations Panorama programmers do need to be cognizant of what is going on behind the curtains. So I have just written a fairly detailed write up about this:

Towards the bottom this new page does mention some new statements in Panorama X 10.2, so you’ll need to skip that part for now, but except for that everything on this page applies to existing versions of Panorama X (and for the most part, to Panorama 6 and earlier as well).

In this specific case, I believe what is happening is that when the procedure starts, it is running in a special internal mode where Panorama hasn’t actually finished updating the current record yet. When in this state adding a record or moving down a record is not allowed, or, for that matter, saving the database.

If the code pauses for any reason, even for a millisecond, Panorama gets a chance to finish updating the record. From that point on it’s ok to add a record or move to a different record. In my post a couple of days ago I suggested using starttimer to do this. However, as explained on this new help page, even updating the display will cause a slight delay. In this case your assignment statement updates the display, so it causes the run loop to cycle. So then the following code works ok.

A fix for this would be to build the equivalent of starttimer into Panorama itself, so that Panorama is for sure finished with updating the current record before any of this code runs. There are other places where code is triggered with a zero second timer this way. I’m going to consider doing that here as well, however, I suspect that this will almost certainly break other users code, which may be relying on the fact that Panorama is in this special mode where the record isn’t finished updating yet. So there is no perfect solution.

By the way, the complications in how code interacts with the run loop is also what has made it so difficult to get single stepping to work correctly, as mentioned in another topic recently.

1 Like

Many thanks for going to the trouble of writing all that up Jim - it explains a lot of things that were previously great mysteries.