Skip to content

Instantly share code, notes, and snippets.

@mhawksey
Last active October 28, 2024 14:17
Show Gist options
  • Save mhawksey/5599539 to your computer and use it in GitHub Desktop.
Save mhawksey/5599539 to your computer and use it in GitHub Desktop.
Experiment to create a document map for Google Docs using Google Apps Script
function onOpen() {
// Add a menu with some items, some separators, and a sub-menu.
DocumentApp.getUi().createMenu('Custom')
.addItem('Show Document Map', 'showDocumentMap')
.addToUi();
}
function showDocumentMap() {
// based on http://stackoverflow.com/a/12244248/1027723
var docmap = {};
var tocDat = {};
var doc = DocumentApp.getActiveDocument(); //get active document
for (var i = 0; i < doc.getNumChildren(); i++) { // loop all the document elements
var p = doc.getChild(i);
if (p.getType() == DocumentApp.ElementType.TABLE_OF_CONTENTS) { // if the element type is a TABLE_OF_CONTENTS extract item links
var toc = p.asTableOfContents();
for (var ti = 0; ti < toc.getNumChildren(); ti++) { // looping over each ToC item
var itemToc = toc.getChild(ti).asParagraph().getChild(0).asText();
var itemText = itemToc.getText();
var itemUrl = itemToc.getLinkUrl();
tocDat[itemText] = itemUrl; // create object array
}
}
// Doesn't appear to be any section level data in ToC so get this manually by going through document
if (p.getType() == DocumentApp.ElementType.PARAGRAPH){ // only need to get paragraphs
var heading = doc.getChild(i).asParagraph().getHeading();
var title = doc.getChild(i).asParagraph().asText().getText();
// if a heading map heading text to heading level
if (heading == DocumentApp.ParagraphHeading.HEADING1){
docmap[title] = 1;
} else if (heading == DocumentApp.ParagraphHeading.HEADING2){
docmap[title] = 2;
} else if (heading == DocumentApp.ParagraphHeading.HEADING3){
docmap[title] = 3;
} else if (heading == DocumentApp.ParagraphHeading.HEADING4){
docmap[title] = 4;
} else if (heading == DocumentApp.ParagraphHeading.HEADING5){
docmap[title] = 5;
} else if (heading == DocumentApp.ParagraphHeading.HEADING6){
docmap[title] = 6;
}
}
}
// build some html to render in sidebar (you can also use UIInstance for this)
var html = "";
var last_level = 0
for (i in docmap){
var level = docmap[i];
// not sure if this entirely works (basically want to nest subsections)
if(level > last_level)
html += "<ul>";
else if (level < last_level){
html += "</ul>";
}
html += Utilities.formatString("<li><a href='%s'>%s</a></li>", tocDat[i],i);
last_level = level;
}
html += "</ul>"; //close unorder list
html += "<p align='right'><a href='http://mashe.hawksey.info/'>MASHe blog</a></p>"; // add link to see if these actually render
// push out to sidebar
DocumentApp.getUi().showSidebar(
HtmlService
.createHtmlOutput(html)
.setTitle('Document Map')
.setWidth(250));
}
@areee
Copy link

areee commented Jan 9, 2016

Thank you, this script seems to be useful!
The only problem is that the code doesn't work nowadays. When running it I get an error message "Error: Not enough arguments (row 59, file Code)". Could you fix it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment