Automatically updating InDesign publications with the latest version of all items
An InDesign document typically contains import links that reference external images.
When both the document and the images are cataloged, ADAM keeps track of the relationship between the publication itself and all items used in the publication.
In AssetStudio, you can immediately see which items are used in a certain publication.
When you order an InDesign document (or another file format supporting publication items),
you have the option to include all import links with the ordered file.
Uploading a new version for an asset used in a publication will not affect the original document.
However, you may want to update the original publication so it includes the latest version of all items.
Using DocMaker Studio, you can easily replace images in an InDesign document,
but manually replacing each updated import link can be a lot of work and you still need to keep track of which items have been updated.
Wouldn't it be cool if you could run a maintenance action that detects which items in a publication
have been updated and automatically creates a new version of the InDesign document where all items
have been replaced with their latest version? Depending on the use case, you could either run this maintenance action
periodically on all InDesign documents, or you could run it on a basket of publications that you are about to order.
This can easily be accomplished by implementing a custom maintenance action using the DocMaker API.
How to implement maintenance actions is explained in the ADAM Developer Guide.
The interesting bit is the OnExecute method of our UpdateImportsAction:
| C# |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
protected override void OnExecute(MaintenanceTarget target)
{
// Only consider the latest version of the master file for updating imports.
FileVersion publication = ((RecordMaintenanceTarget)target).Record.Files.LatestMaster;
// Finds any items in the publication that have been updated to a new version.
Dictionary<string, Guid> updatedItems = FindUpdatedItems(publication);
if (updatedItems.Any())
{
// Updates the imports in the publication to the latest version of the items.
UpdateImports(publication, updatedItems);
}
}
|
There are two steps involved. First we need to determine which items are used in the publication and for which
assets a newer version exists in ADAM. This is straightforward to do and does not require any DocMaker
functionality. For each updated image, we map the path of the original version to the id of the latest version.
The resulting Dictionary can then be used in the next step of our algorithm.
| C# |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
private Dictionary<string, Guid> FindUpdatedItems(FileVersion publication)
{
Dictionary<string, Guid> originalPathToLatestVersionIdMap = new Dictionary<string, Guid>();
Guid[] itemIds = publication.Items.CopyFileVersionIdsToArray();
if (itemIds.Any())
{
RecordHelper helper = new RecordHelper(App);
SearchExpression searchExpression = new SearchExpression("Id in ?", new object[] { itemIds });
RecordLoadOptions options = new RecordLoadOptions();
foreach (FileVersion item in helper.GetFileVersions(searchExpression, "", options))
{
Guid latestVersionId = item.File.Versions.Latest.Id;
if (latestVersionId != item.Id)
{
originalPathToLatestVersionIdMap[item.Path] = latestVersionId;
}
}
}
return originalPathToLatestVersionIdMap;
}
|
Once we know which items have been updated with a new version, we can find and replace those images in the InDesign document.
This can be done in a few lines of code using the DocMaker API. We simply enumerate all non-embedded images in the document
and replace the import links that match one of the updated items.
| C# |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
private static void UpdateImports(FileVersion publication, IDictionary<string, Guid> pathToVersionMap)
{
using (Document document = Document.CreateFromFile(publication.File))
{
// Enumerate all import links (i.e. non-embedded images) and update them if necessary.
foreach (ImageElement imageElement in document.EnumerateAllElements().OfType<ImageElement>().Where(i => !i.IsEmbedded))
{
Guid latestVersionId;
if (pathToVersionMap.TryGetValue(imageElement.ImagePath, out latestVersionId))
{
imageElement.ReplaceImage(ReplaceImageSource.FileVersion, latestVersionId);
}
}
// Save the updated publication as a new version.
if (document.HasChangesToPublish)
{
document.PublishToRecord(DocumentSaveMode.NewVersion);
publication.File.Record.Save();
}
}
}
|
Finally we need to compile our class library, register it in the ADAM database (or in the GAC) and add our provider to the
"Maintenance actions providers" setting:
| XML |
1
2
3
|
<engines>
<add name="UpdateImportsAction" type="UpdateImportsLibrary.UpdateImportsAction,UpdateImportsLibrary" />
</engines>
|
When the
UpdateImportsAction is run against a target publication, and new versions exist for certain assets
used in that publication, a new version of the InDesign document will be created which links to the latest version
of each image. When you order the InDesign document with the option to include all items, the latest version of each
image will be included.
As usual, the warning applies that the above code is meant for illustrative purposes only and has not been prepared for use
in a production environment. For instance, in production you should check that the target for the maintenance action
is indeed an InDesign document and throw an exception otherwise.