FileMaker Geek

Certified FileMaker Developer iOS and Desktop

This is my personal web site for posting FileMaker Tips/Tricks/Solutions for other developers. This site also serves as a point of distribution for my various hobby projects which I have created using FileMaker Pro. My hobby projects include CO Forge (A character builder for the Champions Online MMO) and some AD&D related RPG tools.

Container Field Images in the Web Viewer

Update

I have released a new version of the sample file which demonstrates how to use this technique to embed video files as well.

Introduction

I wanted to create a help system for my clients using FileMaker’s web viewer. I wanted to have images embedded in the help so that they could be displayed within the context of the help. Not too much to ask right? I also wanted to store these images in a repeating container field along with the text and then reference them directly in the web viewer without having to export them or store them on a shared drive or web server somewhere.

This is where Base64 encoding comes in. Why should you care about base64 encoding? Well, it allows you to convert an image into plain text which you can then embed directly into your html code and display the result in a Web Viewer!

If you are on the cutting edge, you already own a copy of FileMaker 13-16 which has Base64 encode and decode functions built right in. However, if you cannot use FileMaker 13-16 yet, there is still hope for you by using the fabulous free BaseElements plugin from Goya.

In the examples to follow, I will be using the BaseElements plugin version of the Base64 encode function.

The following example, if placed into the calculation area of a web viewer, will display an image stored in a container field.

“data:text/html,” &
“<HTML><BODY>” &
“<img src=’data:image/gif;base64,” &
BE_Base64_Encode ( MyTable::MyContainerImage )
& “‘/>”
& “</BODY></HTML>”

Notice the use of the “data:text/html,” string. This instructs the web viewer to use any text which follows as your html web page. This is very cool for those of you not yet familiar with this concept. This means you can construct a dynamic web page on the fly which includes any filemaker field data you want to add.

The next thing we want to do is to combine text data with images so that everything will show up together like is does in a regular web page. To make this work you will need a text field to store your help text in addition to the container field(s) where you store you image(s). This text data must be formatted as a calculation because we will be using the evaluate() function to interpret it. The following is an example of what you could input into your text field:

“This is my help text.<br>
This is my image:” &
“<img src=’data:image/gif;base64,” &
BE_Base64_Encode ( IGI_Webviewer_ContainerImage::MyImage )
& “‘/>”
& “<br>This help is now concluded!”

It is critical that you place all non calculation text within quotes “Like This”.  If you do not, the evaluate() function cannot determine what is text and what is a calculation that requires evaluation.  You can also see that I use <br> in the text above. HTML does not know about any carriage returns I may have typed into my text field, so I have to use <br> to tell HTML when to perform a line break.  Any additional formatting such as bold, italic, underlines, tables, etc will require you to know more HTML, but it’s really pretty easy stuff. One more major thing of importance is the use of the single quote mark aka the apostrophe.  You will see that it is used at the beginning of the <img src='  tag.  It also has a closing single quote at the end:  “‘/>”. It is difficult to see but there is a quote "  followed by an apostrophe '.  Use of the apostrophe allows you to still use quotes within your html code without the need for an escape character, or having to resort to using FileMaker's Quote() function.

This next example when placed into the calculation of a web viewer will display your help text with the image embedded.

“data:text/html,” &
“<HTML><BODY>” &
Evaluate(MyTable::MyHelpText)
& “</BODY></HTML>”

It is important to note that you really need to lock down the security on anything that uses the evaluate function. The reason for this is because evaluate can be used to replace the contents of your global variables you might be using in your solutions.

Sample File: WebviewerB64Img.zip

DiceWare Password Generator

I saw a cool little mention about DiceWare password generation on Twitter today and since it was the end of the work day, I decided to throw a quick little password generator tool together and share it. The technique as well as more detailed information can be found here

The way it works is by using a 6 sided die to roll 5 separate numeric digits which are appended together to form a single 5 digit number.  Each 5 digit number represents a single word, which is chosen from a list of 7,776 words. So if you want a password that is 7 words long, this process would be repeated 7 times to select 7 different words in a completely random fashion.  Secure, not impossible to memorize, and quick to generate!

This solution was designed to work with FileMakerGO or FileMaker Pro v12 or later.

Download File Here (561 KB)

Enjoy!

Sub Summary Inline With Body

Update:  Comment from FMForums totally simplified this using a single calc, and no scripts or variables!

Projects::ClientID = GetNthRecord ( Projects::ClientID ; Get (RecordNumber) - 1 )

--------------------------

I don't know if anyone else has already figured this out (probably) but I was not able to find anything on it.  I did find a post By Daniel Wood about how this was accomplished by overlapping a field just slighting from the sub summary onto the body in FM 11 and earlier, but this trick no longer works in v12 and v13 as far as I can tell.  I suspect this was in preparation for WebDirect so that things would have mirrored behaviors between Filemaker Pro Client and a WebBrowser in WebDirect.

After a bit of thinking it dawned on me I could use a global variable to store IDs and conditional formatting (v12) or object hiding (v13).

The idea is to take a report that uses a sub summary and remove the sub summary completely and still have the same functionality.

So a report that looks like this:

Company 1

                              Department 1

                              Department 2

Company 2

                              Department 1

                              Department 2

 

Would look like this:

Company 1            Department 1

                              Department 2

Company 2           Department 1

                              Department 2

 

This saves paper and printing time since you can embed the sub summary data directly onto the body of the first record for each sort break.

The calc used for conditional formatting or hiding the object would be:

IsEmpty ( Filtervalues ( $$ListToSearch ; MyTable::RecordID ))

Once that is setup you can then move on to writing the script which sorts the records and then Loops through all of the records collecting the ID of each record where a sub summary break would normally occur.

Set Variable[$$ListToSearch;""]

SortRecords[Restore;NoDialog] (CompanyID;Project)

Go To Record/Request/Page[First]

Loop

     If [ isempty($CompanyID) or $CompanyID ≠ MyTable::CompanyID ]

          Set Variable [ $CompanyID ; Value:MyTable::CompanyID ]

          Set Variable [ $$ListToSearch; Value:List($$ListToSearch;MyTable::RecordID) ]

     End If

     Go to record/Request/Page [Next;Exit after last]

End Loop

Search Results By Account Name

Matt Petrowsky made a post on Facebook asking developers if they could find the best way to restrict search results to the current user account using native FileMaker Techniques.  In response I created this solution file so that people can have a better idea of how to accomplish this.  It  only uses Custom Menus and scripts to take complete control of user searching.

Please note that this sample file does not include how to create your own QuickFind interface and scripts.

Find_By_Acctname.zip

Container Drag and Drop From Web Browser/Viewer

Using FileMaker 12 you can drag and drop a file from your desktop into a container field. Unfortunately, doing the same thing from a web browser or the web viewer within FileMaker only yields a URL to the file in question.

Fortunately I came across a technique by Douglas Alder of HomeBase software recently which demonstrated a cool technique on how to use drag and drop from a web browser to place images into a container field using a script trigger and the Insert from URL script step. It didn’t quite meet my needs, so I made some minor modifications to it and thought others could benefit from the changes.

It is important to note that your container field must be set to ‘Optimize for Images’ and not ‘Optimize for Interactive Content’, otherwise you will not be able to drag and drop files onto it.

For those of you who are using FileMaker 13, I have also added a bit of code that is specific to FileMaker v13:

Else If[GetContainerAttribute ( GetFieldName($fn); "Storage Type" ) ≠ "Text"//Verify Data Type]

Please omit this bit of code if you are using FileMaker v12 or earlier since this function does not exist in earlier versions.

SCRIPT

#Improvements:
# Removed file type restrictions to allow for PDFs and other files to be captured.
# Removed the field dependency to allow script to work for any table or field.
#
#Dependencies:
# – Your Container Field should use the OnObjectModify script trigger to run this script.
# – Optional: Pass the Object Name of the Field as the script parameter, otherwise the field object name must be ‘file’.
#
Set Error Capture [On]
# Test Object
Set Variable [$obj; Value:if(Not IsEmpty(Get(ScriptParameter)) ; Get(ScriptParameter) ; "file")]
Go To Object [Object Name:$obj]
If[Get(LastError) ≠ 0]
Show Custom Dialog ["Error: " & Get(LastError):"Unable to locate layout object '"$obj&"'."]
Exit Script[]
End If
#
#Get Container Field Data
Set Variable[$fn ; Value:Get(LayoutTableName) & "::" & get(ActiveFieldName)]
Set Variable[$len ; Value:Length(GetField($fn))]
Set Variable[$txt ; Value:GetAsText(GetField($fn))]
#
#Error Checking
If[Abs(get(SystemPlatform))≠1//Mac Only]
Exit Script[]
Else If[IsEmpty(GetField($fn))//Nothing Exists To Insert]
Exit Script[]
Else If[GetContainerAttribute ( GetFieldName($fn); "Storage Type" ) ≠ "Text"//Verify Data Type]
Exit Script[]
Else If[PatternCount($txt;"://")=0 //No Valid URL Exists]
Exit Script[]
Else If[$len > 1000 //URL Length is too long]
Exit Script[]
End If
#
#Attempt To Insert The File
Insert from URL [Select;No dialog;$txt]
If [Get(LastError) ≠0]
Show Custom Dialog ["Insert URL Error: " & Get(LastError);"Could not insert a file from the URL:" & ¶ & $txt ]
Exit Script[]
End If

 

Sample File: ContDragNDropOSX.zip