I have a script to copy values from one sheet to another that works perfectly except I only want to clear the values in the source sheet, and leave the formula in place in cells E3, I3 and J3
function addLeavers()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getRange("Add Leaver!A3:AM3");
var destSheet = ss.getSheetByName("Leavers");
destSheet.appendRow(source.getValues()[0]);
source.clear();
}
You want to clear the range of source.
You want to clear only values of the range.
You don't want to clear the formulas of the range..
If my understanding is correct, how about this modification? Please think of this as just one of several answers.
In this modification, the formulas are retrieve, and the range is clear using clear() or clearContent(). Then, the retrieved formulas are put to the range.
From:
source.clear();
To:
var formulas = source.getFormulas();
source.clear(): // or source.clearContent();
source.setFormulas(formulas);
References:
clearContent()
getFormulas()
setFormulas()
If I misunderstood your question and this was not the result you want, I apologize.
Related
I have been trying to add a row which keep the formulas.
But when i add any row it always empty.
I could not found a way by searching on google.
I have attached below example sheet. Any help would be greatly appreciate
https://docs.google.com/spreadsheets/d/1HiOrz1KAuV1nN9a2IlwQgv3aWrGNKFaKHq2a8JZw3gI/edit#gid=0
Explanation:
Your goal is to copy the formulas to the newly inserted row upon inserting a new row.
You can use an onChange which has a property INSERT_ROW and
make sure you activate some code when you insert a new row.
The following script will copy the content and formulas from the above row of the one which was inserted to the newly inserted row upon inserting a new row.
Solution:
Add both code snippets below to the script editor:
function myFunction(e) {
const sh = SpreadsheetApp.getActiveSheet();
if(e.changeType === 'INSERT_ROW') {
const row = sh.getActiveRange().getRow();
var fromRng = sh.getRange(row-1,1,1,sh.getLastColumn());
var toRng = sh.getRange(row,1,1,sh.getLastColumn());
fromRng.copyTo(toRng);
}
}
and execute this function createTrigger only and once to create the onChange trigger:
function createTrigger(){
var sheet = SpreadsheetApp.getActive();
ScriptApp.newTrigger("myFunction")
.forSpreadsheet(sheet)
.onChange()
.create();
}
Illustration:
Limitation:
The disadvantage of this approach is that is copies both values and formulas, but it does not seem to matter in your case since you have only formulas as of now. If you want to put only formulas you need to use setFormulaR1C1 but since you have cells with no formulas, you need to make sure that you copy formulas, otherwise you will get errors.
This should let you copy your last row, including data and formula, into its next row.
function addRow() {
var sh = SpreadsheetApp.getActiveSheet();
var lastRow = sh.getLastRow();
var lastCol = sh.getLastColumn();
var range = sh.getRange(lastRow, 1, 1, lastCol);
sh.insertRowsAfter(lastRow, 1);
range.copyTo(sh.getRange(lastRow + 1, 1, 1, lastCol), {contentsOnly:false});
}
The important parameter you need in copyTo here is {contentsOnly:false}. Feel free to modify the coordinates for you to paste the row to anywhere.
For more details, read the usage of copyTo
If you want only the formula in the newly added row, you need to get the formula from the source row and then copy it to your destination row.
var source = sheet.getRange("A1:C1");
var dest = sheet.getRange("A2:C2");
var arr = source.getFormulas();
dest.setFormulas(arr);
This doesn't adjust the formula to the new row, it will copy the exact cell formula so be careful.
I asked this question over at the webapps stack exchange, but I didn't get any responses.
Basically, in one sheet I have data in cells C14 through F15, so it's 4 columns and 2 rows of data, 8 cells in total. With a script, I'd like to be able to "copy and paste" the values from these cells into B13:E14 on a different sheet.
I understand how to move values from one cell to another with a script, but I'm having trouble doing it with ranges of values.
Does anyone have any ideas?
Copying a range works just like copying a cell, since you can think of a cell as a range with one column and one row.
So you can do something like this:
function copyRange() {
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sourceRange = spreadsheet.getSheetByName('Sheet1').getRange('C14:F15');
const destinationSheet = spreadsheet.getSheetByName('Sheet2');
// Copy to B13:E14
sourceRange.copyValuesToRange(destinationSheet, 2, 5, 13, 14);
}
Also, this operation is quite common, so you might want to take a look at other questions and answers: https://stackoverflow.com/search?q=google%20apps%20script%20copy%20to%20another%20sheet
You can use the copyTo() method.
function copy() {
const ss = SpreadsheetApp.getActive();
ss.getRange('Sheet1!C14:F15').copyTo(ss.getRange('Sheet2!B13:E14'), { contentsOnly: true });
}
Note that you can specify the sheet using getSheetByName() (or similar) or you can just write it in as part of your range definition using normal A1 notation.
There are other ways to do this. Here's how it could be done using getValues() and setValues().
function copy() {
const ss = SpreadsheetApp.getActive();
const values = ss.getRange('Sheet1!C14:F15').getValues();
ss.getRange('Sheet2!B13:E14').setValues(values);
}
I have the following that works fine:
function phototable() {
var ss = SpreadsheetApp.openById('####');
var lastRow = ss.getLastRow();
ss.getRange('H'+lastRow)
.setValue('=VLOOKUP("Form Responses_Images/"&B'+lastRow+',importrange("https://docs.google.com/spreadsheets/d/####/edit","Form Responses!U:Z"),4,false)');
}
However, I don't want the formula copied into column H, just the actual value. So I tried:
ss.getRange('H'+lastRow)
.getValue('=VLOOKUP("Form Responses_Images/"&B'+lastRow+',importrange("https://docs.google.com/spreadsheets/d/###/edit","Form Responses!U:Z"),4,false)')
.copyTo('H'+lastRow,{contentsOnly:true});
But that doesn't insert anything into column H. Any ideas?
Modification points:
About I have the following that works fine:, when I saw the above script, I think that an error occurs at getValue. Because getValue has no arguments. I thought that getValue was setValue.
At copyTo('H'+lastRow,{contentsOnly:true}), the 1st argument is thr range object.
In order to copy the result of the formula during the script as the string, it is required to use flush.
When above points are reflected to your script, it becomes as follows.
Modified script:
function phototable() {
var ss = SpreadsheetApp.openById('####');
var lastRow = ss.getLastRow();
var range = ss.getRange('H'+lastRow);
range.setValue('=VLOOKUP("Form Responses_Images/"&B'+lastRow+',importrange("https://docs.google.com/spreadsheets/d/###/edit","Form Responses!U:Z"),4,false)');
SpreadsheetApp.flush();
range.copyTo(range, {contentsOnly:true});
}
Note:
In your script, ss is the 1st tab of the Spreadsheet. Please be careful this.
References:
flush()
copyTo(destination, options)
Issues / Explanation:
You have 2 ways to update the cell in column H with the value of the formula:
If you want to update the cell in H with its value then get the value and set it back:
range.setValue(range.getValue());
Use the copyTo() method:
range.copyTo(range, {contentsOnly:true});
As a bonus information, copyTo() can not be used if the source range and the target range are not of the same spreadsheet file.
Since this process happens really fast, it is a good idea to use flush() for the pending sheet changes to be completed.
Solution:
function phototable() {
var ss = SpreadsheetApp.openById('####').getSheetByName('Sheet1');
var lastRow = ss.getLastRow();
var range = ss.getRange('H'+lastRow);
range.setValue('=VLOOKUP("Form Responses_Images/"&B'+lastRow+',importrange("https://docs.google.com/spreadsheets/d/####/edit","Form Responses!U:Z"),4,false)');
SpreadsheetApp.flush();
range.setValue(range.getValue());
// range.copyTo(range, {contentsOnly:true}); // choose this or the previous line
}
Modify Sheet1 to the name of the sheet you want to apply this operation.
Also it is a better practice to choose a particular sheet before you apply any function to it. To get a sheet by its name use getSheetByName().
I am trying to run a macro on Sheet1 for data validation on Sheet2 by dynamically updating the column. It selects the full column (except for the first row) in Sheet1 to then validate on that same column in Sheet2. As seen in the example spreadsheet.getRange('\'Sheet2'!$P$2:$P$9') is hardcoded to always use P2:P9. This is fine if I am validating the P column, how do I dynamically update this for when I start the script in column N?
function test2() {
var spreadsheet = SpreadsheetApp.getActive();
var currentCell = spreadsheet.getCurrentCell();
spreadsheet.getSelection().getNextDataRange(SpreadsheetApp.Direction.DOWN).activate();
currentCell.activateAsCurrentCell();
spreadsheet.getActiveRange().setDataValidation(SpreadsheetApp.newDataValidation()
.setAllowInvalid(false)
.requireValueInRange(spreadsheet.getRange('\'Sheet2'!$P$2:$P$9'), false)
.build());
};
I believe your goal as follows.
You want to set the data validation rule to the active sheet using the column of "Sheet2" which is the same with the column selected at the active sheet.
For this, how about this answer?
Modification points:
In this modification, the A1Notation is retrieved from the selected range, and the column letter is retrieved from it. By this, the values for setting the data validation rule can be used from the selected column letter.
When your script is modified, it becomes as follows.
Modified script:
Pease copy and paste the following script. In order to use this script, please select the range on "Sheet1" and run this function myFunction. By this, the same column with the selected column is used from "Sheet2", and the data validation rule is set.
function myFunction() {
var spreadsheet = SpreadsheetApp.getActive();
var currentCell = spreadsheet.getCurrentCell();
var range = spreadsheet.getSelection().getNextDataRange(SpreadsheetApp.Direction.DOWN).activate(); // Modified
var column = range.getA1Notation().split(":")[0].replace(/\d+/g, ""); // Added
currentCell.activateAsCurrentCell();
spreadsheet.getActiveRange().setDataValidation(SpreadsheetApp.newDataValidation()
.setAllowInvalid(false)
.requireValueInRange(spreadsheet.getRange(`'Sheet2'!$${column}$2:$${column}$9`), false).build()); // Modified
}
In this modification, the rows are used from 2 to 9 by your script. So when you want to modify this, please modify above script.
Reference:
getA1Notation()
I have a sheet "SourceData" that has a lot of formulas to develop a proposal price based on variables entered on the sheet "Inputs". I need script to generateNewScope, where the "SourceData" sheet is duplicated, formulas removed from the duplicate, and it's renamed from "Copy of SourceData" to 1, then 2, then 3, etc.
I'm close! I can duplicate and rename, and I've gotten a different script to the point where it removes the formulas, but that one removed formulas from both "SourceData" AND "1". I just need to add additional actions here that essentially copy/paste values only directly in the same spot, or just a remove formulas action.
function generateNewScope() {
ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("SourceData"));
var ns = ss.duplicateActiveSheet(),
allSheets = ss.getSheets();
ns.setName(allSheets.length - 4);
}
You want to copy a sheet in a Spreadsheet.
You want to copy only values without the formulas.
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this modification?
Modification points:
In this modification, your script is modified.
Only values are copied using copyTo() after the sheet was copied.
Modified script:
function generateNewScope() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("SourceData"));
var ns = ss.duplicateActiveSheet();
var range = ns.getDataRange(); // Added
range.copyTo(range, {contentsOnly: true}); // Added
allSheets = ss.getSheets();
ns.setName(allSheets.length - 4);
}
Reference:
copyTo()
If I misunderstood your question and this was not the result you want, I apologize.