Copying and Paste Values into next empty Row in Google Sheets - google-apps-script

I have recently started doing some work in Google Sheets, where previously I have been able to code functions in Excel, I am unable to get this working in Google Sheets Scripting.
I have two sheets
Sheet 1. Cells A1 - E5 contain values based on some selection criteria
Sheet 2. Register Sheet
What I need is when executing the script (via drawing and linked macro)
I need it to copy the range A1:E1
Go into Sheet 2, Go to the first Blank Cell in Column A, and then Paste Values.
I am using the following script, and I'm getting
coordinates of the target range are outside of the dimensions of the sheet.
function moveValuesOnly () {
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var source = ss.getRange ("PNG Sheet!A1:E1");
var destSheet = ss.getSheetByName("Project Codes");
var destRange = destSheet.getRange(destSheet.getLastRow()+1,1);
source.copyTo (destRange, {contentsOnly: true});
source.clear ();
}
Any assistance would be greatly appreciated.
Cheers
Graeme

You're receiving this error because you're attempting to select a range in the "Project Codes" sheet that does not exist. Use instead the appendRow() method, which will
paste the passed values into the first blank row, and
automatically resize your sheet.
function moveValuesOnly() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getRange("PNG Sheet!A1:E1");
var destSheet = ss.getSheetByName("Project Codes");
destSheet.appendRow(source.getValues()[0]);
source.clear();
}

Related

How do i copyPaste through AppScript into another file instead of a sheet

Right now I am using this formula to copy and paste to another Sheet. Though due to the file getting bigger and bigger, we want to place it in a seperate file which we dont really have to open.
function copyInfo() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Kenmerken Script");
var pasteSheet = ss.getSheetByName("CopyPaste");
// get source range
var source = copySheet.getRange(3,3,300,6);
// get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+2,1,500,4);
// copy values to destination range
source.copyTo(destination);
// clear source values
source.clearContent();
}
I tried to use getsheetbyURL instead. This did not work as it gave an error.
I also tried to find more information on https://developers.google.com/apps-script/reference/spreadsheet/sheet#copyTo(Spreadsheet). Though I cannot find an clear answer here.
I tried to add another "var" but "var sss = SpreadsheetApp.getActiveSpreadsheet. And then put pastesheet = sss.getsheetbyURL". This didnt work either.
I understand the things in the code which I have now. I only need to find the correct string.
I believe your goal is as follows.
You want to copy C3:H302 of a source sheet of Spreadsheet "A" to the last row of a destination sheet of Spreadsheet "B".
You want to use Spreadsheet URL for retrieving the Spreadsheet.
In this case, when your showing script is modified, how about the following modification?
Modified script:
function copyInfo() {
var destinationSpreadsheetUrl = "###"; // Please set your Spreadsheet URL.
var destinationSheetName = "###"; // Please set the destination sheet name.
// Source sheet.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Kenmerken Script");
// Destination sheet.
var dstSS = SpreadsheetApp.openByUrl(destinationSpreadsheetUrl);
var dstSheet = dstSS.getSheetByName(destinationSheetName);
var temp = copySheet.copyTo(dstSS);
temp.getRange(3, 3, 300, 6).copyTo(dstSheet.getRange(dstSheet.getLastRow() + 2, 1));
// clear source values
copySheet.getRange(3, 3, 300, 6).clearContent();
// Remove temp sheet.
dstSS.deleteSheet(temp);
}
When this script is run, the values of "C3:H302" are copied from the source sheet of the active Spreadsheet to the destination sheet of another Spreadsheet. And, "C3:H302" of the source sheet is cleared.
If you want to use Spreadsheet ID, please use SpreadsheetApp.openById() instead of SpreadsheetApp.openByUrl().
If you want to copy only the values, I thought that getValues and setValues can be also used.
References:
openByUrl(url)
copyTo(spreadsheet)
Added:
From your following reply,
The formula itself works which is great. But it seems to take the formulas and not only the values. See picture: i.imgur.com/VRYCuTP.png . This causes an error since this file is not aware of any sheet named X. Would there be a way to only copy the values?
In this case, how about the following sample script?
Sample script:
function copyInfo() {
var destinationSpreadsheetUrl = "###"; // Please set your Spreadsheet URL.
var destinationSheetName = "###"; // Please set the destination sheet name.
// Source sheet.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Kenmerken Script");
var temp1 = copySheet.copyTo(ss);
var r = temp1.getDataRange();
r.copyTo(r, { contentsOnly: true });
// Destination sheet.
var dstSS = SpreadsheetApp.openByUrl(destinationSpreadsheetUrl);
var dstSheet = dstSS.getSheetByName(destinationSheetName);
var temp2 = temp1.copyTo(dstSS);
temp2.getRange(3, 3, 300, 6).copyTo(dstSheet.getRange(dstSheet.getLastRow() + 2, 1));
// clear source values
copySheet.getRange(3, 3, 300, 6).clearContent();
// Remove temp sheets.
ss.deleteSheet(temp1);
dstSS.deleteSheet(temp2);
}

Trying to build G Sheets scrip that will copy and paste a dynamic range within same spreadsheet

I'm trying to build a script that will allow me to copy and value paste a range from tab "robert" to tab "brendan". However, the range in "robert" is dynamic, so sometimes it will need to copy and paste A1:M3 or A1:M20. I'd also like it to append to the the first rows of the destination. So when run, the script looks for values on the source tab (robert), copies them, and pastes their values at the top of the destination (brendan) without overwriting existing data.
So far I've worked with the below script from a different thread:
function moveValuesOnly() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getRange('Robert!A1:M100');
source.copyTo(ss.getRange('Brendan!A4'), {contentsOnly: true});
source.clear();
}
The problem here is the script range is static, and it overwrites anything in the destination. I do like the clearing of the source though and the values paste. Any help would be greatly appreciated!
Define the range using variables. Use getLastRow() and getLastColumn() Instead of hard-coding it.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var robWs = ss.getSheetByName("Robert");
var brenWs = ss.getSheetByName("Brendan");
var robLr = robWs.getLastRow()
var robLc = robWs.getLastColumn()
//range starts at row 1 and column 1 (A1), you may need to change accordingly
var vals = robWs.getRange(1,1,lr,lc).getValues;
//paste range also starts at A1. you can find the lr on this sheet and start the range there
brenWs.getRange(1,1,lr,lc).setValues(vals);
function moveValuesOnly() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Robert');
var rg=sh.getActiveRange();//copies active range for source
var vA=rg.getValues();
dsh=ss.getSheetByName('Brendan');
dsr=4;//destination start row
dsc=1;//destination start col
dsa=2;//destination number of rows to append to
drg=dsh.getRange(dsr,dsc,rg.getHeight(),rg.getWidth());
var dvA=drg.getValues();
vA.forEach(function(r,i){
if(i<dsa){
r.forEach(function(c,j){
//only write data in destination for these rows if destination value is null
if(dvA[i][j]='') {
dvA[i][j]=c;
}
});
}else{
dvA[i][j]=c;
}
})
drg.setValues(dvA);
}

Why can't I copy ranges between spreadsheets with copyValuesToRange()?

I am able to copy a range of values from one spreadsheet to another with Range.setValues(values) but not with Range.copyValuesToRange(sheet, column, columnEnd, row, rowEnd):
function test()
{
var sourceSheet = SpreadsheetApp.getActiveSheet();
var sourceCols = sourceSheet.getRange("A1:B10");
// Copying the first two columns this way works.
var sheet1 = SpreadsheetApp.create("New Spreadsheet 1").getActiveSheet();
sheet1.getRange("A1:B10").setValues(sourceCols.getValues());
// Copying the first two columns this way does not work.
var sheet2 = SpreadsheetApp.create("New Spreadsheet 2").getActiveSheet();
sourceCols.copyValuesToRange(sheet2, 1, 2, 1, 10);
}
Specifically, after running the code, New Spreadsheet 1 contains range A1:B10 of the source spreadsheet, while New Spreadsheet 2 is empty. Both have a single sheet named "Sheet1". The source spreadsheet is unmodified.
What am I doing wrong? I'm wondering if the failing method only works within a single spreadsheet, but I see nothing in the documentation about that.
The reason I want to use Range.copyValuesToRange() is so I can also copy the formatting with Range.copyFormatToRange().
The methods copyValuesToRange and copyFormatToRange, as well as Range.copyTo, are restricted to copying within the same spreadsheets, although documentation is not explicit about that. A workaround which allows you to copy between spreadsheets with formatting is to copy the entire sheet to the destination spreadsheet, using Sheet.copyTo method. Then copy the required range from there, and optionally, delete the sheet. Like this:
function cc() {
var ss1 = SpreadsheetApp.openByUrl('some url');
var ss2 = SpreadsheetApp.openByUrl('another url');
var sheet1 = ss1.getSheetByName('name');
var sheet2 = ss2.getSheetByName('another name');
// the above was the setup, main code begins here
var copySheet = sheet1.copyTo(ss2);
copySheet.getRange("A1:B2").copyTo(sh2.getRange("C1:D2"));
ss2.deleteSheet(copySheet);
}

Copy content from one spreadsheet to another without IMPORTRANGE

I'm trying to create bidirectional synchronisation of some content between two Google Sheets. My script is working when:
the source and destination ID of the sheets are the same AND have the ID of the active spreadsheet
SO, THIS WORKS:
function myFunction() {
var sourceSpreadsheet = SpreadsheetApp.openById("ID-OF-ACTIVE-SPREADSHEET");
var destinationSpreadsheet = SpreadsheetApp.openById("ID-OF-ACTIVE-SPREADSHEET");
var sourceSheet = sourceSpreadsheet.getSheetByName("sheet1");
var destinationSheet = destinationSpreadsheet.getSheetByName("sheet2");
var sourceRange = sourceSheet.getRange("A1:A4");
// destination, columnStart, columnEnd, rowStart, rowEnd
sourceRange.copyValuesToRange(destinationSheet, 2, 2, 3, 7);
}
But when I replace the destination ID with the ID of another spreadsheet, it doesn't work.
Could it have something to do with permissions?
I have tried to publish both spreadsheets.
THIS DOESN'T:
...
var sourceSpreadsheet = SpreadsheetApp.openById("ID-OF-ACTIVE-SPREADSHEET");
var destinationSpreadsheet = SpreadsheetApp.openById("ID-OF-ANOTHER-SPREADSHEET");
...
Since I'm trying to create bidirectional sync I don't think I can use IMPORTRANGE.
Source SpreadSheet
Destination SpreadSheet
It seems like copyValuesToRange doesn't communicate outside the spreadsheet, here is a working solution:
function onChange() {
var sourceSpreadsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var sourceData = sourceSpreadsheet.getRange("A1:A8").getValues();
var targetSpreadsheet = SpreadsheetApp.openById("ID-OF-ANOTHER-SPREADSHEET").getSheetByName("Sheet1");
targetSpreadsheet.getRange("A1:A8").setValues(sourceData);
}
PS: this also enables bidirectional sync between spreadsheets, just add a copy of this code on both spreadsheet A and B and replace "ID-OF-ANOTHER-SPREADSHEET" with the ID of the other spreadsheet. And then define the from- and to range in place of the "A1:A8".

How could you retrieve a range of user highlighted cells in Google Sheets using Google Apps Script?

At the moment this is the function I'm using but I have no way of testing if it will work in the spreadsheet until I publish the application.
function readSelection() {
//The commented lines aren't needed if the sheet is open already
//var sheetid = "sheet id here";
//var spreadsheet = SpreadsheetApp.openById(sheetid);
//SpreadsheetApp.setActiveSpreadsheet(spreadsheet);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
//sheet.setActiveSelection("B2:B22");
var activerange = sheet.getActiveRange();
var activecells = activerange.getValues();
return activecells;
};
I assume you mean highlighted == selected
The result depends on whether the cells are contiguous or not (non contiguous cell selection is available in the new spreadsheets features http://googleblog.blogspot.co.nz/2013/12/new-google-sheets-faster-more-powerful.html
For contiguous cells selected your code returns the values of the selection as an array, for non-contiguous cells your code will return the an array with the single value of the LAST selected item.
I suggest that this is a bug in the implementation of the new spreadsheet. If it is important to you, I suggest you raise an issue. For the old spreadsheets, you can only select contiguous cells (eg B2:B22) so it will work as you expect.
The easiest way to answer this Q is to run the code you have written! You don't have to publish anything just run the code in the script editor of the spreadsheet you are examining
and look at the log.
function readSelection() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var activerange = sheet.getActiveRange();
var activecells = activerange.getValues();
Logger.log(activecells)
return
};
There is no way to do this at the moment or to obtain the selected ranges from a script.
A request is pending and you can support it here : https://code.google.com/p/google-apps-script-issues/issues/detail?id=4056
by adding a star to the request.
If/when this function is implemented your code would look as follows:
function readSelection() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var activeranges = sheet.getSelectedRanges();
var activecells = [] ;'
for (var ar in activeranges)
activecells = activecells.concat(activeranges[ar].getValues()) ;
Logger.log(activecells)
return ;
}
note that selected ranges may overlap, so some cell contents could be added twice.