Jump to content
Claris Engage 2025 - March 25-26 Austin Texas ×

This topic is 3671 days old. Please don't post here. Open a new topic instead.

Recommended Posts

Posted

Hi folks,

I have an assessment database.

There's a class layout with two portals, one for assessments, and one for a list of pupils in the selected assessments.

When an assessment is created, all the pupils in the current class are linked to it through a join table using a script.

Occasionally, new kids are added to the class, so there's a button on the layout to add missing kids to the assessment.

This works fine.

If no assessment is selected, (i.e $$CurrentAssess is blank), there is an error message and everyone lives happily ever after.

 

 

 

If just rolled the database out to someone else, and they've managed to circumvent this error trap by navigating to another class. - The variable is therefore not empty.

 

Given that I've got severely limited expertise, my ideas:

  1. set a layout script trigger to delete the $$CurrentAssess variable when moving to another class.
  2. set a layout trigger to set the $$CurrentAssess variable to the most recent assessment when moving to a new class.

Any other, better ideas please?

 

Many thanks!!!

Mike

Posted

Tie the variable to the class by referencing a repetition.

 

$$CurrentAsses[ Code ( CLASS::PrimaryKey ) ]

 

You can highlight that assessment in the Assessment Portal using a similar format ( ASSESSMENT::PrimaryKey = $$CurrentAsses[ Code ( CLASS::PrimaryKey ) ] )

Posted

The more obvious thing to do would be to not rely on that global variable in the first place but work with something that is part of the record the user is on.

You haven't given us enough info to make a good call on this.

Posted

I've tried to cut & paste a screen grab of the script / relationship, but jpeg & TIFFs didn't work and I gave up at that point - I assume I could ZIP them, but that seemed more hassle for you guys.

 

I've started to use global fields more for this kind of thing rather than $$variables, but this script had worked well so I left it as:

If [isEmpty] $$CurrentAssess

Show Custom dialogue

End script

David's idea seems to be exactly what's needed, but I don't quite (read; at all!) get how to do it - I've never used "code" before. Does it need a new field?

 

The db is relatively big - I could add a blank copy if that would help.. 

 

Thanks so much guys,

Mike

Posted

Thanks Bruce,

I did try pasting a jpeg and attaching a TIFF.

Will have another go tomorrow with PNG when I've had less beer!

Cheers,

Mike

Posted

You missed the point. You do not copy anything. You do not paste anything. You select the file using the select file button and navigating to wherever you saved your screenshot file; perhaps your desktop?

That's what the first big red arrow was indicating.

Posted

Thanks Bruce,

I was under time pressure to get out for a birthday meal yesterday, so when I used the uploader I tried a Tiff having already failed to cut & paste a jpeg. I've uploaded a jpeg fine now though :-)

post-66258-0-44584600-1412841362_thumb.j

It did occur to me that I don't need a global to select the assessment for each class. If it's a normal stored field, then each class would have a record that was either null or a selected assessment.

Is there anything wrong with this logic - I've always tended to use globals for selections...

 

(My understanding of FM is pretty limited - this might be evident in the relationship graph; some of which works for no reason I can fathom!!)

 

Cheers folks!

Mike

 

post-66258-0-82584800-1412843508_thumb.j

Posted

The issue is not in the screenshot, but long before that when you set and reset the global variable.  Since the user can circumvent your check there is obviously and a workflow that the user can take that does not reset that global variable.

Posted

Thanks Wim,

so would best practice be to attach a script trigger to that layout (on commit?) to rest the variable to empty?

Would that work when the user just left that layout?

 

OK, that didn't work - should this set the variable to nothing or have I got something wrong at this stage?

post-66258-0-66546400-1412860702_thumb.j

 

Bother..

 

Cheers folks!

Mike

Posted

Not enough information about your workflows to suggest one thing over another...

 

Typically you would lock down the navigation in and out of layouts so that the user can only do that through your scripted workflows.  Then you don't have to rely on triggers to catch the scenarios.

Posted

"Not enough information about your workflows to suggest one thing over another…"

 

Which leads back to the question of posting a clone.

 

It is not really possible to get very far with Mike's explanations.

Posted

OK, that didn't work - should this set the variable to nothing or have I got something wrong at this stage?

 

 

Which leads back to the question of posting a clone.

 

Just follow the steps here. Attach File

Posted

David's idea seems to be exactly what's needed, but I don't quite (read; at all!) get how to do it - I've never used "code" before. Does it need a new field?

Code() is just a function that turns a character (or a string) into a numeric value. Do not be afraid.

 

You're already setting the $$CurrentAsses variable somewhere, presumably when a user clicks on a portal row in the Assessment portal.

 

Make the following changes:

1) Change the Set Variable[] script step so the Repetition calculation Set Variable [ $$CurrentAsses ] is a calculation = Code ( CLASS::Primary Key ) where CLASS::Primary Key is the unique ID for the Class table.

2) When someone clicks on the button to add a kid to the assessment, change the reference to $$CurrentAssess to $$CurrentAssess[ Code ( CLASS::Primary Key ) ]

square brackets [ ]  are a way of referencing a repetition of a variable or field.

3) For style points, use conditional formatting to highlight the "selected" row of the Assessment portal.  That calc is $$CurrentAssess[ Code ( CLASS::Primary Key ) ] = ASSESSMENTS::Primary Key

Posted

Here's a clone of the database.

I'm sorry I didn't add it at first; I thought you'd spend more time going through and that attaching it would make you feel obliged to spend that time.

 

If you see any other issues regarding other users (especially hints on how to merge back the data to my master copy every month or so!) I'd be grateful if you could flag them.

 

PupilGradeV07 Clone.fmp12.zip

 

Thanks so much guys!

Mike

Posted

Sorry David, just saw your last post..

 

It seems to make sense, but I'll let it sink in overnight before I start playing.

 

Cheers,

Mike

Posted

Hi Folks,

  • Unfortunately, I still can't get my head round David's solution which is a shame because it looks really cool!
  • Is there anything wrong with my idea of not using a global field, but storing the currently selected assessment for each class. That way, when I navigate to a new class; the last selected assessment will come up automatically?

Cheers,

Mike

Posted

You can use a field, but I consider it bad practice to add unnecessary fields, especially for interface issues.

 

The idea is the same as your original method. You're storing the selected portal record in a global variable. The difference is that you're creating a new variable for each record. Imagine instead of $$CurrentAsses, you have $$CurrentAssess1 and $$CurrentAssesss2 and $$CurrentAssesss3. Same idea. Except the problem is how to tie a variable to a record? You *could* create a variables like $$CurrentAssess_456 and $$CurrentAssess_987 where 456 is the primary key. But creating and testing different variable names is annoying. You've got to have a strong handle on Evaluate(). Instead, you can leverage the fact that variables, like fields, can have repetitions. So, you can have $$CurrentAssess[987] and $$CurrentAssess[456]. If you're primary keys are numbers, that's all you need to do. If they're text, you'll need to encode that text as a number using the Code() function.

 

OK, check out the attached file. Look at the script and the button with conditional formatting. Hopefully, that will clear it up.

Test.fmp12.zip

Posted

Oh wow, now I'm starting to understand. Great explanation!

I hadn't realised this was possible; such a cool technique. I'll have a go at this, fingers crossed :-)

 

Many thanks,

Mike

Posted

OK, got it all working now - thank you so much for your help :-)

Best wishes,

Mike

  • 2 weeks later...
Posted

Oh bother - I've just started teaching again and the script to add pupils to a new assessment record doesn't work anymore.

I thought I'd altered it so it would work, but it doesn't and I can't see why.

The guilty script is below, is there anything anyone can see?

I'll attach an updated database clone after work if that would be helpful.

Cheers,

Mike

 

 

CreateAssessmentRecordsForClass_selectedAssessment

#Written by me on XX-XXX-XXXX
#Purpose: Add missing pupils to selected assessment
#****************************************************
#Dependencies: Uses the CF “ZapValues” by Ray Cologon
#Dependencies: Uses ExecuteSQL to set the check lists
#****************************************************
#The two list-gathering steps are presented in an alternative, FM-“native” way, employing a global and a new relationship #The relationship is driven by the gSelectedAssessment global field and needs to be set in the ”Select Assessment” step #
#check if there *is* a selected assessment
If [ IsEmpty ( $$CurrentAssess[code(Classes::ClassID)] ) ]

#ALTERNATELY If [ IsEmpty ( Classes::gSelectedAssessment ) ]

Show Custom Dialog [ Title: "No assessment selected"; Message: "There is no selected assessment to add pupils to."; Default Button: “OK”, Commit: “Yes” ]

Exit Script [ ] End If

#
#get existing for selected assessment...
Set Variable [ $pupilsInSelectedAssessment; Value:ExecuteSQL

("

SELECT ( PupilID )
FROM Pupil_Class_Assess_Join WHERE GradeID = ? AND ClassID = ?

" ; "" ; ¶ ; $$CurrentAssess[code(Classes::ClassID)] ; Classes::ClassID

)]
#alternate version using a relationship
Set Variable [ $pupilsInSelectedAssessment_ALTERNATE; Value:List ( JPupilClassAssess_forSelectedAssessment::PupilID ) ] #
#... and all in class ...
Set Variable [ $pupilsInClass; Value:ExecuteSQL

("SELECT ( PupilID ) FROM Pupil_Class_Join WHERE ClassID = ?" ; "" ; ¶ ; Classes::ClassID )]

Set Variable [ $pupilsInClass_ALTERNATE; Value:List ( Pupil_Class_Join::PupilID ) ]
#
#... then see who's missing ...
Set Variable [ $pupilsMissing; Value:ZapValues ( $pupilsInClass ; $pupilsInSelectedAssessment ) ] #

If [ not $pupilsMissing ]
#if they're all accounted for ...
Show Custom Dialog [ Title: "Nope"; Message: "All pupils in class are already assigned to this assessment."; Default Button: “OK”, Commit: “Yes” ] Exit Script [ ]

End If

#
#pack in the missing key; we already have a $ with a bunch of pupils keys, plus $$CurrentAssess Set Variable [ $classID; Value:Classes::ClassID ]
#this will be our loop exit condition; calculate it once here, not in loop iteration
Set Variable [ $pupilCount; Value:ValueCount ( $pupilsMissing ) ]
Go to Layout [ “Pupil_Class_Assess_Join” (Pupil_Class_Assess_Join) ]
Loop

Set Variable [ $i; Value:$i + 1 ]

New Record/Request

Set Field [ Pupil_Class_Assess_Join::PupilID; GetValue ( $pupilsMissing ; $i ) ]

Set Field [ Pupil_Class_Assess_Join::GradeID; $$CurrentAssess[code(Classes::ClassID)] ]

Set Field [ Pupil_Class_Assess_Join::ClassID; $classID ]

Commit Records/Requests

[ Skip data entry validation; No dialog ] #exit when list is processed
Exit Loop If [ $i = $pupilCount ]

End Loop
Go to Layout [ original layout ]
#tab has an object name
Go to Object [ Object Name: "classAssessments" ] 

Posted

It's a long script, when you step through it with debugger, at what point does it stop working / does not give you the result you expect?


As an aside, you use this function call a few times:

code(Classes::ClassID)

Put that in a variable and use the variable instead.  That also allows you to inspect it and see if holds a plausible value.

 

It will also avoid this error:

In the loop of the script you use that code() call but the context is wrong: you are in Pupil_Class_Assess_Join, but the code() call tries to read from Classes

Posted

Thanks Wim,

As far as I can tell, the script debugger gives no error message, it just runs through (I've got it to pause on error, but it doesn't).

The script doesn't add any pupils though.

The first part works, to check that there is an assessment selected.

 

I thought I was using the code bit in a variable - $$CurrentAssess[code(Classes::ClassID

This is the variable for the selected assessment. The variable is doing its job in other places on the page so I think it's fine - can I check its value without copying it to a field somewhere?

Does it matter what the context is for a global variable?

I've got a class coming, need to run - would it help if I post the database when I'm finished?

 

Cheers!

Mike

Posted

It's all about context.

 

I always prefer to set local variables rather than using globals or field values in a script. In this case, at the beginning of your script set a variable, say $assess.ID, to $$CurrentAssess[code(Classes::ClassID)] ), then use that variable in place of the global variable.

 

Why? Because you move contexts from Classes to Pupil_Class_Assess_Join and when you set the Grade ID, you're referencing the Classes field in the global repetition, which, I'm guessing, isn't related to the current context in a useful way.

Posted

 

I thought I was using the code bit in a variable - $$CurrentAssess[code(Classes::ClassID

 

Nope, you keep calling Code() on a field, even if you have no access to the field because you are in a different context.

 

So you need to:

- set a variable called $bucket = Code(Classes::ClassID), and do it early in your script when you have access to that field

- then use $$currentAccess[ $bucket ] where you need it.

Posted

Ah, I think I see..

Although the global variable can be accessed from anywhere, it's generated using a field, and I can't always access that.

Will play tonight.

Many thanks!!!

 

P.S

why $bucket??!

Posted

Here's the corrected script - it seems to work fine.

Does it look OK to you?

 

Thanks so much for your help folks - soooo useful!

 

 

CreateAssessmentRecordsForClass_selectedAssessment

#Written by me on XX-XXX-XXXX
#Purpose: Add missing pupils to selected assessment
#****************************************************
#Dependencies: Uses the CF “ZapValues” by Ray Cologon
#Dependencies: Uses ExecuteSQL to set the check lists
#****************************************************
#The two list-gathering steps are presented in an alternative, FM-“native” way, employing a global and a new relationship #The relationship is driven by the gSelectedAssessment global field and needs to be set in the ”Select Assessment” step #
#Sets SelectedAssessment variable so it's not broken by the changed context. $bucket = Code(Classes::ClassID)
Set Variable [ $bucket; Value:Code(Classes::ClassID) ]
#
#check if there *is* a selected assessment
If [ IsEmpty ( $$CurrentAssess[$bucket] ) ]

#ALTERNATELY If [ IsEmpty ( Classes::gSelectedAssessment ) ]

Show Custom Dialog [ Title: "No assessment selected"; Message: "There is no selected assessment to add pupils to."; Default Button: “OK”, Commit: “Yes” ]

Exit Script [ ] End If

#
#get existing for selected assessment...
Set Variable [ $pupilsInSelectedAssessment; Value:ExecuteSQL

("

SELECT ( PupilID )
FROM Pupil_Class_Assess_Join WHERE GradeID = ? AND ClassID = ?

" ; "" ; ¶ ; $$CurrentAssess[$bucket]; Classes::ClassID

)]
#alternate version using a relationship
Set Variable [ $pupilsInSelectedAssessment_ALTERNATE; Value:List ( JPupilClassAssess_forSelectedAssessment::PupilID ) ] #
#... and all in class ...
Set Variable [ $pupilsInClass; Value:ExecuteSQL

("

SELECT ( PupilID ) FROM Pupil_Class_Join WHERE ClassID = ?

" ; "" ; ¶ ; Classes::ClassID 4 November 2014 8:58:02

PupilGradeV074.fmp12 - CreateAssessmentRecordsForClass_selectedAssessment -1-

)]

("

SELECT ( PupilID ) FROM Pupil_Class_Join

CreateAssessmentRecordsForClass_selectedAssessment

WHERE ClassID = ?

" ; "" ; ¶ ; Classes::ClassID

)]
#alternate version using a relationship
Set Variable [ $pupilsInClass_ALTERNATE; Value:List ( Pupil_Class_Join::PupilID ) ]
#
#... then see who's missing ...
Set Variable [ $pupilsMissing; Value:ZapValues ( $pupilsInClass ; $pupilsInSelectedAssessment ) ] #
If [ not $pupilsMissing ]

#if they're all accounted for ...

Show Custom Dialog [ Title: "Nope"; Message: "All pupils in class are already assigned to this assessment."; Default Button: “OK”, Commit: “Yes” ]

Exit Script [ ] End If

#
#pack in the missing key; we already have a $ with a bunch of pupils keys, plus $$CurrentAssess Set Variable [ $classID; Value:Classes::ClassID ]
#this will be our loop exit condition; calculate it once here, not in loop iteration
Set Variable [ $pupilCount; Value:ValueCount ( $pupilsMissing ) ]
Go to Layout [ “Pupil_Class_Assess_Join” (Pupil_Class_Assess_Join) ]
Loop

Set Variable [ $i; Value:$i + 1 ]

New Record/Request

Set Field [ Pupil_Class_Assess_Join::PupilID; GetValue ( $pupilsMissing ; $i ) ]

Set Field [ Pupil_Class_Assess_Join::GradeID; $$CurrentAssess[$bucket] ]

Set Field [ Pupil_Class_Assess_Join::ClassID; $classID ]

Commit Records/Requests

[ Skip data entry validation; No dialog ] #exit when list is processed
Exit Loop If [ $i = $pupilCount ]

End Loop
Go to Layout [ original layout ]
#tab has an object name
Go to Object [ Object Name: "classAssessments" ] 

Posted

 

why $bucket??!

 

The technique to give names to individual repetitions of a variable is sometimes referred to as "named buckets"

This topic is 3671 days old. Please don't post here. Open a new topic instead.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.