Reputation: 301
Is there a way of calling sheet function in google-app-script?
I want to call MATCH(), IMPORTRANGE(), and INDEX() functions to compute the return value in function definition like below.
function abc(foo, bar) {
a = MATCH(foo, IMPORTRANGE("address of sheet", "A:A"),0)
b = MATCH(bar, IMPORTRANGE("address of sheet", "B:B"),0)
return INDEX(IMPORTRANGE("address of sheet", "C:Z"),a,b)
}
Applying the sample provided by @Tanaike
function doGet(e) {
const [sheet1, sheet2, sheet3] = [e.parameter.url1, e.parameter.url2, e.parameter.url3].map(f => SpreadsheetApp.openByUrl(f).getSheets()[0]);
const a = sheet1.getRange("A:A").createTextFinder(e.parameter.foo).findNext().getRow();
const b = sheet2.getRange("B:B").createTextFinder(e.parameter.bar).findNext().getRow();
const res = sheet3.getRange("C:Z").offset(a - 1, b - 1).getValue();
return ContentService.createTextOutput(res);
}
function abc(foo, bar) {
const url1 = "https://docs.google.com/spreadsheets/d/###/edit";
const url2 = "https://docs.google.com/spreadsheets/d/###/edit";
const url3 = "https://docs.google.com/spreadsheets/d/###/edit";
const baseUrl = "https://script.google.com/a/###/macros/s/###/exec";
const res = UrlFetchApp.fetch(`${baseUrl}?url1=${encodeURIComponent(url1)}&url2=${encodeURIComponent(url2)}&url3=${encodeURIComponent(url3)}&foo=${foo}&bar=${bar}`);
console.log(res.getContentText())
return res.getContentText();
}
With above which is basically the copy of sample, the abc function returns #VALUE error with length of 50,000 letters.
The console log begins like below.
Logging output too large. Truncating output.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="width=300, initial-scale=1" name="viewport">
Upvotes: 0
Views: 464
Reputation: 201388
How about this answer?
MATCH(foo, IMPORTRANGE("address of sheet", "A:A",0)
might be MATCH(foo, IMPORTRANGE("address of sheet", "A:A") ,0)
.openByUrl
for achieving IMPORTRANGE("address of sheet", "A:A",0)
. If you want to use this converted script as the custom function, in this case, the custom function cannot use openByUrl
due to the permission. So in this case, it is required to run the script using the script editor, the custom menu and the button in Spreadsheet. This is the current specification at Google side. Please be careful this.
address of sheet
. So in this answer, I would like to propose to run the script with the script editor.When above points are reflected to the pseudo script in your question, it becomes as follows. The flow of this sample is as follows.
a
and b
.
a
and b
.Please copy and paste the following script to the script editor of the Spreadsheet. And, please set the variables of url1
, url2
and url3
, foo
and bar
. When you run the script, please run the function of myFunction
with the script editor. By this, you can see the retrieved value at the console and also, the value is also put to the active cell as the sample.
function abc(foo, bar) {
const url1 = "https://docs.google.com/spreadsheets/d/###/edit"; // Please set this.
const url2 = "https://docs.google.com/spreadsheets/d/###/edit"; // Please set this.
const url3 = "https://docs.google.com/spreadsheets/d/###/edit"; // Please set this.
// 1. Retrieve sheets.
const [sheet1, sheet2, sheet3] = [url1, url2, url3].map(e => SpreadsheetApp.openByUrl(e).getSheets()[0]); // Modified
// 2. Retrieve values of `a` and `b`.
const a = sheet1.getRange("A:A").createTextFinder(foo).findNext().getRow();
const b = sheet2.getRange("B:B").createTextFinder(bar).findNext().getRow();
// 3. Retrieve the result value using `a` and `b`.
return sheet3.getRange("C:Z").offset(a - 1, b - 1).getValue();
}
// Please run this function.
function myFunction() {
const foo = "###"; // Please set this.
const bar = "###"; // Please set this.
const res = abc(foo, bar);
console.log(res)
SpreadsheetApp.getActiveRange().setValue(res); // Heare, the value is put to the active cell.
}
address of sheet
is the same URL. So in above sample script, 3 different URLs can be used. Also, the same 3 URLs can be used.const a = sheet1.getRange("A:A").createTextFinder(foo).findNext().getRow();
and const b = sheet2.getRange("B:B").createTextFinder(bar).findNext().getRow();
are a = MATCH(foo, IMPORTRANGE("address of sheet", "A:A",0)
and b = MATCH(bar, IMPORTRANGE("address of sheet", "B:B",0)
, respectively.
IMPORTRANGE("address of sheet", "A:A")
means "A:A" of the 1st tab in address of sheet
.return sheet3.getRange("C:Z").offset(a - 1, b - 1).getValue();
is return INDEX(IMPORTRANGE("address of sheet", "C:Z"),a,b)
.When all values of address of sheet
in your pseudo script are the active Spreadsheet, abc
can be modified as follows. In this case, you can use this function as the custom function like =abc(foo, bar)
.
function abc(foo, bar) {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
const a = sheet.getRange("A:A").createTextFinder(foo).findNext().getRow();
const b = sheet.getRange("B:B").createTextFinder(bar).findNext().getRow();
return sheet.getRange("C:Z").offset(a - 1, b - 1).getValue();
}
Please use this script with enabling V8.
As other method, in order to use openByUrl
in the custom function, I would like to propose to use Web Apps.
Please do the following flow.
Sample script of Web Apps is a Google Apps Script. Please copy and paste the following script (Google Apps Script) to the script editor. This script is for the Web Apps. And please set the URLs. About baseUrl
, please set it after the Web Apps is deployed.
function doGet(e) {
const [sheet1, sheet2, sheet3] = [e.parameter.url1, e.parameter.url2, e.parameter.url3].map(f => SpreadsheetApp.openByUrl(f).getSheets()[0]);
const a = sheet1.getRange("A:A").createTextFinder(e.parameter.foo).findNext().getRow();
const b = sheet2.getRange("B:B").createTextFinder(e.parameter.bar).findNext().getRow();
const res = sheet3.getRange("C:Z").offset(a - 1, b - 1).getValue();
return ContentService.createTextOutput(res);
}
function abc(foo, bar) {
const url1 = "https://docs.google.com/spreadsheets/d/###/edit";
const url2 = "https://docs.google.com/spreadsheets/d/###/edit";
const url3 = "https://docs.google.com/spreadsheets/d/###/edit";
const baseUrl = "https://script.google.com/macros/s/###/exec";
const res = UrlFetchApp.fetch(`${baseUrl}?url1=${encodeURIComponent(url1)}&url2=${encodeURIComponent(url2)}&url3=${encodeURIComponent(url3)}&foo=${foo}&bar=${bar}`);
return res.getContentText();
}
https://www.googleapis.com/auth/drive.readonly
.https://script.google.com/macros/s/###/exec
.
Please set the URL of your Web Apps to baseUrl
of the above Google Apps Script and redeploy the Web Apps as new version. By this, the latest script is reflected to the Web Apps.
And, as the test of this script, please put =abc(foo, bar)
to a cell. By this, the function abc
is run and the result value is retrieved using UrlFetchApp.
Upvotes: 3