Basically I am receiving errors about the formsubmit and everything has been changed around multiple times and re-edited PLUS re written but the script just wont budge.
I have deleted and recreated+edited the code multiple times and deleted and recreated the trigger multiple times and to no avail.
I originally made it so only hard edits could work to bring data down to the bottom cells but that is not what I wanted in the end.
/** #OnlyCurrentDoc */
function formsubmit()
{
var sheet=SpreadsheetApp.getActiveSheet();
var email_address = Session.getActiveUser().getEmail();
var lastRow=sheet.getLastRow()
var lastColumn=sheet.getLastColumn()
var entries=sheet.getRange(lastRow,1,1,lastColumn)
for(var i=1; i<=lastColumn; i++)
{
var cell=sheet.getRange(lastRow,i).getValues()
if(cell==0)
{
var previousCell=sheet.getRange((lastRow-1),i).getValues()
sheet.getRange(lastRow,i).setValues(previousCell)
}
}
}
6/23/19 4:48 PM
myFunction
Script function not found: myFunction
formSubmit
6/23/19 4:48 PM.
Edit: I believe it is case sensitive.
So Google Sheet is looking for 'formSubmit', when your function is called 'formsubmit' (lower case S)
Related
very new to javascript and appscript, this is what I have so far given my limited exposure to the language, so please correct any misconceptions I have through my code:
GOAL: to copy a single sheet from a spreadsheet into a new google drive folder.
METHOD: i spend last couple of days finding a way to do it but I couldn't so I decided to brute force it step by step using the logic I understand; first function i will cop the entire spreadsheet into a new folder, then my second function i will loop through the sheets in the new copied spreadsheet and delete all sheets except the one I want. I know it's not efficient but it's the best idea i could come up with.
ISSUE: both functions worked perfectly well separately, but when I combine them together on the same script, the delete function does not work. Here is what I have so far separately and together:
the first function to make copy of the spreadsheet using its ID which works fine is
function exportedSheet() {
let targetSheet = DriveApp.getFileById("INSERT ORIGINAL SHEET ID");
var destFolder = DriveApp.getFolderById("INSERT DESTINATION FOLDER ID");
var finalFile=DriveApp.getFileById(targetSheet.getId()).makeCopy("NEW FILE NAME", destFolder);
var ss= SpreadsheetApp.openById(finalFile.getId());
}
the second function to delete all the sheets in the new file except the desired sheet, let's call it "KEEP" is this, which also works fine:
function DeleteAllSheets() {
let ss= SpreadsheetApp.openById(NEW OBTAINED SHEET ID FROM THE LAST FUNCTION ADDED MANUALLY);
var sheets = ss.getSheets();
for (i = 0; i < sheets.length; i++) {
switch(sheets[i].getSheetName()) {
case "KEEP":
break;
default:
ss.deleteSheet(sheets[i]);
}
}
}
now here is what i did to combine them into one script that would ultimately create the new copy spreadsheet, then pull the ID of the new spreadsheet the first function created from the function itself? and apply it to the second function so it can be accessed and deleted unwatned sheets. I assume this logic makes sense, but it's clealry not since the code isn't running correctly.
I decided to finished the first function that creates the copy by returning a variable with the file i created, then i tried to call that function exportedSheet() in the second function so that I can call the .getID() method from it, my logic is that the second function will pull the variable from the first function and then apply it to the rest of the code
function exportedSheet() {
let targetSheet = DriveApp.getFileById("INSERT ORIGINAL SHEET ID");
var destFolder = DriveApp.getFolderById("INSERT DESTINATION FOLDER ID");
var finalFile=DriveApp.getFileById(targetSheet.getId()).makeCopy("test", destFolder);
var ss= SpreadsheetApp.openById(finalFile.getId());
return finalFile
}
function DeleteAllSheets() {
var test= exportedSheet();
let ss= SpreadsheetApp.openById(test.getId());;
var sheets = ss.getSheets();
for (i = 0; i < sheets.length; i++) {
switch(sheets[i].getSheetName()) {
case "KEEP":
break;
default:
ss.deleteSheet(sheets[i]);
}
}
}
if you run the code however, the new copied spreadsheet will appear, but it will include all the sheets within it rather than deleting them except the one I need. this is the extent of what i did in the past 5 hours and i can't remember all the other things i tried to tinker with it so it works. If you read this far thank you, I appreciate any input!
Copy sheets to new spreadsheet in another folder
function copysheetstonewspreadsheet() {
const fldr = DriveApp.getFolderById("folderid");
const ss = SpreadsheetApp.getActive();
const shts = ss.getSheets().filter(sh => sh.getName().startsWith("Sheet"));//did not want to mess around with other sheets
shts.forEach(sh => {
let f = SpreadsheetApp.create(sh.getName());
Drive.Files.update({"parents": [{"id": fldr.getId()}]}, f.getId());
let d = SpreadsheetApp.openById(f.getId());
sh.copyTo(d);
d.deleteSheet(d.getSheets()[0]);//There is only one sheet in a new spreadsheet
});
}
Drive.Files.Update
So I have two separate sheets, one with a data list full of unique names, their location and their current status. The second would have an input to type someones name and it would pull up the row that contains their current location/status(first function), from there I could change the status and run the second function that updates the first sheet with the new status. I have been googling all day trying to cobble together something that would work and I think I am almost there on the first function but I am stuck and any help to point me in the right direction would be greatly appreciated.
Ideally the first function would trigger upon typing the name in and the second would trigger upon changing the status but I can find a manual workaround if need be.
function dataPull() {
var data = SpreadsheetApp.openById('Spreadsheet_ID'); //replace with Data spreadsheet ID
var filteredRows = data.filter(function (data) {
var employee = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange('b2').getValue();
if (data[1] === employee) {
return data
}
});
SpreadsheetApp.getActiveSheet().getRange('A2:D').setValue(filter)
}
Here are some screenshots that will hopefully better explain what I am looking to accomplish.
Sample data
Type someones name in Input sheet
Pull up current status w/ function one
Update Status and run function two
Sample data updates to reflect change in status
Edit Dialog in a Sheet
There is two sections to this function. The top section triggers off of edits to the Edit sheet in column 2 and row 2 which is a dropdown that contains all of the name in the Data Sheet. An edit here cause the top section to run which reads the the data on the Data sheet and file a matching name when it finds it that line is loaded into columns 1 through 4 and row 2 of the Edit sheet. Then you can edit the status and click the checkbox to save it back to the Data sheet. The lower portion then runs which reset's the checkbox, clears the Edit range and loads the edits back into the Data Sheet.
Please take a look at the animation to see the process in action.
Just to let you know upfront, you can run this function from the script editor you must put it into you sheet and name your sheets properly. You must also set up the data validations for the two drop downs. If you try to run this function from the script editor you will get the Error: Cannot find method getsheet() of undefined
function onEdit(e) {
e.source.toast('Entry');
var sh=e.range.getSheet();
if(sh.getName()=='Edit' & e.range.columnStart==2 && e.range.rowStart==2) {
e.source.toast('flag1');
var found=false;
var dsh=e.source.getSheetByName('Data');
var vA=dsh.getRange(2,1,dsh.getLastRow()-1,dsh.getLastColumn()).getValues();
for(var i=0;i<vA.length;i++) {
if(vA[i][1]==e.range.getValue()) {
sh.getRange(2,1,1,4).setValues([vA[i]]);
found=true;
e.source.toast('Value Found at i = ' + i + 'value = ' + vA[i][1],'',-1);
break;
}
}
if(!found) {
e.source.toast('No Value found = ' + e.value);
}
Logger.log(vA);
}
if(sh.getName()=='Edit' & e.range.columnStart==5 && e.range.rowStart==2) {
e.range.setValue("FALSE");
dsh=e.source.getSheetByName('Data');
dsh.getRange(Number(e.range.offset(0,-4).getValue()+1),4).setValue(e.range.offset(0,-1).getValue());
sh.getRange(2,1,1,4).clearContent();
}
}
Data Sheet:
Edit Sheet:
Animation:
You can't use the built-in onEdit(e) trigger; as it behaves in the same manner as a custom function would eg.(Restricted to the sheet it's bound to).
You can install a trigger in your bound script, and have it execute your un-restricted function.
function importData(e){
// Get the cell where the user picked its name
var range = e.range;
// The Id of your data source sheet
var dataSheetId = 'XXXXXXXXXXXXX';
// Get all values from source sheet as an array
var data_values = SpreadsheetApp.openById(dataSheetId).getDataRange().getDisplayValues();
// Return the row with data for matching employee
var filteredRow = data_values.filter(check)[0];
// Input location data in input sheet
SpreadsheetApp.getActiveSheet().getRange(range.getRow(),range.getColumn()+1).setValue(filteredRow[2]);
}
function check(row) {
// Get the name that the user picked
var employee_name = SpreadsheetApp.getActiveSheet().getActiveCell().getValue();
// Check if it matches and return the row
if (row[1].toLowerCase() === employee_name.toLowerCase()) {
return row
}
}
You can install the trigger from within your Apps Script by following Edit/Current project's triggers/Add trigger.
As the event source for the trigger select: "From spreadsheet"; and for function to run select "importData" (or the name of your function).
I'm trying to create a macro to have a box prompt to confirm the action like "Do you want to clear the sheet?" with a yes or no question.
If YES, to delete the given cells
If NO, do nothing.
The YES condition works. But I can't seem to make the NO work. Even if I click on NO, it still executes the clear command. What am I doing wrong?
I'm not well versed in coding. I simply rely in Google. I have tried to change the "else" to "End if" and also tried "then" but none works. I'm not sure how to stop the code from running.
function myFunction() {
var sh1=SpreadsheetApp.getActive();
var sheet1=sh1.getSheetByName("Sheet1")
var sh=SpreadsheetApp.getUi();
var response=sh.alert("Clear?",sh.ButtonSet.YES_NO)
if(response.YES);{
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
sheet.getRange('b1:b21').clearContent();
sheet.getRange('C13:C18').clearContent();
}
Else {}
}
Even clicking NO from the prompt it still executes the clearContent command.
You're not using response correctly. It contains a UI.Button.YES or UI.Button.NO value. The correct test would be
function myFunction() {
var sh1 = SpreadsheetApp.getActive();
var sheet1 = sh1.getSheetByName("Sheet1")
var sh = SpreadsheetApp.getUi();
var response = sh.alert("Clear?", sh.ButtonSet.YES_NO)
if(response == UI.Button.YES) {
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
sheet.getRange('b1:b21').clearContent();
sheet.getRange('C13:C18').clearContent();
}
}
For more information, see the documentation for UI.Alert
(You also had a misplaced ; in your original code after the if(), with if(response.YES);{, which my answer removes as well.)
I'm trying to program a spreadsheet so that whenever I add a new entry to it, it copies the data from that cell into another spreadsheet. Here's my code (that doesn't seem to work):
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var target = SpreadsheetApp.openById("*************");
var target_sheet = target.getSheetByName("Dashboard");
var last_row = target_sheet.getLastRow();
target_sheet.insertRowAfter(last_row);
var target_range = target_sheet.getRange("A"+(last_row+1)+":G"+(last_row+1));
e.range.copyTo(target_range);
}
Any ideas what I'm doing wrong?
There are two types of triggers in Apps Scripts - simple triggers and installable triggers.
onEdit() is an example of a simple trigger (the name is implicit). And there are limits to what you can do inside a simple trigger. And that includes opening another spreadsheet.
So, coming to the solution.
Rename your function to something else, say onEdit1() . And set up an installable trigger manually and set it to run each time the spreadsheet is edited.
Hint: Use Resources --> Current project's triggers from the script editor
I'm a beginner at this, so this error might be on account of faulty coding, but this is why I'm here! lol.
I have written a Sheets function that (in theory) would go through all the files in a particular folder and find all the instances of a particular word and then return the number of instances of that word. Here is the code I wrote:
function commentCount(name) {
var files = DocsList.getFolderById('FOLDER ID GOES HERE').getFiles();
var counter = 0;
for(i in files) {
var doc = DocumentApp.openById(files[i].getId());
var text = doc.getText();
text = text.replace( /\./g, "" );
var textArray = text.split(" ");
for(w in textArray){
if(textArray[w] == name){
counter++;
}
}
}
return counter;
}
When I call the function in Sheets, an error reads - Error: You do not have permission to call getFolderById (line 3, file "commentCount")
I've tried using getFolder("Folder name"), and getFolder(path), and the same error occurs. It seems that the DocList functions are not working correctly.
Not sure what the issue is because everything seems fine when I debug the function.
I won't be able to figure out if the rest of my code is sound until I figure out this error. Any help would be greatly appreciated!
Phil Bozak clarified that formulas in Spreadsheets that call scripts functions do not get full permissions, which makes it impossible to use getFolderByID function in this case.