I am using this script and an input form to search a Google spreadsheet, this script has a range of one sheet,i.e. Data , but I need to extend my range to all sheets in the same spreadsheet, any ideas?
function doGet(e) {
return HtmlService.createTemplateFromFile("Index").evaluate()
.setTitle("WebApp: Search By Password")
.addMetaTag('viewport', 'width=device-width, initial-scale=1')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
/* PROCESS FORM */
function processForm(formObject) {
var concat = formObject.searchtext + formObject.searchtext2;
var result = "";
if (concat) {//Execute if form passes search text
result = search(concat);
}
return result;
}
//SEARCH FOR MATCHED CONTENTS ;
function search(searchtext) {
var spreadsheetId = ' '; //** CHANGE !!!!
var sheetName = "Data"
var range = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName).getDataRange();
var data = range.getValues();
var ar = [];
data.forEach(function (f) {
if (~[f[8]].indexOf(searchtext)) {
ar.push([f[2], f[3], f[4], f[5], f[6], f[7]]);
}
});
return ar;
}
I believe your goal is as follows.
You want to search for a text from all sheets of a Google Spreadsheet.
You want to achieve this by modifying the script in your question.
In this case, I would like to propose modifying the function search as follows.
Modified script:
function search(searchtext) {
return SpreadsheetApp
.getActiveSpreadsheet()
.getSheets()
.flatMap(s =>
s
.getDataRange()
.getValues()
.filter(r => r[8] && r[8].includes(searchtext))
.map(([,,c,d,e,f,g,h]) => [c,d,e,f,g,h])
);
}
Note:
When you modified the Google Apps Script, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful about this.
You can see the detail of this in the report of "Redeploying Web Apps without Changing URL of Web Apps for new IDE".
References:
getSheets()
filter()
map()
Related
I have google sheet. There are two sheet named "Subjects" and "Subjects_Classes"
I have written a script for sheet "Subjects" as follows:
const ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/.../edit?usp=sharing")
const sheet = ss.getSheetByName("Subjects")
function doGet(e){
let obj = {};
let data = sheet.getRange("A1:B1000").getValues();
obj.content = data;
return ContentService.createTextOutput(JSON.stringify(obj)).setMimeType(ContentService.MimeType.JSON)
}
I am processing the same with Javascript in html as follows: It is working perfectly.
fetch('https://script.google.com/macros/s/AKfycbxAlLPXi0Knsl1xEUQGpyUgZ26oeVtlLlajiHHGc9sMHMjkg9WKZigqUvbRiunkcA1UwQ/exec')
.then(res => res.json())
.then(data => {
let subjectsdiv = "";
data.content.forEach(item => {
if (item[0] === "") {
// skip to the next iteration if item[0] is empty
return;
} else {
subjectsdiv += `<div class="col">
<div class="card h-100">
<img src="#" class="card-img-top img-responsive" alt="...">
<div class="card-body">
<h5 class="card-title">${item[0]}</h5>
<p class="card-text">Explore the many ${item[0]} resources available online to enhance your understanding of the subject</p>
</div>
Read
</div>
</div>`;
}
});
document.querySelector("#Subjects").innerHTML = subjectsdiv;
});
</script>
Now I need another JSON for sheet "Subjects_Classes" as follows: Hence Sheet and columns are different.
const ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/ ... /edit?usp=sharing")
const sheet = ss.getSheetByName("Subjects_Classes")
function doGet(e){
let obj = {};
let data = sheet.getRange("A1:C1000").getValues();
obj.content = data;
return ContentService.createTextOutput(JSON.stringify(obj)).setMimeType(ContentService.MimeType.JSON)
}
I need help to create script for another sheet. Also need help to access the same in html (if changes is required).
Although I'm not sure whether I could correctly understand your expected situation, how about the following modification?
In this modification, the spreadsheet and range are changed using a query parameter.
Google Apps Script side:
Please set your Spreadsheet ID and range to object.
function doGet(e) {
const object = {
pattern1: { spreadsheetId: "###", range: `'Subjects'!A1:B1000` }, // Please set your Spreadsheet ID and range.
pattern2: { spreadsheetId: "###", range: `'Subjects_Classes'!A1:C1000` }, // Please set your Spreadsheet ID and range.
};
if (object[e.parameter.pattern]) {
const { spreadsheetId, range } = object[e.parameter.pattern];
let obj = {};
let data = SpreadsheetApp.openById(spreadsheetId).getRange(range).getValues();
obj.content = data;
return ContentService.createTextOutput(JSON.stringify(obj)).setMimeType(ContentService.MimeType.JSON)
}
return ContentService.createTextOutput(JSON.stringify({content: []})).setMimeType(ContentService.MimeType.JSON)
}
Javascript side:
Please set your Web Apps URL including the query parameter like ?pattern=pattern1 or ?pattern=pattern2 like https://script.google.com/macros/s/###/exec?pattern=pattern1.
From:
fetch('https://script.google.com/macros/s/AKfycbxAlLPXi0Knsl1xEUQGpyUgZ26oeVtlLlajiHHGc9sMHMjkg9WKZigqUvbRiunkcA1UwQ/exec')
To:
fetch('https://script.google.com/macros/s/AKfycbxAlLPXi0Knsl1xEUQGpyUgZ26oeVtlLlajiHHGc9sMHMjkg9WKZigqUvbRiunkcA1UwQ/exec?pattern=pattern1')
or
fetch('https://script.google.com/macros/s/AKfycbxAlLPXi0Knsl1xEUQGpyUgZ26oeVtlLlajiHHGc9sMHMjkg9WKZigqUvbRiunkcA1UwQ/exec?pattern=pattern2')
You can retrieve the values from 'Subjects'!A1:B1000 and 'Subjects_Classes'!A1:C1000 by the query parameter.
Note:
When you modified the Google Apps Script of Web Apps, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful about this.
You can see the detail of this in my report "Redeploying Web Apps without Changing URL of Web Apps for new IDE (Author: me)".
I am building an HTML page in Google Apps Script with CRUD functionality. The user can currently add data, edit data, and search data (I am not adding a delete feature). I would like the user to receive the form url link with an ID that when they go BACK to that link, it auto-fills the form with the previously added data.
In my HTML file, I have the following button defined:
document.getElementById("sbtn").addEventListener("click",getTID);
Once a user has entered data, it gets sent to a Google Sheet. The user HAS to enter a unique ID that they've already been provided. Using this ID, they can enter it, hit search, and it runs getTID():
function getTID() { //TID CODE
var transID = document.getElementById("tid").value;
if (transID.length === 36) {
google.script.run.withSuccessHandler(updateAllData).getID(transID);
} else {
alert("Transaction ID is not long enough.\nPlease copy the Transaction ID EXACTLY!\n\nFor Example: https:/workwebsiteconcealedforprivacy/w?txid=36275284-2ed6-4868-97b2-16bc1fde1a08\n\nThe Transaction ID is: 36275284-2ed6-4868-97b2-16bc1fde1a08")
}
}
This takes the ID they gave, references the spreadsheet and then returns values it found by index. Now, I have in my server-side GS file, the following in doGet:
var urlValue = '';
function doGet(e) {
// Test Code
var ss = SpreadsheetApp.openById(id);
var ws = ss.getSheetByName("Options");
var list = ws.getRange(1, 1, ws.getRange("A1").getDataRegion().getLastRow(), 1).getValues();
var htmlListArray = list.map(function (r) { return '<option>' + r[0] + '</option>'; }).join('');
var title = "Please Work";
var vals = JSON.stringify(e);
if ('v' in e.parameter){
urlValue = String(e.parameter['v']);
//return HtmlService.createHtmlOutput(urlValue);
}
return render("page",{list: htmlListArray, title});
and the following:
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
function render(file, argsObject) {
var tmp = HtmlService.createTemplateFromFile(file);
if (argsObject) {
var keys = Object.keys(argsObject);
keys.forEach(function (key) {
tmp[key] = argsObject[key]
});
}
return tmp.evaluate();
}
If I uncomment the return HtmlService.createHtmlOutput(urlValue); line, I can see that IF an ID is in the URL, it returns the correct parameter.
My problem is that I cannot get the HTML to read the urlValue variable and autorun getTID() when the user enters the url with the correct parameter. The correct functionality is that IF the parameter is found, it auto populates the HTML form. If it doesn't, it returns the blank form.
There is an error on
return render("page",{list: htmlListArray, title});
On {list: htmlListArray, title} the name of the second property is missing.
To "read the urlValue variable" there are two options:
pass the parameters from the URL using the event object of the doGet function. For this you have two options, create the HtmlService.HtmlOutput object from an html string generated using "vanilla" JavaScript or create it from a HtmlService.HtmlTemplate object.
get the parameters from the URL directly on the client-side code using google.script.url.getLocation .
If you go for the first option, then you should pass someway the urlValue to the render function. In the question code urlValue is a global variable, so you might add the following before the render's return statement.
tmp.urlValue = urlValue;
Then you have to add a scriptlet on the html file to handle this value and "autorun" getTID. Scriptlets is a feature of Templated HTML.
I am trying to get my Google Sheet to clear certain cells on opening it. I've never added Apps Script to any sheet, so step by sp instructions will be greatly appreciated.
I'm getting an error when trying to deploy the script below.
function onOpen() {
function clearRange() {
// replace 'Sheet2' with your actual sheet name
// replace '1AsVArsUf5DaIXqzyPEokCRkPVglxSPW4NgWg_PVtLhA/edit#gid=1395849459' with your actual sheet ID
var sheetActive = SpreadsheetApp.openById("1AsVArsUf5DaIXqzyPEokCRkPVglxSPW4NgWg_PVtLhA/edit#gid=1395849459").getSheetByName("Sheet2");
sheetActive.getRange('G83,G143,E143,G210,G221').clearContent();
}
}
Clear Ranges:
function onOpen() {
clearRange()
}
function clearRange() {
const ss = SpreadsheetApp.openById("1AsVArsUf5DaIXqzyPEokCRkPVglxSPW4NgWg_PVtLhA/edit#gid=1395849459");
const sh = ss.getSheetByName("Sheet2");
const rgl = sh.getRangeList(['G83','G143','E143','G210','G221']).getRanges().forEach(r => r.clearContent())
}
You probably need an installable trigger because you are using openById()
Sheet.getRangeList
I am attempting to create a visualization of the data we have on Snipe-IT Asset Management on Google Data Studio. To do so, I am creating a Google Sheets spreadsheet with an App Script extension that will communicate with the Snipe-IT API, retrieve the data, and populate it on the Google Sheet. So far, I've been able to get the API to populate some of our data on the terminal but not on the spreadsheet itself.
I wrote a simple script that should list out the assets assigned to one particular user, for testing purposes. Again, the script works fine, it populates the data I need on the terminal but not on the Google Sheet. Here is my exact code (excluding SETUP section details):
//SETUP
serverURL = 'SERVER-URL'; (ignore)
apiKey = 'API-KEY' (ignore)
function onOpen(e) {
createCommandsMenu();
}
function createCommandsMenu() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Run Script')
.addItem('Get Assets By Department', 'runGetAssetsByDepartment')
.addToUi();
}
function testGetAssetsByUser(){
getAssetsByUser("1745")
}
//Get assets for a user by id
//Returns a list of assets by id
function getAssetsByUser(userID) {
var url = serverURL + 'api/v1/users/' + userID + '/assets';
var headers = {
"Authorization" : "Bearer " + apiKey
};
var options = {
"method" : "GET",
"contentType" : "application/json",
"headers" : headers
};
var response = JSON.parse(UrlFetchApp.fetch(url, options));
var rows = response.rows;
var assets = []
for (var i=0; i<rows.length; i++) {
var row = rows[i];
if (row.category.name == "Laptop" || row.category.name == "Desktop" || row.category.name == "2-in-1") {
var asset = row.id
assets.push(asset)
}
}
return assets
}
console.log(getAssetsByUser(1745));
There are several ways to write values into an spreadsheet
The basics
Grab the spreadsheet
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
This works in bounded projects and add-ons
Grab the destination sheet
var sheet = spreadsheet.getSheetByName('put here the sheet name');
You might use SpreadsheetApp.getActiveSheet() if your spreadsheet has only one sheet, but for functions being called from a custom menu this one is risky.
Write values into the destination sheet
Preparation: Make a 2D Array
var output = assets.map(v => [v]);
Do: Write values into the destination sheet
sheet.getRange(1,1,output.length, 1).setValues(output);
Resources
https://developers.google.com/apps-script/guides/sheets
So, Google recently updated Google App Script API and added lots of nice features, however, in the process, they also depreciated LOTS of API. I have been working on a Library Database user interface for the place I work on my college campus, and when I wanted to update my app to the new API, a lot of things broke, and I can't figure out how to make them work again.
What I am trying to do is get a value from a Google Sheets file, and simply put that value in a text box on the web app. Currently I cannot get that work work. In addition, I discovered something that was troublesome, and that is, the debugger seems to not be correct. I know, bold accusation. Let me try to show you.
Code.gs
function doGet(e) {
var html = HtmlService.createHtmlOutputFromFile('index')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
return html;
}
function searchBooks(searchItem, searchType){
var sI = searchItem;
Logger.log(sI);
var sT = searchType;
Logger.log(sT);
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var ss = sheets[0];
var itemDataRange = ss.getRangeByName("itemInformation");
var selectedItem = null; //the item that will be returned
//var selectedSearch = searchItem;
var titles = sheet.getRange("K2:K9507").getValues(); //get the titles of the items
var authors = sheet.getRange("J2:J9507").getValues(); //get the authors in the sheet
var barcodes = sheet.getRange("B2:B9507").getValues(); //get the barcodes in the sheet
var itemsArray = new Array();
if (sT == '')
{
return null;
}
else if (sT.value == 'Please select type...')
{
var test = "this works";
Logger.log(test);
return selectedItem;
}
else if(sT == 'Barcode')
{
var selectedBarcode = sI;
for(var i = 0; i < barcodes.length; i++) //search for the barcode
{
if(barcodes[i] == selectedBarcode)
{
selectedItem = titles[i];
break; //break immediately because barcodes are not duplicated
}
}
if(selectedItem != null)
{
return selectedItem;
}
else
{
selectedItem = "No book(s) found";
return selectedItem;
}
return selectedItem;
}
}
...
index.html
<script>
function bookSearch()
{
var searchItem = String(document.getElementById('searchItem').value.toLowerCase());
var searchType = String(document.getElementById('searchType').value.toLowerCase());
google.script.run.withSuccessHandler(bookFound).searchBooks(searchItem, searchType);
}
...
function bookFound(selectedItem)
{
document.getElementById("bookResultBox").innHTML = selectedItem;
alert(selectedItem);
}
</script>
When I test this code, and put a search value with the category "Barcodes" selected, I successfully get console logs of the data being brought into the function searchBooks, however the debug console says that the variables sI, sT, searchItems, and searchType are all undefined.
I've also been having trouble trying to figure out the proper API calls to use to search through the spreadsheet (when dealing with stuff like getRangeByName). I think there might be a slightly different way to do this since the big update. I may have had it working before I changed some of the code, although I started changing a lot of it when I was trying to figure out WHY nothing was displaying. When I saw at the "undefined" debug console logs, it scared me a bit. I can't tell if I'm messing up, or the API is messing up.
Any help is much appreciated in advance :)
There's probably an error in your code. It's probably coming from line:
var itemDataRange = ss.getRangeByName("itemInformation");
Your variable ss is not a spreadsheet class, it's a sheet class. You can't get a RangeByName of a sheet class. There is no getRangeByName() method of the Sheet class.
I'd change your code to this:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var itemDataRange = ss.getRangeByName("itemInformation");
If you need to get the first sheet:
var theFirstSheet = ss.getSheets()[0];