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.
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.
<?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).

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.

This is a great tip especially to those fresh to the blogosphere. Short but very precise info… Thank you for sharing this one. A must read post!
LikeLike