How to exclude table cells paragraphs from getParagraphs() in DocumentApp, apps script - google-apps-script

I need to get all the paragraphs from a google document. For that, I am using body.getParagraphs().
The problem is, in any document, if any table exists, the body.getParagraphs() method takes all the table cells as a paragraph and returns as a paragraph. Now what I want is to get all the paragraphs only, from a document and exclude the table and table cells from that. How can I achieve this?
Thanks!

I believe your goal as follows.
You want to retrieve the paragraphs except for the table cell using Google Apps Script.
In this case, how about checking the element type? When this is reflected to a script, it becomes as follows.
Sample script:
Please copy and paste the following script to the script editor of Google Document.
function myFunction() {
const doc = DocumentApp.getActiveDocument();
const body = doc.getBody();
const paragraphs = body.getParagraphs();
const res = paragraphs.filter(p => p.getParent().getType() != DocumentApp.ElementType.TABLE_CELL);
// do something
}
In this sample script, the values of paragraphs include the paragraphs of table cell.
By filtering the element type, res can have only the paragraphs except for the table cell.
References:
getParent() of Class Paragraph
getType()

Related

Google Script Select Partial Text in Docs

My Goal is to build a system that selects whitespace that has been underlined, and so far I have a system that moves the cursor to the start of the underlined section and highlights it.
I'm new to using Google's Apps Script, and have gotten stuck trying to programatically select only part of a paragraph. I've figured out how to select an entire paragraph and how to move the cursor to a specific location within a paragraph, but I can't figure out how to only select part of a paragraph; partially highlighted text.
I've tried using var range = DocumentApp.getActiveDocument().newRange(); and DocumentApp.getActiveDocument().setSelection(range.build());, but they only select entire paragraphs, not small portions of them.
Is there a way to select text in a paragraph between a start point and and end point?
I believe your goal is as follows.
From Is there a way to select text in a paragraph between a start point and and end point?, you want to select a part of the text on Google Document using Google Apps Script.
About I've tried using var range = DocumentApp.getActiveDocument().newRange(); and DocumentApp.getActiveDocument().setSelection(range.build());, but they only select entire paragraphs, not small portions of them., I think that in your script an erro occurs, because no range is included. In this case, it is required to include the range.
The sample script is as follows. In this case, a part of text in a paragraph is selected using the method of addElementsBetween(startTextElement, startOffset, endTextElementInclusive, endOffsetInclusive) of Class RangeBuilder.
Sample script:
Please copy and paste the following script to the script editor of Google Document. And, please set start and end. In this sample script, a part of the text in 1st paragraph is selected using a script.
function myFunction() {
const start = 8; // Please set the start offset.
const end = 14; // Please set the end offset.
const doc = DocumentApp.getActiveDocument();
const paragraph = doc.getBody().getParagraphs()[0]; // As a sample, the 1st paragraph is used.
const text = paragraph.editAsText();
const range = doc.newRange().addElementsBetween(text, start, text, end).build();
doc.setSelection(range);
}
Testing:
When this script is used, the following result is obtained.
From:
To:
Note:
This is a simple sample script. So, please modify this for your actual situation.
References:
Class RangeBuilder
addElementsBetween(startTextElement, startOffset, endTextElementInclusive, endOffsetInclusive)

Canonical way to reference Elements

Is there a canonical way to set an ID—or other searchable, persistent data attribute—on Elements in Google Docs, such that I can easily refer back to it later? I'm looking for something equivalent to getElementById in javascript. Almost all examples I've seen, including Google's own docs, seem to reference objects by searching for text strings or inserting new strings.
I've found one reference in the NamedRanges class to a getId function, but I can't find any place to set that ID. I do see the setAttributes function on Elements but that seems to apply only for pre-defined attribute types. I haven't tested that, though.
In case it's relevant: my interest is in automatically creating a document from a Google Sheet and populating based on the current values in the sheet. I'd like to assign specific Elements individual IDs so I can easily retrieve the Element and replace the text if the values in the sheet change later on.
Turns out that this is possible using NamedRanges, I just didn't read carefully enough.
Note: All the following examples are working off this Google doc. You can make a copy and select "Script Editor" from the Tools menu to see the code.
You can assign named ranges pretty easily using Apps Script. The below code looks through the doc for [[TITLE]] and [[ABSTRACT]] and assigns named ranges to those chunks. Note that in the aforelinked doc I put them in a table to avoid issues with partial ranges.
function assignNamedRanges() {
const doc = DocumentApp.getActiveDocument();
const body = doc.getBody();
const placeholders = ["title", "abstract"];
placeholders.forEach(p => {
const rangeBuilder = doc.newRange();
const text = body.findText("[[" + p.toUpperCase() + "]]");
rangeBuilder.addElement(text.getElement());
doc.addNamedRange(p, rangeBuilder.build());
});
}
Once you assigned them, you can update the range to something else in a separate function:
function updateNamedRanges() {
const doc = DocumentApp.getActiveDocument();
const body = doc.getBody();
const title = doc.getNamedRanges("title")[0];
const abstract = doc.getNamedRanges("abstract")[0];
title.getRange().getRangeElements()[0].getElement().asText().setText("Bob");
abstract.getRange().getRangeElements()[0].getElement().asText().setText("I like pancakes");
}
Note that NamedRanges are persistent, and the multiple NamedRange instances can have the same name. This means that if you run the first function four times, you'll have eight named ranges. You can make a convenience function to clear all those out pretty easily:
function clearNamedRanges() {
DocumentApp.getActiveDocument().getNamedRanges().forEach(r => {
r.remove();
})
}
So I been checking the documentation about elements for Google Docs in AppScript and it seems that some of them can be modified but not as freely as it looks as noted in the documentation:
Elements shown in bold can be inserted; non-bold elements can only be manipulated in place.
I tried checking with setAttributes as you mentioned however the attributes itself can only be from a document elements like: TEXT, PARAGRAPH, TABLE, ETC, this elements can't receive an ID as there is not method to insert an specific ID as you are requiring, most of the values that can be inserted are specific element attributes like: Font size, Font family, etc.

DocumentApp's TableCell.appendImage creates an unnecessary paragraph before the image. How can I avoid this?

I'm trying to create a Google Document file using DocumentApp API.
I want to make a table and insert an inline-image into its cell.
Like this:
table = body.appendTable([[''],[contact]]);
let img = table.getCell(0,0).appendImage(DriveApp.getFileById(imgFileId).getBlob());
It works, but there is a paragraph ( or '\n' or '\r'? I'm not sure.) before the inserted image.
I want that the cell to contain only the image.
Is there any way to do that?
Thanks.
When a table is created, the cell has one child as the default as mentioned by Cooper's comment. So, in your situation, in order to achieve your goal, how about the following modification?
Modified script:
From:
let img = table.getCell(0,0).appendImage(DriveApp.getFileById(imgFileId).getBlob());
To:
In this modification, the image is appended to the cell and removed in the 1st paragraph. I thought that this modification might help to understand the above situation.
var cell = table.getCell(0, 0);
cell.appendImage(DriveApp.getFileById(imgFileId).getBlob());
cell.getChild(0).removeFromParent();
Or, you can also use the following modification. In this modification, the image is inserted into the 1st paragraph.
table.getCell(0, 0).getChild(0).asParagraph().insertInlineImage(0, DriveApp.getFileById(imgFileId).getBlob());
Reference:
getChild(childIndex) of Class TableCell

How to copy and paste specific information in a same doc using Google App Script?

I'm very new using GAS what I'm trying to do is to copy some information that is already on the bottom of my doc to anywhere I want in my docs, this should work just by copying the information and paste it at the place I desire, but I want it to be done with Google App Script because it's a daily task and it's easier to do it with a function, instead of copying and pasting manually. Searching on how to do this, I found a lot of information about how to do it on Spreadsheets, but I needed it to be done on Google Docs. How can I do that?
If someone can guide me or send me a link to another similar question that would be very helpful, I don't know where to start.
This is what I have until now, I get all the data of the current doc and set it again to the page, the code gives me problems because it deletes my other information, also it selects all the doc's information. I want to select a piece of specific information and don't copy the content style.
function copyPasteInfo() {
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var notesText = body.getText();
body.appendPageBreak();
body.setText(notesText);
}
Link to the doc document
https://docs.google.com/document/d/1s2TCspXbjvHVurwhIWSdwJ_hMcZIoLTKj4FAB82nmhM/edit
Video example of how what i want to do
https://www.screencast.com/t/UmEon8Fm0lPe
Picture of the information i'm trying to copy and paste to the bottom of my doc
If I correctly understood your question, this code will help you to achieve your goal.
let body = DocumentApp.getActiveDocument().getBody();
function moveTable() {
// Get the last table and the previous table found in your Doc
const [previousTable, bottomTable] = getDesireTables();
// Make a copy of your last table
const bottomTableCopy = bottomTable.copy();
// Get the previous table's index
const previousTableIndex = body.getChildIndex(previousTable);
// Insert the last table's copy under the previous table in your Doc
body.insertTable(previousTableIndex + 1, bottomTableCopy);
// Remove the original last table
body.removeChild(bottomTable);
}
function getDesireTables(){
const tablesArr = body.getTables().slice(-3);
// Get the parent element type to check if it's a cell
const parentELementType = tablesArr[tablesArr.length - 1].getParent().getType();
if(parentELementType === DocumentApp.ElementType.TABLE_CELL){
// If there's a table inside a table, return this
return tablesArr.slice(0, 2);
}
else{
return tablesArr.slice(-2);
}
}
What I did was to get the last two tables in the Doc, then I made a copy of the last one and with the index of the previous one, I inserted it under the previous one.
Edit
I noticed you had a table inside a table. therefore I added the getDesireTables function. Which it will check if your bottom table has a table inside.
Docs
These are the docs I used to help you:
getTables().
copy().
insertTable(childIndex, table).

Google Script different aligment in same table row in Docs table

I'm trying to put three paragraphs (loaded from google spreadsheet) into docs via google app script.
One should be on its own row and the other two should be on same row but with different alignment.
Pic. 1 - What I want
The problem is, google allow only appending paragraphs into table cells. And paragraph contains new line so the second text is on the new line.
Pic. 2 - What I get
I've tried appending paragraph and then appending text.
But I don't know how to set up right-aligned tab and insert tab after first text.
Is it even possible to set up tabs using google script only ?
I welcome any help or suggestion how can I create text as showed in Pic. 1. Than you for any help.
There is actually an issue (3211) that prevents doing exactly what you want : the merge() method is causing the doc crash.
so the code below will result in something like this :
because we cannot merge the 2 cells in the first row from the script.
Doing it manually works well :
code :
function myFunction() {
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
body.clear();
var table = body.appendTable([['',''],['','']]);
table.setBorderColor('#ffffff');
table.getCell(0,0).appendParagraph('Some important text important text important text important text ');
//table.getCell(0,1).merge();// this is the issue...it crashes the doc
table.getCell(1,0).appendParagraph('left text').setAlignment(DocumentApp.HorizontalAlignment.LEFT);
table.getCell(1,1).appendParagraph('right text').setAlignment(DocumentApp.HorizontalAlignment.RIGHT);
doc.saveAndClose()
}