Trouble getting docs script to recognise active document

632 views
Skip to first unread message

Dean Strachan

unread,
Feb 15, 2023, 7:55:29 AM2/15/23
to Google Apps Script Community
I want to write some code that will take a google doc (which fwiw is produced from a linked google sheets) and

i) set line spacing to single 
ii) Switch off ‘allow rows to flow across page breaks’ 
iii) Set cell padding to 0.1cm

The code I have is 

function setDocumentProperties() {
  var doc = DocumentApp.getActiveDocument();
  var body = doc.getBody();

  // Set line spacing to Single
  body.setLineSpacing(DocumentApp.LineSpacing.SINGLE);

  // Switch off ‘allow rows to flow across page breaks’
  var tableStyle = {};
  tableStyle[DocumentApp.TableCellVerticalAlignment] = DocumentApp.VerticalAlignment.TOP;
  tableStyle[DocumentApp.TableRow] = {
    allowBreakAcrossPages: false
  };
  body.setTableStyles(tableStyle);

  // Set cell padding to 0.1cm
  var table = body.getTables()[0]; // Assuming you want to apply this to the first table in the document
  var cellStyle = {};
  cellStyle[DocumentApp.VerticalAlignment] = DocumentApp.VerticalAlignment.TOP;
  cellStyle[DocumentApp.PaddingBottom] = 0.1 * 72; // 0.1cm to points
  cellStyle[DocumentApp.PaddingTop] = 0.1 * 72; // 0.1cm to points
  cellStyle[DocumentApp.PaddingLeft] = 0.1 * 72; // 0.1cm to points
  cellStyle[DocumentApp.PaddingRight] = 0.1 * 72; // 0.1cm to points
  table.setCellStyleAttributes(0, 0, table.getNumRows() - 1, table.getNumColumns() - 1, cellStyle);
}

I opened up the doc, clicked extension then apps script, entered and saved that code and hit run, getting the following error code:

TypeError: Cannot read properties of undefined (reading 'SINGLE')
setDocumentProperties
@ Code.gs:6

How do I get this all working? When I click tool in the doc I don't see a direct option to run an apps script. Thank you!


Mumbling Fumbler

unread,
Feb 15, 2023, 1:46:03 PM2/15/23
to Google Apps Script Community
 var doc = DocumentApp.getActiveDocument()
will only work if you run the script from the document UI.
Sounds like you ran the script from the GAS IDE.
In that case, the active document context doesn't exist.
You can either add the UI to the Docs app via a
DocumentApp.getUI().createMenu(), or make your script standalone
by replacing
var doc = DocumentApp.getActiveDocument()
with
var doc = DocumentApp.openById(<id of my document file>)
If you are going to create menus for the document app, see
Menu creation should be done in an onOpen(e) trigger for the document.
See:

Brett Grear

unread,
Feb 16, 2023, 6:24:12 AM2/16/23
to Google Apps Script Community
Isn't setLineSpacing a method for a paragraph object, not the body?

Dean Strachan

unread,
Feb 17, 2023, 8:58:54 AM2/17/23
to Google Apps Script Community
You are right. I managed to fix that but I'm having trouble with the rest.

function formatGoogleDoc() {
  var doc = DocumentApp.openById("<id of document file>");
  var body = doc.getBody();

 // Set the line spacing to single
var paragraphs = doc.getBody().getParagraphs();

  for (var i = 0; i < paragraphs.length; i++) {
    paragraphs[i].setLineSpacing(1);
  }

  // Disable "Allow rows to flow across page breaks"
  var tables = doc.getBody().getTables();

  for (var i = 0; i < paragraphs.length; i++) {
    paragraphs[i].setLineSpacing(1);
  }

  // Disable "Allow rows to flow across page breaks"
  var tables = doc.getBody().getTables();

  for (var i = 0; i < tables.length; i++) {
    var table = tables[i];
    var numColumns = table.getNumColumns();
    var columnWidth = (doc.getBody().getPageWidth() - doc.getBody().getMarginLeft() - doc.getBody().getMarginRight()) / numColumns;
    for (var j = 0; j < numColumns; j++) {
      table.setColumnWidth(j, columnWidth);
    }
    var rows = table.getRows();
    for (var j = 0; j < rows.length; j++) {
      var row = rows[j];
      var rowStyle = {};
      rowStyle[DocumentApp.TableCellVerticalAlignment] = DocumentApp.VerticalAlignment.TOP;
      rowStyle[DocumentApp.Attribute.ALLOW_ROW_TO_BREAK_ACROSS_PAGES] = false;
      row.setAttributes(rowStyle);
      // Set cell padding to 0.1cm
      var cells = row.getTableCells();
      for (var k = 0; k < cells.length; k++) {
        cells[k].setPaddingTop(0.1 * 72);
        cells[k].setPaddingBottom(0.1 * 72);
        cells[k].setPaddingLeft(0.1 * 72);
        cells[k].setPaddingRight(0.1 * 72);
      }
    }
  }
}

I get the error code "TypeError: table.getNumColumns is not a function formatGoogleDoc    @ Code.gs:24" - where should I look to see how to fix this?

Full disclosure - I'm mostly using ChatGPT to produce this. It's not very good at Google Script. This is a one off so I'm not willing to put in too much time - feel free to ignore me if you think this is laziness.

Brett Grear

unread,
Feb 17, 2023, 10:25:40 AM2/17/23
to google-apps-sc...@googlegroups.com
Yeh there's quite a few little errors in that code. Seems chat gpt has confused the Google sheets and docs methods interchangeably. 

Sorry, I don't have the time to fix it for you.

Still amazed at how close the AI can get though

--
You received this message because you are subscribed to a topic in the Google Groups "Google Apps Script Community" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-apps-script-community/lUYj-pFz2LM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-apps-script-c...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-apps-script-community/7be5634c-059f-4aeb-ad90-3ffe1b10877en%40googlegroups.com.

Dean Strachan

unread,
Feb 17, 2023, 6:31:46 PM2/17/23
to Google Apps Script Community
That's too bad. Do you have time to point me in the right direction? I don't mind putting some work in but it's unlikely I'll be doing much more scripts work in the near future and this isn't super important so it doesn't make sense to start from scratch. Regardless of what you say thanks a lot for your help (it seems like it might have successfully got the single line spacing thing after I prompted it with with your " Isn't setLineSpacing a method for a paragraph object, not the body? " comment ).

Mumbling Fumbler

unread,
Feb 18, 2023, 2:16:07 PM2/18/23
to Google Apps Script Community
You actually have to read the GAS documentation - guessing at service methods doesn't really work.
Documentation for the Google Apps Document Service can be found here: 
https://developers.google.com/apps-script/reference/document
For instance, if you had read the documentation, you would have discovered, as the error is telling you, 
there is no  getNumColumns() method on the Document Table class.
This method exists on the Slides Table class as part of the Slides Service, which is not of particular use in your stated application
Also, you would also have seen that there is no getRows() method on the Document Table class. This method doesn't appear to exist in any GAS class in any service.

One thing that you can rely on is the arbitrariness and inconsistency of methods across GAS services.
With this in mind, implementing the 1st and 3rd items in
---------------------------------------------------------------------------------------
i) set line spacing to single 
ii) Switch off ‘allow rows to flow across page breaks’ 
iii) Set cell padding to 0.1cm
-----------------------------------------------------------------------------------------
is pretty straightforward, but the correct solution bears little relationship to your existing code.
The 2nd item Switch off ‘allow rows to flow across page breaks’ , is more complicated, and
requires the Google Docs API, not Google Document service.

The good news is that GPT AI is not going to put any human GAS developers out of business any time soon, (perhaps because of the poor design and special cases of GAS Services and APIs)
The generated code looks reasonable until you take a closer look and you discover that it is garbage, and would take more time to fix than writing the code from scratch.


Dean Strachan

unread,
Feb 18, 2023, 2:50:55 PM2/18/23
to Google Apps Script Community
Thanks for your help. As previously said this isn't a high priority and I'm unlikely to use Google Apps Script other than for this any time soon. But I will look at the documentation and have a bash.

It seems the GPT AI has little training data on Google App Script, at least for docs.

Dean Strachan

unread,
Feb 19, 2023, 11:25:20 AM2/19/23
to Google Apps Script Community
I've written script which will

i) Creates an option so people can click "Menu" (next to Extensions and Help) and then "Function" which will then
ii) Set line spacing to single 
iii) Set cell padding to 0.1cm

Progress!

The idea is people will be able to access the google doc, make a copy on their own drive and then click Menu/Function to run the script. 
When making a copy of the code the menu/function doesn't copy over - person because they haven't run the script yet?
In the copy, if you click Extensions/Apps Script you will see the code and can press run. Annoyingly, it now asks you to review permissions, and then says google hasn't verified the app. You then have to click advanced and "Go to Untitled project (unsafe)". 

What's the best way to remove this final bit? Is there an easier way than that outlined here? Ideally people would be able to copy the document with the menu/function bit intact, so they just had to do two clicks, but anything that removes the permissions bit would be good.

(fyi - the code)

'''
function createMenu() {
  DocumentApp.getUi()
   .createMenu("Menu")
   .addItem("Function","myFunction")
   .addToUi();
}

function myFunction() {
  var doc = DocumentApp.getActiveDocument();
  var paddingTop = 3; 
  var paddingBottom = 3; 
  var paddingLeft = 3; 
  var paddingRight = 3; 

  var paraStyle = {};
    paraStyle[DocumentApp.Attribute.LINE_SPACING] = 1;

  var tables = doc.getBody().getTables();
  tables.forEach(table => {
    for (var r = 0; r < table.getNumRows(); r++) {
      var row = table.getRow(r);
      for (var c = 0; c < row.getNumCells(); c++) {
        var cell=row.getCell(c);
        cell.setPaddingTop(paddingTop)
        cell.setPaddingBottom(paddingBottom);
        cell.setPaddingLeft(paddingLeft)
        cell.setPaddingRight(paddingRight);
        var items = cell.getNumChildren();
        for (var i = 0; i < items; i++){
          var paraInCell = cell.getChild(i).asParagraph();
          paraInCell.setAttributes(paraStyle);
        }
      }
    }
  });
}
'''





Reply all
Reply to author
Forward
0 new messages