I am trying to insert a CellImage taken from a Google Sheet into a newly created Google Doc using Apps Script.
I have a CellImage in a Google Sheet:
[A Google Sheet with an image created by the formula:
=image("https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=...)](https://i.stack.imgur.com/XHz9s.png)
I've created an Apps Script that is supposed to create a new Google Doc and insert the image from cell A1 into the Doc:
function myFunction() {
let doc = DocumentApp.create("QR Holder");
let sheet = SpreadsheetApp.getActiveSpreadsheet();
let range = sheet.getRange("A1");
let image = range.getValue();
let url = image.getUrl();
console.log(url);
let blob = UrlFetchApp.fetch(url).getBlob();
let body = doc.getBody();
body.insertImage(0, blob);
}
Execution log
11:01:18 AM Notice Execution started
11:01:21 AM Info
11:01:20 AM Error
Exception: Attribute provided with no value: url
myFunction # Code.gs:8
This shows that the url variable does not store a valid URL and the blob is not properly fetched.
Modification points:
Unfortunately, the URL cannot be retrieved from image of let image = range.getValue(); with getUrl(). In this case, it is required to retrieve the URL from the formulas retrieved with getFormula.
In your sample image, it seems that the formula is =image("https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=...')". In this case, the last ) might not be required to be used. But, I'm not sure whether this is your expected situation.
When these points are reflected in your script, how about the following modification?
From:
let image = range.getValue();
let url = image.getUrl();
To:
let url = encodeURI(range.getFormula().replace(/\=image\("(.*)"\)/i, "$1"));
Reference:
getFormula()
Related
I'm trying to get the data from this csv file: "https://app.matrixify.app/files/vasasro/99320ce64bfe22f855ce03e71796e4db/MatrixifyAllExport.csv"
This is for product that we want to edit for vasaro.com and we need to export the data to Google Sheets automatically.
Thank you for your help.
When I tried IMPORTDADA, it worked for small files, but not for this larger file.
When I check the CSV data of your URL, it seems that the data size is 2,413,638 bytes and 1158 rows and 93 columns. I think that this is the reason for your current issue. In this case, in order to put the values into Spreadsheet, how about using Google Apps Script?
Sample script 1:
Please copy and paste the following script to the script editor of Spreadsheet, and save the script. When you use this script, please put a custom function of =SAMPLE("https://app.matrixify.app/files/vasasro/99320ce64bfe22f855ce03e71796e4db/MatrixifyAllExport.csv") to a cell. By this, the CSV data is retrieved and put the values to the Spreadsheet. This can be used like IMPORTDATA.
const SAMPLE = url => Utilities.parseCsv(UrlFetchApp.fetch(url).getContentText());
Sample script 2:
Please copy and paste the following script to the script editor of Spreadsheet, and save the script. And, please set the sheet name. In this case, please run the function myFunction with the script editor. By this, the CSV data is downloaded and put to the Spreadsheet.
function myFunction() {
const sheetName = "Sheet1"; // Please set your sheet name.
const url = "https://app.matrixify.app/files/vasasro/99320ce64bfe22f855ce03e71796e4db/MatrixifyAllExport.csv"; // This is from your URL.
const res = UrlFetchApp.fetch(url);
const values = Utilities.parseCsv(res.getContentText());
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
sheet.getRange(1, 1, values.length, values[0].length).setValues(values);
}
Sample script 3:
If the CSV data is large, when Sheets API is used, the process cost can be reduced a little. In that case, please enable Sheets API at Advanced Google services. And, please set the sheet name. And, please run the function myFunction with the script editor. By this, the CSV data is downloaded and put to the Spreadsheet.
function myFunction() {
const sheetName = "Sheet1"; // Please set your sheet name.
const url = "https://app.matrixify.app/files/vasasro/99320ce64bfe22f855ce03e71796e4db/MatrixifyAllExport.csv"; // This is from your URL.
const res = UrlFetchApp.fetch(url);
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheetId = ss.getSheetByName(sheetName).getSheetId();
const requests = [{ pasteData: { data: res.getContentText(), delimiter: ",", coordinate: { sheetId } } }];
Sheets.Spreadsheets.batchUpdate({ requests }, ss.getId());
}
References:
Custom Functions in Google Sheets
parseCsv(csv)
setValues(values)
PasteDataRequest
I have been trying to use a getlink function for extracting the URL of a hyperlink. The cell from which I need to extract a link is not configured with a hyperlink formula.
Screenshot Spreadsheet with link to URL (hovered above cell)
However when I use the script below, I always get:
*TypeError: Cannot read properties of null (reading 'getLinkUrl') (line 5). Why is that? *
The formula that I use for this function:
=GETLINK(CELL("Address";R2))
Script that I use:
function GETLINK(input){
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange(input);
var value = range.getRichTextValue();
var url = value.getLinkUrl(0,1);
return url;
}
Modification points:
From your following sample image and your error message of TypeError: Cannot read properties of null (reading 'getLinkUrl'),
I thought that your current issue might be due to the number value. In the current stage, when the cell value is the number value, range.getRichTextValue() returns null. (This has already been reported to the Google issue tracker. Ref) In this case, an error like your error message is shown even when the cell has a hyperlink.
In order to remove this issue and retrieve the hyperlink, how about the following modification?
Modified script:
Please copy and paste the following script to the script editor of Google Spreadsheet and save the script.
In this modification, this script cannot be used as the custom function because of setNumberFormat. So, I proposed a sample script for retrieving the URLs from the source range and putting the URL into the destination range.
When you use this script, please set the values of srcRange and dstRange, and run the script by the script editor. By this, the script is run and retrieves the URL from srcRange, and the retrieved URLs are put to dstRange.
function sample() {
var srcRange = "Sheet1!A1:A10"; // Please set the source range you want to use.
var dstRange = "Sheet2!B1:B10"; // Please set the destination range you want to use.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getRange(srcRange);
var orgNumberFormats = range.getNumberFormats();
var values = range.setNumberFormat("#").getRichTextValues();
var urls = values.map(r => r.map(c => c && (c.getLinkUrl() || "")));
range.setNumberFormats(orgNumberFormats);
ss.getRange(dstRange).setValues(urls);
}
When this script is run, the number formats of srcRange are saved, the cell values are converted to the string values, and the rich text values are retrieved from srcRange. And then, the URL is retrieved and the URLs are put to dstRange.
Note:
In the case that your error is removed from your showing script, the following script can be used. But, in this case, when the cell value is the number value, no value is returned even when the cell has a hyperlink. Please be careful about this.
function GETLINK(input) {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange(input);
var value = range.getRichTextValue();
return value && value.getLinkUrl(0, 1);
}
References:
map()
getNumberFormats()
setNumberFormats(numberFormats)
I have this formula that extracts the link from a word with hyperlink. Now when I'm trying to move it to another spreadsheet and run it I get an 'Exception: Range not found' error. I was reading this might be cuz I need a 'getRangeList' insted of getRange, but it doesn't work this way either. Now I get the 'Exception: The parameters (number) don't match the method signature for SpreadsheetApp.Sheet.getRangeList.'
Here's the code I'm using:
function URL(refrence) {
var sheet = SpreadsheetApp.getActiveSheet();
var formula = SpreadsheetApp.getActiveRange().getFormula();
var a1 = formula.replace("=url(","");
a1 = a1.replace(")","");
var url = sheet.getRange(a1).getRichTextValue().getLinkUrl();
return url
}
FINDINGS
The part getRange(a1) is incorrect as the variable a1 contains an invalid Sheet range.
SUGGESTION
If your main goal is to easily extract the URL from a cell with hyperlink like =HYPERLINK("http://www.google.com/","Google") you may use these tweaked scripts below:
These scripts were derived from the answers of these posts How to extract URL from Link in Google Sheets using a formula & Google Apps Script Regular Expression
This version of the script will only show the url value from the Apps Script editor's log results:
function URL() {
var sheet = SpreadsheetApp.getActiveSheet();
var formula = sheet.getActiveRange().getFormula();
var regExp = new RegExp("\"(.*)\",\"", "gm");
var url = regExp.exec(formula)[1];
Logger.log(url)
}
Note: Before running, make sure the cell with hyperlink is selected on your sheet (in my case it was on cell A1).
Sample result on the logs:
This another version will let you to use your script as a custom function =URL() on your spreadsheet file:
function URL(refrence) {
var regExp = new RegExp("\"(.*)\",\"", "gm");
var url = regExp.exec(refrence)[1]
return url
}
Sample Result as a custom function:
=URL(FORMULATEXT(A1))
Reference:
FORMULATEXT function
I have a working code that I want to be able to pull down on all my rows but at the moment it only returns data from the first cell rather than updating as I drag down.
I have tried so many different things but no luck. Please help me. Here is the current Sheet https://docs.google.com/spreadsheets/d/1tKy_1BugK1vlq4hPAbjkTCmeunlb6LU0C7pv1rPeSqs/edit?usp=sharing
I believe your goal as follows.
You want to retrieve the values from URLs at the column "B" using the custom function.
The screen shot of your sample Spreadsheet is as follows.
Your current script is as follows. (This script is from your sample Spreadsheet.)
function AsxPrice() {
var url = SpreadsheetApp.getActiveSheet().getRange('B2').getValue();
var response = UrlFetchApp.fetch(url);
var content = response.getContentText();
Logger.log(content);
var json = JSON.parse(content);
var last_price = json["last_price"];
return last_price;
}
In your script, the cell range is constant like B2. So in this answer, I would like to propose to retrieve the URLs as the arguments for the custom function. The sample script is as follows.
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet. And in this custom function, when your sample Spreadsheet is used, please put the formula of =AsxPrice2(B2:B4) to a cell. By this, the URLs are retrieved from the cells "B2:B4" and retrieve the values.
function AsxPrice2(values) {
const reqs = values.flat().map(url => ({url: url, muteHttpExceptions: true}));
return UrlFetchApp.fetchAll(reqs).map(r => [r.getResponseCode() == 200 ? JSON.parse(r.getContentText()).last_price : ""]);
}
Result:
When above scvript is used for your sample Spreadsheet, it becomes as follows.
Note:
When a lot of URLs are used, an error might occur. Please be careful this.
References:
Custom Functions in Google Sheets
fetchAll(requests)
Solution
You only have to modify your function to have an input parameter which is the url
Code
function AsxPrice(url) {
var response = UrlFetchApp.fetch(url);
var content = response.getContentText();
Logger.log(content);
var json = JSON.parse(content);
var last_price = json["last_price"];
return last_price;
}
References:
Custom functions
Maybe someone can help me with my Problem.
First some background: I have copied some WhatsApp chats to Google Sheets. I use Latex to generate a book containing the chats. Google Sheet is able to display all Emojis from WhatsApp, Latex, of course, isn't. So I downloaded the Emojis as png files and defined Latex commands to include those emojis as graphic.
For Example: Too display the regular smiling emoji I type \grin. I have a list with hundreds of emojis in one row and the corresponding command in the next row.
Until now I used search and replace -> replace all in the same sheet for every single type of emoji. But as this takes hours I wondered if there is any way to make this more effective.
Here is a spreadsheet with a small example: Google Sheet
Thanks in advance!
You want to replace the Emojis to the defined Latex commands.
For example, you want to replace as follows.
From 03.01.19, 00:29 - me: Hi 😊 to 03.01.19, 00:29 - me: Hi \nettnett.
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.
Flow:
The flow of this sample script is as follows. This sample script uses your shared Spreadsheet.
Retrieve data from the sheet of Codes for Smileys.
Create the request body for the findReplace request of batchUpdate method of Sheets API.
Run the method of batchUpdate.
Sample script:
This script used Sheets API. So, before you run the script, please enable Sheets API at Advanced Google services.
function myFunction() {
var dataSheet = "Codes for Smileys";
var sourceSheet = "unedited Chats with Smileys";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getSheetByName(dataSheet).getDataRange().getValues();
data.shift();
var sheetId = ss.getSheetByName(sourceSheet).getSheetId();
var requests = data.map(function(row) {return {findReplace: {sheetId: sheetId, find: row[0], replacement: row[1]}}});
Sheets.Spreadsheets.batchUpdate({requests: requests}, ss.getId());
}
This sample script uses your shared Spreadsheet. So in this case, the data sheet is Codes for Smileys. And the source sheet for converting is unedited Chats with Smileys.
Note:
If you change the sheet name, also please modify above script. Please be careful this.
When you run the script for the first time, the authorization screen is opened. So please authorize the scopes for using the script.
References:
Advanced Google services
spreadsheets.batchUpdate
FindReplaceRequest
Added:
You want to put the converted values to the sheet of Chat with Latex Code.
The sample script for achieving above is as follows.
Sample script:
function myFunction2() {
var dataSheet = "Codes for Smileys";
var sourceSheet = "unedited Chats with Smileys";
var destinationSheet = "Chats with LaTeX Codes";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(dataSheet);
var data = ss.getSheetByName(dataSheet).getDataRange().getValues();
data.shift();
var srcSheet = ss.getSheetByName(sourceSheet);
var tempSheet = srcSheet.copyTo(ss);
var sheetId = tempSheet.getSheetId();
var requests = data.map(function(row) {return {findReplace: {sheetId: sheetId, find: row[0], replacement: row[1]}}});
Sheets.Spreadsheets.batchUpdate({requests: requests}, ss.getId());
var tempValues = tempSheet.getDataRange().getValues();
var destSheet = ss.getSheetByName(destinationSheet);
destSheet.getRange(destSheet.getLastRow() + 1, 1, tempValues.length, tempValues[0].length).setValues(tempValues);
ss.deleteSheet(tempSheet);
}
In this sample script, the following flow is run.
Copy the source sheet unedited Chats with Smileys as a temporal sheet.
Create request body for the batchUpdate method to the temporal sheet.
Run the batchUpdate.
Copy the converted values from the temporal sheet to the destination sheet Chats with LaTeX Codes.
In this case, the converted values are put to the last row of the sheet.
Delete the temporal sheet.