Custom GetValue () Function

In FileMaker , we have GetValue(list;valueNumber) to identify a value within a list.

For example:-

GetValue ( “john¶chris¶matt¶dave” ; 2 )  = chris

GetValue ( “john¶chris¶matt¶dave” ; 3 )  = matt

This “¶” is the default delimiter set by FileMaker.
Suppose ,we have a condition in which the list data is having 2 or more carriage returns (“¶”) for each data ,

then how can we distinguish the individual data.

For example:-

record 1 , fieldData = john¶chris

record 2 , fieldData = matt

record3 , fieldData = dane¶steve

By taking the list of all these records , we cannot identify the individual record’s data from GetValue() function.

We can come across this List situation in a number of odd environments.

*There is a solution for this.

Lets get the List of all required values in the way of ExecuteSQL ,separated by a delimiter (let’s say “|”).

For Exampe:-

listData = ExecuteSQL(“SELECT name FROM Contact WHERE country = ?” ; “”;”|”;”india”)

= john¶snow|matt|deman¶white|robin
There is a custom function ,i have developed for this purpose.

GetValueCustom(listData;delimiter;posn)
——————————————–

// GetValueCustom ( “abcd|dadsad|fsdadfds|”; “|” ; 2 ) = dadsad

// GetValueCustom ( “abcd|dadsad|fsdadfds|”; “|” ; 3 ) = fsdadfds

// GetValueCustom ( “abcd|dadsad|fsdadfds|”; “|” ; 1 ) = abcd

// GetValueCustom ( “abcd|dadsad|fsdadfds|”; “|” ; 4 ) = “”
// GetValueCustom ( “abcd|dadsad|fsdadfds|”; “|” ; 5 ) = “”

Let (

[ l = listData ;
d = delimiter ;
p = posn ;

noDem = PatternCount ( l; d );

dataInitialPos = Position ( l ; d ;1 ;posn -1 ) ;

dataFinalPos = Position ( l; d ; 1 ; posn )

];
If ( (noDem < 1) or not(posn < noDem + 1) ; “” ; Middle (l ; dataInitialPos+1 ; dataFinalPos – dataInitialPos -1) )

)

Multiple checkbox selection for a list or valuelist items.

Multiple checkbox selection for a list or valuelist items.
———————————————————————————————–

This is one such way to have multiple checkbox selection by the help of web-viewer (javascript and html).

Lets consider a Scenario:-

Suppose we need to select multiple email addresses for a “To” field.
Then , we can add all the email address list on an html and trigger a script through FM URL to get the the checked emails separated by semicolon(;).

image link:-  image

first.jpg

 

Downloading a CSV File from Web-direct

Exporting a file from FileMaker can be accomplished from 3 steps.

1.Export Records[]

2.Export Field Contents[]

3.Save Records as Excel[]

When we need to export data which comes from different tables ,we usually takes the help of Temporary table or we can take the data in HTML form and push it to a field and then Export Field Contents[] ,which is an appropriate way to export data without taking the help of Temporary table.

But Export Field Contents[] works partially in Web-direct.
For that we can invoke a javascript function which can take data in Array or JSON form and can export the data as an Excel/CSV file.

Here is an example to show how to accomplish the task.

Let the data set be: -

Adam,18,M
Phil,20,F
Rick,30,M
Sam,40,F

Then ,we need to convert to JSON form as "String" below by some appropriate custom function :-

var PersonalInfo = [ 
 {
 Name: "Adam",
 Age: 18,
 Gender: "M"
 },
 {
 Name: "Phil",
 Age: 20,
 Gender: "F"
 },
 {
 Name: "Rick",
 Age: 30,
 Gender: "M"
 },
 {
 Name: "Sam",
 Age: 40,
 Gender: "F"
 }
 ];

Then , we need to set a global variable as $$data to below as a web-viewer content :-

Javascript functions adopted from : -https://halistechnology.com/2015/05/28/use-javascript-to-export-your-data-as-csv/

$$data =


"data:text/html,

<!doctype html> 
 
Export as CSV
 var PersonalInfo = [ 
 {
 Name: \"Adam\",
 Age: 18,
 Gender: \"M\"
 },
 {
 Name: \"Phil\",
 Age: 20,
 Gender: \"F\"
 },
 {
 Name: \"Rick\",
 Age: 30,
 Gender: \"M\"
 },
 {
 Name: \"Sam\",
 Age: 40,
 Gender: \"F\"
 }
 ];

function convertArrayOfObjectsToCSV(args) {
 var result, ctr, keys, columnDelimiter, lineDelimiter, data;

data = args.data || null;
 if (data == null || !data.length) {
 return null;
 }

columnDelimiter = args.columnDelimiter || ',';
 lineDelimiter = args.lineDelimiter || '\n';

keys = Object.keys(data[0]);

result = '';
 result += keys.join(columnDelimiter);
 result += lineDelimiter;

data.forEach(function(item) {
 ctr = 0;
 keys.forEach(function(key) {
 if (ctr > 0) result += columnDelimiter;

result += item[key];
 ctr++;
 });
 result += lineDelimiter;
 });

return result;
 }

function downloadCSV(args) {
 var data, filename, link;

var csv = convertArrayOfObjectsToCSV({
 data: PersonalInfo
 });
 if (csv == null) return;

filename = args.filename || 'export.csv';

if (!csv.match(/^data:text\/csv/i)) {
 csv = 'data:text/csv;charset=utf-8,' + csv;
 }
 data = encodeURI(csv);

link = document.createElement('a');
 link.setAttribute('href', data);
 link.setAttribute('download', filename);
 link.click();
 }
 
 "

Custom Function to get max of numbers represented as text

Suppose we are given a field called “Level” having data as 1,2,3,5 … etc as separate records or data separated by carriage return, but as text field.
Then, ExecuteSQL() or Max() function shall not work as the field entries are described as TEXT.

Below is a custom function which resolves the issue.

maxNumFromList(listt;counter1 ;maxx)

listt = the list of numbers
counter1= always 1
maxx = “”

Example:-
————-
maxNumFromList ( “11” & “¶” & “2” & “¶” & “11” & “¶” & “111” & “¶” & “22” & “¶” & “2”; 1 ; “” ) = 111

Let (
[ value1 = GetAsNumber ( GetValue ( listt;counter1 ) );
max =If ( maxx > value1 ;maxx ; value1 );
count1 = ValueCount ( listt );
counter1 = counter1+1

];
If ( counter1 >count1 ; max ; maxNumFromList(listt;counter1 ;max))

)

 

Custom Function to format number in accordance to FM Inspector

-I had got a request to show a report layout in Excel sheet , the way it is in report , by coping all the colors , fonts,conditional formatting , styling etc.
-So , we need to design an HTML that would look like the same report page on FileMaker layout and then paste the HTML to Excel sheet.

One hurdle that we can come across, is the styling of number field as we do it from FM Inspector. (styling of numbers can also be done through HTML , but this example shows how to format from FM side)

Example:- Decimal = 2 , thousand separator = ,  (setting from inspector)
For decimal =3 , the number becomes as follows:-
15.2345 = 15.234 (truncate function can achieve this)
15 = 15.000
15.1 = 15.100
15.12 = 15.120
So , for this number format conversion , i have devised a custom function ,

addingPrecision(number:precsn)
number= number to be formatted
precsn=the number of digits after decimal to be formatted.
——————————————————————————
Let (

[ data = GetAsText ( number ) ;

posnDecimal = Position ( data ; “.” ; 1 ; 1 );

len = Length ( data );

digitAfterDecimal = Middle ( data ; posnDecimal +1  ; len – posnDecimal +1 );

digitAfterDecimalTotal = Length (digitAfterDecimal);

new = Case (  IsEmpty ( data ) or data = “0” ;”0.” & repeatText ( “0” ; precsn  ; 1 );

Int ( data ) = data ; data  & “.”   & repeatText ( “0” ; precsn  ; 1 );

digitAfterDecimalTotal  ≥ precsn   ; Truncate ( data ; precsn ) ;

digitAfterDecimalTotal  < precsn   ; data & repeatText ( “0” ; precsn – digitAfterDecimalTotal ; 1 )

)

];

new
)

——————————————————————————

——————————————————————————
Supporting Custom Function:-

repeatText(txt;rept;count1)

txt = text to be repeated
rept= number of repetitions
count1 = always 1

——————————————————————————
Let (
[
// nothing requires here
];

If ( count1 = rept ;txt ; txt  & repeatText(txt;rept;count1+1) )
)
——————————————————————————

Custom Function for PatternCount() and PatterCount() for case sensitive occurences.

**Here is a custom function for PatternCount as PatternCount sometimes doesnot work for operators.

PatternCountNew(text;searched;count1;repeat0)

text – the text to be formatted.
searched – the text which is to be searche for its number of occurances.
count1 – 1 (always)
repeat0 – 0 (always)

Supporting custom function :-

Comparing(text;searched;textPos;count1)

text – the text to be formatted.
searched – the text which is to be searche for its number of occurances.
textPos – Position (number) of searched text from the original text.
count1 – 1 (always)

PatternCountNew(text;searched;count1;repeat0)
———————————————————————————
Let (

[
text1 = text;

letter = Middle ( text1 ; count1 ; 1 );

repeat0 = If ( letter = Left ( searched ; 1 ) and Comparing(text1;searched;count1;1) = Length ( searched ) ;
repeat0 + 1 ;repeat0  );

count1 =  If ( letter = Left ( searched ; 1 ) and Comparing(text1;searched;count1;1) = Length ( searched ) ;
count1 + Length ( searched ) ;count1+1   )

];

If ( count1 > Length ( text1 ) ; repeat0 ; PatternCountNew(text1;searched;count1;repeat0) )

)
———————————————————————————

Comparing(text;searched;textPos;count1)
———————————————————————————
Let (

[ text1 = text ;
value = searched;
letter = Middle ( text1; textPos ; 1 );
searchedLetter = Middle ( searched; count1 ; 1 )

];

Case (
count1 > Length ( value ) ; count1 -1 ;
letter = searchedLetter ; Comparing(text1;value;textPos+1;count1+1);
count1 – 1

)
)
———————————————————————————

************************************************************************************************************

**Here is another custom function for PatternCount of Exact text as PatternCount is case insensitive.

PatternCountExatc(text;searched;count1;repeat0)

text – the text to be formatted.
searched – the text which is to be searche for its number of occurances.
count1 – 1 (always)
repeat0 – 0 (always)

Supporting custom function :-

Comparing(text;searched;textPos;count1)

text – the text to be formatted.
searched – the text which is to be searche for its number of occurances.
textPos – Position (number) of searched text from the original text.
count1 – 1 (always)

PatternCountExact(text;searched;count1;repeat0)
———————————————————————————
Let (

[
text1 = text;

letter = Middle ( text1 ; count1 ; 1 );

repeat0 = If ( letter = Left ( searched ; 1 ) and Comparing(text1;searched;count1;1) = Length ( searched ) and Exact ( searched ; Middle ( text1 ; count1 ; Length(searched) ) ) ;
repeat0 + 1 ;repeat0  );

count1 =  If ( letter = Left ( searched ; 1 ) and Comparing(text1;searched;count1;1) = Length ( searched ) and Exact ( searched ; Middle ( text1 ; count1 ; Length(searched) )) ;
count1 + Length ( searched ) ;count1+1   )

];

If ( count1 > Length ( text1 ) ; repeat0 ; PatternCountExact(text1;searched;count1;repeat0) )

)
———————————————————————————

Comparing(text;searched;textPos;count1)
———————————————————————————
Let (

[ text1 = text ;
value = searched;
letter = Middle ( text1; textPos ; 1 );
searchedLetter = Middle ( searched; count1 ; 1 )

];

Case (
count1 > Length ( value ) ; count1 -1 ;
letter = searchedLetter ; Comparing(text1;value;textPos+1;count1+1);
count1 – 1

)
)
———————————————————————————

XML Parsing Custom Function in FileMaker Pro

Here is a custom function to parse the data within the attributes contained in an XML.
Suppose there is an XML content as follows:-<address>
<city>bbsr</city>
<country>india</city>
<city>ctc</city>
<country>pakistan</city>
</address>

We want to get data within the attribute <city> i.e “bbsr” and “ctc” separated by carraige return.

So , here is a custom function for it.

XMLParse(xml;textWithBrace;count1)

xml = “<address>

<city>bbsr</city>
<country>india</city>

<city>ctc</city>
<country>pakistan</city>

</address>”

textWithBrace = “<city>”

count1 = 1 (always)

——————————————————————————–

Let (
[ patterns = PatternCount ( xml ; textWithBrace);

posn = Position ( xml ;  textWithBrace ; 1;count1 );

posnRight = PositionNextRightBrace ( xml ; posn ; 1 );

posnLeft = PositionNextLeftBrace ( xml ; posnRight  ; 1 );

count1 = count1 + 1

];Case (

patterns <1 ; “No matching attributes”;

count1 > patterns ; Middle ( xml ; posnRight  ; posnLeft  –  posnRight -1) ;

Middle ( xml ; posnRight  ; posnLeft  –  posnRight  – 1 ) & “¶”  & XMLParse(xml;textWithBrace;count1)

)
)

——————————————————————————–

Supporting custom functions:-

1.PositionNextRightBrace(text ; posLeftBrace ; count1)

——————————————————————————–
Let (

[text = xml;
data =Middle ( text ; count1 + posLeftBrace  ; 1 )

];

If ( data = “>” ; posLeftBrace + count1+1 ; PositionNextRightBrace(text ; posLeftBrace ; count1+1))

)
——————————————————————————–

2.PositionNextLeftBrace(text ; posRightBrace ; count1)

——————————————————————————–
Let (

[text = xml;
data =Middle ( text ; count1 + posRightBrace  ; 1 )
];

If ( data = “<” ; posRightBrace + count1+1 ; PositionNextLeftBrace(text ; posRightBrace ; count1+1))

)
——————————————————————————–

Thanks
Happy FileMaking

Email Template

After long time friends !!!
This is a script to decode Email Template.
A sample EMail Template  ( variable – $template )is as follows :-
==================================================================

Dear Vendor,
The following  <<Client>>  has now been released for print.  Please confirm when you receive this email.

<<ConditionCheckForDisplayTitles>>

Mainstream Ref:   <<JPG Ref>>  – <<SKU>>
SKU Name:   <<SKU Name>>
Bundle Type:  <<Pack Type>>

If there is a problem with the design, Download Links or Colour Proofs – please contact: <<AccountName>>

Regards,
<<contactMail>>
<<contactPhone>>
<<contactAddress>>

====================================================================
Provided that every text within the angular braces shall constitute the same fieldname .
For Example:-<<ContactMail>> should be a field named as “ContactMail” in a table.

call this script as :-

Perform Script [Email Template Coding; $template]         ($template is the actual template)

set variable [$decodedTemplate;get(ScriptResult)]

email-template

scrolling text field without editing

Suppose we have a text field , say NameList , which has a list of 50000 names and
we want to display in layout without editing it.

Normally , developers used to prefer to show the field data within a web viewer .
But loading such data to web viewer takes a lot of time.

**Another way , is to show the NameList with scrollbar.But , scrollbar can only be moved on browse mode and
the list can be editable (which contradicts our requirement)

So , we can use a small tip by validating the NameList field to validate by calculation =
“!@#$%” (check on validate only if the field has been modified)(any such text which users cannot typically modify on text field)

-ON radio button -Validate during data entry.
-Uncheck checkbox button – Allow user to override during data entry.

Now ,the browse mode will be ON ,user can also scroll the text field , and if the user modifies data , then validation error prompts up.