Table of Contents generation for PDFs using Microsoft Flow

One of the most common features of professional documents is the table of contents (TOC). Muhimbi PDF Converter provides excellent support and feature-rich facility that gives you full control over the generated TOC, from start to finish. In this post we will focus on generating a Table Of Contents via Microsoft Flow.

Please make sure the following prerequisites are in place:

  • An Office 365 subscription with, SharePoint Online license.
  • Muhimbi PDF Converter Services Online full, free or trial subscription(Sign up).
  • Appropriate privileges to create Flow.
  • Working knowledge of Microsoft Flow

From a high level, our Flow will get the file content from a SharePoint document library, Convert it to PDF, Add a Table Of Content to the PDF and write the generated PDF back to the SharePoint document library.

Note: This works equally well using Muhimbi’s REST API and the SharePoint Designer workflow actions.


Step 1: For this demo, we will use the trigger “When a file is created in a folder“.
In the trigger action specify the path to the SharePoint Online folder to monitor for new files.

TOC.jpg

Note: To trigger a Flow for files created anywhere in a Document Library, use the ‘When a file is created (properties only)’ trigger.

Step 2: Add the Muhimbi “Convert Document” action.

  • Source File name: “File name” is the output from the “When File is created in a Folder”.
  • Source file content: “File Content” is the output of the “When File is created in a Folder”.
  • Output Format: PDF.
  • Override settings: Copy the XML below.

TOC

<?xml version="1.0" encoding="UTF-8"?>
<Override>
   <ConversionSettings>
      <TOCSettings>
         <MinimumEntries>0</MinimumEntries>
         <Bookmark>Table Of Contents</Bookmark>
         <Location>Front</Location>
         <Properties>
            <NameValuePair>
               <Name>title</Name>
               <Value>Index</Value>
            </NameValuePair>
         </Properties>
         <Template><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0" exclude-result-prefixes="msxsl">
   <xsl:output method="html" indent="yes" />
   <xsl:template match="/toc">
      <html>
         <head>
            <style type="text/css">ul.toc {
     margin: 0;
     padding: 0;
     list-style: none;
}
 ol.toc {
     margin: 0;
     padding: 0;
     margin-left: 10px;
     list-style: none;
}
 ul.toc li, ol.toc li {
     list-style: none;
     overflow: hidden;
}
 .bookmark-container {
     position: relative;
     width: 100%;
}
 .bookmark-container table {
     width: 100%;
     display: inline-table;
     border-collapse: collapse;
}
 .bookmark-container td {
     padding:0;
}
 td.page {
     vertical-align: bottom;
     text-align: right;
}
 a.toc {
     text-decoration: none;
     color: #000;
}
 span.title {
     background-color: white;
     padding-right: 4px;
}
 span.page {
     text-align: right;
     padding-left: 4px;
     background-color: white;
}
 .dots {
     width: 100%;
     height: 2px;
     position: absolute;
     bottom: 5px;
     border-bottom: 2px dotted black;
     z-index: -1;
}
</style>
         </head>
         <body>
            <h1>
               <xsl:value-of select="properties/property[@name='title']" />
            </h1>
            <br />
            <br />
            <xsl:apply-templates />
         </body>
      </html>
   </xsl:template>
   <xsl:template match="topics">
      <ul class="toc">
         <xsl:apply-templates />
      </ul>
   </xsl:template>
   <!-- Empty template so properties are not appearing -->
   <xsl:template match="properties" />
   <xsl:template match="topic[@level='0']">
      <li>
         <div class="bookmark-container">
            <table>
               <tr>
                  <td>
                     <span class="title" style="font-weight: 900;">
                        <xsl:element name="a">
                           <xsl:attribute name="href">
                              <xsl:value-of select="@target" />
                           </xsl:attribute>
                           <xsl:attribute name="class">toc</xsl:attribute>
                           <xsl:value-of select="@title" />
                        </xsl:element>
                     </span>
                  </td>
                  <td class="page">
                     <span class="page">
                        <xsl:element name="a">
                           <xsl:attribute name="href">
                              <xsl:value-of select="@target" />
                           </xsl:attribute>
                           <xsl:attribute name="class">toc</xsl:attribute>
                           <xsl:value-of select="@page" />
                        </xsl:element>
                     </span>
                  </td>
               </tr>
            </table>
            <div class="dots" style="" />
         </div>
      </li>
      <ol class="toc">
         <xsl:apply-templates />
      </ol>
   </xsl:template>
   <xsl:template match="topic">
      <li>
         <div class="bookmark-container">
            <table>
               <tr>
                  <td>
                     <span class="title">
                        <xsl:element name="a">
                           <xsl:attribute name="href">
                              <xsl:value-of select="@target" />
                           </xsl:attribute>
                           <xsl:attribute name="class">toc</xsl:attribute>
                           <xsl:value-of select="@title" />
                        </xsl:element>
                     </span>
                  </td>
                  <td class="page">
                     <span class="page">
                        <xsl:element name="a">
                           <xsl:attribute name="href">
                              <xsl:value-of select="@target" />
                           </xsl:attribute>
                           <xsl:attribute name="class">toc</xsl:attribute>
                           <xsl:value-of select="@page" />
                        </xsl:element>
                     </span>
                  </td>
               </tr>
            </table>
            <div class="dots" style="" />
         </div>
      </li>
      <ol class="toc">
         <xsl:apply-templates />
      </ol>
   </xsl:template>
</xsl:stylesheet>]]></Template>
      </TOCSettings>
   </ConversionSettings>
</Override>

Step 3: Use the “Create file” SharePoint action to create the PDF document into SharePoint document library.

  • File name: “Base file name“.pdf  (output variable of the “Convert document” action.
  • File content: “Processed file content” (output variable of the “Convert document” action).
Createfile.jpg

Step 4: All done! Now it’s time to test our Flow.

  • The best way to test this is to convert an MS-Word file that contains proper heading definitions (Heading1, Heading 2 etc).
  • Upload a document to the library.
  • The Flow will be triggered automatically.
  • You should have a PDF generated with Table of Contents in the Destination document library.
Final.jpg
Happy Converting..

One thought on “Table of Contents generation for PDFs using Microsoft Flow

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s