Google sheet script - copy & plase a cell value - google-apps-script

I need a simple script for Google sheet which will automatically daily will do simple task - copy a 3 cell's values and paste into another 3 cells as a plain text.
Is anyone can help me?

Assuming your spreadsheet page is named PAGE 1 and you want to copy the data from A1 to A3 and paste it into the same PAGE 1 in cells B1 through B3, this is the script to use:
function MyFunction() {
var ss = SpreadsheetApp.getActive();
ss.getRange('Page 1!A1:A3').copyTo(ss.getRange('Page 1!B1:B3'), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
}

To achieve what you want to do. I recommend you to use the Time-driven triggers, which help you to trigger events every "n" time (mins, hours, days). Follow these steps to configure the Time-driven triggers.
1) Go to your Apps Script project
2) Click Edit->Current project's triggers
3) Click "+ Add Trigger"
4) Select :
Choose which function to run -> setTimeTrigger
Select event source->Time-driven
Select type of time based trigger->Day timer
Select time of day->[Hour you want]
5) Click Save
6) Use this code in your Apps Script project:
// Name this function as "setTimeTrigger"
function setTimeTrigger(){
// Get first sheet in the active Spreadsheet
var ss = SpreadsheetApp.getActive().getSheets()[0];
// Parameters you set
var sourceVals = "A1:A3";
var destination = "B1:B3";
// Copy and paste the values where you want to
ss.getRange(sourceVals).copyTo(ss.getRange(destination));
}
Docs
You can learn more about triggers and Spreadsheet Class in the following docs:
Installable Triggers
Class Spreadsheet

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

Creating a backup of data entered into a sheet via Google App Scripts

I have a spreadsheet where users can enter data and then execute a function when clicking on a button. When the button is clicked it logs the time and entered data in a new row on another sheet in that spreadsheet.
To make sure that sheet is not accidentally edited by the users I want to create a non-shared backup of that data.
I import the range to another spreadsheet, but just importing the range means that if the original sheet is edited/erased that data will also be edited/erased, so I wrote the following script to log the changes as they come in.
function onEdit(event){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var incomingSheet = ss.getSheetByName('Incoming');
var lastRow = incomingSheet.getLastRow();
var incomingData = incomingSheet.getRange(lastRow,1,1,7);
var permanentSheet = ss.getSheetByName('PermanentLog')
var newdataRow = permanentSheet.getLastRow();
incomingData.copyTo(permanentSheet.getRange(newdataRow+1,1));
}
This works when Run from the Apps Script Editor, however, when I enter new data and click the button on the original spreadsheet, it logs the data to the log sheet there, and the range is imported to the 'Incoming' sheet of the new Spreadsheet, but the data is not copied over to the 'Permanent Log' sheet (unless I Run it manually from within the Apps Script Editor). It also works if I remove the ImportRange function from the first sheet and then just manually enter data in on the 'Incoming' sheet.
So does this mean new rows from an Imported Range do not trigger onEdit? What would be the solution? I don't want to run this on a timed trigger, I want to permanently capture each new row of data as it comes in.
Also, am I overlooking a more elegant and simple solution to this whole problem?
Thank you for your time.
This function will copy the data to a new Spreadsheet whenever you edit column 7 which I assume is the last column in your data. It only does it for the sheets that you specify in the names array. Note: you cannot run this from the script editor without getting an error unless you provide the event object which replaces the e. I used an installable onEdit trigger.
The function also appends a timestamp and a row number to the beginning of the archive data row
function onMyEdit(e) {
e.source.toast('entry');//just a toast showing that the function is working for debug purposes
const sh = e.range.getSheet();//active sheet name
const names = ['Sheet1', 'Sheet2'];//sheetname this function operates in
if (~names.indexOf(sh.getName()) && e.range.columnStart == 7) {
const ass = SpreadsheetApp.openById('ssid');//archive spreadsheet
const ash = ass.getSheetByName('PermanentLog');//archive sheet
let row = sh.getRange(e.range.rowStart, 1, 1, 7).getValues()[0];
let ts = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyy/MM/dd HH:mm:ss");//timestamp
row.unshift(ts, e.range.rowStart);//add timestamp and row number to beginning
Logger.log(row);//logs the row for debug purposes
ash.appendRow(row);//appends row to bottom of data with ts and row
}
Logger.log(JSON.stringify(e));
}
Restrictions
Script executions and API requests do not cause triggers to run. For example, calling Range.setValue() to edit a cell does not cause the spreadsheet's onEdit trigger to run.
https://developers.google.com/apps-script/guides/triggers
So yeah, as far as I understand you it can't be done that way.

Google Sheets new sheet templating

I'd like every new added sheet (when user presses "+" in lower left corner) to contain some templated information (headers for table). I'm not talking about whole document template, I'd like to make it only for one document. Now for that purpose I use special sheet with template and just duplicate it.
Answer:
While you can't create 'template' sheets to copy from, you can use the onChange() trigger to insert the template to the new sheet as soon as it has been added.
More Information:
As per the documentation on Event Objects, there exists a changeType value in the event object that is generated when the structure of a Spreadsheet is changed:
changeType The type of change (EDIT, INSERT_ROW, INSERT_COLUMN, REMOVE_ROW, REMOVE_COLUMN, INSERT_GRID, REMOVE_GRID, FORMAT, or OTHER).
The INSERT_GRID value can be used to execute some code when a new sheet is added.
Code Example:
For this example, I will assume that you have a template sheet from which you can copy the templated information from, and for this example I will assume it is called Template.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const templateSheet = ss.getSheetByName("Template");
var sheets = ss.getSheets();
function saveSheetNames() {
var names = sheets.map(x => x.getName());
PropertiesService.getScriptProperties().setProperty("sheets", names.toString())
}
function onChange(e) {
if (e.changeType == "INSERT_GRID") {
var rangeToCopy = templateSheet.getDataRange();
var oldSheets = PropertiesService.getScriptProperties().getProperty("sheets").split(",");
var names = sheets.map(x => x.getName());
names.forEach(function(name) {
if (oldSheets.indexOf(name) == -1) {
rangeToCopy.copyTo(ss.getSheetByName(name).getRange(1, 1, rangeToCopy.getNumRows(), rangeToCopy.getNumColumns()));
PropertiesService.getScriptProperties().setProperty("sheets", names.toString());
}
});
}
}
Set up:
The first thing you need to do, after inserting this script into your script editor, is run the function saveSheetNames(). This stores the current sheet names to the script's properties so that when you add a new sheet later, the new sheet can be determined.
Next, you will need to set up an onChange installable trigger.
Follow the Edit > Current project's triggers menu item, and you will have a new page open in the G Suite Developer Hub. Click the + Add Trigger button in the bottom right and set up the trigger settings as follows:
Choose which function to run: onChange
Choose which deployment should run: Head
Select event source: From spreadsheet
Select event type: On change
And press save.
Now, when you add a new sheet with the default + button in the UI, the onChange() function will run, and copy the template sheet to the new sheet. It might take a couple of seconds, but it will be done automatically.
References:
Event Objects | Apps Script | Google Developers

onChange to Run ONLY if A3 has data - Google Apps Script / Google Sheets

I am trying to get this script to only run if is sees data in A3. the data is coming to this sheet from another sheet. I tried the onChange but it wouldnt trigger when the new data arrived in "Top Up Needed". add the onchange to the project triggers but still doesnt run script.
function TopUpNeeded() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('TOP UP NEEDED'), true);
var sheet = spreadsheet.getSheetByName('TOP UP NEEDED');
sheet.getRange('J3').activate().setFormula('=QUERY({\'SKU & Qty\'!$A$3:$C},"SELECT * WHERE Col1 MATCHES \'" & JOIN("|",FILTER(I2:I, NOT(ISBLANK(I2:I)))) & "\' ")');
}
also tried this code above my code,but no good.
function onChange() {
var sheet = SpreadsheetApp.getActive();
ScriptApp.newTrigger("TopUpNeeded")
.forSpreadsheet(sheet)
.onChange()
.create();
}
Thanks In Advance
onChange does not run if changes were not made by a human, see restrictions
The exception is if the data is being updated with the cell formula IMPORTRANGE
You can paste into cell "A3" of sheet "Top Up Needed" the formula
IMPORTRANGE(spreadsheet_url, range_string)
specifying the spreadsheet and range that is expected to populate the cell content.
In this case your first function will fire on onChange trigger each time the content of A3 updates.

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.