I have a table in google doc, in which I want to extract the hyperlinked text and its link using appscript
Suppose : The community is here to help you with specific coding, algorithm, or language problems.
I have a code for google spreadsheet which can extract links from the text, however the same code is not usuable in google docs.
function myFunction() {
var sheet= SpreadsheetApp.getActiveSheet();
var isCell4Blank1 = sheet.getRange("A1").isBlank();
if (!isCell4Blank1) {
var linkData = sheet.getRange("A1").getRichTextValue().getRuns().reduce((ar, e) => {
var url = e.getLinkUrl();
Logger.log(url);
if (url) {
var color = e.getTextStyle().getForegroundColor();
var startIndex = e.getStartIndex();
var endIndex = e.getEndIndex();
var text = e.getText()
//ar.push(color);
ar.push(text);
ar.push(startIndex);
ar.push(endIndex);
//ar.push(url);
}
return ar;
}, [])
}
}
How to modify it for google docs ?
Related
I want to copy the text from the title within this document, but I am only used to using Google App Script in sheets, not docs:
I have tried lot of different methods, but nothing is populating in Logger.log(), so I am not sure it is working. Currently, all I want to return is the text in the Title, so I can go on to search for this in a spreadsheet. So far I have the following:
function autoFill() {
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var searchResult = body.findElement(DocumentApp.ElementType.PARAGRAPH);
var searchHeading = searchResult.getElement(DocumentApp.ParagraphHeading.TITLE);
The only part of the document that has the format of Title is the first line in the document.
Here is an example of how to find the paragraph with the Heading style Title. In my Doc I have a line of text "This is some text" with style Title.
function findTitle() {
try {
let doc = DocumentApp.getActiveDocument();
let body = doc.getBody();
let paras = body.getParagraphs();
let text = null;
paras.some( para => {
let attribs = para.getAttributes();
if( attribs["HEADING"] === DocumentApp.ParagraphHeading.TITLE ) {
text = para.getText();
return true;
}
return false;
}
);
console.log(text);
}
catch(err) {
console.log(err);
}
}
Execution log
8:08:39 AM Notice Execution started
8:08:39 AM Info This is some text
8:08:39 AM Notice Execution completed
Found that using Regular Expression would be able to identify the text needed:
function autoFill() {
var ss = DocumentApp.getActiveDocument();
var body = ss.getBody();
var header = DocumentApp.getActiveDocument().getHeader();
var contents = body.getText();
var racm = SpreadsheetApp.openById('[enter sheet ID').getSheetByName('Risks & Controls matrix');
var lr = racm.getLastRow();
var colID = racm.getRange(1,1,lr,1).getValues();
//you need to tweak below to the control name pattern
var regexName = /\w+[-]\w+[-]\w+/ //use website: regexr.com to create & www.geeksforgeeks.org/write-regular-expressions/
var titleFound=regexName.exec(contents)[0];
let row = colID.findIndex(users => {return users[0] == titleFound})+1;
Then goes on to finding the relevant data in the ranges from the spreadsheet and .replaceText() within the doc.
Works really well. Thanks for your help!
I'm new to App scripts and need help with copying the data to spreadsheet from URL.
However, URL is not a website but link which after clicking with directly download csv file into the computer. Also, its not ending with .csv as I have seen in other examples here.
URL basically coming to my inbox at a specific time. I'm trying to use Fetch URL but its not working at all.
Sample URL -
https://docs.google.com/spreadsheets/d/1oPUPPUmy7psliSznUItT0DnHvilXwZHzyrmdyHpHi18/export?format=csv
function ABC () {
const searchQuery = 'XYZ';
const threads = GmailApp.search(searchQuery, 0,1);
const urls = [];
threads.forEach(thread => {
const messages = thread.getMessages();
messages.forEach(message => {
const body = message.getBody();
var re = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'"".,<>?«»“”‘’]))/i;
const match = body.match(re);
if (match) { urls.push(match[1]); }
});
}) ;
Logger.log(urls);
url = urls.toString().replace("[","").replace("]","") ;
Logger.log(url);
function getData() {
var attValue = '';
// making a call to the target website
var response = UrlFetchApp.fetch(url);
//logging response from target website - In Script Editor > View > Logs
Logger.log(response.getContentText());
//parsing the response data from website
//https://developers.google.com/apps-script/reference/url-fetch/http-response
var rawData = response.getContentText();
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[1]);
var cell = sheet.getRange(1, 1);
cell.setValue(rawData);
}
};
Kindly help so that I can copy the data directly into spreadsheet or store the file in Google Drive with filename as combination of text and date.
Thanks
SUGGESTION
You can try the tweaked script below.
In my understanding, here is your goal:
Get your email messages that contain URLs (CSV file) via "XYZ" search terms.
Process the URL using URLFetchApp service
Place the CSV data into your second sheet tab.
Note: If there's anything else missing or something may have been misunderstood, feel free to let me know.
Tweaked Script
function ABC() {
/**TWEAKED: Created a function call method called "getData" */
const url = {
getData: function () {
const searchQuery = 'XYZ';
const threads = GmailApp.search(searchQuery, 0, 1);
const urls = [];
threads.forEach(thread => {
const messages = thread.getMessages();
messages.forEach(message => {
const body = message.getBody();
var re = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'"".,<>?«»“”‘’]))/i;
const match = body.match(re);
if (match) { urls.push(match[1]); }
});
});
Logger.log(urls);
/**TWEAKED: Instead of using the redundant replace method,
* used "regex" inside a single replace method to replace
* all [ and ] characters */
var geturl = urls.toString().replace(/\[|]/gm, "");
console.log(geturl)
return geturl;
}
}
var attValue = '';
/**TWEAKED: Call the "url" variable's "getData" function that will return the URL */
var response = UrlFetchApp.fetch(url.getData.call());
//logging response from target website - In Script Editor > View > Logs
Logger.log(response.getContentText());
//parsing the response data from website
//https://developers.google.com/apps-script/reference/url-fetch/http-response
var rawData = response.getContentText();
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[1]);
var cell = sheet.getRange(1, 1);
cell.setValue(rawData);
};
Demonstration
After running the ABC() function on the Apps Script editor, the second sheet tab gets populated with the CSV data:
The Apps Script execution log view
References:
JavaScript Function call()
I'm currently working on a code in Google Apps Script that allows a user to fill out a spreadsheet and have the spreadsheet generate printouts for a job board. I'm trying to design this in a way where the user can simply insert a logo image into a row of my Google sheet and have it replace a placeholder in my doc template.
I have found lots of answers about how you can take an image and convert it to a blob and insert it from a url or an ID, however, I can't seem to find a way to get the ID or url from the image in the cell.
Here's my code currently:
//Creates menu option on spreadsheet
function onOpen() {
const ui = SpreadsheetApp.getUi();
const menu = ui.createMenu('AutoFill Docs');
menu.addItem('Create New Docs', 'createNewGoogleDocs');
menu.addToUi();
}
//Defines where to get template and info from
function createNewGoogleDocs() {
const googleDocTemplate = DriveApp.getFileById('14MJNd37pn6D-EmNKCQzXXvxJCcOAoB3KS-TlDgZuWMI');
const destinationFolder = DriveApp.getFolderById('120Sb_CJJlmz5NzJW8W3DB4TNuC4kdD3e');
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('JobBoard');
const rows = sheet.getDataRange().getValues();
rows.forEach(function(row, index) {
if (index === 0) return;
if (row[9]) return;
const copy = googleDocTemplate.makeCopy(`${row[1]}, ${row[0]} Printout`, destinationFolder);
const doc = DocumentApp.openById(copy.getId())
const body = doc.getBody();
const friendlyDate = new Date(row[2]).toLocaleDateString();
//Replacing text
body.replaceText('{{Company}}', row[1]);
body.replaceText('{{jobTitle}}', row[0]);
body.replaceText('{{datePosted}}', friendlyDate);
body.replaceText('{{Description}}', row[3]);
body.replaceText('{{Qualifications}}', row[5]);
body.replaceText('{{Wage}}', row[4]);
body.replaceText('{{Apply}}', row[6]);
//A subfunction to handle replacing the image
function textToImage() {
var replaceTextToImage = function(body, searchText, image, width) {
var next = body.findText(searchText);
if (!next) return;
var r = next.getElement();
r.asText().setText("");
var img = r.getParent().asParagraph().insertInlineImage(0, image);
if (width && typeof width == 100) {
var w = img.getWidth();
var h = img.getHeight();
img.setWidth(width);
img.setHeight(width * h / w);
}
return next;
};
var documentId = doc;
var replaceText = "{{Upload Image}}";
var imageFileId = "### File ID of image ###"; //I don't know how to get this variable
var body = DocumentApp.openById(documentId).getBody();
var image = DriveApp.getFileById(imageFileId).getBlob();
do {
var next = replaceTextToImage(body, replaceText, image, 200);
} while (next);
}
//Close and saves new doc
doc.saveAndClose();
const url = doc.getUrl();
sheet.getRange(index + 1, 10).setValue(url)
})
}
I think what might be messing me up is that I have to loop through all my cells right now so that I can create multiple documents at once (meaning each row will have a different doc and different image ID). I'm just not sure how to work around that.
Here's the template and spreadsheet
https://docs.google.com/spreadsheets/d/1cySHogAxcUgzr0hsJoTyPZakKQkM6uIOtmyPzcMoJUM/edit?usp=sharing
https://docs.google.com/document/d/14MJNd37pn6D-EmNKCQzXXvxJCcOAoB3KS-TlDgZuWMI/edit?usp=sharing
There is a bit of an issue trying to get an image in a specific cell. There's even a Feature Request for that. This year Google released a few classes for image management but there seems to be issues when retrieving those using cellImage class.
I found a related answer (workaround) from user #Tanaike where images are retrieved from Google Sheets, converted to a Blob and inserted into a Google Doc.
Sample code provided was:
const spreadsheetId = "###"; // Google Spreadsheet ID
const res = DocsServiceApp.openBySpreadsheetId(spreadsheetId).getSheetByName("Sheet1").getImages();
console.log(res); // You can check the retrieved images at the log.
if (res.length == 0) return;
const blob = res[0].image.blob; // Here, 1st image of Sheet1 is retrieved. Of course, you can choose the image on the sheet.
let doc = DocumentApp.create("newDocName Goes_Here");
var body = doc.getBody();
var imgPDF = body.appendImage(blob);
Take into consideration that to make the above work you need to:
Install Google Apps Script library. (instructions here)
Enable Drive API.
I tested this and indeed, got the images from the given sheet and inserted them into the Google Doc specified. For some reason, running your code did not show me a newly created file from the template but you can tweak the above accordingly to your case.
I have implemented following script to do OCR on single and multiple images using image URL.
function doOCRALL() {
var selected = SpreadsheetApp.getActiveSheet().getActiveRange().getValues().length;
for (var i = 0; i < selected; i++) {
var activeCol = SpreadsheetApp.getActiveSheet().getActiveCell().getColumn();
var activeRow = SpreadsheetApp.getActiveSheet().getActiveCell().getRow();
var valueURL = SpreadsheetApp.getActiveSheet().getRange(activeRow + i, activeCol).getValue();
var image = UrlFetchApp.fetch(valueURL).getBlob();
var file = {
title: 'OCR File',
mimeType: 'image/png'
};
// OCR is supported for PDF and image formats
file = Drive.Files.insert(file, image, {ocr: true});
var doc = DocumentApp.openByUrl(file.embedLink);
var body = doc.getBody().getText();
//Get link Doc that Generated
SpreadsheetApp.getActiveSheet().getRange(activeRow + i, activeCol + 2).setValue(file.embedLink);
//Get Content of Doc that Generated
SpreadsheetApp.getActiveSheet().getRange(activeRow + i, activeCol + 1).setValue(body);
}
}
function doOCR() {
//
var activeCol = SpreadsheetApp.getActiveSheet().getActiveCell().getColumn();
var activeRow = SpreadsheetApp.getActiveSheet().getActiveCell().getRow();
var valueURL = SpreadsheetApp.getActiveSheet().getRange(activeRow, activeCol).getValue();
var image = UrlFetchApp.fetch(valueURL).getBlob();
var file = {
title: 'OCR File',
mimeType: 'image/png'
};
// OCR is supported for PDF and image formats
file = Drive.Files.insert(file, image, {ocr: true});
var doc = DocumentApp.openByUrl(file.embedLink);
var body = doc.getBody().getText();
// Print the Google Document URL in the console
Logger.log("body: %s", body);
Logger.log("File URL: %s", file.embedLink);
//Get link Doc that Generated
SpreadsheetApp.getActiveSheet().getRange(activeRow, activeCol + 2).setValue(file.embedLink);
//Get Content of Doc that Generated
SpreadsheetApp.getActiveSheet().getRange(activeRow, activeCol + 1).setValue(body);
}
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('OCR Tools')
.addItem('Extract Cell', 'doOCR')
.addItem('Extract All Cell', 'doOCRALL')
.addSeparator()
.addSubMenu(ui.createMenu('About US')
.addItem('Infomation', 'menuItem2'))
.addToUi();
}
function menuItem2() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.alert('AIO Team');
}
When I provide an image URL for any image, it works. But if I upload the same image on my drive and then provide the image URL from drive, it only gives me "Sign in Main menu". For other drive images it gives the same text.
Thanks in advance.
If content is already in Drive, you do not need to get a link to it - just supply the file id (which you can get from a link to it).
Once you have the file ID, you can simply copy it, and use the optimal arguments to activate OCR. The full options list is, of course, available on the Drive REST API page: https://developers.google.com/drive/api/v2/reference/files/copy#parameters
I encourage you to also read about best practices such as fields specification (which is a requirement of the more recent drive API version).
This function takes an input Drive file ID that you got from somewhere, and a truth-y value to set the "use OCR" option.
Obvious assumptions are that you have permission, the id is valid, you have enabled the advanced service and the Drive API in cloud console, etc.
function getIdOfCopyOfDriveFile(fileId, useOcr) {
const options = {
fields: "choose the metadata fields to return in the response e.g. 'id,title,parents'"
};
const existingMetaData = Drive.Files.get(fileId, options);
options.ocr = !!useOcr;
existingMetaData.title += " (copied with" + (options.ocr ? " " : "out ") + "ocr)";
// We could do other modifications of fields we requested before
// copying, like changing the parents array to move the new file.
const newFileMetaData = Drive.Files.copy(existingMetaData, fileId, options);
return newFileMetaData.id;
}
Trying to retrieve form entries which are stored in google firebase under the node called entries and append to a google sheet using the script editor in google sheets.
I have added the FirebaseApp library to google sheet script editor. Then my code looks like this:
function getAllData() {
var firebaseUrl = "https://myapp.firebaseio.com/";
var secret = "pCOCwKCC582jpqdZe2EqPqnW3IAd3UyO9oB4uaEL2";
var base = FirebaseApp.getDatabaseByUrl(firebaseUrl, secret);
var data = base.getData();
Logger.log(data);
}
when I run this nothing happens. Any ideas?
Next I need to add the returned data from firebase to the google sheet. I was using this code to do this via the sheets api, however I'm not sure how this works in the google script editor?
function addEntries() {
gapi.client.sheets.spreadsheets.values.append({
spreadsheetId: '10lyQpQtEA7euCfdU2isrqB_bgPuy-eSbW74h7oDP3ko',
range: "Sheet1!A1:D100",
majorDimension: "ROWS",
"values": [
["testa", "testb", "testc", "testd"]
],
valueInputOption: 'USER_ENTERED'
}).then(function(response) {
}, function(response) {
appendPre('Error: ' + response.result.error.message);
});
}
I'm using the newest Firebase version. This snippet code works for me.
function getFacturasClientesExistentes() {
var firebaseUrl = "https://test.firebaseio.com/FacturasBLP/clienteExistente";
var base = FirebaseApp.getDatabaseByUrl(firebaseUrl);
var data = base.getData();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Facturas Clientes Existentes");
var num = 2;
range = sheet.getRange("A"+num+":F"+num+"");
for(var i in data) {
var values = [
[ data[i].fecha, data[i].sucursal, data[i].cantidad, data[i].cliente, data[i].correo, data[i].estatus ]
];
range.setValues(values);
num += 1;
range = sheet.getRange("A"+num+":F"+num+"");
}
}
Some notes:
I have previously write the headers for my data in the spreadsheet
In the line range = sheet.getRange("A"+num+":F"+num+""); from A to F I have my headers
I hope this helps someone, this worked for me.
function writeSheets() {
var ss = SpreadsheetApp.openById("10lyQpQtEA7euCfdU2isrqB_bgPuy-eSbW74h7oDP3ko");
var sheet = ss.getSheets()[0];
var firebaseUrl = "https://myapp.firebaseio.com/";
var secret = "pCOCwKCC582jpqdZe2EqPqnW3IAd3UyO9oB4uaEL2"; // get this from firebase project settings
var base = FirebaseApp.getDatabaseByUrl(firebaseUrl);
var data = base.getData();
var keys = Object.keys(data.entries);
var sheetRow = [];
var entryKeys;
for (index in keys) {
sheetRow = [];
entryKeys = Object.keys(data.entries[keys[index]])
for (i in entryKeys) {
sheetRow.push(data.entries[keys[index]][entryKeys[i]]);
}
//Logger.log(sheetRow);
sheet.appendRow(sheetRow);
}
}
Note: in order for this code to work, you need to install the firebaseapp library in the script editor as per these instructions, https://sites.google.com/site/scriptsexamples/new-connectors-to-google-services/firebase