Finding Tables in Google Docs

A Project to Help you Identify and Edit Tables and Cells in Google Docs from Google Apps Script

This project loads into your side bar and reads your document to look for tables. When it finds tables in display all of the rows, cells, row indexes, cell indexes and cell text. Each cell has a text box and a Save button which allows you to edit the cell text. But you can also get just the indices to use in your own program.


You will have to create an html file named 'script' and load the script.html code into it and the rest of the code can go into the Code.gs file. If you make separate project from the one you're working then you can run the onOpen and it will create a menu that won't bother any possible menus in your project.


Code.gs

The function "findingTableCells()" generates a sidebar which utilizes a templated approach so that Javascript Functions can be developed in a less cumbersone method rather that trying to include into a string as though they were minified. It also has tool tips included to help you identify the various indexes and table elements.

function onOpen() {

DocumentApp.getUi().createMenu('Table Menu')

.addItem('Find Table Cells', 'findingTableCells')

.addToUi();

}




function findingTableCells() {

var d=DocumentApp.getActiveDocument();

var body=d.getBody();

var numChildren=body.getNumChildren();

var html='<html><head>';

html+='<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>';

html+='<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">';

html+='<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>';

html+='<style>';

html+='body{font-size:14px;font-family:calibri;}';

html+='td,th{border:1px solid black;}';

html+='.tblcell input[type="text"]{background-color:#ffff00;margin:2px 1px;}';

html+='.tblcell input{margin:1px;}';

html+='.tblcell a{text-decoration:none;}';

html+='.childhdr{background-color:#00ffff;}';

html+='.childhdr a{text-decoration:none;}';

html+='</style></head><body><table>';

for(var i=0;i<numChildren;i++) {

var child=body.getChild(i);

if(child.getType()==DocumentApp.ElementType.TABLE) {

html+=Utilities.formatString('<span class="childhdr">Child[<a href="#" title="Child Index">%s</a>]:</span><br />',i);

var numRows=child.asTable().getNumRows();

for(var ri=0;ri<numRows;ri++) {

var numCells=child.asTable().getRow(ri).getNumCells();

for(var ci=0;ci<numCells;ci++) {

var cellText=child.asTable().getRow(ri).getCell(ci).editAsText().getText();

html+=Utilities.formatString('<span class="tblcell">R:[<a href="#" title="Row Index">%s</a>]&nbsp;C:[<a href="#" title="Cell Index">%s</a>]:<input type="text" value="%s" id="%s-%s-%s" size="10" title="Editable Cell Text"/>',ri,ci,cellText,i,ri,ci);

html+=Utilities.formatString('<input type="button" value="Save" onClick="saveCellText({child:%s,row:%s,cell:%s})"/>', i,ri,ci);

html+=Utilities.formatString('<input type="button" value="Bold" onClick="setCellTextStyleBold({child:%s,row:%s,cell:%s})"/></span><br />', i,ri,ci);

}

}

}

}

html+='<?!= include("script") ?>'

html+='</table></body></html>';

var ui=HtmlService.createTemplate(html).evaluate().setTitle('Finding Table Cells');

DocumentApp.getUi().showSidebar(ui);

}


function include(filename) {

return HtmlService.createHtmlOutputFromFile(filename).getContent();

}


function saveCellText(cObj) {

var doc=DocumentApp.getActiveDocument();

var body=doc.getBody();

body.getChild(cObj.child).asTable().getRow(cObj.row).getCell(cObj.cell).editAsText().setText(cObj.text).setAttributes(Normal1);

return cObj;

}


function setCellTextStyleBold(cObj) {

var doc=DocumentApp.getActiveDocument();

var body=doc.getBody();

body.getChild(cObj.child).asTable().getRow(cObj.row).getCell(cObj.cell).editAsText().setAttributes(Bold1);

return cObj;

}


script.html

There's just two functions here, one that save any edits that you make in the cells at one style . The other just bolds and enlarges the text. They both perform client to server communication with google.script.run.

<script>

function saveCellText(cObj) {

var id='#' + cObj.child + '-' + cObj.row + '-' + cObj.cell;

$(id).css('background-color','#ffffff');

var txt=$(id).val();

cObj['text']=txt;

google.script.run

.withSuccessHandler(function(cObj) {

var id1='#' + cObj.child + '-' + cObj.row + '-' + cObj.cell;

$(id1).css('background-color','#ffff00');

})

.saveCellText(cObj);

}

function setCellTextStyleBold(cObj) {

var id='#' + cObj.child + '-' + cObj.row + '-' + cObj.cell;

$(id).css('background-color','#ffffff');

var txt=$(id).val();

cObj['text']=txt;

google.script.run

.withSuccessHandler(function(cObj) {

var id1='#' + cObj.child + '-' + cObj.row + '-' + cObj.cell;

$(id1).css('background-color','#ffff00');

})

.setCellTextStyleBold(cObj);

}

</script>


styles.gs

var Bold1={};

Bold1[DocumentApp.Attribute.BOLD]=true;

Bold1[DocumentApp.Attribute.FONT_SIZE]=14;

var Normal1={};

Normal1[DocumentApp.Attribute.BOLD]=false;

Normal1[DocumentApp.Attribute.FONT_SIZE]=10;