Remove Horizontal Line in Google Doc with Google Apps Script - google-apps-script

I have a Google Doc with text followed by a Horizontal Line below. If the user selects "NO" from a ui.alert, I need to remove all this text (simple using regex) and the horizontal line. I have no clue how to remove this Horizontal Line via Google Apps Script. Can't find anything about it in the documentation. Anyone have any ideas? Thanks!
var regExpFirstBriefing = "[A-Z \(\)]{42}\\v+[A-Za-z\.\", ]*[\\v+]{1}"; // This accounts for all the text I need removed along with an extra new line. The horizontal line is the next line.
// Ask user if this is the first briefing
var responseFirstBriefing = ui.alert('Question here...' , ui.ButtonSet.YES_NO);
if (responseFirstBriefing == ui.Button.YES) {
document.replaceText(regExpFirstBriefing, '');
}

You want to remove the searched text in Google Document.
You want to delete "HORIZONTAL_RULE" below the text.
You want to run above when the user selects "NO" from a ui.alert.
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this sample script? Although I'm not sure about your actual Document, from your explanation, I imaged about it and prepare a sample script. Please think of this as just one of several answers. The flow of this sample script is as follows.
Flow:
Search text is searched using findText().
Put the element of searched text in an array.
This array is used for deleting element.
Search "HORIZONTAL_RULE" below the searched text.
In this case, when "HORIZONTAL_RULE" doesn't adjacent the searched text, "HORIZONTAL_RULE" is searched by offsetValue. In this sample, it is searched up to 3 paragraph ahead.
When "HORIZONTAL_RULE" is found, the element is put to the array.
Delete elements in the array.
From your script, the searched text is cleared. In this case, the paragraph is not deleted.
From your question, about "HORIZONTAL_RULE", the paragraph is deleted.
When above flow is reflected to the script, it becomes as follows.
Sample script:
When you run the script, the texts searched with regExpFirstBriefing are cleared and "HORIZONTAL_RULE" below the text is also removed.
function myFunction() {
var document = DocumentApp.getActiveDocument(); // Added
var ui = DocumentApp.getUi(); // Added
var regExpFirstBriefing = "[A-Z \(\)]{42}\\v+[A-Za-z\.\", ]*[\\v+]{1}";
var responseFirstBriefing = ui.alert('Question here...' , ui.ButtonSet.YES_NO);
if (responseFirstBriefing == ui.Button.YES) {
document.replaceText(regExpFirstBriefing, '');
// I added below script.
} else if (responseFirstBriefing == ui.Button.NO) {
var offsetValue = 3; // When "HORIZONTAL_RULE" doesn't adjacent the searched text, "HORIZONTAL_RULE" is searched by "offsetValue". In this sample, it is searched up to 3 paragraph ahead.
var body = document.getBody();
var r = body.findText(regExpFirstBriefing);
var remove = [];
while (r) {
remove.push(r.getElement().asText())
var parentParagraph = body.getChildIndex(r.getElement().getParent());
var totalChildren = body.getNumChildren();
for (var offset = 1; offset <= offsetValue; offset++) {
if (parentParagraph + offset <= totalChildren) {
var nextParagraph = body.getChild(parentParagraph + offset);
if (nextParagraph.getType() === DocumentApp.ElementType.PARAGRAPH) {
var c = nextParagraph.asParagraph().getNumChildren();
for (var i = 0; i < c; i++) {
var childOfNextParagraph = nextParagraph.asParagraph().getChild(i);
if (childOfNextParagraph.getType() === DocumentApp.ElementType.HORIZONTAL_RULE) {
remove.push(childOfNextParagraph.asHorizontalRule());
break;
}
}
if (remove[remove.length - 1].getType === DocumentApp.ElementType.HORIZONTAL_RULE) {
break;
}
}
}
}
r = body.findText(regExpFirstBriefing, r);
}
for (var i = remove.length - 1; i >=0; i--) {
/////
// If you want to delete the paragraph of searched text, please delete this if statement.
if (remove[i].getType() === DocumentApp.ElementType.TEXT) {
remove[i].removeFromParent();
continue;
}
/////
remove[i].getParent().asParagraph().removeFromParent();
}
}
}
Note:
This script supposes that the regex of [A-Z \(\)]{42}\\v+[A-Za-z\.\", ]*[\\v+]{1} works for your Document.
If you want to delete the paragraph of searched text, please delete this if statement of as follows from above script.
if (remove[i].getType() === DocumentApp.ElementType.TEXT) {
remove[i].removeFromParent();
continue;
}
References:
findText(searchPattern, from)
removeFromParent()
Class HorizontalRule
If I misunderstood your question and this was not the result you want, I apologize. At that time, in order to correctly understand your situation, can you provide a sample Document you want to use? Of course, please remove your personal information. I would like to confirm the issue from it.

Related

Highlight the hyperlinks in google doc if link is present in middle Sentence /Line using apps script

Okay So, I have a some complex google documents containing tables, and paragraphs and in the middle of these paragraph there are some hyperlinks which I want to find and highlight them I have tried many solution already provided on Stack Overflow but they are not exactly what I looking for those solution only works if doc contain direct URL instead of hyperlinks.
I have write some code which working pretty much fine. but the problem is if any hyperlink present in middle of any line or sentence so it will not targeting that hyperlink. only hyperlink which is single element or at starting of new line is getting target by this code.
here is demo file:- https://docs.google.com/document/d/16cbYg-g2pjpcBuUserhrCRfJw7VcHaXGvtmL0LxMzko/edit
code.gs
function highlightLink(){
let highlightColor = {[DocumentApp.Attribute.BACKGROUND_COLOR]: '#FFFF00'}
let doc = DocumentApp.getActiveDocument();
let body = doc.getBody();
let paraChild = body.getParagraphs();
paraChild.forEach(ele=>{
if(ele.getText()!= ""){
let sentence = ele.getText();
sentence.split(" ").map(item => {
let word = body.findText(item.trim())
let url = word.getElement().getLinkUrl();
if(url!= null){
word.getElement().setAttributes(highlightColor)
}
})
}
})
}
I have already tried the solution available on stack overflow but they not what exactly I am looking for.
Modification points:
In your script, it seems that the part of the text cannot be checked, and also, for example, when the same word is included in the paragraph, only 1st word is checked. I thought that this might be the reason for your current issue.
How about the following modification when these points are reflected in your script?
Modified script 1:
function highlightLink2() {
// let highlightColor = { [DocumentApp.Attribute.BACKGROUND_COLOR]: '#FFFF00' } // This is not used.
let doc = DocumentApp.getActiveDocument();
let body = doc.getBody();
let paraChild = body.getParagraphs();
paraChild.forEach(ele => {
if (ele.getText() != "") {
let sentence = ele.getText();
// --- I modified the below script.
[...new Set(sentence.split(" ").map(e => e.trim()))].forEach(t => {
let word = ele.findText(t);
while (word) {
let e = word.getElement();
let start = word.getStartOffset();
if (e.getLinkUrl(start)) {
e.asText().setBackgroundColor(start, word.getEndOffsetInclusive(), '#FFFF00');
}
word = ele.findText(t, word);
}
});
// ---
}
});
}
Modified script 2:
As another approach, the following modified script might be able to be used.
function highlightLink3() {
const body = DocumentApp.getActiveDocument().getBody();
const text = body.getText();
const words = [...new Set(text.split(/[\n ]/g).map(e => e.trim()).filter(String))];
words.forEach(t => {
let word = body.findText(t);
while (word) {
const e = word.getElement();
const start = word.getStartOffset();
if (e.getLinkUrl(start)) {
e.asText().setBackgroundColor(start, word.getEndOffsetInclusive(), '#FFFF00');
}
word = body.findText(t, word);
}
});
}
Note:
In this modified script, your provided Document is used as a test. When you change the Document, this script might be required to be modified. Please be careful about this.
References:
setBackgroundColor(startOffset, endOffsetInclusive, color)
findText(searchPattern, from)

How to delete selected text in a Google doc using Google Apps Script

In a Google document is there a way to delete selected text with Google Apps Script? The find criterion for the text to delete is not a string, but instead is relative to a bookmark. This question is related to a workaround for my open question at https://webapps.stackexchange.com/questions/166391/how-to-move-cursor-to-a-named-bookmark-using-google-apps-script).
Here is code I wish worked.
function UpdateBookmarkedText() {
var doc = DocumentApp.getActiveDocument();
var bookmarks = doc.getBookmarks();
for (var i = 0; i < bookmarks.length; i++){
// Delete the old text, one step in a longer process.
var text = bookmarks[i].getPosition().getElement().asText().editAsText();
var range = doc.newRange().addElementsBetween(text, 5, text, 7).build(); // arbitrary offsets for testing
doc.setSelection(range); // The selected range is successfully highlighted in the document.
doc.deleteSelection(); // This command does not exist.
} }
This documentation seems relevant but is over my head: https://developers.google.com/docs/api/how-tos/move-text
Use deleteText()
You may use the following script as the basis for your script:
function deleteSelectedText() {
var selection = DocumentApp.getActiveDocument().getSelection();
if (selection) {
var elements = selection.getRangeElements();
if (elements[0].getElement().editAsText) {
var text = elements[0].getElement().editAsText();
if (elements[0].isPartial()) {
text.deleteText(elements[0].getStartOffset(), elements[0].getEndOffsetInclusive());
}
}
}
}
This is a modified version of the script featured in the Class Range guide. This modification works for selected sentences within a paragraph. Thus, the use of the for loop (in the sample script) is not anymore necessary since the script operates within a single element/paragraph.
Optimized Script:
function test() {
var selection = DocumentApp.getActiveDocument().getSelection();
var elements = selection.getRangeElements();
var text = elements[0].getElement().editAsText();
(selection && elements[0].getElement().editAsText && elements[0].isPartial()) ? text.deleteText(elements[0].getStartOffset(), elements[0].getEndOffsetInclusive()):null;
}
References:
Class Range
deleteText(startOffset, endOffsetInclusive)
I'm not sure what exactly you're trying to do, so here is a guess. If you able to select something you can remove the selected text about this way:
function UpdateBookmarkedText() {
var doc = DocumentApp.getActiveDocument();
var bookmarks = doc.getBookmarks();
for (var i = 0; i < bookmarks.length; i++){
// Delete the old text, one step in a longer process.
var text = bookmarks[i].getPosition().getElement().asText().editAsText();
var range = doc.newRange().addElementsBetween(text, 5, text, 7).build(); // arbitrary offsets for testing
doc.setSelection(range); // The selected range is successfully highlighted in the document.
// the way to handle a selection
// from the official documentation
// https://developers.google.com/apps-script/reference/document/range
var selection = DocumentApp.getActiveDocument().getSelection();
if (selection) {
var elements = selection.getRangeElements();
for (let element of elements) {
if (element.getElement().editAsText) {
var text = element.getElement().editAsText();
if (element.isPartial()) {
text.deleteText(element.getStartOffset(), element.getEndOffsetInclusive());
} else {
text.setText(''); // not sure about this line
}
}
}
}
}
}

How to search for text in a google document by background color?

I'm trying to set the background color of text that is of a particular color into another color within a Google Doc file.
Essentially what I'd like to do is parse through it and as I find text that has a "x" background color, I want to change it to a "y" background color via Apps Script.
Here is the code that I've been using
function onOpen() {
DocumentApp.getUi()
.createMenu('Utilities')
.addItem('Auto-Replace', 'replaceSuits')
.addToUi();
};
function replaceSuits() {
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var text = body.editAsText();
var found = text.getBackgroundColor() === '#ff8c82';
var apple = body.findText(found);
while (apple) {
var elem = apple.getElement();
if (apple.isPartial()) {
var start = apple.getStartOffset();
var end = apple.getEndOffsetInclusive();
elem.setBackgroundColor(start, end, "#000000");
}
else {
elem.setBackgroundColor("#000000");
}
apple = body.findText(found, found);
}
};
I know my variables are repetitive and a bit nonsensical but it's due to the various testing that I've been doing trying to figure out why this code isn't working. My apologies in advance.
Any thoughts on how to go about this in an efficient manner?
You want to modify the background color of the text from #ff8c82 to #000000 in the Google Document.
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification point:
In your case, the color is modified by checking the color from the text object retrieved by body.editAsText().
Modified script:
function replaceSuits() {
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var text = body.editAsText();
// I modified below script.
for (var i = 0; i < text.getText().length; i++)
if (text.getBackgroundColor(i) == "#ff8c82") text.setBackgroundColor(i, i, "#000000");
}
References:
getBackgroundColor(offset)
setBackgroundColor(startOffset, endOffsetInclusive, color)
If I misunderstood your question and this was not the direction you want, I apologize.

search slide and get page element text

My script searches one specific slide in a presentation. Then it gets the text from the first page element. This page element is a shape with only one word. After this, when I put strings before and after this page element text, there is a break in the text.
function readShapeText() {
var presentation = SlidesApp.getActivePresentation();
var slides = presentation.getSlides();
for (i = 0; i < slides.length; i++) {
if(slides[i].getObjectId() == 'mySlideId'){
var pageElement = slides[i].getPageElements()[0].asShape().getText().asString();
}
}
var myModifiedElement = "My_" + pageElement + "_is_cool";
}
The output is with a break, but I need in one line:
My_TestElement
_is_cool
How can I eliminate or suppress the break? And is there a better way to find a specific slide without using "for loop" f.e. like presentation.openSlideById(xxxxxx)?
How about these answers?
Q1: How can I eliminate or suppress the break?
It seems that the end of texts is always given \n. This can be also seen from values retrieved by Slides.Presentations.get(). So if you want to retrieve the values without \n, you can do it using replace("\n", "").
Q2: Is there a better way to find a specific slide without using "for loop" f.e. like presentation.openSlideById(xxxxxx)?
How about the following sample script? It retrieved the specific slide using filter(), because the key of objectId is included in the array. And replace("\n", "") was also used.
function readShapeText() {
var mySlideId = "mySlideId"; // Please input this.
var presentation = SlidesApp.getActivePresentation();
var slides = presentation.getSlides();
var slide = slides.filter(function(e){return e.getObjectId() == mySlideId})[0];
var pageElement = slide.getPageElements()[0].asShape().getText().asString().replace("\n", "");
var myModifiedElement = "My_" + pageElement + "_is_cool";
Logger.log(myModifiedElement)
}
If I misunderstand your question, I'm sorry.

Google Docs Apps script - how to remove really empty paragraphs

How we can remove really empty paragraphs from Google Document?
This code will remove any paragraphs that contains images, hr's etc. Can't understand how to check if a paragraph really empty?
getText() and editAsText() gives nothing to this.
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var docParagraphs = doc.getBody().getParagraphs();
for (var i = 0; i < docParagraphs.length; i++) {
if (docParagraph[i].getText() === '') {
docParagraphs[i].removeFromParent();
}
}
I know there are topic related to ~similar problem, but not the same. How to find and remove blank paragraphs in a Google Document with Google Apps Script?
UPD: correct answer:
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
for (var i = 0; i < doc.getBody().getParagraphs().length; i++) {
if (docParagraph[i].getText() === '') {
if (docParagraph_i.getNumChildren() == 0 && i < (docParagraphs.length - 1)) {
docParagraph[i].removeFromParent();
}
}
}
I've changed for expression too to limit i by a current elements count, not stored in variable. Because elements are deleted (or in other implementation added, for example) there will be error when no paragraphs but cycle will want to get them.
&& i < (...)
because last paragraph can't be deleted and throws an error.
You will want to check for children in the paragraph
paragraph.getNumChildren() //returns the number of children