Google Script: getActiveSheet() when there is no Active Sheet? - google-sheets

I've been working on this for a couple on days, and I can't find any answer to this issue.
I don't have a programmer background, so it might be an easy question for some of you.
The issue:
I have 5 Google Forms that fill 5 different Sheets in 1 Master Google Sheet.
--> When Google Form 1 is filled, there is a new line in sheet1
--> When Google Form 2 is filled, there is a new line in sheet2
--> When Google Form 3 is filled, there is a new line in sheet3
--> When Google Form 4 is filled, there is a new line in sheet4
--> When Google Form 5 is filled, there is a new line in sheet5
Now, I would need to be able to run some script (different ones) when a new line is added to each sheets.
The idea is:
--> When a new line is added to sheet1, do this.
--> When a new line is added to sheet2, do this.
.
.
.
I tried something like this (see below). But it doesn't return anything since there is no "Activesheet" when the google form is filled and add a new row by himself to Google sheet.
function onChange(event) {
var s = event.source.getActiveSheet();
var sName = s.getName();
Browser.msgBox(sName);
}
Question:
In other words, do you have a idea about how I can get the sheet that was edited by the google form, so that I can run specific script for each sheet when it gets modified ?

the onChange trigger does not fire on form submission, use the FormSubmit trigger instead
The related event objects are specified here.
The event object source is not available, but instead you can use the event object range in combination with getSheet().
Sample:
function onChange(event) {
var s = event.range.getSheet();
var sName = s.getName();
Browser.msgBox(sName);
}

Related

How to add live view count from Instagram into Google Sheets

I am currently using a Google Sheet to keep track of viewer count on several Instagram videos. My current formula:
=REGEXEXTRACT(IMPORTXML("A1","//script[#type='application/ld+json']"),"userInteractionCount"":""(\d+)")
(A1 is actually the instagram page link)
It grabs the viewer count that I need , but it doesn't seem to auto-update when I refresh the page or when I close and reopen the page. Only way for the number to update is deleting are re-entering the formula. As I will be eventually keeping tabs on almost 1,000 videos, I would love a solution on how it updates with a page refresh or when I re-open the page.
Solution:
In order to make sure the imported data updates periodically, you can set up an Apps Script time-driven trigger that will periodically execute a function (called myFunction in the example below) that will:
Retrieve the formula, using Range.getFormula()
Clear the cell, using Range.clearContent().
Set the formula again, using Range.setFormula(formula).
Workflow:
Click Tools > Script editor in order to open the script editor.
Install the time-driven trigger. You can do that manually, following these steps, or programmatically, by copying this function to the script editor and executing it once:
function createTrigger() {
ScriptApp.newTrigger("myFunction")
.timeBased()
.everyMinutes(1) // Alternatively, set it to 5,10,15,30 or use .everyHours
.create()
}
Note: In this example, the function is set to run every minute; you can change that period by setting another value at .everyMinutes(1) -1, 5, 10, 15, 30 are allowed, see everyMinutes(n)- or using everyHours(n) instead, that's up to you.
Once the trigger is installed, a function called myFunction will run with the periodicity you have previously set. For example, if the formula is in cell A2 from Sheet1:
function myFunction() {
const sheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
const cell = sheet.getRange("A2");
const formula = cell.getFormula();
cell.clearContent();
SpreadsheetApp.flush();
cell.setFormula(formula);
}
Related:
Periodically refresh IMPORTXML() spreadsheet function

How to conditionally copy a drop down in google-sheet?

I have a drop down with a few options.
I want to conditionally copy the drop down to the following line. Keeping the selected value and its options.
I have tried:
=IF(Placements!$B3="", "", D$2)
but only the content was copied.
It is possible to copy an entire dropdown list into another cell using Apps Script.
Please see sample code below for fetching dropdown list as well as creating a dropdown with the fetched values from the original dropdown.
function myFunction() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = sheet.getRange(1,1).getDataValidation().getCriteriaValues();
var range2 = sheet.getRange(1,2);
var rule = SpreadsheetApp.newDataValidation().requireValueInList(range[0]).build();
range2.setDataValidation(rule)
}
With this, you can add the condition that you want before creating the dropdown copy.

Is it possible to display a Google sheet as HTML without revealing the URL of the sheet?

I know it's possible to display a Google Sheet as HTML using the spreadsheet ID and GID, i.e.:
https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/gviz/tq?tqx=out:html&tq&gid=GID
But in order to view that, you have to know the URL of the sheet. What I'm wondering is whether it's possible to display this HTML version of the sheet but without revealing the URL of the sheet?
Manually
To retrieve a Spreadsheet in HTML format you can export it accordingly by clicking on File -> Download -> Web Page. That will get you a zip file with the HTML of your Spreadsheet that you can rename as you like without revealing the Spreadsheet ID.
With Apps Script
You can also automate this process creating an Apps Script function that for instance gets triggered every time you click on an inserted button (to do this you can simply click on the menu bar Insert -> Drawing and the on the three dots of the top right of this button click on assign script and set it to the name of your function).
The following function will display a modal dialog on the Spreadsheet when run that if the user clicks on Download it will automatically download the zip file with the Spreadsheet in HMTL format. This function has self explanatory comments :
function downloadHTML() {
// Get ID of the Spreadsheet
var id = SpreadsheetApp.getActive().getId();
// Get the download URL of this Spreadshet in format HTML on the background
var url = "https://docs.google.com/a/mydomain.org/spreadsheets/d/" + id + "/export?exportFormat=zip&access_token=" + ScriptApp.getOAuthToken();
// Download when clicked on the button of the opened dialog
var html = '<input type="button" value="Download" onClick="location.href=\'' + url + '\'" >';
// create an HTML output from the given string
var dialog = HtmlService.createHtmlOutput(html);
// Show a modal dialog on the Spreadsheet UI when the function is run with the Title download
SpreadsheetApp.getUi().showModalDialog(dialog, "Download");
}
Reference
createHTMLOutput
showModalDialog

Is it possible to display text in one cell based on text color from another cell?

So it's sort if reverse conditional formatting I guess?
I'm making a my own spreadsheet to consolidate all my tasks which are listed on our group's tasks spreadsheet. So far, my spreadsheet is working as I intended, except for the status column.
Basically, I want it so when I turn the task green (change font color) on the group's tasks spreadsheet, the cell beside that task on MY spreadsheet will display "Done".
You can create functions using apps script and run it using Simple Triggers. To create apps script, Go to Tools->Script Editor
Simple Triggers
Triggers let Apps Script run a function automatically when a certain event, like opening a document, occurs. Simple triggers are a set of reserved functions built into Apps Script, like the function onOpen(e), which executes when a user opens a Google Docs, Sheets, Slides, or Forms file. Installable triggers offer more capabilities than simple triggers but must be activated before use. For both types of triggers, Apps Script passes the triggered function an event object that contains information about the context in which the event occurred.
Here is an example on how to modify Google Sheets using Apps Script.
Sample Function:
/**
* The event handler triggered when editing the spreadsheet.
* #param {Event} e The onEdit event.
*/
function onChange(e){
//Select the active sheet
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
//Select the active cell
var activeCell = activeSheet.getActiveCell();
//Note: I want to input the status next to the task's column
var taskrow = activeCell.getRow();
var statusCol = activeCell.getColumn() + 1;
//Check if font color is green then set the status column to Done
if(activeCell.getFontColor() == '#00ff00'){
activeSheet.getRange(taskrow,statusCol).setValue('Done');
}
//Check if font color is red then set the status column to Delayed
else if(activeCell.getFontColor() == '#ff0000'){
activeSheet.getRange(taskrow,statusCol).setValue('Delayed');
}
};
onChange() method can be triggered whenever there are changes done in the sheet's user interface (like font color).
Using the getFontColor() of the Range Class in SpreadsheetApp, you can get font color of the cell in CSS notation (such as '#ffffff' or 'white').
Then you can set the cell value using setValue() of the Range Class in SpreadsheetApp
To learn more about SpreadsheetApp and its classes, you can refer to this reference:
https://developers.google.com/apps-script/reference/spreadsheet
To learn more regarding Simple Triggers and Event object:
https://developers.google.com/apps-script/guides/triggers
https://developers.google.com/apps-script/guides/triggers/events
To automate the execution of onChange(), you need to add it to your project's triggers
Open current project's triggers using the clock icon beside the play button
Click Add trigger at the bottom right page of your current project's triggers
Populate the necessary information and make sure to select "On change" under Select event type option.
Sample Output:

How to delete a jqgrid row without reloading the entire grid?

I have a webpage with multiple jqgrids each with inline editing enabled, "action" column (edit icons) enabled and pager disabled. I need to handle the delete event for each row so that I can process the delete without reloading server-side data. I've looked at the approach mentioned in jqGrid Delete a Row and it's very helpful except I have two questions that are stumping me -
Are there more details around the rp_ge parameter in the delOptions.onClickSubmit event?
My column has the delOptions set as this -
delOptions: {onclickSubmit: function(rp_ge, rowid) {return onRowDelete(rp_ge,rowid);}},processing:true }},
Is there a way to get the grid id from within that event? I'd like to have a generic function that I can use to handle delete events from all the grids on the page. The rp_ge parameter has a gbox which sometimes contains the grid id appended? But I have no idea what it is since i'm not able to figure out when it's populated, when it's not.
function onRowDelete(rp_ge, rowid) {
//hardcoded grid id.. don't like it.
var gridid = '#Grid_X';
//what is this gbox?? can i get grid id predictable from it?
//var gridid = rp_ge.gbox.replace("#gbox_", "");
var grid = $('#Grid_X');
rp_ge.processing = true;
var result = grid.delRowData(rowid);
if (result) {
$("#delmod" + grid[0].id).hide();
}
return true;
}
In the jqGrid Delete a Row approach, the code $("#delmod"+grid[0].id).hide(); is hiding the popup delete confirmation dialog manually. What I noticed is that when the dialog pops-up, jqgrid de-emphasizes the background page (makes it light greyish). But after the popup is manually closed (hidden actually?), the background remains de-emphasized. So it looks like the page doesn't have focus (or even disabled). Any way this can be fixed? This can also be seen on the demo that Oleg wrote.
Any help would be appreciated.
(PS - I would've commented on the same post but I don't have enough points to comment on someone else's answer yet.)
In answer to your second point.
Several examples by Oleg such as this one have the following modification.
$("#delmod" + grid[0].id).hide();
is replaced with
$.jgrid.hideModal(
"#delmod"+grid_id,
{gb:"#gbox_"+grid_id,jqm:rp_ge.jqModal,onClose:rp_ge.onClose}
);
This will return focus after the delete operation.

Resources