Office is shipping a new feature that enables PDFs created from Office using Export to PDF or Save As PDF to retain the source document’s labels or encryption into the output PDF. Office also enables Office Add-in developers to hook into and reuse some or all of Office’s PDF creation code. This feature may cause some add-ins to fail and may require development effort to adjust to new Office behavior. This applies to VBA for Word, PowerPoint, Excel.
Potential challenges to existing VBA add-insÂ
For add-ins that use an object model path such as the Document.ExportAsFixedFormat2 method to ask Office to export to PDF, if the add-in doesn’t provide a custom IMsoDocExporter instance via the FixedFormatExtClassPtr argument, then the add-in will inherit Office’s PDF code. If the source document is encrypted, the output PDF will also be encrypted with Microsoft IRM protection for PDFs. Your add-in may either fail or fail to produce meaningful results if it does any post-processing without knowing how to decrypt the PDF. Note that add-ins that provide a custom IMsoDocExporter instance don’t use Office’s PDF encryption logic and therefore shouldn’t need to mitigate anything — you’ll need to do your own PDF encryption, if desired. Â
Transition periodÂ
As the Export to PDF feature launches, we’re introducing a temporary mitigation to allow you time to update your add-ins. We’ve disabled all requests via the object model to keep encryption for PDFs. At the appropriate time, we’ll re-enable honoring the request, resulting in potential encrypted PDFs. Â
Word and PowerPoint offer object model arguments that allow the add-in to request keeping IRM settings for PDFs via the ExportAsFixedFormat family of functions. Excel currently does not, but the setting defaults to TRUE. We’ll also turn this to FALSE for the same time period to provide you adequate time to update your add-in. Word’s argument is called KeepIRM while PowerPoint’s is called KeepIRMSettings. These arguments will be ignored and forced to FALSE for PDFs until we release an update to honor these settings again.Â
How to update your Office Add-inÂ
Add-ins need a way to decrypt PDFs programmatically if you want to adjust or alter the PDF file Office creates. The PDF will be encrypted with v2 of Microsoft’s IRM for PDF specification. This results in a Microsoft Information Protection (MIP) encrypted PDF. One such way to decrypt these files is via the MIP SDK. This can be used to decrypt the PDF on behalf of the user so the add-in can adjust the PDF contents, and then re-encrypt the PDF so as not to strip the protection from the newly encrypted PDF from Office. For an example of how to decrypt the PDF, see Encrypt/Decrypt text using the C++ MIP Protection SDK. For how to get what sensitivity labels the PDF has (if any), see List sensitivity labels in a Microsoft Purview Information Protection tenant using C++ MIP SDK. From there, the MIP SDK can encrypt the PDF again.Â
Another option is for add-ins to pass FALSE for the KeepIRM/KeepIRMSettings flags. This won’t solve the problem for Excel since Excel doesn’t expose this argument to object model users. This also strips labels and encryption in the output PDF unnecessarily and may not be preferable for customers. Â
Down the road, we’ll provide a preview program for this second phase of PDF protection from Office where organizations can opt-in to validate their flows against the updates where Office again honors the IRM settings flag for PDFs. Â
Happy coding! Chris Dietsch | Senior Software Engineer | Microsoft Office Add-ins platform
Am I going insane, or is FixedFormatExtClassPtr a required parameter? What should I pass if I don’t have a custom IMsoDocExporter?
Hi Mike, not insane, but no it’s not a required parameter, it can accept a null value or just nothing as it should be Optional.
Hmmm...I agree that pretty much everything I have seen in documentation, and the general format of the function says it should be optional, but this C# code:
<code>
(where "this" is an implementation of a Document class, and "Word" is Microsoft.Office.Interop.Word)
Produces this error:
<code>
I’m not as familiar with the C# code, but have you tried or been able to pass some form of null as one of the arguments to the function?