Pasting a value into a new cell each time another is updated? - google-apps-script

I'm hoping to have 2 cells that update their value every week. Each time these cells get their values updated I would like them to also be printed onto another two cells on a different sheet. Each week these cells that they are printed onto moving down by one. For example Week 1, the two cells are printed in A1 and B1. Week 2 they are printed in A2 and B2, and so on.
I know how to do this in Excel but no idea how I can change that over to Google Sheets / Scripts.

Assumptions:
Your new inputs are in input!A1 and input!B1; and
Your outputs will by in output!A and output!B.
You can write a script by clicking on Tools on the menu and entering Script Editor.
Then write this function:
function writeData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var input = ss.getSheetByName("input")
.getRange(1, 1, 1, 2)
.getValues();
var outputSheet = ss.getSheetByName("output");
var numRows = outputSheet.getLastRow();
outputSheet.getRange(numRows + 1, 1)
.setValue(input[0][0]);
outputSheet.getRange(numRows + 1, 2)
.setValue(input[0][1]);
}
Next, set up a trigger. Within Script Editor, under Resources, select Current project's triggers and then set up your trigger. If you want it to run weekly, use a time-driven trigger. You can also set a spreadsheet-driven trigger to run on every edit. Save everything.
If you don't want to use automatic triggers, you can execute the writeData() function by adding an item on the menu bar of the spreadsheet:
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
menuEntries.push({name: "Write data", functionName: "writeData"});
ss.addMenu("Custom functions", menuEntries);
}
Save, and if you refresh the spreadsheet you'll see a new item on the menu bar.

Related

Move row on spreadsheet using scripts and have a button on the sheet to activate it?

I have this spreadsheet where essentially I would like all actioned lines to be moved to an archive tab once actioned. As a lot of people will be using it I would ideally like a button at the top which would activate the script? I've tried a few things I've found on the web but nothing seems to fit in with what I need exactly.
I'm not sure whether it would work best to have a tickbox in column J which would be the ones to move or if having a "Complete" status in Column F would work better?
I've attached a dummy document to work on, any help would be greatly appreciated!!
https://docs.google.com/spreadsheets/d/1CoBzUxme8Rrwy6XfFy1m0BzwhWtqR-KyGDMGQq2F478/edit?usp=sharing
EDIT - have now updated with a script however it doesn't seem to work for all users, is there some way to change the trigger from upon an edit to pushing a button on the spreadsheet or something like that?
Error message when trying to run script - think this may be because it is triggered on edit?
Option 1: Installable Trigger
You can create an onEdit Installable Trigger that will check if the value of column F is changed to "Completed". onEdit Trigger will automatically execute your script when a user changes a value in a spreadsheet.
Try this:
Rename the function onEdit(e) from previous answer with moveRow(e) to avoid double execution of triggers.
function moveRow(e) {
var range = e.range;
var row = range.getRow();
var column = range.getColumn();
var value = e.value;
if(range.getSheet().getSheetName() == "Log Sheet" && row > 1 && column == 6 && value == "Completed"){
var archiveSheet = e.source.getSheetByName("ARCHIVE DO NOT USE");
var lastRow = archiveSheet.getLastRow();
var sheet = e.range.getSheet();
sheet.getRange(row, 1, 1, 10).moveTo(archiveSheet.getRange(lastRow + 1, 1));
sheet.deleteRow(row);
}
}
How to create Installable Trigger?
Open your Apps Script project.
At the left, click Triggers alarm.
At the bottom right, click Add Trigger.
Select and configure the type of trigger you want to create.
Click Save.
Your trigger setup should look like this:
Note: To make this script works, the user must update the value of a cell to "Completed" in the Status column of the Log Sheet. This was also tested using multiple users editing the Sheet. Also, Installable triggers always run under the account of the person who created them. For example, if you create an installable open trigger, it runs when your colleague opens the document (if your colleague has edit access), but it runs as your account.
Option 2: Button
In your script editor, paste the following code.
function moveRows(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Log Sheet");
var range = sheet.getRange(2, 1, sheet.getLastRow() - 1, 10);
var data = range.getValues();
var archiveSheet = ss.getSheetByName("ARCHIVE DO NOT USE");
for(var i = data.length-1; i >= 0; i--){
if(data[i][5] == "Completed"){
var lastRow = archiveSheet.getLastRow();
sheet.getRange(i+2, 1, 1, 10).moveTo(archiveSheet.getRange(lastRow + 1, 1));
sheet.deleteRow(i+2);
};
};
Then assign script to a button in Google Sheets:
Add a button via the Insert > Drawing menu > Add the desired button shape and save.
Right click to the button > click the 3 vertical dot > click Assign Script > type moveRows.
Click the button to execute the script
Output:
Example:
Before changing Status to Completed:
Log Sheet:
Archive:
After changing Status to Completed:
Log Sheet:
Archive:
References:
Event Object
Class Sheet
Class Range
Installable Trigger

Function for saving range of data in google sheets sometimes copies blank cells, how to get it to pause and wait for source data to refresh?

rephrase to clarify it's not a duplicate of existing question: Setvalue executes before the scripts that produce the data has finished pulling in the data. i.e. setvalue pastes blank cells because the source cells haven't calculated the data
I have the following function for copying data and appending to the bottom of the sheet. I combine this function with a time driven project trigger into order to save this data every day.
However the source data that I wish to save from range "28SEP18!A1:K49" sometimes hasn't refreshed so the function just copies and pastes blank cells.
Is there something I can add to my function to get it to wait for all the formulas and functions in the source data to refresh before it copies and pastes the data? i.e. before setvalues()
function saveData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var optiondata = sheet.getRange("28SEP18!A1:K49").getValues();
var lastRow = sheet.getLastRow()
sheet.getRange(lastRow + 1, 1, 49, 11)
.setValues(optiondata);
}

Create Script to clear cell every time sheet is opened

I am very new to scrips on google sheets and have been having no success
I have been trying to create a script that clears the content of 1 cell every time the sheet is opened but have had no luck, i have looked up how to do it but every example i try just errors. I need cell A2 to be clear every time someone new opens the sheet
https://docs.google.com/spreadsheets/d/1vvq7k_sdP2CBLZXzkpfxGvcmoTPdxC0NaH3I7-8wAoo/edit?usp=sharing
After you create the function in the script editor, Goto "Edit->Current Project's Triggers" and click on "add one now". Set the function that you want and under Events, choose "From SpreadSheet". On the next drop down list, choose "On Open"
I have create a function that clear the content of cell "A2" just to show how it works.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange("A2");
range.clearContent();
}
Please Note that after you open the sheet, it will take upto 5 seconds to clear the cell.

Google New Sheets Protection Issues

I am experiencing some strange problems with protection in Google New Sheets. I have created a demo of what I am experiencing. The URL to the sheet is:
https://docs.google.com/spreadsheets/d/1IbAiqU6oN48Ql_wM3TeRl9TqG6DFsBKtc86jElv0Kbo/edit?usp=sharing
I have protected the sheet for edit by owner only except for rows 5 to 7 using the 'Sheet protect except certain cells' method under 'Data - Protected sheets and ranges...'
I also have a simple User Function menu which is invoked on open wich contains a simple Google Apps Script to insert a given number of rows (code below).
The following is happening when another user accesses the sheet:
The basic protection seems to be working. The user can only edit the rows 5 to 7.
The insert row function (selected under User Functions menu) produces a 'Service error: Spreadsheets'.
If the user tries to delete any of the 3 unprotected rows then the message 'Can't save your changes. Copy any recent changes, then revert to an earlier version...' appears in a red box at the top of the screen. Clicking on the 'revert to an earlier version...' link reverses the delete.
If I remove all protection then everything is 100% for the user - insert rows funtion - delete rows etc.
The functionality I have reproduced here is very similar to what I have been using in the old sheets for years without any problems (i.e. protecting certain areas of the spreadsheet from edit by shared users).
I must add, I posted the issue about the insert row function not working a couple of days ago.
Here's my function code:
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [{name: "Insert Rows", functionName: "insertRows"}];
ss.addMenu("User Functions", menuEntries);
}
function insertRows() {
var numRows = Browser.inputBox('Insert Rows', 'Enter the number of rows to insert', Browser.Buttons.OK);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var curs = sheet.getActiveCell();
var cursRow = curs.getRow();
var cursLastCol = sheet.getLastColumn();
sheet.insertRowsAfter(cursRow, numRows);
var source_range = sheet.getRange(cursRow,1,1,cursLastCol);
var target_range = sheet.getRange(cursRow+1,1,numRows);
source_range.copyTo(target_range);
Browser.msgBox('Insert Rows', +numRows+' rows successfully inserted.', Browser.Buttons.OK);
}
Can anyone help with this. I have some large customers I have built complex online spreadsheets for that now don't function correctly under New Sheets.
Try setting up a project trigger for onOpen() rather than using the simple onOpen(). Then it runs with your privileges rather than those of the current user. Just click on Resources/Current Project Triggers and add a new trigger.

Google Sheets script to copy/paste from one sheet to another

Could someone help me with creating a script that does the following:
Function: Upon adding a new sheet to my already existing workbook, I would like it to copy Column "E" from Sheet 1 and (Paste Special > Conditional formatting only) to the newly introduced Sheet "X"
Where can I learn more on how to write code? I have never used Stackoverflow by the way someone just recommended me to come here. I believe I just answered my own question somehow on the post, which I am sure was wrong to do but I couldn't comment on an already existing answer without exceeding the limit.
// Adds custom menu
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('CustomMenu').addItem('Copy format', 'copyFormat') //Add function to menu.'GIVE NAME HERE', 'functionName'
.addToUi();
}
function copyFormat() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh1 = ss.getSheets()[0]; //Gets the first sheet of the workbook. Can use ss.getSheetByName('Name of sheet here'); If it is not the first sheet
var activeSh = ss.getActiveSheet(); //Get the active sheet, you should be on the sheet just added
var rowEnd = activeSh.getLastRow(); //Last row of active sheet
sh1.getRange("E1:E").copyFormatToRange(activeSh, 5, 5, 1, rowEnd); //Copy format, including conditional, to column E of active sheet
}
This just adds a button that allows you to select a cell and give it the same conditions has in the original sheet.
Example: Sheet 1: Column E1:E100 has a given condition.. which needs to apply in the exact same way to any new incoming sheets since they all come in the same format. Right now its at a point of which when a new sheet arrives in the workbook: I can enter the new sheet > Select the cell which requires the conditions > Select the custom menu > Cell gets conditioned. So the next step would be automate the process I just mentioned since there is several sheets added daily to the workbook.