FMP 14 - Auto Populate a Field based on a calculation - filemaker

I am using FMP 14 and would like to auto-populate field A based on the following calulation:
If ( Get ( ActiveLayoutObjectName ) = "tab_Visits_v1" ; "1st" ) or
If ( Get ( ActiveLayoutObjectName ) = "tab_Visits_v2" ; "2nd" ) or
If ( Get ( ActiveLayoutObjectName ) = "tab_Visits_v3" ; "3rd" ) or
If ( Get ( ActiveLayoutObjectName ) = "tab_Visits_v4" ; "4th" ) or
If ( Get ( ActiveLayoutObjectName ) = "tab_Visits_v5" ; "5th" ) or
If ( Get ( ActiveLayoutObjectName ) = "tab_Visits_v6" ; "6th" )
The above code is supposed to auto-populate the value 1st, 2nd, 3rd ... in field A depending on the name of the object the Get (ActiveLayoutObjectName) function returns. I have named each of my tabs, but the calculation is only returning 0.
Any help would be appreciated.
thanks.

The way your calculation is written makes very little sense. Each one of the If() statements returns a result of either "1st", "2nd", etc. or nothing (an empty string). You are then applying or to all these results. Since only of them can be true, your calculation is essentially doing something like:
"" or "2nd" or "" or "" or "" or ""
which happens to return 1 (true), but has no useful meaning.
You should be using the Case() function here:
Case (
Get ( ActiveLayoutObjectName ) = "tab_Visits_v1" ; "1st" ;
Get ( ActiveLayoutObjectName ) = "tab_Visits_v2" ; "2nd" ;
Get ( ActiveLayoutObjectName ) = "tab_Visits_v3" ; "3rd" ;
Get ( ActiveLayoutObjectName ) = "tab_Visits_v4" ; "4th" ;
Get ( ActiveLayoutObjectName ) = "tab_Visits_v5" ; "5th" ;
Get ( ActiveLayoutObjectName ) = "tab_Visits_v6" ; "6th"
)
Note also that a calculation field may not always refresh itself as a result of user switching a tab. This refers to an unstored calculation field; if you are trying to use this as the formula to be auto-entered into a "regular' (e.g. Text) field, it will never update.
Added:
Here is our situation. We see a patient a maximum of 6 times. We have
a tab for each one of those 6 visits.
I would suggest you use a portal to a related table of Visits instead of a tab control. A tab control is designed to display fixed components of user interface - not dynamic data. And certainly not data split into separate records. You should have only one unique record for each patient - and as many records for each patient's visits as may be necessary (potentially unlimited).
If you like, you can use the portal rows as buttons to select a specific visit to view in more detail (similar to a tab control, except that the portal shows the "tabs" as vertical rows). A one-row portal to the same Visits table, filtered by the user selection, would work very well for this purpose, I believe.

With 1. .... it would be easy:
Right (Get ( ActiveLayoutObjectName ) ; 1) & "."
Thanks for pointing out, that my first version does not work.

Related

I want to add database triggers to record changes to the RESB table in SAP HANA to enable delta extraction

We are running ECC6 on HANA, currently the extraction of RESB does a full table scan. I want to record that a change has happened to a Z table (I don't care what change).
I've attempted to create the triggers (in Word) from Help & Google, I would appreciate any suggestions for improvement.
create trigger tr_RESB_insert
after insert on RESB
referencing new row NR
for each row
begin
insert into ZBW_RESB_CDC (
MANDT
,RSNUM
,RSPOS
,RSART
,CHNGIND
,AEDAT
,AEZEIT
,AETMSTMP
,TZONE
,DELFLG )
values ( NR.MANDT
, NR.RSNUM
, NR.RSPOS
, NR.RSART
, ‘I’
, current_utcdate
, current_utctime
, current_utctimestamp
, ‘UTC’
,’ ’
)
end;
and
create trigger tr_RESB_update
after update on RESB
referencing new row NR
for each row
begin
merge ZBW_RESB_CDC as T
using NR
on ( NR.MANDT = T.MANDT and
,NR.RSNUM = T.RSNUM and
,NR.RSPOS = T.RSPOS and
,NR.RSART = T.RSART )
when matched then update
set T.CHNGIND = ‘U’
,T.AEDAT = current_utcdate
,T.AEZEIT = current_utctime
,T.AETMSTMP = current_utctimestamp
,T.TZONE = ‘UTC’
,T.DELFLG = ‘ ’
when not matched then insert (
MANDT
,RSNUM
,RSPOS
,RSART
,CHNGIND
,AEDAT
,AEZEIT
,AETMSTMP
,TZONE
,DELFLG )
values ( NR.MANDT
,NR.RSNUM
,NR.RSPOS
,NR.RSART
, ‘U’
, current_utcdate
, current_utctime
, current_utctimestamp
, ‘UTC’
,’ ’
end;
similarly for delete
At some time we'll upgrade to S4 but for the moment I would like to improve what we have.
I chose to use MERGE so that I don't need to initialise the table and so I can delete old records. Nor do I want to keep images of every change, just the fact that it has changed.
Thanks,
G.

FileMaker global list field

I'm trying to create a multi select function by adding and removing record IDs into a global field.
I've created a global field called current_selection.
I attached a script action to the name field that is suppose to add or remove the record id to the global field.
If ( PatternCount ( committee::current_selection; committee::id & "¶"); Substitute ( committee::current_selection; committee::id &"¶"; "¶"); committee::id & "¶" &committee::current_selection)
and that is how i set the global field.
Meanwhile I set conditional formatting for the name field for a visual of what is selected
PatternCount ( committee::current_selection; committee::id & ¶)
so what happens is 1 is selected when 11 is selected then if I click 1 it takes 1 off 11
Not sure why this is happening
Well, "1" is included in "11", so your test produces a false positive. And substituting "1¶" out of "11¶" leaves "1".
To see if an item exists in a list of return-separated values, use:
IsEmpty ( FilterValues ( item ; listOfValues ) )
Removing an item from a list is more difficult than it might seem. Start with:
Substitute ( ¶ & listOfValues & ¶ ; ¶ & item & ¶ ; ¶ )
then remove the extra carriage returns from the result.

Multiple AND statements in a FileMaker calculation

I want to calculate if a value falls outside of 10% of the last two values added to a database. This calculation is not giving me correct feedback when I have 'Weight" values close to 10, or from 100-110. Otherwise it works fine.
Case (
Get(RecordNumber) ≤ 2 ; "Continue Collecting Data" ;
(((GetNthRecord ( Weight ; Get(RecordNumber)-2))*.9) ≤ Weight) and
(((GetNthRecord ( Weight ; Get(RecordNumber)-2))*1.1) ≥ Weight) and
(((GetNthRecord ( Weight ; Get(RecordNumber)-1))*.9) ≤ Weight) and
(((GetNthRecord ( Weight ; Get(RecordNumber)-1))*1.1) ≥ Weight);
"Stable";
"Unstable")
I’m going to start with the assumption that your table includes fields for both the primary key and the creation timestamp. If not, I would highly recommend adding both to this table and every other table you create.
Assuming these fields are in place, you need to create another occurrence of the table on which this layout is based, then relate the primary key to itself via a Cartesian (×) join. Sort the relationship by creation timestamp descending. Your calculation is then:
Case (
(((GetNthRecord ( Weight ; 1 ) *.9 ) ≤ Weight) and
(((GetNthRecord ( Weight ; 1 ) *1.1 ) ≥ Weight) and
(((GetNthRecord ( Weight ; 2 ) *.9 ) ≤ Weight) and
(((GetNthRecord ( Weight ; 2 ) *1.1 ) ≥ Weight);
"Stable";
"Unstable")
Another thing I noticed is that your code is kind of complex. The Let function can make things easier to read, and your four criteria can be cut down to whether either difference is out of range. So, a simpler version becomes:
Let ( [
#weight1 = GetNthRecord ( all::weight ; 1 ) ;
#weight2 = GetNthRecord ( all::weight ; 2 )
] ; //end define Let
Case (
Abs ( #weight1 - weight ) > .1 ; "Unstable" ;
Abs ( #weight2 - weight ) > .1 ; "Unstable" ;
"Stable"
) //end Case
) //end Let
Does that help?
Assuming you are using FileMaker v12 or later, this looks like a good place to use the ExecuteSQL function (not the script step) to retrieve the last two values. You could do something like this:
Let (
sqlQuery = "
SELECT t.weight
FROM MyTable t
WHERE t.id <> ?
ORDER BY t.id DESC
FETCH FIRST 2 ROWS ONLY
" ;
ExecuteSQL ( sqlQuery ; "" ; "" ; MyTable::id )
)
This query assumes you have a unique 'id' field (i.e. a primary key) that's defined as an 'auto-enter serial' value. The WHERE clause makes sure that the current record (presumably the one the user is entering) is not included in the query. The ORDER BY DESC clause forces the last two records to the top where we can fetch the 'weight' values easily into a value list.
Assuming you use a 'Set Variable' script step to put the query results into $lastValues, you can then test for whether they are in range like so:
Let ( [
lastValue1 = GetValue ( $lastValues ; 1 ) ;
lastValue2 = GetValue ( $lastValues ; 2 ) ;
Value1_InRange = lastValue1 - Abs ( lastValue1 - weight ) >= ( 0.9 * lastValue1 ) ;
Value2_InRange = lastValue2 - Abs ( lastValue2 - weight ) >= ( 0.9 * lastValue2 )
] ;
Value1_InRange and Value2_InRange // returns 1 if both values within range, 0 if not
)
If I were doing this, I would put the above range-checking code into a custom function so it's generic and can be easily reused:
IsWithinRange ( valueToTest ; lastValue ; range ) =
lastValue - Abs ( lastValue - valueToTest ) >= ( ( 1 - range ) * lastValue )
Then the above range-checking code can be reduced to:
IsWithinRange ( MyTable::weight ; GetValue ( $lastValues ; 1 ) ; 0.1 ) &
IsWithinRange ( MyTable::weight ; GetValue ( $lastValues ; 2 ) ; 0.1 )
And one last note.. if you use the ExecuteSQL function in a calculated field, be sure to make it 'unstored' so that it only executes when needed. However, I would recommend you avoid that altogether and simply call it from a script step like 'Set Variable'. That way you can control exactly when it executes.
Hope that helps!

getting a calculated result from mixing records in the same table

I am a particular situation on my hands that I do not what to call it, so I am just going to explain it! I am working on File-maker pro database for a university that keeps track of students that are majoring in education one of the tables keeps track of all of the standardized test taken by students that range from the following; ACT, SAT, ETS, and Papa. before when I made this table, all test stood alone or in other words you couldn't combine scores to make a passing grade. That has now changed with two test, PAPA and ETS. In order words, you can combine scores from each test to make one grade to pass.
Here is an example
lets just say for simplicity sake that you need a grand total of 10 for the PAPA and ETS test in order to pass those individual test
Test Name | Reading | Writing | Math | Total | pass/fail
--------------------------------------------------------
PAPA | 2 | 2 | 2 | 6 | FAILED
ets | 1 | 2 | 6 | 9 | FAILED
So A couple weeks ago.. this individual would not pass there standard test, but now this indivdual would hve passed because he/she has gotten a a 6 in the ETS Math and two 2's in Reading and writing in the PAPAS.
Here's what my current calculation looks like:
If (
ReadingScore ≥ BasicTest::PassReading
and MathScore ≥ BasicTest::PassMath
and WritingScore ≥ BasicTest::PassWriting ;
"PASSED" ;
If ( Score >= BasicTest::QMScore ;
If ( ReadingScore >= BasicTest::QMReading ;
If ( MathScore >= BasicTest::QMMATH ;
If ( WritingScore >= BasicTest::QMWriting ;
"PASSED" ;
"DOES NOT MEET WRITING REQUIREMENTS"
) ;
"DOES NOT MEET MATH REQUIREMENTS"
) ;
"DOES NOT MEET READING REQUIREMENTS"
) ;
"FAILED"
)
)
So my question here today is how should I approach this with the Filemaker pro application? Should I make this a report or should a just rebuild the table completely?!?!?!?
While I'm not sure exactly how your calc matches up with your question (I think Score in your calc is the total of the other scores?), I think I can offer some pointers.
Given what you say and what the calc shows, I think the following are true:
Given multiple tests, you're interested in the maximum score for each category.
Each maximum score needs to be greater than the minimum score from either BasicTest::Pass* or BasicTest::QM*.
The test taker passes if all their max scores are greater than all the test minimum scores or the total max scores is greater than the BasicTest::QMScore.
Given the above, I came up with the following calc:
Let (
[
_reading_score = Max ( papa_reading_score ; ets_reading_score ) ;
_math_score = Max ( papa_math_score ; ets_math_score ) ;
_writing_score = Max ( papa_writing_score ; ets_writing_score ) ;
_total_score = _reading_score + _math_score + _writing_score ;
_target_reading = Min ( BasicTest::PassReading ; BasicTest::QMReading ) ;
_target_math = Min ( BasicTest::PassMath ; BasicTest::QMMath ) ;
_target_writing = Min ( BasicTest::PassWriting ; BasicTest::QMWriting ) ;
_pass_reading = ( _reading_score ≥ _target_reading ) ;
_pass_math = ( _math_score ≥ _target_math ) ;
_pass_writing = ( _writing_score ≥ _target_writing ) ;
_passed = ( _pass_reading and _pass_math and _pass_writing )
or ( _total_score ≥ BasicTest::QMScore );
_result = Case (
_passed ; "PASSED" ;
not _pass_reading ; "DOES NOT MEET READING REQUIREMENTS" ;
not _pass_math ; "DOES NOT MEET MATH REQUIREMENTS" ;
not _pass_writing ; "DOES NOT MEET WRITING REQUIREMENTS" ;
"FAILED"
)
] ;
_result
)
Even if the above isn't exactly what you need, I hope it'll provide some direction. With a complicated calc like this, break it up into pieces with each piece (in this case, each variable assignment) being easy to understand.
Note that Max and Min can take many arguments and can also take fields that have multiple values (related fields in a one-to-many relationship or repeating fields), so if you have more than two scores or two tests to check for maximum and minimum values, just add them as more parameters.

Crystal Reports filtering using optional parameters

I'm working on a report in Crystal Reports XI that allows someone to filter help desk tickets using a number of optional dynamic parameters. If I make a selection for each parameter it returns the expected results, but if I leave out any of the parameters it doesn't return anything and when I look at the SQL query it says, "No SQL Query is used because the record selection formula returns no records." I currently have the following code for Record Selection:
{Incident.State:} = "C" and
{Incident.Close Date & Time} in {?BDate} to {?EDate} and
If HasValue({?Group}) Then (
{Groups.Code} = {?Group}
)
and
If HasValue({?Category}) Then (
{Incident.Subject Description} = {?Category}
)
and
If HasValue({?Staff}) Then (
{Incident_Details.Login ID} = {?Staff}
)
and
If HasValue({?Community}) Then (
{Incident.Company Name} = {?Community}
)
To me, this seems like it should work and if I leave out the If statement to verify the parameters have values I get an error so it seems like the HasValue is working properly. Any ideas?
Your problem stems from not explicitly handling the optional parameter configurations. It's easy to run into this problem when using if-statements in the record selection formula. Instead, explicitly handle the cases where the parameters DO and DO NOT have values. Something like this:
...
(not(hasvalue({?Group})) or {Groups.Code}={?Group})
and
(not(hasvalue({?Category})) or {Incident.Subject Description} = {?Category})
and
(not(hasvalue({?Staff})) or {Incident_Details.Login ID} = {?Staff} )
and
(not(hasvalue({?Community})) or {Incident.Company Name} = {?Community})
Doing it this way effectively tells CR to just ignore the parameter if is doesn't have a value, otherwise select records based on what was entered in those parameters.
The Record Selection formula indicates whether a record must be used, or not, by returning true or false. With that in mind, if some value is informed, the formula must return True if it meets some criteria. If nothing is informed on the filter, the formula must always return True.
Try something like this:
{Incident.State:} = "C" and
{Incident.Close Date & Time} in {?BDate} to {?EDate} and
(If HasValue({?Group}) Then (
{Groups.Code} = {?Group}
) else
(True))
and
(If HasValue({?Category}) Then (
{Incident.Subject Description} = {?Category}
) else
(True))
and (
If HasValue({?Staff}) Then (
{Incident_Details.Login ID} = {?Staff}
) else
(True))
and (
If HasValue({?Community}) Then (
{Incident.Company Name} = {?Community}
) else
(True))