How to move individual cells in Google Sheets - javascript

Would anyone happen to know of a quick way to move the contents of one cell into another in Google Sheets. All of the cells will remain static, so I don't have to worry about additional rows or columns being added to my sheet.
I have tried to getCell(), just like the getLastColumn() function, but getCell() doesn't seem to be a valid function.
Code that I currently have:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Sheet4" && r.getColumn() == 15 && r.getValue() == "GO" ) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Sheet4");
ss.getSheets()[1].getRange("A48:A48").copyTo(ss.getSheets()[2].getRange("A3:A3"),{contentsOnly:true});

Something like this should work:
function CopyTo() {
var ss = SpreadsheetApp.getActive().getSheetByName('Sheet4');
var s = ss.getRange('H48');
s.copyTo(ss.getRange('D13'), {contentsOnly: true});
s.clear ();
}

Var source = ss.getRange ("Sheet4!H48:H48");
var targetSheet = ss.getSheetByName("Sheet4");
var targetRange = targetSheet.getRange("D13:D13");
source.copyTo(targetRange, {contentsOnly: true});
source.clear ();

Related

I want to apply script to multiple subsheet in one Sheet

I followed youtube instruction and copied this script
var SHEET_NAME = 'Sheet1';
var DATETIME_HEADER = '입력일시';
function getDatetimeCol(){
var headers = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME).getDataRange().getValues().shift();
var colindex = headers.indexOf(DATETIME_HEADER);
return colindex+1;
}
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSheet();
var cell = ss.getActiveCell();
var datecell = ss.getRange(cell.getRowIndex(), getDatetimeCol());
if (ss.getName() == SHEET_NAME && cell.getColumn() == 1 && !cell.isBlank() && datecell.isBlank()) {
datecell.setValue(new Date()).setNumberFormat("yyyy-MM-dd hh:mm:ss");
}
};
I want to apply this script to all subsheet in the file.
so I tried to add more sheet name like
var SHEET_NAME = 'Sheet1'; => var SHEET_NAME = ['Sheet1','Sheet2','Sheet3',]
or
var SHEET_NAME = 'Sheet1';
var SHEET_NAME = 'Sheet2';
var SHEET_NAME = 'Sheet3';
and they didn' work.
I don't have any, even rudimentary knowledge to this area, could you teach me how can I apply this script on whole subsheet, please?
I have changed your code slightly according to the task at hand:
SHEET_NAMES = ['Sheet1','Sheet2','Sheet3'];
DATETIME_HEADER = '입력일시';
function onEdit(e) {
let range = e.range,
sheet = range.getSheet();
if (SHEET_NAMES.includes(sheet.getName()) && range.rowStart > 1 && range.columnStart == 1 && !e.value == '') {
let colindex = sheet.getDataRange().getValues().shift().indexOf(DATETIME_HEADER)+1,
datecell = sheet.getRange(range.rowStart,colindex);
if (datecell.isBlank()) datecell.setValue(new Date()).setNumberFormat("yyyy-MM-dd hh:mm:ss");
}
};
I don't think it's a good idea to run getDatetimeCol() every time you make a change in the table - it's better to do it only when the changes occur in the right sheets and cells

Copy values to next column(if blank) in the same row. If not blank, copy to the second column(if blank) in same row. Repeat

Disclaimer: Im very new to google scripts. I jumbled together this code with mixed success.
When I run the script, it works fine with the first two attempts. Then it doesnt work after that because column Q now has values in other cells within the column and the script is technically correct but not running at intended. I need to ignore column Q cells that are not blank and still run the script to copy P values to the other cells in column Q.
Also, when column Q with in the same row is not blank, I need to copy the value from column P to column R (if blank). Rinse and Repeat script...
function copyVals () {
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var source = ss.getRange ("Sheet1!P2:P");
var destSheet = ss.getSheetByName("Sheet1");
var destRange = destSheet.getRange('Q2:Q')
var destRange2 = destSheet.getRange('R2:R')
if (destRange.isBlank()) {
source.copyTo (destRange, {contentsOnly: true});
source.clear ();
}
if (destRange2.isBlank()) {
source.copyTo (destRange2, {contentsOnly: true});
source.clear ();
}
}
You need to do the blank check for each cell separately
However, if you do it wiht the Apps Script method isBlank() - this will make your code a bit slow.
I suggest you to
retreive the existing values both in the source and destination ranges with getValues
check for each of the destinations values either those are empty and replace the empty values through source values
assign the modified values back to the sheet with setValues
Sample code:
function copyVals () {
var ss = SpreadsheetApp.getActiveSpreadsheet ()
var sheet = ss.getSheetByName("Sheet1")
var lastRow = sheet.getLastRow()
var source = sheet.getRange ("P2:P" + lastRow)
var destSheet = sheet
var destRange = destSheet.getRange('Q2:Q' + lastRow)
var destRange2 = destSheet.getRange('R2:R' + lastRow)
var sourceValues = source.getValues().flat()
var destValues = destRange.getValues()
var dest2Values = destRange2.getValues()
sourceValues.forEach(function(value, i){
console.log("i" + i)
if (destValues[i][0] == "") {
destValues[i][0] = value
}
if (dest2Values[i][0] == "") {
dest2Values[i][0] = value
}
})
destRange.setValues(destValues)
destRange2.setValues(dest2Values)
source.clear ();
}
UPDATE
If you want to copy to column Q and R alternately, you can use script properties to save the run count of the script and execute different code blocks for odd and even number.
Sample:
function copyVals () {
var ss = SpreadsheetApp.getActiveSpreadsheet ()
var sheet = ss.getSheetByName("Sheet1")
var lastRow = sheet.getLastRow()
var source = sheet.getRange ("P2:P" + lastRow)
var destSheet = sheet
var destRange = destSheet.getRange('Q2:Q' + lastRow)
var destRange2 = destSheet.getRange('R2:R' + lastRow)
var sourceValues = source.getValues().flat()
var destValues = destRange.getValues()
var dest2Values = destRange2.getValues()
var scriptProperties = PropertiesService.getScriptProperties()
var myProperty = scriptProperties.getProperty('timesCalled')
if (!myProperty){
myProperty = "1"
}
myProperty = JSON.parse(myProperty)
var isOdd = myProperty % 2
if(isOdd){
sourceValues.forEach(function(value, i){
console.log("i" + i)
if (destValues[i][0] == "") {
destValues[i][0] = value
}
})
destRange.setValues(destValues)
} else{
sourceValues.forEach(function(value, i){
if (dest2Values[i][0] == "") {
dest2Values[i][0] = value
}
})
destRange2.setValues(dest2Values)
}
source.clear ()
myProperty++
scriptProperties.setProperty('timesCalled', JSON.stringify(myProperty))
}

How to select a entire row and highlight in different color in google sheet using script editor?

I want to use code below to find blank values in column 6 and highlight the entire row in yellow:
function myFunction() {
var app = SpreadsheetApp;
var sheet = app.getActiveSpreadsheet();
var ActiveSheet = sheet.getActiveSheet();
for (i=2;i<=ActiveSheet.getLastRow();i++){
var day = ActiveSheet.getRange(i, 6).getValue();
if (day == ''){
ActiveSheet.getRange('i').setBackground('#ffff00');
}
}
}
However this doesn't work. Do anybody know how to select row "i" and highlight it?
Thank you so much!
Your code just needs a slight modification:
function myFunction() {
var app = SpreadsheetApp;
var sheet = app.getActiveSpreadsheet();
var ActiveSheet = sheet.getActiveSheet();
for (i=2;i<=ActiveSheet.getLastRow();i++){
var day = ActiveSheet.getRange(i, 6).getValue();
if (day == ''){
ActiveSheet.getRange(i,1,1,ActiveSheet.getLastColumn()).setBackground('#ffff00');
}
}
}
Explanation:
The range should be defined as
getRange(row, column, numRows, numColumns)

Trouble creating events in Google Agenda from Google Sheets with a script

I created a script in a Google Sheet to create events in Google Agenda, in order to study.
My goal is to create many events like this : if i study on D0, the first event must be at D+3, then D+10 , D+30, D+60.
I get many problems :
the script write "AJOUTE" in each box of the column (which means in french that the events are added to Agenda) , even if they are not completed with dates (I want to update for each chapter when it's done, and I do not do a whole chapter the same day!)
the script doesn't care if the events are already created, so i get multiple events for the same thing...
My script is the following :
var EVENT_IMPORTED = "AJOUTE";
var ss = SpreadsheetApp.getActiveSpreadsheet();
function onOpen() {
var menuEntries = [{name: "Ajouter les événements à l'agenda", functionName: "importCalendar"}];
ss.addMenu("Agenda", menuEntries);
}
function importCalendar() {
var sheet = SpreadsheetApp.getActiveSheet();
var startcolumn = 1
var numcolumns = 30
var dataRange = sheet.getRange(startcolumn, 1, numcolumns, 6)
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var column = data[i];
var titre = column[1];
var DateJ3 = column[2];
var DateJ10 = column[3];
var DateJ30 = column[4];
var DateJ60 = column[5];
var eventImported = column[6];
var setupInfo = ss.getSheetByName("agenda");
var calendarName = setupInfo.getRange("A1").getValue();
if (eventImported != EVENT_IMPORTED && titre != "") {
var cal = CalendarApp.openByName(calendarName);
cal.createAllDayEvent(titre, new Date(DateJ3));
cal.createAllDayEvent(titre, new Date(DateJ10));
cal.createAllDayEvent(titre, new Date(DateJ30));
cal.createAllDayEvent(titre, new Date(DateJ60));
sheet.getRange(startcolumn + i, 7).setValue(EVENT_IMPORTED);
SpreadsheetApp.flush();
}
}
}
Thank you in advance, i'm despair, i searched for hours but found nothing to help...

Prevent google script from duplicating protected ranges

I have this script that I am using to copy over (convert formulas to values) and then protect the range when a user enters a value "Burned" in to a certain cell (A2, A6, etc) at the end of each month (can't make it triggered by date as users may be completing data entry on slightly different dates). The spreadsheet needs users to lock the data every month, so the script is set up for converting and protecting data each month as the user enters "Burned" into each month. The script is working well to convert formulas to values and it is also working to protect the range. However, every time I edit the sheet, it creates duplicate protected ranges so I end up with multiple protected ranges called January Burned, February Burned, etc. Is there any way to prevent the script from duplicating the protected ranges? Any help is greatly appreciated.
function onEdit(e)
//January
{
var ss = SpreadsheetApp.getActive();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Caseload");
var valueToCheckA = sheet.getRange("A2").getValue();
var rangeA = sheet.getRange("A2:AZ5");
{
if(valueToCheckA == "Burned")
{
rangeA.copyTo(rangeA, {contentsOnly:true});
var protection = rangeA.protect().setWarningOnly(true).setDescription('January Burned');
}
}
}
//February
{
var ss = SpreadsheetApp.getActive();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Caseload");
var valueToCheckB = sheet.getRange("A6").getValue();
var rangeB = sheet.getRange("A6:AZ9");
{
if(valueToCheckB == "Burned")
{
rangeB.copyTo(rangeB, {contentsOnly:true});
var protection = rangeB.protect().setWarningOnly(true).setDescription('February Burned');
}
}
}
//March
{
var ss = SpreadsheetApp.getActive();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Caseload");
var valueToCheckC = sheet.getRange("A10").getValue();
var rangeC = sheet.getRange("A10:AZ13");
{
if(valueToCheckC == "Burned")
{
rangeC.copyTo(rangeC, {contentsOnly:true});
var protection = rangeC.protect().setWarningOnly(true).setDescription('March Burned');
}
}
}
You had some weird things going on in your code. So I'd reformat it like this:
//January
function onEdit(e)
{
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Caseload");
var valueToCheckA = sheet.getRange("A2").getValue();
var rangeA = sheet.getRange("A2:AZ5");
if(valueToCheckA == "Burned")
{
rangeA.copyTo(rangeA, {contentsOnly:true});
var protection = rangeA.protect().setWarningOnly(true).setDescription('January Burned');
}
}
Try it again and let me know if anything has changed.
After looking over you code again. I grabbed entire code and took a close look at it and I made an interesting discovery. Several of your sections of code are not within the function onEdit so they run every time you access your scripts even when onEdit is not called. In fact, when I think about it, I believe you just run this once a month so why not just put it in a separate function and call once a month and forget the onEdit trigger.
function onEdit(e)
{
var ss = SpreadsheetApp.getActive();//January
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Caseload");
var valueToCheckA = sheet.getRange("A2").getValue();
var rangeA = sheet.getRange("A2:AZ5");
if(valueToCheckA == "Burned")
{
rangeA.copyTo(rangeA, {contentsOnly:true});
var protection = rangeA.protect().setWarningOnly(true).setDescription('January Burned');
}
}
// This section is not in the onEdit function so it's run every time you come to this page
var ss = SpreadsheetApp.getActive();//February
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Caseload");
var valueToCheckB = sheet.getRange("A6").getValue();
var rangeB = sheet.getRange("A6:AZ9");
if(valueToCheckB == "Burned")
{
rangeB.copyTo(rangeB, {contentsOnly:true});
var protection = rangeB.protect().setWarningOnly(true).setDescription('February Burned');
}
// This section is not in the onEdit function so it's run every time you come to this page
var ss = SpreadsheetApp.getActive();//March
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Caseload");
var valueToCheckC = sheet.getRange("A10").getValue();
var rangeC = sheet.getRange("A10:AZ13");
if(valueToCheckC == "Burned")
{
rangeC.copyTo(rangeC, {contentsOnly:true});
var protection = rangeC.protect().setWarningOnly(true).setDescription('March Burned');
}
So here's a rough start of a function that could do the job for you and you can just run it once a month. I haven't tested it and it most likely has some mistakes in it so check it out.
function monthlyBurn()
{
var ui = SpreadsheetApp.getUi();
var response = ui.prompt('Enter checkCell,protectRange,description all separate by commas', ui.ButtonSet.OK);
var t = response.getResponseText().split(',');
if(t.length !== 3)
{
ui.alert('Invalid input. Your missing a parameter')
return;
}
var ss = SpreadsheetApp.getActive();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Caseload");
var valueToCheckC = sheet.getRange(t[0]).getValue();
var rangeC = sheet.getRange(t[1]);
if(valueToCheckC == "Burned")
{
rangeC.copyTo(rangeC, {contentsOnly:true});
var protection = rangeC.protect().setWarningOnly(true).setDescription(t[2]);
}
}
Thanks for all the input and assistance, I have spoken with a colleague who was able to write this script which is working great.
function onEdit(e)
{
var sheet = e.range.getSheet();
if (sheet.getName() != "Caseload" || e.value != "Burned") return;
var moment = Moment.load();
var date = moment.utc(e.range.offset(0, 1).getValue());
if (!date.isValid()) return;
var month = date.format('MMMM');
var range = sheet.getRange(e.range.getRow(), e.range.getColumn(), 4, 26*2); // 4 rows and 26*2 columns (AZ)
range.copyTo(range, {contentsOnly: true});
range.protect().setWarningOnly(true).setDescription(month + ' Burned');

Categories

Resources