Script to auto highlight certain words in Google Docs? - google-apps-script

I'm looking for a simple script for a Google Docs add-on that will highlight words held in an array. I want the script to auto-highlight the words as I type. Is this simple enough?
Thanks!

Based on Can I color certain words in Google Document using Google Apps Script?
function highlight_words() {
var doc = DocumentApp.getActiveDocument();
var words = ['one','two','three'];
var style = { [DocumentApp.Attribute.BACKGROUND_COLOR]:'#FFFF00' };
var pgfs = doc.getParagraphs();
for (var word of words) for (var pgf of pgfs) {
var location = pgf.findText(word);
if (!location) continue;
var start = location.getStartOffset();
var end = location.getEndOffsetInclusive();
location.getElement().setAttributes(start, end, style);
}
}

Related

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
}
}
}
}
}
}

Export Google Docs comments into Google Sheets - The Basics

Trying to produce a Comment Log in a Google sheet based on a Google Doc.
I applied the script as suggested by NaziA in this link. And I activated the DriveAPI service.
function listComments() {
// Change docId into your document's ID
// See below on how to
var docId = '1fzYPRldd16KjsZ6OEtzgBIeGO8q5tDbxaAcqvzrJ8Us';
var comments = Drive.Comments.list(docId);
var hList = [], cList = [];
// Get list of comments
if (comments.items && comments.items.length > 0) {
for (var i = 0; i < comments.items.length; i++) {
var comment = comments.items[i];
// add comment and highlight to array's first element
hList.unshift([comment.context.value]);
cList.unshift([comment.content]);
}
// Set values to A and B
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange("A1:A" + hList.length).setValues(hList);
sheet.getRange("B1:B" + cList.length).setValues(cList);
}
}
I used the suggested code verbatim with one change. I replaced the DocumentID with the ID from the new Google sheet I was using as a target. After I approved the permission, it executed without errors but did not write any values to the Google Sheet. I had a demo Google Doc as a source with few comments.
Screenshot of Comment Doc
Any suggestions?

Identify specific charts on google sheets using google script

I have a google Slides presentation containing a chart tied to a google Spreadsheets Sheet. I created a plug-in (google script), using which I am able to paste the sheets url and have all available charts by id.
I am unable to overcome the issue of identifying the chart I need solely using its id which is generated.
Right now I can do this:
var spreadSheetContainingChartAndData = Sheets.Spreadsheets.get(sheetsId)
var allSheets = spreadSheetContainingChartAndData.sheets
var allChartsOnTheOnlyExistingSheet = dataSheet.sheets[0].charts
var firstChart = allChartsOnTheOnlyExistingSheet[0]
var chartId = firstChart.chartId
Ideally I would want to find the chart by some form of user defined identifier like this:
var chartId = findByAnythingElse(allChartsOnTheOnlyExistingSheet, 'user-defined-tag')
The usecase is to have a spreadsheet template containing client data and a number of charts visualising said data.
Whenever someone wants to make a presentation, he can click on the plugin menu and have certain slides to be populated with specific charts which will be cropped and resized to a predefined format.
You want to retrieve the chartId from all charts in a Spreadsheet.
You want to search the chartId using the specific tag.
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this sample script? Please think of this as just one of several answers.
In this answer, the chart's title, subtitle and alt title are used as the search tags.
Sample script:
Before you use this script, please enable Sheets API at Advanced Google Services. And when you test this script, please set the variables for searching the chart and run the function of run().
function findByAnythingElse(spreadsheetId, searchObj) {
var obj = Sheets.Spreadsheets.get(spreadsheetId, {fields: "sheets(charts(chartId,spec(altText,subtitle,title)))"});
var chartIds = [];
for (var i = 0; i < obj.sheets.length; i++) {
var charts = obj.sheets[i].charts;
if (charts) {
for (var j = 0; j < charts.length; j++) {
var title = charts[j].spec.title;
var subTitle = charts[j].spec.subtitle;
var altText = charts[j].spec.altText;
if (title == searchObj.searchTitle || subTitle == searchObj.searchSubTitle || altText == searchObj.searchAltText) {
chartIds.push(charts[j].chartId);
}
}
}
}
return chartIds;
}
// Please run this fnuction for testing.
function run() {
var searchObj = { // Please set search values.
searchTitle: "sample1",
searchSubTitle: "",
searchAltText: "",
}
var spreadsheetId = "###"; // Please set Spreadsheet ID here.
var res = findByAnythingElse(spreadsheetId, searchObj);
Logger.log(res)
}
In this sample script, when run() is run, one of searchTitle, searchSubTitle and searchAltText of searchObj is matched, the chart ID is retrieved.
For example, the chart ID can be also retrieved from only searchTitle.
When there are several charts with the same title, several chart IDs are returned.
Note:
This is a simple sample script. So please modify it for your situation.
References:
Advanced Google services
Charts
If I misunderstood your question and this was not the direction you want, I apologize.

Uploading Google Spreadsheet to a Google Site

I'd like to begin by stating that the end goal is to display our company directory (a list of our employees names/job title/extension#/office location/email), which is in a Google Sheet, on a page in one of our Google Sites.
I tried to use Google's embed function, and it works... but it is very clunky, does not have a "Sort" function, and it just looks weird.
I pulled a Google Apps Script from somewhere online like 3 months ago and it actually did pull in a way that made me happy:
(This is as it appears currently on the Google Sites page. So in this screenshot, the embedded Sheet is at the top. The Sheet when, imported via the script, is below. Yes, they are both on the same page. I'm in testing!)
This is the code I used (I THINK - I don't remember how I implemented it):
function myFunction() {
}
function onOpen(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
if(ScriptProperties.getProperty("page url") == null){
ss.addMenu("List page", [{name: "Create list", functionName: "create_list"},null,
{name: "Fetch list items", functionName: "fetch_items"}]);
}
else{
ss.addMenu("List page", [{name: "Push Items", functionName: "push_items"}]);
}
}
function create_list() {
var data = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
var parent_page = Browser.inputBox("URL of the parent page:");
var title = Browser.inputBox("Choose a name for your list page:");
var data = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
var list = SitesApp.getPageByUrl(parent_page).createListPage(title, title.split(' ').join(''), '', data[0]);
ScriptProperties.setProperty("page url", list.getUrl());
onOpen();
push_items();
}
function push_items(){
var done = false;
while(!done){
try{
var data = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
var list = SitesApp.getPageByUrl(ScriptProperties.getProperty("page url"));
var list_items = list.getListItems();
for(i in list_items){
list_items[i].deleteListItem();
}
for(var i = 1; i < data.length; i++){
var item = list.addListItem(data[i]);
}
done = true;
}
catch(e){
}
}
SpreadsheetApp.getActiveSpreadsheet().toast(ScriptProperties.getProperty("page url"), "List page updated", 10);
}
function fetch_items(){
var url = Browser.inputBox("URL of your list page:");
var col_number = Browser.inputBox("Number of columns in the list:");
var data = new Array();
var list_items = SitesApp.getPageByUrl(url).getListItems();
for(i in list_items){
var row = new Array();
for(j = 0; j < col_number; j++){
row.push(list_items[i].getValueByIndex(j));
}
data.push(row);
}
SpreadsheetApp.getActiveSheet().getRange(1, 1, data.length, data[0].length).setValues(data);
}
[I do not take credit for writing this!]
So I would like to ask (since this ceases to make much sense to me) is if this is viable code for a Google Apps Script, and if so, how do I implement it to output Sheet data similarly in the same type of format as in the screenshot?
Alternatively, is there a better way to display this Sheet data in Google Sheets?
A totally different alternative would be to use Romain Vialard's "awesome tables" gadget. It works... awesome, and it is really easy to use. Besides, it admits filters, ...

Compare a list of words in a spreadsheet with 'highlighted' words in a Google Doc

I'm looking for a "is this possible" answer before I dive into the "how" to do it.
Can a list of words in a Google Spreadsheet (answer key) be compared with only the "highlighted" words in a Google Document?
If yes, can a report be generated to tell me which "answer key" words were 'not' highlighted in the Google Document?
I'm a high school teacher and I'm looking for a way to evaluate large numbers of student work to see if they've identified key terms. I'd like to know if this is "possible" via Google AppScript before I attempt to build it.
Yes, it can, and I already did it for you :D. You can find the folder with relevant example files here: https://drive.google.com/folderview?id=0B_5rNbCI5MM9eXI2M005WVR1SUU&usp=sharing and the how is with this script which references the student's document submission and your answer key.
function findAnswersFromKey(){
var fileId = '1nI4rIvexA87s0eRmPUTJWxDtVxyx8qZ9nwQUKiK6Q4U';
var doc = DocumentApp.openById(fileId);
var ss = SpreadsheetApp.openById('1oikQnTcTx0KnCiwiy-pEUz9HLwLBh6ND4Xpo36xNS9o');
var sheet = ss.getSheetByName('Planets Quiz Key');
var answerRange = sheet.getRange(2,1,8,1);
var targetAnswers = answerRange.getValues();
Logger.log(targetAnswers);
for (var i = 0; i < targetAnswers.length; i++){
var target = targetAnswers[i];
Logger.log(target);
var targetBackground = sheet.getRange(i+2,1,1,1).getBackground();
Logger.log(targetBackground);
var answerCount = 0;
var bodyElement = doc.getBody();
var searchResult = bodyElement.findText(target);
while (searchResult !== null) {
var thisElement = searchResult.getElement();
var thisElementText = thisElement.asText();
thisElementText.setBackgroundColor(searchResult.getStartOffset(), searchResult.getEndOffsetInclusive(),targetBackground);
// search for next match
searchResult = bodyElement.findText(target, searchResult);
answerCount++;
Logger.log(answerCount);
}
sheet.getRange(i+2,2,1,1).setValue(answerCount);
}
var studentId = DriveApp.getFileById(fileId).getOwner().getEmail();
sheet.getRange(1,2,1,1).setValue(studentId+"'s Quiz Answer Count");
}
There are various ways to integrate this solution, such as a UiApp to upload a .docx file that is converted to a google document, folder.find("Planets Quiz"), etc., but I'll leave those to you to decide.
I used the getBackground() and setBackground methods to find the text elements (words) that match the answer key. I also counted the matching elements so you can see how many times each is referenced. You will notice that two of the planets are not discussed in the document, and have a count of 0.