* Expression guidance
Expression guidance
I read a recent topic with some interest and did some experimenting but failing out of syntax ignorance so some guidance on multi conditional expressions would be appreciated.
Cobblers, Boot and Shoe maker were occupations which ran back through history in one line of my family and my little learning experiment was to try and visualize them on diagrams with a little graphic. The following expression appears to work in it's most simplistic form.
=ContainsText(%INDI.OCCU[1].CAUS%,"cobbler")
The ContainsText could be "cobbler", "boot" or "shoe" and I tried to add "or" and "OR" to combine another expression but that failed so I am wondering should the various possibilities be within the round brackets maybe comma delimited?
My second question is whether it is possible to omit the [1] to test any occupation event rather than the first?
Thank you in advance for any guidance
Cobblers, Boot and Shoe maker were occupations which ran back through history in one line of my family and my little learning experiment was to try and visualize them on diagrams with a little graphic. The following expression appears to work in it's most simplistic form.
=ContainsText(%INDI.OCCU[1].CAUS%,"cobbler")
The ContainsText could be "cobbler", "boot" or "shoe" and I tried to add "or" and "OR" to combine another expression but that failed so I am wondering should the various possibilities be within the round brackets maybe comma delimited?
My second question is whether it is possible to omit the [1] to test any occupation event rather than the first?
Thank you in advance for any guidance
- tatewise
- Megastar
- Posts: 28410
- Joined: 25 May 2010 11:00
- Family Historian: V7
- Location: Torbay, Devon, UK
- Contact:
Re: Expression guidance
Have you reviewed FHUG Knowledge Base Understanding Expressions?
The answer to your question about using boolean 'and' and 'or' is illustrated there with =IsTrue(...) functions.
It also explains the [1] index and that omitting it defaults to the 1st instance.
There is a looping index [1+] that includes all instances but it only works in Diagram Text Schemes.
One idea that you might like is to set the Preferred Flag on one Occupation fact.
Then INDI.OCCU[preferred] will refer to that Occupation (or revert to the 1st Occupation if none have the Preferred Flag).
BTW:
It is somewhat unconventional to set the INDI.OCCU.CAUS (i.e. Cause field) to the name of the occupation.
The Cause is usually reserved for holding some reason for the event happening, e.g. Cause of Death.
Usually, the occupation name is the value of the Occupation Attribute and is represented simply by %INDI.OCCU%
That occupation name appears in the box next to the label Occupation: in the lower pane on the Facts tab.
The answer to your question about using boolean 'and' and 'or' is illustrated there with =IsTrue(...) functions.
It also explains the [1] index and that omitting it defaults to the 1st instance.
There is a looping index [1+] that includes all instances but it only works in Diagram Text Schemes.
One idea that you might like is to set the Preferred Flag on one Occupation fact.
Then INDI.OCCU[preferred] will refer to that Occupation (or revert to the 1st Occupation if none have the Preferred Flag).
BTW:
It is somewhat unconventional to set the INDI.OCCU.CAUS (i.e. Cause field) to the name of the occupation.
The Cause is usually reserved for holding some reason for the event happening, e.g. Cause of Death.
Usually, the occupation name is the value of the Occupation Attribute and is represented simply by %INDI.OCCU%
That occupation name appears in the box next to the label Occupation: in the lower pane on the Facts tab.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
Re: Expression guidance
And don't forget to include "cordwainers"...
Out of interest, my grandfather was a boot & shoemaker, and although I never met him I'm told was mortally offended if anyone suggested that he was a cobbler ( who would only repair shoes, not make them).
Out of interest, my grandfather was a boot & shoemaker, and although I never met him I'm told was mortally offended if anyone suggested that he was a cobbler ( who would only repair shoes, not make them).
Re: Expression guidance
Thank you tatewise and AnthonyM for your input, I have now read the Understanding Expressions in detail and of course have another question.
The question is <> and especially in reference to a headstone photo which I attach to facts so as to include in reports. I have a query which includes %INDI.BURI[1].OBJE[1]>FILE[1]% and using Exclude If -- Contains I can report those entries not having media attached.
How could I use an expression for diagrams to highlight those individuals where headstone photographs are still to be collected and attached using a conditional expression?
Thank you in advance
The question is <> and especially in reference to a headstone photo which I attach to facts so as to include in reports. I have a query which includes %INDI.BURI[1].OBJE[1]>FILE[1]% and using Exclude If -- Contains I can report those entries not having media attached.
How could I use an expression for diagrams to highlight those individuals where headstone photographs are still to be collected and attached using a conditional expression?
Thank you in advance
- tatewise
- Megastar
- Posts: 28410
- Joined: 25 May 2010 11:00
- Family Historian: V7
- Location: Torbay, Devon, UK
- Contact:
Re: Expression guidance
In the Understanding Expressions advice it says Expressions often involve Operators such as + - * / = < > and or etc.
Click on the hyperlink to Operators and it show how to detect non-existent items using =Not(Exists(%INDI.DEAT.DATE%))
So =Not(Exists(%INDI.BURI.OBJE>FILE%)) will work.
You don't need any explicit [1] indexes as the default is always the 1st item.
Thus the above Expression is testing the 1st Burial event, its 1st attached Media record, and its 1st File link.
If that does not exist, then either no Media exist at all, or the 1st Media has no File link but subsequent Media might have a File link. However, that would be a strange scenario!
Click on the hyperlink to Operators and it show how to detect non-existent items using =Not(Exists(%INDI.DEAT.DATE%))
So =Not(Exists(%INDI.BURI.OBJE>FILE%)) will work.
You don't need any explicit [1] indexes as the default is always the 1st item.
Thus the above Expression is testing the 1st Burial event, its 1st attached Media record, and its 1st File link.
If that does not exist, then either no Media exist at all, or the 1st Media has no File link but subsequent Media might have a File link. However, that would be a strange scenario!
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
Re: Expression guidance
@tatewise, thank you for that information, I think I really need to build my own idiot guide to expressions in a language I understand.
Your example above works splendidly except it encompasses living people who have no Burial fact. I tried the expression below and still fail to understand the syntax of multi condition expressions, regardless this did not work, sorry for being so slow to grasp this language concept.
=Exists(%INDI.BURI.PLAC%) and =Not(Exists(%INDI.BURI.OBJE>FILE%))
Really I just want to encompass those with a Burial Fact. I really hope I get the hang of this as it's a powerful FH feature with many benefits not available in my previous software.
TIA
- ColeValleyGirl
- Megastar
- Posts: 5499
- Joined: 28 Dec 2005 22:02
- Family Historian: V7
- Location: Cirencester, Gloucestershire
- Contact:
Re: Expression guidance
Try a fact query for burials rather than an individual query as a starting point. That way, you know the burial fact exists and you're just checking for the image.
Start from the All Facts standard query and create a custom query that filters by Fact Label to get all burials.
Start from the All Facts standard query and create a custom query that filters by Fact Label to get all burials.
Helen Wright
ColeValleyGirl's family history
ColeValleyGirl's family history
- tatewise
- Megastar
- Posts: 28410
- Joined: 25 May 2010 11:00
- Family Historian: V7
- Location: Torbay, Devon, UK
- Contact:
Re: Expression guidance
@wildbill: I know some users find it awkward to read detailed specification articles but all the clues to answer your question are in the Understanding Expressions article.
One rule that trips up many users initially is in the section headed Expressions:
In the Operators article, it explains that to use boolean operators 'and' and 'or' you must use a 'wrapper' function such as IsTrue, Calc or Text to provide a context for them to be used.
Understanding Expressions has several examples such as:
=IsTrue( ( %INDI.BIRT.SOUR>_TYPE% = "Birth" ) or ( %INDI.BIRT.SOUR[2]>_TYPE% = "Birth" ) )
So your Expression would become:
=IsTrue( Exists( %INDI.BURI.PLAC% ) and Not( Exists( %INDI.BURI.OBJE>FILE% ) ) )
However, in a Query, the Rows tab can have multiple filters to reach the desired subset of records.
The 1st Row could be
Add if... %INDI.BURI.OBJE>FILE% is null i.e. add those without a Burial event, or Media record, or File link
The 2nd Row could be
Exclude if... %INDI.BURI% is null i.e. exclude those without a Burial event
As Helen says, in this case, it might be easier to use a Fact type Query instead of an Individual type Query.
See An Overview of Queries under Custom Query Types for details.
A good starting point is the Downloads > Fact Query > All Facts Filter by Label.
Use the Query Menu to Save As Custom Query...
Change the existing Rows tab filter so it explicitly matches with Burial and untick the Parameter prompt.
That will only include Burial events in the Result Set.
Then add the filter Exclude unless... %FACT.OBJE>FILE% is null
That will remove all Burial events with a Media File.
One rule that trips up many users initially is in the section headed Expressions:
For example, =Not( Exists( %INDI.BURI.OBJE>FILE% ) ) does not use =Exists(...) even though Exists is a function because it is within the =Not(...) function.Functions, that begin with an = sign (except when used within another Function), e.g.=RecordId()
In the Operators article, it explains that to use boolean operators 'and' and 'or' you must use a 'wrapper' function such as IsTrue, Calc or Text to provide a context for them to be used.
Understanding Expressions has several examples such as:
=IsTrue( ( %INDI.BIRT.SOUR>_TYPE% = "Birth" ) or ( %INDI.BIRT.SOUR[2]>_TYPE% = "Birth" ) )
So your Expression would become:
=IsTrue( Exists( %INDI.BURI.PLAC% ) and Not( Exists( %INDI.BURI.OBJE>FILE% ) ) )
However, in a Query, the Rows tab can have multiple filters to reach the desired subset of records.
The 1st Row could be
Add if... %INDI.BURI.OBJE>FILE% is null i.e. add those without a Burial event, or Media record, or File link
The 2nd Row could be
Exclude if... %INDI.BURI% is null i.e. exclude those without a Burial event
As Helen says, in this case, it might be easier to use a Fact type Query instead of an Individual type Query.
See An Overview of Queries under Custom Query Types for details.
A good starting point is the Downloads > Fact Query > All Facts Filter by Label.
Use the Query Menu to Save As Custom Query...
Change the existing Rows tab filter so it explicitly matches with Burial and untick the Parameter prompt.
That will only include Burial events in the Result Set.
Then add the filter Exclude unless... %FACT.OBJE>FILE% is null
That will remove all Burial events with a Media File.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
Re: Expression guidance
@tatewise thank you for taking the time to add to this discussion, you are quite correct the expression structure and rules are not natural to me but I am learning.
I support your approach of not providing copy and paste answers, that only leads to another request next time the need arises. The impatient part of me wanted the answer but I have learned some rules playing with existing examples from the Knowledgebase and started a document to note my successes and failures as reminders for the future.
I support your approach of not providing copy and paste answers, that only leads to another request next time the need arises. The impatient part of me wanted the answer but I have learned some rules playing with existing examples from the Knowledgebase and started a document to note my successes and failures as reminders for the future.
Re: Expression guidance
I read this with interest for diagram highlighting but cannot get the below to work-wildbill wrote: ↑17 Mar 2022 12:30
Cobblers, Boot and Shoe maker were occupations which ran back through history in one line of my family and my little learning experiment was to try and visualize them on diagrams with a little graphic. The following expression appears to work in it's most simplistic form.
=ContainsText(%INDI.OCCU[1].CAUS%,"cobbler")
The ContainsText could be "cobbler", "boot" or "shoe" and I tried to add "or" and "OR" to combine another expression but that failed so I am wondering should the various possibilities be within the round brackets maybe comma delimited?
=ContainsText((%INDI.DEAT.CAUS%,"carcinoma",STD) or (%INDI.DEAT.CAUS%,"cancer",STD))
I would have another few possible text strings to add to the list of medical death causes but I can't even get this simple combined version to work although I can create multiple conditions and expressions. I have tries it with and without ContainsText, "or" and "OR" so I am missing some simple syntax rule and welcome some help.
- tatewise
- Megastar
- Posts: 28410
- Joined: 25 May 2010 11:00
- Family Historian: V7
- Location: Torbay, Devon, UK
- Contact:
Re: Expression guidance
Sophie, that expression is not syntactically valid, so I presume FH rejected it as invalid.
It is important to check the parameters required for each function as defined in the Help pages.
The =ContainsText(...) function needs three comma separated parameters.
e.g. =ContainsText( %INDI.DEAT.CAUS%, "carcinoma", STD ) and returns the value true or false.
If you start inserting brackets and or inside that function then it upsets the syntax.
The complementary function is =ContainsText( %INDI.DEAT.CAUS%, "cancer", STD ) also returning true or false.
It is those two true or false values that must be combined with or inside the =IsTrue(...) function.
e.g. =IsTrue( ContainsText( %INDI.DEAT.CAUS%, "carcinoma", STD ) or ContainsText( %INDI.DEAT.CAUS%, "cancer", STD ) )
There are examples of that form of expression in Understanding Expressions.
It is important to check the parameters required for each function as defined in the Help pages.
The =ContainsText(...) function needs three comma separated parameters.
e.g. =ContainsText( %INDI.DEAT.CAUS%, "carcinoma", STD ) and returns the value true or false.
If you start inserting brackets and or inside that function then it upsets the syntax.
The complementary function is =ContainsText( %INDI.DEAT.CAUS%, "cancer", STD ) also returning true or false.
It is those two true or false values that must be combined with or inside the =IsTrue(...) function.
e.g. =IsTrue( ContainsText( %INDI.DEAT.CAUS%, "carcinoma", STD ) or ContainsText( %INDI.DEAT.CAUS%, "cancer", STD ) )
There are examples of that form of expression in Understanding Expressions.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
Re: Expression guidance
@tatewise, thank you so much for your guidance, I knew it was something silly I was doing and I might have been a long time working it out without your True/False explanation.tatewise wrote: ↑11 May 2022 23:39 Sophie, that expression is not syntactically valid, so I presume FH rejected it as invalid.
There are examples of that form of expression in Understanding Expressions.
Thanks again, time to go off and see what I can achieve now.