In this article we want to introduce you the new functions from the MBS FileMaker Plugin in version 16.4.
MongoDB
In this edition, we'd like to introduce you to the new features related to bulk operations on a MongoDB database. Bulk operations allow you to modify multiple data records simultaneously. This results in significant time savings and improved performance, especially when working with large amounts of data. First, you can use MongoDB.BulkOperation.Create to create a bulk operation. You can then plan operations on your database using methods such as MongDB.BulkOperation.UpdateOne, MongoDB.BulkOperation.RemoveMany, and MongoDB.BulkOperation.Insert. MongoDB.BulkOperation.Execute is then used to execute the block of operations on the database. If you like, you can combine this with a transaction to perform a rollback in case of an error. You can find these and several other new, helpful features related to bulk operations in the documentation.
DynaPDF
We have some new features in the DynaPDF area. With the DynaPDF.HaveOpenPath function, we can check whether there is an open path in memory that has not yet been closed by a DynaPDF.ClosePath or DynaPDF.ClipPath function. To discard the path, you can call the new DynaPDF.AbortPath function.
There are new functions available that allow you to access the internal error log. DynaPDF uses the error log to store non-fatal errors or warnings when it is not required to break processing or if more detailed error information should be provided than is possible with the normal exception handling.For example, when opening a damaged PDF file with DynaPDF.OpenPDFFromFile the function tries first to open the file in normal mode. All errors which occur in this step are written to the error log. Depending on the kind of found errors, the function maybe falls back into repair mode and reads the file again. If this action is successful then the function returns with success and no error message is provided over the normal exception handling. So, you'll not notice that the file contained damages unless you take a look into the error log. The error log was introduced with DynaPDF 3.0. It is used when reading a PDF file, e.g. DynaPDF.OpenPDFFromFile, DynaPDF.ImportPDFPage, DynaPDF.ImportPDFFile, and when parsing or rendering PDF pages, e.g. DynaPDF.ParseContent, DynaPDF.IsEmptyPage, DynaPDF.IsColorPage, DynaPDF.ExtractPageText, DynaPDF.RenderPage, DynaPDF.RenderPDFFile, and so on. To determine the number of entries in the ErrorLog, use the DynaPDF.ErrLogMessageCount function. If you want to retrieve a single error, you can do so by specifying the index of the corresponding error using the DynaPDF.ErrLogMessage function.
{
"Message": "syntax error at line 1",
"ObjNum": -1,
"Offset": 1,
"SrcFile": "../svg/svg_loader.cpp",
"SrcLine": 421,
"ErrCode": -1,
"ErrType": -1
}
If you want to read all of them at once, use the DynaPDF.ErrLogMessages function. As with the single-error version, you'll receive a JSON response listing all errors along with their corresponding information.
We've also introduced new features related to vector graphics. For example, you can insert your company logo if it's available as an SVG. Using the DynaPDF.LoadSVG and DynaPDF.LoadSVGFile functions, you can load an existing SVG either from a container or from a file on your hard drive. Using the DynaPDF.InsertSVG function, you can then place and scale the graphic in your PDF. The function uses a native SVG-to-PDF converter that translates SVG graphics directly into PDF drawing operations and resources. Vector graphics remain vector-based whenever possible, preserving their scalability and rendering quality.
# Start new PDF document
Set Variable [ $pdf ; Value: MBS("DynaPDF.New") ]
Set Variable [ $r ; Value: MBS("DynaPDF.AppendPage"; $pdf) ]
#
# Load SVG
Set Variable [ $r ; Value: MBS("DynaPDF.LoadSVG"; $pdf; SVG::SVG) ]
#
# Place the image
Set Variable [ $width ; Value: 500 ]
Set Variable [ $Height ; Value: 0 // automatic ]
Set Variable [ $r ; Value: MBS("DynaPDF.InsertSVG"; $pdf; 0; 0; $width; $height) ]
#
# close page and save
Set Variable [ $r ; Value: MBS("DynaPDF.EndPage"; $pdf) ]
Set Field [ MyTable::ContainerField; MBS( "DynaPDF.Save"; $pdf; "report.pdf" ) ]
Set Variable [ $r ; Value: MBS("DynaPDF.Release"; $pdf) ]
In addition to inserting SVG files, you can also retrieve additional information about a loaded SVG-such as its size-using DynaPDF.GetSVGSize and DynaPDF.GetSVGSizes. An SVG file can consist of multiple embedded SVG graphics. You can determine the number of these using DynaPDF.GetSVGSymbolCount. The functions DynaPDF.GetSVGSymbolName and DynaPDF.GetSVGSymbolNames return the names of the SVG symbols.
Encryption
In the Encryption section, we have two new functions designed to help you with AES encryption using GCM mode. The Encryption.SetGCMTag function sets the GCM authentication tag for the next decryption. The Encryption.GetGCMTag function retrieves the GCM authentication tag from the last encryption.
Relationships in JSON
Let's move on to a tool designed to help you gain an overview of the database structure, for example, when working with external solutions. We're talking about the FM.Relations function. This function displays the relationships in the database as JSON. The relationships for each individual table are specified in this JSON. Take a look, for example, at this JSON, which was generated from the relationship diagram shown in the image:

[
{
"TableName": "Customer",
"TableID": 1065090,
"BaseTableName": "Customer",
"BaseFileName": "16.4",
"ModCount": 1,
"Relations": [
{
"Source": "16.4",
"Table": "Orders",
"Options": "",
"Conditions": [
"Orders::Customer_ID = Customer::P_Customer_ID"
]
},
{
"Source": "16.4",
"Table": "Mails",
"Options": "",
"Conditions": [
"Mails::Customer_ID = Customer::P_Customer_ID"
]
},
{
"Source": "16.4",
"Table": "Shipping_Addresses",
"Options": "",
"Conditions": [
"Shipping_Addresses::Customer_ID = Customer::P_Customer_ID"
]
}
]
},
{
"TableName": "Items",
"TableID": 1065092,
"BaseTableName": "Items",
"BaseFileName": "16.4",
"ModCount": 2,
"Relations": [
{
"Source": "16.4",
"Table": "Orders",
"Options": "",
"Conditions": [
"Orders::P_Orders_ID = Items::Orders_ID"
]
}
]
},
{
"TableName": "Mails",
"TableID": 1065093,
"BaseTableName": "Mails",
"BaseFileName": "16.4",
"ModCount": 2,
"Relations": [
{
"Source": "16.4",
"Table": "Customer",
"Options": "",
"Conditions": [
"Customer::P_Customer_ID = Mails::Customer_ID"
]
}
]
},
{
"TableName": "Orders",
"TableID": 1065091,
"BaseTableName": "Orders",
"BaseFileName": "16.4",
"ModCount": 2,
"Relations": [
{
"Source": "16.4",
"Table": "Customer",
"Options": "",
"Conditions": [
"Customer::P_Customer_ID = Orders::Customer_ID"
]
},
{
"Source": "16.4",
"Table": "Items",
"Options": "",
"Conditions": [
"Items::Orders_ID = Orders::P_Orders_ID"
]
}
]
},
{
"TableName": "Shipping_Addresses",
"TableID": 1065094,
"BaseTableName": "Shipping_Addresses",
"BaseFileName": "16.4",
"ModCount": 2,
"Relations": [
{
"Source": "16.4",
"Table": "Customer",
"Options": "",
"Conditions": [
"Customer::P_Customer_ID = Shipping_Addresses::Customer_ID"
]
}
]
},
{
"TableName": "Table",
"TableID": 1065089,
"BaseTableName": "Table",
"BaseFileName": "16.4",
"ModCount": 1,
"Relations": []
}
]
In comparison to the relational diagram, the JSON sometimes makes it even easier to understand the relationships, since-in addition to the table names-we also learn the BaseTable name and exactly how the relationships between the tables are defined. We hope this tool will be helpful to you in your analyses.
