In FileMaker 17

Recent FileMaker releases have seen new features that allow the developer a little more control over their custom app on the back end. I’m talking primarily about FileMaker Data API that was introduced with FileMaker 16. Which made interaction with a FileMaker solution possible from a host of outside platforms. FileMaker 17 continues to pull back the curtain, if ever so slightly, to give developers a peak under the hood of the platform, and make possible a pretty handy time saving feature.

New in FileMaker 17 is support for custom default fields. Basically what this means is that it’s possible to have a set of predefined fields be automatically created for any new table that gets created in a solution. During development, as new tables are added to a solution, there are inevitably certain recurring fields that need to be created in each new table. Fields like ‘ID’ or some variation of a ‘Primary Key’. Most likely you use some list of creation and/or modification meta data fields to capture time stamps and user info. The ability to copy/paste fields between tables is extremely useful in this and was a welcome addition when it was introduced. However, it will now be possible for developers to control the automatic creation of such fields for any new table from a central location.

Some ‘default’ default fields

Below is a sample version of an XML file that can be used to control the default fields that will be created for any new table in any file that is edited using the client machine where the XML file is installed.

<?xml version="1.0" encoding="utf-8"?>
<FMDefaultItems version="1" source="17.0.1" membercount="1">
	<DefaultFields membercount="5">
		<Field id="1" name="PrimaryKey" fieldtype="Normal" datatype="Text" comment="Unique identifier of each record in this table">
			<AutoEnter type="Calculated" prohibitModification="True" overwriteExisting="True" alwaysEvaluate="False">
				<Calculated>
					<Calculation>
						<Text><![CDATA[Get( UUID )]]></Text>
					</Calculation>
				</Calculated>
			</AutoEnter>
			<Validation type="Always" allowOverride="False" notEmpty="True" unique="True" existing="False"></Validation>
			<Storage autoIndex="True" index="None" global="False" maxRepetitions="1">
				<LanguageReference name="Unicode" id="2"></LanguageReference>
			</Storage>
			<TagList primary="True">#_FMI_0 </TagList>
		</Field>
		<Field id="2" name="CreationTimestamp" fieldtype="Normal" datatype="Timestamp" comment="Date and time each record was created">
			<AutoEnter type="CreationTimestamp" prohibitModification="True"></AutoEnter>
			<Validation type="Always" allowOverride="False" notEmpty="True" unique="False" existing="False">
				<Strict>FourDigitYear</Strict>
			</Validation>
			<Storage autoIndex="True" index="None" global="False" maxRepetitions="1"></Storage>
			<TagList>#_FMI_0 </TagList>
		</Field>
		<Field id="3" name="CreatedBy" fieldtype="Normal" datatype="Text" comment="Account name of the user who created each record">
			<AutoEnter type="CreationAccountName" prohibitModification="True"></AutoEnter>
			<Validation type="Always" allowOverride="False" notEmpty="True" unique="False" existing="False"></Validation>
			<Storage autoIndex="True" index="None" global="False" maxRepetitions="1"></Storage>
			<TagList>#_FMI_0 </TagList>
		</Field>
		<Field id="4" name="ModificationTimestamp" fieldtype="Normal" datatype="Timestamp" comment="Date and time each record was last modified">
			<AutoEnter type="ModificationTimestamp" prohibitModification="True"></AutoEnter>
			<Validation type="Always" allowOverride="False" notEmpty="True" unique="False" existing="False">
				<Strict>FourDigitYear</Strict>
			</Validation>
			<Storage autoIndex="True" index="None" global="False" maxRepetitions="1"></Storage>
			<TagList>#_FMI_0 </TagList>
		</Field>
		<Field id="5" name="ModifiedBy" fieldtype="Normal" datatype="Text" comment="Account name of the user who last modified each record">
			<AutoEnter type="ModificationAccountName" prohibitModification="True"></AutoEnter>
			<Validation type="Always" allowOverride="False" notEmpty="True" unique="False" existing="False"></Validation>
			<Storage autoIndex="True" index="None" global="False" maxRepetitions="1"></Storage>
			<TagList>#_FMI_0 </TagList>
		</Field>
	</DefaultFields>
</FMDefaultItems>

Save the file as DefaultFields.xml and place it in the following locations:

MacOS: /Users/Shared/FileMaker/Shared/
Windows: <drive>:\ProgramData\FileMaker\Shared\

The sample contains values for 5 basic starting fields that will be useful is just about any context.

The XML file can be edited to modify these fields or include additional ones. Alternatively a blank version of the file can be placed in the same location to stop any default fields from being created.

Some other fields you may find useful

Copy/Paste these examples into your DefaultFields.xml file to try them out. (Be sure to modify both the ‘membercount’ and the individual ‘Field id’ attributes in your own file in order for them to work correctly)

  1. Host Timestamps – It’s sometimes necessary to capture creation/modification meta not only from the client but from the host machine as well. This can be useful when hosting apps for clients that are on mobile devices or in different time zones.
    <Field id="6" name="HostCreationTimestamp" fieldtype="Normal" datatype="Text" comment="The timestamp from the host machine at the time of record creation">
    	<AutoEnter type="Calculated" prohibitModification="True" overwriteExisting="False" alwaysEvaluate="True">
    		<Calculated>
    			<Calculation>
    				<Text><![CDATA[Let ( ~trigger = GetField ( "" ) ; Get ( CurrentHostTimestamp ) )]]></Text>
    			</Calculation>
    		</Calculated>
    	</AutoEnter>
    	<Validation type="Always" allowOverride="False" notEmpty="True" unique="False" existing="False"/>
    	<Storage autoIndex="True" index="None" global="False" maxRepetitions="1">
    		<LanguageReference name="Unicode" id="2"/>
    	</Storage>
    	<TagList>#_FMI_0 </TagList>
    </Field>
    
  2. Constant Value – Some relationship models make use of relationships based on constant values such a constant value of “1” in every record of the related table.
    <Field id="7" name="Constant_1" fieldtype="Normal" datatype="Text" comment="A constant value of 1 in all records">
    	<AutoEnter type="Calculated" prohibitModification="True" overwriteExisting="False" alwaysEvaluate="True">
    		<Calculated>
    			<Calculation>
    				<Text><![CDATA[1]]></Text>
    			</Calculation>
    		</Calculated>
    	</AutoEnter>
    	<Validation type="Always" allowOverride="False" notEmpty="True" unique="False" existing="False"/>
    	<Storage autoIndex="True" index="None" global="False" maxRepetitions="1">
    		<LanguageReference name="Unicode" id="2"/>
    	</Storage>
    	<TagList>#_FMI_0 </TagList>
    </Field>
    
  3. Always Null – In the same vein as the constant value field, maybe you need a field that is ALWAYS empty.
    <Field id="8" name="AlwaysEmpty" fieldtype="Normal" datatype="Text" comment="This field is always empty">
    	<AutoEnter type="Calculated" prohibitModification="True" overwriteExisting="True" alwaysEvaluate="True">
    		<Calculated>
    			<Calculation>
    				<Text><![CDATA[""]]></Text>
    			</Calculation>
    		</Calculated>
    	</AutoEnter>
    	<Validation type="Always" allowOverride="False" notEmpty="False" unique="False" existing="False"/>
    	<Storage autoIndex="True" index="None" global="False" maxRepetitions="1">
    		<LanguageReference name="Unicode" id="2"/>
    	</Storage>
    	<TagList>#_FMI_0 </TagList>
    </Field>
    
  4. Get (RecordModificationCount) – It’s easy enough to simply call the function to get details of the current record. However, maybe you want to create a virtual list that displays the records that have seen the most activity. This field would have to be unindexed, but it would make for a simple way to see those numbers. This could also be useful in audit logging.
    <Field id="9" name="ModificationCount" fieldtype="Calculated" datatype="Number" comment="Running count of modifications">
    	<Calculation>
    		<Text><![CDATA[Get(RecordModificationCount)]]></Text>
    	</Calculation>
    	<Storage storeCalculationResults="False" indexLanguage="English" global="False" maxRepetition="1">
    		<LanguageReference name="Unicode" id="2"/>
    	</Storage>
    	<TagList>#_FMI_0 </TagList>
    </Field>
    
  5. Company Logo – It’s a little out of the box thinking, but maybe you want to store a simple company logo which has been Base64 encoded in a global text field. Of course, you wouldn’t need the field in ‘every’ table since it’s global, but we’re just brainstorming here.

While the default fields feature is supported in FileMaker 17 it is not getting much of a footprint especially when it comes to documentation. The format and naming convention of all the attributes in the XML file are not yet fully documented (though I imagine the community will have their heads around it fairly soon). To get some good direction on how some of the other attributes need to be used you can refer to an XML version of a DDR produced using FileMaker Pro Advanced. The formats are not 100% identical, but many of the attribute formats are the same.

Jeremy Upton is a FileMaker 16 Certified Developer at Skeleton Key in St. Louis, MO.

About Skeleton Key

Skeleton Key helps turn complex, complicated, and outdated systems into true information platforms. Our team of consultants and developers do this by developing custom-fit software tools and reporting dashboards that help businesses find, use, and understand their data, freeing them to focus on and grow their core business.

In addition to custom databases and applications, we also provide training and coaching for getting the most out of your existing systems and understanding your unruly data. Skeleton Key is an open-book management company and active player of the Great Game of Business.

Recent Posts

Start typing and press Enter to search

My Apps - FileMaker 17