Export Google Docs comments into Google Sheets - The Basics - google-drive-api

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?

Related

Custom functions workaround for Google Workspace add-ons

I'm looking for a workaround to the limitation that custom functions are not available in Google Workspace Add-ons. As proven by #Rubén in this SO answer.
I am building a Google Workspace Add-on. I want to get data from a specified range in the Spreadsheet, then run a function in the code, then output the data back to the user in the Spreadsheet.
I'm guessing I might use SpreadsheetApp.getActiveRange() to facilitate the spreadsheet data interactions. Something similar to the following pseudocode.
Pseudocode
const sourceRange = SpreadsheetApp.getActiveRange();
// do stuff
const destinationRange = foo;
destinationRange.setValues( bar, );
Is this a viable path forward?
Yes, you might use code like the shown in the question in Workspace add-ons for Google Sheets to make that your add-on UI interacts with the active spreadsheet.
The below code snippet is a complete helper function used in sample Workspace Add-on provided by Google Developers. It was taken from Translate text from Google Docs, Sheets, and Slides.
Breadcrumb: Samples by project type > Workspace Add-ons > Translate text
Specific URL: https://developers.google.com/apps-script/add-ons/translate-addon-sample#code.gs.
Please note that it uses
var ranges = SpreadsheetApp.getActive().getSelection().getActiveRangeList().getRanges();
/**
* Helper function to get the text of the selected cells.
* #return {CardService.Card} The selected text.
*/
function getSheetsSelection(e) {
var text = '';
var ranges = SpreadsheetApp.getActive().getSelection().getActiveRangeList().getRanges();
for (var i = 0; i < ranges.length; i++) {
const range = ranges[i];
const numRows = range.getNumRows();
const numCols = range.getNumColumns();
for (let i = 1; i <= numCols; i++) {
for (let j = 1; j <= numRows; j++) {
const cell = range.getCell(j, i);
if (cell.getValue()) {
text += cell.getValue() + '\n';
}
}
}
}
if (text !== '') {
var originLanguage = e.formInput.origin;
var destinationLanguage = e.formInput.destination;
var translation = LanguageApp.translate(text, e.formInput.origin, e.formInput.destination);
return createSelectionCard(e, originLanguage, destinationLanguage, text, translation);
}
}

How do you extract comments from an MS Word doc that's been imported into Google Docs and put in a Google Sheet?

How do you extract comments from an MS Word doc that's been imported into Google Docs and put in a Google Sheet?
I've followed this suggestion to get REALLY close, including adding my own line for another column that shows WHO left the comment.
I am suspecting that MS Word native files that are imported into GDocs use some other convention for comments because there's a footer for those comments that says, "From Imported Document".
If this is true, then is there a solution for Word>GDocs imported documents with comments?
Here's my code but w/o my docID:
function listComments() {
// Change docId into your document's ID
// See below on how to
var docId = '';
var comments = Drive.Comments.list(docId);
var hList = [], cList = [], nList = [];
// 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]);
nList.unshift([comment.author.displayName]);
}
// Set values to A and B
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange("A1:A" + nList.length).setValues(nList);
sheet.getRange("B1:B" + hList.length).setValues(hList);
sheet.getRange("C1:C" + cList.length).setValues(cList);
}
}

Google Sheets Scraping Options Chain from Yahoo Finance, Incomplete Results [duplicate]

This question already has answers here:
Scraping data to Google Sheets from a website that uses JavaScript
(2 answers)
Closed last month.
I'm attempting to scrape options pricing data from Yahoo Finance in Google Sheets. Although I'm able to pull the options chain just fine, i.e.
=IMPORTHTML("https://finance.yahoo.com/quote/TCOM/options?date=1610668800","table",2)
I find that it's returning results that don't completely match what's actually shown on Yahoo Finance. Specifically, the scraped results are incomplete - they're missing some strikes. i.e. the first 5 rows of the chart may match, but then it will start returning only every other strike (aka skipping every other strike).
Why would IMPORTHTML be returning "abbreviated" results, which don't match what's actually shown on the page? And more importantly, is there some way to scrape complete data (i.e. that doesn't skip some portion of the available strikes)?
In Yahoo finance, all data are available in a big json called root.App.main. So to get the complete set of data, proceed as following
var source = UrlFetchApp.fetch(url).getContentText()
var jsonString = source.match(/(?<=root.App.main = ).*(?=}}}})/g) + '}}}}'
var data = JSON.parse(jsonString)
You can then choose to fetch the informations you need. Take a copy of this example https://docs.google.com/spreadsheets/d/1sTA71PhpxI_QdGKXVAtb0Rc3cmvPLgzvXKXXTmiec7k/copy
edit
if you want to get a full list of available data, you can retrieve it by this simple script
// mike.steelson
let result = [];
function getAllDataJSON(url = 'https://finance.yahoo.com/quote/TCOM/options?date=1610668800') {
var source = UrlFetchApp.fetch(url).getContentText()
var jsonString = source.match(/(?<=root.App.main = ).*(?=}}}})/g) + '}}}}'
var data = JSON.parse(jsonString)
getAllData(eval(data),'data')
var sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
sh.getRange(1, 1, result.length, result[0].length).setValues(result);
}
function getAllData(obj,id) {
const regex = new RegExp('[^0-9]+');
for (let p in obj) {
var newid = (regex.test(p)) ? id + '["' + p + '"]' : id + '[' + p + ']';
if (obj[p]!=null){
if (typeof obj[p] != 'object' && typeof obj[p] != 'function'){
result.push([newid, obj[p]]);
}
if (typeof obj[p] == 'object') {
getAllData(obj[p], newid );
}
}
}
}
Here's a simpler way to get the last market price of a given option. Add this function to you Google Sheets Script Editor.
function OPTION(ticker) {
var ticker = ticker+"";
var URL = "finance.yahoo.com/quote/"+ticker;
var html = UrlFetchApp.fetch(URL).getContentText();
var count = (html.match(/regularMarketPrice/g) || []).length;
var query = "regularMarketPrice";
var loc = 0;
var n = parseInt(count)-2;
for(i = 0; i<n; i++) {
loc = html.indexOf(query,loc+1);
}
var value = html.substring(loc+query.length+9, html.indexOf(",", loc+query.length+9));
return value*100;
}
In your google sheets input the Yahoo Finance option ticker like below
=OPTION("AAPL210430C00060000")
I believe your goal as follows.
You want to retrieve the complete table from the URL of https://finance.yahoo.com/quote/TCOM/options?date=1610668800, and want to put it to the Spreadsheet.
Issue and workaround:
I could replicate your issue. When I saw the HTML data, unfortunately, I couldn't find the difference of HTML between the showing rows and the not showing rows. And also, I could confirm that the complete table is included in the HTML data. By the way, when I tested it using =IMPORTXML(A1,"//section[2]//tr"), the same result of IMPORTHTML occurs. So I thought that in this case, IMPORTHTML and IMPORTXML might not be able to retrieve the complete table.
So, in this answer, as a workaround, I would like to propose to put the complete table parsed using Sheets API. In this case, Google Apps Script is used. By this, I could confirm that the complete table can be retrieved by parsing the HTML table with Sheet API.
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet, and please enable Sheets API at Advanced Google services. And, please run the function of myFunction at the script editor. By this, the retrieved table is put to the sheet of sheetName.
function myFunction() {
// Please set the following variables.
const url ="https://finance.yahoo.com/quote/TCOM/options?date=1610668800";
const sheetName = "Sheet1"; // Please set the destination sheet name.
const sessionNumber = 2; // Please set the number of session. In this case, the table of 2nd session is retrieved.
const html = UrlFetchApp.fetch(url).getContentText();
const section = [...html.matchAll(/<section[\s\S\w]+?<\/section>/g)];
if (section.length >= sessionNumber) {
if (section[sessionNumber].length == 1) {
const table = section[sessionNumber][0].match(/<table[\s\S\w]+?<\/table>/);
if (table) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const body = {requests: [{pasteData: {html: true, data: table[0], coordinate: {sheetId: ss.getSheetByName(sheetName).getSheetId()}}}]};
Sheets.Spreadsheets.batchUpdate(body, ss.getId());
}
} else {
throw new Error("No table.");
}
} else {
throw new Error("No table.");
}
}
const sessionNumber = 2; means that 2 of =IMPORTHTML("https://finance.yahoo.com/quote/TCOM/options?date=1610668800","table",2).
References:
Method: spreadsheets.batchUpdate
PasteDataRequest

Pushing a simple Log string from a Google Ad Script to a Google Sheet

I am trying to set up a script which can push data from an App Script into a Google Sheet.
I have the script successfully logging what I want, which goes in the following format Account budget is 12344, but now I want to push this into a Google Sheet. I have set up a variable containing the URL and another variable containing the sheet name, and also a clear method to delete anything already there.
Find the code I have below:
// - The link to the URL
var SPREADSHEET_URL = 'abcdefghijkl'
// - The name of the sheet to write the data
var SHEET_NAME = 'Google';
// No to be changed
function main() {
var spreadsheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
var sheet = spreadsheet.getSheetByName(SHEET_NAME);
sheet.clearContents();
}
function getActiveBudgetOrder() {
// There will only be one active budget order at any given time.
var budgetOrderIterator = AdsApp.budgetOrders()
.withCondition('status="ACTIVE"')
.get();
while (budgetOrderIterator.hasNext()) {
var budgetOrder = budgetOrderIterator.next();
Logger.log("Budget Order Amount " + budgetOrder.getSpendingLimit());
}
}
Assuming you want to clear the entire Sheet every time you extract the data this should work for you. You will need to set the url and shtName variables.
function getActiveBudgetOrder() {
var url = 'https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxx/';
var shtName = 'Sheet1';
var arr = [];
var sht = SpreadsheetApp.openByUrl(url).getSheetByName(shtName);
// There will only be one active budget order at any given time.
var budgetOrderIterator = AdsApp.budgetOrders()
.withCondition('status="ACTIVE"')
.get();
while (budgetOrderIterator.hasNext()) {
var budgetOrder = budgetOrderIterator.next();
arr.push(["Budget Order Amount " + budgetOrder.getSpendingLimit()]);
}
sht.clearContents();
sht.getRange(1, 1, arr.length, arr[0].length).setValues(arr);
}

Creating Google Docs file by getting data from Google Sheets.

I am an experienced programmer who isn't experienced with using the script editor of Google Drive.
Since I need to make some reports, I was wondering about ways to exploit the script functionale of Google Drive to ease my process.
So my goal is there's this format that I created in Words, and for some parts of the Words, I need to put in each student's score. However, as doing this manually is very demanding, i was wondering ways to utilize google sheets and google docs for this.
So I was wondering if there's a way for me to get certain data from the spreadsheet (one column for each doc) and put the numbers in the appropriate space in the google docs file, and save it in google drive or send it as an email. Then, I will repeat this process for each column in the spreadsheet until everyone's report has been created.
If you professional programmers can help me out here it will be deeply appreciated. I never had any experience with google script editor and I do not know where to start. Thank you!
You may check this Script for generating Google documents from Google spreadsheet data source tutorial.
/**
* Generate Google Docs based on a template document and data incoming from a Google Spreadsheet
*
* License: MIT
*
* Copyright 2013 Mikko Ohtamaa, http://opensourcehacker.com
*/
// Row number from where to fill in the data (starts as 1 = first row)
var CUSTOMER_ID = 1;
// Google Doc id from the document template
// (Get ids from the URL)
var SOURCE_TEMPLATE = "xxx";
// In which spreadsheet we have all the customer data
var CUSTOMER_SPREADSHEET = "yyy";
// In which Google Drive we toss the target documents
var TARGET_FOLDER = "zzz";
/**
* Return spreadsheet row content as JS array.
*
* Note: We assume the row ends when we encounter
* the first empty cell. This might not be
* sometimes the desired behavior.
*
* Rows start at 1, not zero based!!! 🙁
*
*/
function getRowAsArray(sheet, row) {
var dataRange = sheet.getRange(row, 1, 1, 99);
var data = dataRange.getValues();
var columns = [];
for (i in data) {
var row = data[i];
Logger.log("Got row", row);
for(var l=0; l<99; l++) {
var col = row[l];
// First empty column interrupts
if(!col) {
break;
}
columns.push(col);
}
}
return columns;
}
/**
* Duplicates a Google Apps doc
*
* #return a new document with a given name from the orignal
*/
function createDuplicateDocument(sourceId, name) {
var source = DocsList.getFileById(sourceId);
var newFile = source.makeCopy(name);
var targetFolder = DocsList.getFolderById(TARGET_FOLDER);
newFile.addToFolder(targetFolder);
return DocumentApp.openById(newFile.getId());
}
/**
* Search a paragraph in the document and replaces it with the generated text
*/
function replaceParagraph(doc, keyword, newText) {
var ps = doc.getParagraphs();
for(var i=0; i<ps.length; i++) {
var p = ps[i];
var text = p.getText();
if(text.indexOf(keyword) >= 0) {
p.setText(newText);
p.setBold(false);
}
}
}
/**
* Script entry point
*/
function generateCustomerContract() {
var data = SpreadsheetApp.openById(CUSTOMER_SPREADSHEET);
// XXX: Cannot be accessed when run in the script editor?
// WHYYYYYYYYY? Asking one number, too complex?
//var CUSTOMER_ID = Browser.inputBox("Enter customer number in the spreadsheet", Browser.Buttons.OK_CANCEL);
if(!CUSTOMER_ID) {
return;
}
// Fetch variable names
// they are column names in the spreadsheet
var sheet = data.getSheets()[0];
var columns = getRowAsArray(sheet, 1);
Logger.log("Processing columns:" + columns);
var customerData = getRowAsArray(sheet, CUSTOMER_ID);
Logger.log("Processing data:" + customerData);
// Assume first column holds the name of the customer
var customerName = customerData[0];
var target = createDuplicateDocument(SOURCE_TEMPLATE, customerName + " agreement");
Logger.log("Created new document:" + target.getId());
for(var i=0; i<columns.length; i++) {
var key = columns[i] + ":";
// We don't replace the whole text, but leave the template text as a label
var text = customerData[i] || ""; // No Javascript undefined
var value = key + " " + text;
replaceParagraph(target, key, value);
}
}
As #James Donnellan stated, please check the official documentation on how to use the service which allows scripts to create, access, and modify Google Sheets files.