The second step when using DocumentData to set up an integration to an external system, will be to transform data from the external system. To learn more about DocumentData and the data flow, read the basics.
In this article, you can read about how we transform data once the fetch step is complete. When you have the transformed data you need, the next and final step in configuring your integration is to output your data to a document or presentation.
Contents
General info [Back to top]
Once we have run commands to fetch data from external systems, the data will be temporarily stored in DocumentData before it is committed to the document or discarded.
While the data is stored in DocumentData, we can transform it using commands - typically running from the DocumentData plugin in combination with various BaseExtensions commands.
The transformation of data happens in the same module as the fetching of data. This means that on the event or button click that triggers the specialised commands that fetches data from the external system, you will need to transform this data as well. This is due to the fact mentioned above: that DocumentData only stores the data temporarily. Sometimes, the configuration requires some level of storing between commits. Luckily, there is some support for this...
Storing data between commits
If we need to store data in a document or presentation after committing or discarding data from DocumentData, we generally utilise custom document properties or, in rare cases, customXML, to store the data until it is needed for and update.
When using DocumentData for more advanced features, it can be helpful to enable pending changes before and to commit afterwards. In between enabling and committing, the transformation take place.
EnablePendingChanges [Back to top]
This command enters the pending changes, where the given data will be received, but nothing will happen in the document yet. This command should be the first one of the chain in the module.
CMD
<Cmd case="SkabelonDesign.DocumentData:EnablePendingChanges"/>
Once pending changes are enabled, DocumentData will expect to face either a commit- or discard command in the following chain. Usually, configurations does not require discarding data.
Parameter
disableAutoCommit
Optional. Document data can be used in conjunction with with other integrations. In cases where this integration provides a dialog to a user setting this parameter to true
will cancel the commit action preventing any update in the document, on selecting to cancel the dialog.
Commit [Back to top]
This command updates the entire document including document properties. This command should not be run before transformation of data is complete. Document update will happen based on configuration in the output step.
CMD
<Cmd case="SkabelonDesign.DocumentData:Commit"/>
Parameters
selectionOnly
If set to true
, the command will only update the selection in the document.
InsertValueSelection
If set to true
, the value is resolved and inserted at selection. In this way, the value is inserted as plain text at the location of the cursor. Be aware that cursor position can be manipulated through the use of various BaseExtensions commands.
InsertValueContentControls
Using this parameter, the data will be committed into a specific range using content controls. Define the title of content controls. If there are more than one, separate them with a semicolon. The parameter accepts name of the parent content control. The updated data will be inside the parent content control and only child content controls will be updated.
DefineData [Back to top]
We are able to define a key that refers to multiple combinations of values available in DocumentData at the current state of the command chain. Each of the elements in the command will be evaluated, and the variable name will be assigned to the first non-empty one.
CMD
<cmd case="SkabelonDesign.DocumentData:DefineData" variableName="x">xx</Cmd>
Parameter
variableName
Define the name of the variable. The variable name is the value you input into your JSON binding in Word/PowerPoint.
Examples of usage
Create list of recipients
The first example illustrates how the command can be used to create a list. At first, pending changes are enabled. Afterwards, there is a command that opens the Outlook address book to allow the user to insert a recipient. Using DefineData
, we are able to insert the selected recipients as a list. Here, the defined variable Module.Participants
will be a long string concatenated using the rules specified inside the definition. If the user picks three recipients from the Outlook.To
, the command will build a string with these three recipients separated by comma and space. The comma and space are defined in the <s>
tag, which is a string.
<Button label="Outlook">
<cmd case="SkabelonDesign.DocumentData:EnablePendingChanges"/> <cmd case="SkabelonDesign.OutlookAddressBook:insert-recipient-list" prefix="Outlook" /> <cmd case="SkabelonDesign.DocumentData:DefineData" variableName="Module.Participants"> <Outlook.To> <Outlook.FirstName/> <Outlook.LastName/> <Separator> <s>, </s> </Separator> </Outlook.To> <s/> </cmd> <cmd case="SkabelonDesign.DocumentData:Commit" InsertValueSelection="Module.Participants"/> </Button>
Use custom XML or document property
In the second example, we insert stuff in the content control Module.Version
with either custom XML, document property or null in prioritized order:
<cmd case="SkabelonDesign.DocumentData:EnablePendingChanges"/> <cmd case="SkabelonDesign.DocumentData:DefineData" variableName="Module.Version"> <Doc.CustomXml.DLCPolicyLabelValue> <Doc.CustomXml.DLCPolicyLabelValue/> </Doc.CustomXml.DLCPolicyLabelValue> <Doc.Prop.Ram_Document_Version> <Doc.Prop.Ram_Document_Version/> </Doc.Prop.Ram_Document_Version> <s/> </cmd> <cmd case="SkabelonDesign.DocumentData:Commit"/>
Slide number
The command can be used to define how the slide number should be inserted. It can be used so that the user determine whether the page number should be Page X or Page X of Y in Templafy before opening the template. Depending on what is selected, a document property is inserted into the template with a matching value. In extension, we execute the following event, where <#> is interpreted as field for actual slide number and <##> as field for the total number of slides. Another example can be seen in the below. Note that we in this example does not use fetching, but instead read data from the presentation.
<event type="BaseExtensions:NewDocument" showInExcel="false" showInWord="false"> <Cmd case="SkabelonDesign.DocumentData:EnablePendingChanges"/>
<Cmd case="BaseExtensions:If" if-1-type="documentprop" if-1-key="PageNumberVisible" if-1-value="PageX">
<True>
<Cmd case="SkabelonDesign.DocumentData:DefineData" variableName="Module.PageNo">
<s><![CDATA[ | Page <#>]]></s>
</Cmd>
</True>
</Cmd>
<Cmd case="BaseExtensions:If" if-1-type="documentprop" if-1-key="PageNumberVisible" if-1-value="PageXY">
<True>
<Cmd case="SkabelonDesign.DocumentData:DefineData" variableName="Module.PageNo">
<s><![CDATA[ | Page <#> of <##>]]></s>
</Cmd>
</True>
</Cmd>
<Cmd case="SkabelonDesign.DocumentData:Commit"/>
</event>
Define data from any XML part text value
We support defining data from the value in an XML part in the document. Based on this, use the following to define data:
<Cmd case="SkabelonDesign.DocumentData:DefineData" variableName="Value1"> <Doc.Prop.thisIsADocProp> <Doc.Prop.thisIsADocProp/> </Doc.Prop.thisIsADocProp> <Custom Name="Doc.XPath/*[local-name() = 'GrowBusinessDocument']/*[local-name() = 'OurRef.Title']">
<Custom Name="Doc.XPath/*[local-name() = 'GrowBusinessDocument']/*[local-name() = 'OurRef.Title']"/>
</Custom> <s/> </Cmd>
The reason for the local name part is because of the need to ignore namespace in the XML. See syntax here. The idea is that we can use any name for the XML element, but use the "Name" attribute for the actual name. Doc.XPath
goes through all XML parts in the document and finds the first that matches the XPath
expression. In the example above, the command will search for an XML part named GrowBusinessDocument
, and thus grab the text value from OurRef.Title
to be defined in the variable Value1
.
Evaluate group to empty string if value is "false"
DocumentData can evaluate the false
value and act on that.
<Cmd case="SkabelonDesign.DocumentData:DefineData" variableName="Module.FooterText">
<Doc.Prop.TemplateId>
<Doc.Prop.IsDocument>
<Doc.Prop.DocTitle>
<Doc.Prop.Title>
<Doc.Prop.Title/>
<s><![CDATA[ | ]]></s>
</Doc.Prop.Title>
<Doc.Prop.DocTitle/>
</Doc.Prop.DocTitle>
</Doc.Prop.IsDocument>
</Doc.Prop.TemplateId>
</Cmd>
If the TemplateId document property contains false
value, the inside binding will not be resolved and thus result in an empty string value for that part of the binding. It means that the document properties DocTitle
and Title
will not be resolved. However, if the value is true
or anything else, the document properties will be resolved and therefore inserted into a destination.
Split data into multiple strings
DefineData can be given an optional split
and select
parameter for only selecting part of the data. In this way, we limit the data definition.
In the examples below, the split
parameter defines the separator used to split the data of Doc.Prop.Ram_Document_Version
into multiple strings, while the select
parameter defines which of the multiple strings to use for DocumentData. The index of the first string is 0. If the value defined in the select
parameter is larger than the number of strings, the last one is used.
Assuming Ram_Document_Version
uses the format xx.xx.xx.xx, the following example gets the last xx.
<Cmd case="SkabelonDesign.DocumentData:EnablePendingChanges"/>
<Cmd case="SkabelonDesign.DocumentData:DefineData" variableName="Module.Version">
<Doc.CustomXml.DLCPolicyLabelValue> <Doc.CustomXml.DLCPolicyLabelValue/>
</Doc.CustomXml.DLCPolicyLabelValue> <Doc.Prop.Ram_Document_Version>
<Doc.Prop.Ram_Document_Version split=”.” select=”100”/>
</Doc.Prop.Ram_Document_Version> <s/>
</Cmd>
<Cmd case="SkabelonDesign.DocumentData:Commit"/>
Using the previous case, the following example gets the first xx.
<Cmd case="SkabelonDesign.DocumentData:EnablePendingChanges"/>
<Cmd case="SkabelonDesign.DocumentData:DefineData" variableName="Module.Version">
<Doc.CustomXml.DLCPolicyLabelValue> <Doc.CustomXml.DLCPolicyLabelValue/>
</Doc.CustomXml.DLCPolicyLabelValue> <Doc.Prop.Ram_Document_Version>
<Doc.Prop.Ram_Document_Version split=”.” select=”0”/>
</Doc.Prop.Ram_Document_Version> <s/>
</Cmd>
<Cmd case="SkabelonDesign.DocumentData:Commit"/>
Insert todays date
We support the ability to insert todays date using DocumentData. This works in both Word, Excel, PowerPoint and Outlook.
The type in the binding needs to be set to "Date". Otherwise, the format in the binding will not be read. Here is an example of the binding:
{"SkabelonDesign":{"type":"Date","ignoreBlank":"true","binding":"Date","format":"dd.MM.yyyy"}}
Corresponding module:
<Cmd case="SkabelonDesign.DocumentData:EnablePendingChanges"/>
<Cmd case="SkabelonDesign.DocumentData:DefineData" variableName="Date">
<Doc.DateTime.Today>
<Doc.DateTime.Today/>
</Doc.DateTime.Today>
</Cmd>
<Cmd case="SkabelonDesign.DocumentData:Commit"/>
This will insert the date, e.g. 29.06.2021, into a content control with the binding above.
Translate Data
It is possible to translate defined document data based on a preconfigured translations file. An example of this can be seen with Hamburger's solution where job titles fetched as part of their Active Directory integration are then translated into one of four different languages before being inserted into the users document.
Example module:
<Cmd case="SkabelonDesign.DocumentData:EnablePendingChanges" disableAutoCommit="true"/>
<Cmd case="SkabelonDesign.AD:AD" prefix="AD"/>
<Cmd case="SkabelonDesign.DocumentData:DefineData" variableName="LanguageId">
<Doc.Prop.TemplafyLanguageCode>
<Doc.Prop.TemplafyLanguageCode/>
</Doc.Prop.TemplafyLanguageCode>
</Cmd>
<Cmd case="Omnidocs.TranslateData:TranslateDocumentData" path="TranslateDocumentData.json" languageKey="LanguageId"/>
<Cmd case="SkabelonDesign.DocumentData:Commit" InsertValueContentControls="ADGroup"/>
<Cmd case="BaseExtensions:show-hide-named-cc" name="ADGroup" visible="true"/>
Here, we are defining the content that we wish to translate (LanguageID) and TranslateData is referring to TranslateDocumentData.json to correctly translate this. The translations document must be added to the the users Content\Omnidocs.TranslateData folder.
{
"Rechtsanwältin": {
"de-CH": "Rechtsanwältin",
"en-US": "Attorney at law",
"fr-CH": "Avocate",
"it-CH": "Avvocato"
},
"Rechtsanwalt": {
"de-CH": "Rechtsanwält",
"en-US": "Attorney at law",
"fr-CH": "Avocat",
"it-CH": "Avvocato"
}
}
NOTE that this all requires an additional Plugin called Omnidocs.TranslateData.
Update bookmark with value from document property
With DocumentData, we are able to replace content in a bookmark with the value from a document property in Word. It is necessary to use this command in conjunction with a command that enables pending changes. See below.
Module is located here:
...\ModuleLibrary\DocumentData\01_nocontext_DocumentData\01_updateBookmark.xml
CMD
<Cmd case="SkabelonDesign.DocumentData:DefineBookmark" name="x" key="x"/>
Parameters
name
Define bookmark name.
key
Define binding value of document property. The value must be written in the parameter with Doc.Prop., e.g. Doc.Prop.SomeSD
Here is an example of how it works:
In this example, the bookmark name is SD_bookmark
, while the key is Doc.Prop.SomeSD
.
Insert a bookmark and name it as defined in parameter. Afterwards, make sure that the document property is present.
Now, you will be able to update the bookmark and replace the content with the value from your document property:
Update Document Property [Back to top]
As mentioned, the commit command will update the entire document including all document properties. Depending on the scenario, sometimes it is necessary to control this update with either selectionOnly
or InsertValueSelection
. If these are used, the command will not update document properties. Therefore, we need to use a command that will update named document properties. This makes sense to use if a specific document property should be changed, when we overwrite parts of the document. Note that the document property will be updated with out being committed.
CMD
<cmd case="SkabelonDesign.DocumentData:UpdateProperties" include="x"/>
Parameter
include
Define the name of the document properties that should be updated. If there are several document properties, separate them with a semicolon, e.g. DocProp1;DocProp2;DocProp3
.
Notice: In the output step of the data flow, is possible to merge multiple values in custom document properties using the _src suffix.
Run Update [Back to top]
<Cmd case="SkabelonDesign.DocumentData:RunUpdate"/>
Updates all bindings in the document.
Discard [Back to top]
This command will flush the currently appended data and go to the non-appending mode. This means, instead of automatically committing the data appended, DocumentData will continue as if no data was defined, and thus override any data. If this call is succeeded by any DocumentData calls, the plugin will execute as if no calls have been performed earlier.
CMD
<cmd case="SkabelonDesign.DocumentData:Discard"/>
Example: Discard if no data found
This example builds on the first example in the article. The user is going to insert a recipient, but now we have applied an action if none is selected. To do so, we use an "If" command that will check if the value in our variable Module.Participants
is either "None" or "None selected". If this returns to be true
, the data will be discarded and go to non-appending mode. In contrast, if the value returns to be false
, the document property Participants
will be updated and the commit command is executed to inserted the selected recipients where the cursor is located.
<Button label="Outlook">
<cmd case="SkabelonDesign.DocumentData:EnablePendingChanges"/>
<cmd case="SkabelonDesign.OutlookAddressBook:insert-recipient-list" prefix="Outlook" clearOnCancel="false"/>
<cmd case="SkabelonDesign.DocumentData:DefineData" variableName="Module.Participants">
<Outlook.To>
<Outlook.FirstName/>
<s> </s>
<Outlook.LastName/>
<Separator> <s>, </s> </Separator>
</Outlook.To>
<s>None selected</s>
</cmd>
<cmd case="BaseExtensions:If" if-1-type="DOCUMENTDATA" if-1-key-1="Module.Participants" if-1-value-1="None" if-1-value-2="None selected">
<True>
<cmd case="SkabelonDesign.DocumentData:Discard"/>
</True>
<False>
<cmd case="SkabelonDesign.DocumentData:UpdateProperties" include="Participants"/>
<cmd case="SkabelonDesign.DocumentData:Commit" InsertValueSelection="Module.Participants"/>
</False>
</cmd> </Button>
Circumvent parsing errors [Back to top]
In some cases, you will need transform data that will mess up XML module parsing. For instance when targeting items in an array, like in the example below.
<cmd case="SkabelonDesign.DocumentData:DefineData" variableName="RecipientInfo">
<lb.contact.memberno>
<lb.contact.firstname/> <s><![CDATA[ ]]></s> <lb.contact.familyname/> <s><![CDATA
]]></s> <e Name="lb.contact.addresses.address[0].streetname"/>
</lb.contact.memberno>
</cmd>
<e Name="DocumentData.Name.Here[0].$"/>
By writing <e Name=xx/>
you can write characters, that XML usually do not accept in DocumentData
StripIfStartsWith [Back to top]
<Cmd case="SkabelonDesign.DocumentData:StripIfStartsWith" value="xx"/>
This command will evaluate data stored in DocumentData and remove value
if found at the start of data string. This command can be useful for trimming away redundant spaces or if string is concatenated from multiple sources.
Comments
0 comments
Article is closed for comments.