Ray Cologon's FileMaker UltraLog Modified to use XML

raycolognfilemaker

Dr. Ray Cologon is a genius. He really is. He's created so many amazing FileMaker Demo files over the past several years. As listing of many of them is available on his Australian website:

http://www.nightwing.com.au/FileMaker/demos.html

One example in particular is UltraLog. Dr. Ray's description: This logging system captures all changes to data, regardless of how they are made (including changes made by script, via IWP, xDBC, CWP and so on)! Moreover the UltraLog system operates transactionally - it doesn't log anything until the record is committed (or submitted in the case of web transactions) and then it logs changes since the last commit.

The UltraLog info and download page is here:

http://www.nightwing.com.au/FileMaker/demosX/demoX01.html

It works and it works great! However, we wanted to store the logged data as XML. You can copy and paste the modified versions below as either text or for Clip Manager.

The first thing thing we did was to rename the function to LogUltraXML to fit our naming scheme as we prefer top down naming so our scripts sort nicely. Second was to rename Dr. Ray's Let Variables. He really is a genius. We had a hard time understanding what each variable meant, like 'Pst'. So we started at the top and renamed them to something that we could understand. For 'Pst', we ended up call it 'theFieldValuePositionStart'. Next we changed the log delimiters to use xml tags so we could read data out of the log a bit easier using another Custom Function 'ParseData'.

Try it out and let us know what you think!

LogUltraXML as Text:

// SYNTAX:  LogUltraXML ( LogField ; ModTime ; FieldsToLog )
// Example: LogUltraXML ( LogData ; ModStamp ; "TheText¶TheText[2]¶TheNumber¶TheDate¶TheTime" )
// ORIGIN:  http://www.nightwing.com.au/FileMaker
// NOTES:  Transactional ( IWP Compatible ) Audit Log Function.
// VERSION: 1.0v3
// © 2009 Ray Cologon, NightWing Enterprises, Melbourne, Australia
// UPDATED: By Hal Gumbert to Store Values as XML
Case ( ValueCount ( FieldsToLog ) and not $ClearLogPermit ;
Let ( [
theFieldName = GetValue ( FieldsToLog ; 1 ) ;
theFieldNamePosition = Position ( LogField ; "" & theFieldName & "" ; 1 ; 1 ) ;
theFieldValuePositionStart = Position ( LogField ; "" ; theFieldNamePosition ; 1 ) + 7 ;
theFieldValuePositionEnd = Position ( LogField ; "
" ; theFieldNamePosition ; 1 ) ;
theFieldValueOld = If ( theFieldNamePosition ; Middle ( LogField ; theFieldValuePositionStart ; theFieldValuePositionEnd - theFieldValuePositionStart ) ; "[---]" ) ;
theFieldValueCurrent = GetField ( theFieldName ) ;
theFieldValueClean = Substitute ( theFieldValueCurrent ; ¶ ; "‡" ) ;
theFieldValueNew = If ( Length ( theFieldValueCurrent ) ; theFieldValueClean ; "[null]" ) ;
vInit = theFieldNamePosition = 0 and IsEmpty ( theFieldValueCurrent ) ;
Prep = Exact ( $ClearLogPermit ; "0" ) ] ;
If ( not Exact ( theFieldValueOld ; theFieldValueNew ) and not vInit ;
TextStyleAdd ( TextColor (
"" & GetAsDate ( ModTime )  & "" & "" &
"" & If ( Prep ; "[Log Prep]" ; Get ( AccountName ) ) & "" &
"" & theFieldName & "" &
"" & theFieldValueOld & "" &
"" & theFieldValueNew & "¶" ; Prep*11776947 ) ; Prep*Italic ) ) &
LogUltraXML ( LogField ; ModTime ; RightValues ( FieldsToLog ; ValueCount ( FieldsToLog ) - 1 ) )
) ;
LogField
)

LogUltraXML as ClipManager

// SYNTAX:  LogUltraXML ( LogField ; ModTime ; FieldsToLog ) // Example: LogUltraXML ( LogData ; ModStamp ; "TheText¶TheText[2]¶TheNumber¶TheDate¶TheTime" ) // ORIGIN:  http://www.nightwing.com.au/FileMaker // NOTES:  Transactional ( IWP Compatible ) Audit Log Function. // VERSION: 1.0v3 // © 2009 Ray Cologon, NightWing Enterprises, Melbourne, Australia // UPDATED: By Hal Gumbert to Store Values as XML Case ( ValueCount ( FieldsToLog ) and not $ClearLogPermit ; Let ( [ theFieldName = GetValue ( FieldsToLog ; 1 ) ; theFieldNamePosition = Position ( LogField ; "<Field>" & theFieldName & "</Field>" ; 1 ; 1 ) ; theFieldValuePositionStart = Position ( LogField ; "<Value>" ; theFieldNamePosition ; 1 ) + 7 ; theFieldValuePositionEnd = Position ( LogField ; "</Value>" ; theFieldNamePosition ; 1 ) ; theFieldValueOld = If ( theFieldNamePosition ; Middle ( LogField ; theFieldValuePositionStart ; theFieldValuePositionEnd - theFieldValuePositionStart ) ; "[---]" ) ; theFieldValueCurrent = GetField ( theFieldName ) ; theFieldValueClean = Substitute ( theFieldValueCurrent ; ¶ ; "‡" ) ; theFieldValueNew = If ( Length ( theFieldValueCurrent ) ; theFieldValueClean ; "[null]" ) ; vInit = theFieldNamePosition = 0 and IsEmpty ( theFieldValueCurrent ) ; Prep = Exact ( $ClearLogPermit ; "0" ) ] ; If ( not Exact ( theFieldValueOld ; theFieldValueNew ) and not vInit ; TextStyleAdd ( TextColor ( "<Date>" & GetAsDate ( ModTime )  & "</Date>" & "<Time>" & GetAsTime ( ModTime )  & "</Time>" & "<Account>" & If ( Prep ; "[Log Prep]" ; Get ( AccountName ) ) & "</Account>" & "<Field>" & theFieldName & "</Field>" & "<ValuePrior>" & theFieldValueOld & "</ValuePrior>" & "<Value>" & theFieldValueNew & "</Value>¶" ; Prep*11776947 ) ; Prep*Italic ) ) & LogUltraXML ( LogField ; ModTime ; RightValues ( FieldsToLog ; ValueCount ( FieldsToLog ) - 1 ) ) ) ; LogField )