FileMaker 13 introduces a new function that gives us some 30 different attributes about the data we store in a container field: GetContainerAttribute().
One of those attributes is the name of the file that we can ask for like this:
GetContainerAttribute ( theContainer ; "filename" )
And another attribute is to see whether the file was inserted as a reference only.
GetContainerAttribute ( theContainer ; "storageType" )
The response will be either:
- External (Secure),
- External (Open)
- File Reference
“Text” is when you get when the container’s content is not a file but some text that was inserted or pasted into the container field.
“External” indicates that the container field is set up for the “Remote Container” functionality.
Before FileMaker 12, when we wanted to keep the size of the FileMaker file down the only option was to store container data by reference only. That way the files were not stored in the file. The huge downside of that was that the path to the container files had to be the accessible from each client through OS-level file sharing. That setup was not always trivial, especially in mixed Windows/Mac environment. Backups were also complex since FileMaker Server only backed up the FileMaker file and not the referenced data.
That problem was solved in FileMaker 12 with Remote Containers. Through that feature FileMaker kept the container data outside of the FileMaker file but still managed backups and access to those files so that it worked from all clients without the need for fragile OS-level sharing.
But… there was one big caveat: the remote container folder had to be on the same drive as the FileMaker file, you could not choose your own location when you hosted the file on FileMaker Server.
Now with FileMaker 13, that issue has been solved and you can specify your own folder where that container data will be stored.
So what do you do if you have a solution that currently uses a lot of referenced container data and you want to switch over to the improved Remote Container functionality? Your only option really is to re-insert the referenced file as en embedded file. If the container field is set up for Remote storage, FileMaker will take care of that when you insert the data.
Fortunately, this does not have to be a manual process. Using the new attributes we can get from a container it is very easy to script it. Below is an example of how.
First of all, I’ve created custom functions for all 30 of the different attributes you can ask about a container:
So instead of doing this (and having to remember the name of the attribute):
GetContainerAttribute ( ContainerData::myContainer ; "storagetype" )
I can simply do this:
CONTAINER_storageType ( ContainerData::myContainer )
On to the script:
- The first thing we do is to check if the container data is stored as a reference. If not then there is nothing to do.
- If the container file is a reference, we ask for its name and also determine the file type (image, movie, file,…).
- When we have all the info we need, we export the referenced file to a temporary folder (FileMaker creates that folder for the duration of the script and then cleans up after itself when the script ends).
- After extracting the file we empty out the container.
- Then, re-insert the file from the temporary folder. This is where we need the file type so that we can call the proper “Insert” script step.
And we’re done.
Here is a screenshot of the container and its info before running the script:
And after running the script:
Get the Demo
To try it out, manually insert a file into the container and make sure to set the “by reference” toggle:
Happy New Year!
# Allow User Abort [Off] Set Error Capture [On] # # Set Variable [$tempPath; Value:Get ( TemporaryPath )] # # check if the container is by reference If [_CONTAINER_storageType ( ContainerData::myContainer ) = _CONTAINER_STORAGE_FILEREFERENCE] # # it is, do an export field contents and then insert it again # get the file name Set Variable [$containerAsText; Value:ContainerData::myContainer] Set Variable [$fileName; Value:_CONTAINER_file_name ( ContainerData::myContainer )] # # figure out what file type it is Set Variable [$type; Value:LeftWords( $containerAsText ; 1 )] If [Right( $fileName ; 4 ) = ".pdf" and $type <> "PDF"] Set Variable [$type; Value:"PDF"] Else If [$type = "size"] # probably an image, the path is on the 2nd line, first line is the size Set Variable [$type; Value:LeftWords( GetValue( $containerAsText ; 2 ) ; 1 )] End If # # construct the temp path and file name Set Variable [$temp; Value:"file:" & $tempPath & $fileName] # # export Export Field Contents [ContainerData::myContainer; "$temp"] # # delete the container and commit Set Field [ContainerData::myContainer; ""] Commit Records/Requests [Skip data entry validation] # # now get the container back Go to Field [Select/perform; ContainerData::myContainer] If [$type = "image"] Set Variable [$temp; Value:Substitute ( $temp ; "file:/" ; "image:/" )] Insert Picture [$temp] Else If [$type = "PDF"] Set Variable [$temp; Value:Substitute ( $temp ; "file:/" ; "image:/" )] Insert PDF [$temp] Else If [$type = "movie"] Set Variable [$temp; Value:Substitute ( $temp ; "file:/" ; "movie:/" )] Insert Audio/Video [$temp] Else Insert File [ContainerData::myContainer] End If # Commit Records/Requests [Skip data entry validation] # End If