I'm trying to figure out how I can write and run a custom function in a Google spreadsheet and I've been following this google tutorial.
However at the time of this posting, I fear that this tutorial is out of date. I followed the steps, but see no way to access my in2mm function from within the spreadsheet that I started at. The tutorial suggests the following to make it show up
You can manually start the scan by going to Tools > Script Manager... and clicking the Reload button.
However, no such menu item exists.
Just cut off in that screenshot is a "Script Center Menu", which has just one option for "Read Data". It's unclear what that does. It's also unclear how the "Script Editor" ends up tying back into the existing spreadsheet to become available...
Does anyone know the current steps required to write a simple google script function and then access it from within a Google spreadsheet?
I had the same problem, and while the tutorial and Sum Ting Wong's answer actually do work, it didn't help in my case.
The sheet I was trying to use the custom function from was in the old format. So I converted it to the new format,created a custom function, and now I can use it the sheet.
Here's how you see if it's an old format sheet Check out the new Google Sheets
You can tell that a spreadsheet has been created in, or upgraded to, the new Google Sheets if it has a green checkmark at the bottom.
and here's how to convert it to the new format:
Moving spreadsheets to the new Google Sheets
you can manually move spreadsheet contents into the new version of Sheets to take advantage of new functionality, following any of these steps:
Copy and paste content from a spreadsheet created in the old version to a spreadsheet created in the new version.
In a spreadsheet created in the old version, click the down arrow next to a sheet tab and click Copy to…, and copy the sheet (and its contents) to a spreadsheet created in the new version.
Export the contents from the old version and import them into a spreadsheet created in the new version.
forget the reload button hint.
if you have in the first step write your function in the script editor and save it.
function in2mm(inNum) { // Function to convert from INCHES to MILLIMETERS
var outNum = 0; // this will hold the answer
var factor = 25.4; // multiply input by this factor to get output
if (typeof inNum != "number") { // check to make sure input is a number
throw "input must be a number"; // throw an exception with the error message
}
outNum = inNum * factor; // calculate the answer
return outNum; // return the answer to the cell which has the formula
}
for your second step write e.g. in cell A1 of your sheet, to call the function
=in2mm(10)
important is that you call your function-name started with the equal sign =
if you do a type-mismatch by your second step you get the message
#NAME?
there is no mystic and no out of date ;-) btw i imagine they talk from the browser reload button
Custom Function still work in google sheets.
function GETKWEEKDAYFROMNBR(weekdayNbr) {
var weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
return weekdays[weekdayNbr];
}
usage example:
=GETKWEEKDAYFROMNBR(WEEKDAY(A2,2))
I've got the same problem. I've had a spreadsheet open for a few days and under Tools there are three script options, those being Script Gallery, Script Manager and Script Editor.
I started a new sheet and went to the script editor, and there's only two options available, just like in your image. If I select Script Gallery I get this message;
Script gallery is now the add-on store
In the new Google Sheets, the script gallery has been replaced with the add-on store. Click the new Add-ons menu to get started. Learn more
The only solution I can see to get the script to work is by running it from within the script editor itself.
Related
Update: I'm sorry I didn't post the code originally. In my newbie-ness, I didn't think it honestly mattered, but I've been around long enough to know better. See below:
function openForm(e)
{
populateQuestions();
}
function populateQuestions() {
var form = FormApp.getActiveForm();
var googleSheetsQuestions = getQuestionValues();
var itemsArray = form.getItems();
itemsArray.forEach(function(item){
googleSheetsQuestions[0].forEach(function(header_value, header_index) {
if(header_value == item.getTitle())
{
var choiceArray = [];
for(j = 1; j < googleSheetsQuestions.length; j++)
{
(googleSheetsQuestions[j][header_index] != '') ? choiceArray.push(googleSheetsQuestions[j][header_index]) : null;
}
item.asCheckboxItem().setChoiceValues(choiceArray);
// If using Dropdown Questions use line below instead of line above.
//item.asListItem().setChoiceValues(choiceArray);
}
});
});
}
function getQuestionValues() {
var ss= SpreadsheetApp.openById('1QeckPxMYSYGMkZ-QggY76u03N1qBKBGL2UEMcUvu7sM');
var questionSheet = ss.getSheetByName('Sheet5');
var returnData = questionSheet.getDataRange().getValues();
return returnData;
}
After months of work, I finally have cracked the script to getting what I wanted. Now I need to use this script over and over in multiple Google Forms (forms, for short). By copy and pasting the Form within Drive, I carry the App Script with each copy, but not the trigger or the authorization needed to run it. I need assistance in learning how I can make this process quicker.
I have very limited knowledge of add-ons and things, but I’m willing to learn. I do not necessarily need this to be a public access Script, just want to make my life less repetitious.
I would also like to make it so after installing the add-on, users can just pick the Sheet/Tab through a UI and not editing the code specifically, but that's a different story.
For the moment, You can create an installable trigger so you don't have to add the trigger manually anymore. You should use this:
function createFormOpenTrigger() {
const gf = FormApp.getActiveForm()
ScriptApp.newTrigger('populateQuestions')
.forForm(gf)
.onOpen()
.create();
}
Instead of:
function openForm(e)
{
populateQuestions();
}
As for the credentials, deploying the script as an add-on I will help you with the OAuth part. However, I was unable to test it today due to propagation. I’m still getting a message that the Apps Script is not bound to the GCP project. I will try my luck tomorrow, in the meantime you can read the following documentation about it. Here.
Sorry, I took some time to post the answer since you mentioned that you didn't know how to create an add-on, so I tried to add step by step information.
Update:
You can add this part at the top of the code, this will create a menu that will allow you to run the script for the first time in the Google Form after we make it an Add-on.
function onOpen() {
//you can change the names of the menu, just not change
// this part "createFormOpenTrigger"
FormApp.getUi()
.createMenu('formTest')
.addItem('Run Apps Script', 'createFormOpenTrigger')
.addToUi();
}
If you do not have a GCP project, you can created one by following the steps here, or following the steps:
Open the Google API Console projects list.
Click Create Project.
Fill out the project information for your add-on.
Click Create.
Copy the Project number, and add it to the Apps Script to switch to a different standard Cloud project.
Deploy the Apps Script as an Add-on.
Remember the version number you will need later on. Access to the Google Cloud Project link with the Apps Script.
Setup the OAuth consent screen, select internal to make sure that only you have access to it (and users of your Workspace if you have one)
We will need to the Add-on listing, so we will need to add "Google Workspace Marketplace SDK" in the Library.
Add the App configuration information, add all the require information there, the only recommendation I can provide you are these 2:
Note: this can be found under "Project Settings"
Lastly, fill out the information under "Store listing".
Note: You can add dummy information if only you are going to use the add-on.
Once all that is done, use the "App URL" link to install the add-on. When you open a Google Form it will show up under the Add-on list:
And you will see the option to Run the Apps Script, thanks to the last part of the code we added.
Click on it, and it might ask you for permission the very first time you use it. But it will not request it again even if you add it to a new form.
I am running Google's Analytics Add-on for Google Sheets, for Chrome, to pull in analytics for several properties. This runs once a day and works very well. Two data points that I pull are the approximate latitude and longitude of the visitor.
Prior to using the add-on I used the older "magic script" written by Nick Mihailovski however this doesnt work any longer so we're advised to the add-on.
What I would like to do is extend the add-on such that after it populates the sheets I would like to add a column that shows the reverse geocode of the coordinates.
I have this function that I used to modify Nick's script:
function reverse_geocode(lat,lng) {
Utilities.sleep(1500);
var response = Maps.newGeocoder().reverseGeocode(lat,lng);
for (var i = 0; i < response.results.length; i++) {
var result = response.results[i];
Logger.log('%s: %s, %s', result.formatted_address, result.geometry.location.lat,
result.geometry.location.lng);
return result.formatted_address;
}
}
I was able to modify Nick's code so that as each row was written to the sheet I could add the cell with the address from the lat/long. Now I must do this manually. I'd like to get it back to working automatically.
Is it possible to do this with an add-on for which I can not see nor access the code? I have tried to add this function to a file in my sheet called "geocode.gs" and tried to call it via a trigger but it does nothing. No visible error that I can see, nothing in the execution log either. Is there another way to automate this with a closed-source add-on?
You can do this by creating a bound script in the Sheet you are running the report on.
If you've already tried and it doesn't work it may just be due to an error in your code.
I don't think there are add-ons that can do what you want specifically, also because doing it with the code in Google Apps Script (since you already have a function that does its job) is the quickest and most effective way.
I have
an Apps Script Library 'MyLib'.
template Google Spread Sheet ('MyGSSheet'). Through Script Editor I added the library 'MyLib' to 'MyGSSheet'. I set 'Development mode' 'on'.
users get a 'copy' of this template ('MyGSSheet').
How can I have a setup wherein any changes I make to 'MyLib' get picked up across these copies automatically (once the Spreadsheet is reloaded)?
I thought having 'Development mode' 'on' is all that's needed for this continuous update of the code in all the Spreadsheets.
However, I don't see this happening. The copies aren't picking the latest code.
I also granted 'edit' permission to all users within our company domain.
I am not able to comment so I hope I am contributing enough to justify an answer..
So I tried to reproduce this:
I created a standalone App Script 'MyLib' and wrote a single function:
function myFunction()
{
SpreadsheetApp.getUi().alert("TEST");
}
Next I created a spreadsheet and added a script to it via Tools. I'll call it "Spreadsheet Script".
In the Spreadsheet Script I added the MyLib as a library and turned the development mode 'on'.
Also I added two functions to Spreadsheet Script:
function onOpen(e)
{
myFunction();
}
function myFunction()
{
MyLib.myFunction();
}
Ok, now I shared the Spreadsheet and the MyLib - script to my colleague with edit rights. He opened the spreadsheets and got the alert "TEST".
Now when I modified the alert text from the MyLib-script's myFunction to "TEST 2 " and just saved the file (File/Save, did not save a new version), my colleague saw the changes in the spreadsheet. Then, I made him to take a copy of the spreadsheet( To test the effect of the spreadsheet owner change).
I changed the alert the text to "TEST 3". The change was reflected in his copy of the spreadsheet.
Are you able to reproduce this or does this approach fail to update for the other users? I am choosing this kind of simple example as sometimes the reason might reside in the code too...
I'm using this code to use data in a Google Apps Script:
function getCurrentRow() {
var currentRow = SpreadsheetApp.getActiveSheet().getActiveSelection().getRowIndex();
return currentRow;
}
But when I use other sheet than the first one (number "gid=0"), my function remains getting data from that first sheet and not from my current active sheet. Since I'm using the method .getActiveSheet() how can I fix that?
PS - I'm not calling the code from a cell. I'm using this code:
http://opensourcehacker.com/2013/01/21/script-for-generating-google-documents-from-google-spreadsheet-data-source/
I created from scratch a brand new spreadsheet, within which, I created a few tabs/sheets with some data within each; and then in google apps script in that spreadsheet I installed the following code:
function getCurrentRow() {
var currentSelection = SpreadsheetApp.getActiveSheet().getActiveSelection()
var currentValue = currentSelection.getValue();
var currentRow = currentSelection.getRowIndex();
Logger.log(currentValue);
Logger.log(currentRow);
return currentRow;
}
I ran the script, and it gave me the correct results for the sheet that was open/which cell was selected. So I would say that this code pretty much works as you expect.
In your case, may I suggest that the quickest way to get more info about the error, or to see if the error persists, is for you start from scratch too, with a new spreadsheet, and paste in the code above, and then test to prove that at least that much works for you too. Then, only after this, paste in the greater code (that you have linked to), and see if it still/stops working.
I'm having the same problem while developing in the Script Editor -- the Script Editor instance/window becomes 'disconnected' from the Sheets instance/window and just has the first sheet / A1 etc as the 'actives'.
What worked for me:
Closing the Script Editor window and re-opening from Sheet > Tools > Script editor. Voila, .getActive...()s are working again.
Also:
As implied by some of the other answers, triggering the execution from the Sheets window/instance (probably always) also works. One of the answers calls a function from a cell, which means it's going to be triggered by the Sheet. Another option would be to add a .UI menu and menu-option and trigger it there.
Do you use your function as a formula?
Maybe I'm not understanding well the case, but using your code as a formula, it works as expected.
In Sheet1 (Active) apply the formula:
Then manually change the Sheet2 (Active) and apply the formula again:
Its because you are calling it from a custom function in a cell. You cant do that because custom functions must be deterministic. The answer from wchiquito works because he is using a different cell to try the 2nd case. If you use the same cell it will show the old cached result. Search s.o. for the issues about dedeterministic functions. Ive provided workarrounds in those (basically pass a second param =now()
create a spreadsheet in google drive and save it.
In the spreadsheet go to tools menu and script editor
and type the function.
I have created a form that pushes data to a Google Spreadsheet. The data is latitude, longitude, location, and other identifying data. The spreadsheet is then published as a .CSV file and imported into ARC GIS to be displayed on an interactive map. It works exactly as I wanted and I set it to republish after each change.
The problem is that when the spreadsheet has rows appended by the script, it is not seeing it as a change and republishing. In order to get the updated data imported to the map, I need to go in and manually republish. Is there anyway through the Google Apps Script that I could make a few lines of code to force a republish? I could then add that to the "on form submit" script I have or another time based one that already runs at 3 am everyday.
I have looked through the Google Apps Script documents and not found anything. When searching for help on the web, the overwhelming majority of responses are for how to publish your script as a template for other.
My testing sheet was republished after the following function was executed by either a menu entry or a time-based trigger.
function ChangeIt() {
var sheet = SpreadsheetApp.getActiveSpreadsheet()
var t = new Date()
var x = 'upd: ' + t
var range = sheet.getRange('a3')
range.setValue(x)
}
If I were in your shoes, I'd add an extra column to the end of the sheet with some benign constant data that a script can change without affecting the systems consuming the data. If an extra column isn't an option, try modifying my sample to read in a current value, change it, and immediately change it back.
Also, I'd see if the spreadsheet onEdit() trigger fires when the form submit adds a new row. If so, tie your GAS function to it to force the republish. If not, setup a timed trigger to execute the GAS function.
A quick workaround for this issue that doesn't require scripting is to simply make an array copy of the data.
For example, I made a new tab and in A1 put this: =ArrayFormula('Form Responses 1'!A1:Z1000)
While the main Form responses tab will insert rows and not play nice with formulas this new tab stay nice and constant and updates automatically when new data is added.