How Can I Change My Range to Include Merged Cells? - google-apps-script

I am trying to copy and paste "A4:J4" and "A5:H5" but I am getting an error because A5 is merged. Also "STAGE 3" only pastes in "G4" in Sheet2. How can I copy and paste this data to Sheet2 with merged cells?
function hi()
{
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var yourRange = sheet.getRange("A4");
var ss = SpreadsheetApp.getActiveSpreadsheet();
var destSheet = ss.getSheetByName('Sheet2');
var yourLastColumn=sheet.getRange("A4:4").getLastColumn();
var range = ss.getRangeByName("A4");
var yourLastRange=sheet.getRange("A4").offset(0, yourLastColumn-1);
var rsltRange1 = yourLastRange.getNextDataCell(SpreadsheetApp.Direction.PREVIOUS);
var rsltRange2 = sheet.getRange("A4:" + rsltRange1.getA1Notation());
if (rsltRange2.isPartOfMerge()) {
var rangeTest = rsltRange2.getMergedRanges()[0];
} else {
}
Logger.log(rangeTest.getA1Notation());
var destRange = destSheet.getRange("A4");
rsltRange2.copyTo(destRange, {contentsOnly: false});
}

Here is a simplified version of your code that should copy your range correctly no matter if the range is merged or not:
function hi(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1');
var destSheet = ss.getSheetByName('Sheet2');
var startColumn=1;
var startRow=4;
var numRows=2;
var numColumns=sheet.getLastColumn()-startColumn+1;
var range=sheet.getRange(startRow, startColumn, numRows, numColumns);
var destRange = destSheet.getRange("A4");
range.copyTo(destRange);
}

Related

Copy Specific Sheet from Drive Folder and Paste Data into Active Sheet

I have 10 to 15 Files in the Drive Folder All files have more than 1 Google sheets in it with some sort of Conditional Formatting.
I want to copy the Specific Sheet Named "MasterSheet" from each File and Combine the data into the Active Sheet where from script is bieng run.
Copied data should keep conditional formatting cell color. I will appreciate the help. Thanks
function myFunction()
{
var myFolder = DriveApp.getFolderById("FolderID");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var ActiveSpreadSheet = SpreadsheetApp.getActive().getSheetByName(Sheet1);
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
for(var y in spreadSheet.getSheets())
{
spreadSheet.getSheets()[y].copyTo(ActiveSpreadSheet);
}
}
}
UPDATE to check if there's a sheet called that way:
function copywithLog()
{
var destinsheet = SpreadsheetApp.getActiveSpreadsheet()
var myFolder = DriveApp.getFolderById("16CxTO70ipcUt8U_beokid3vFOOLGTnPh");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var activeSpreadSheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
var i = 1
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
var sheets = spreadSheet.getSheets()
var filtered = sheets.filter(n => ["DATA"].lastIndexOf(n.getSheetName()) == 0)
if (filtered.length==1){
var newsheet = spreadSheet.getSheetByName('DATA').copyTo(destinsheet)
newsheet.getDataRange().copyTo(activeSpreadSheet.getRange(activeSpreadSheet.getLastRow()+2,1))
destinsheet.deleteSheet(newsheet)
Logger.log("Process successfully finished with the workbook named '"+spreadSheet.getName()+"'")}
else Logger.log("The worbook named '"+spreadSheet.getName()+ "' does not have a sheet called DATA")
}
}
It returns something like this:
UPDATE:
function copyinsamesheet()
{
var destinsheet = SpreadsheetApp.getActiveSpreadsheet()
var myFolder = DriveApp.getFolderById("FolderID");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var activeSpreadSheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
var i = 1
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
var newsheet = spreadSheet.getSheetByName('MasterSheet').copyTo(destinsheet)
newsheet.getDataRange().copyTo(activeSpreadSheet.getRange(activeSpreadSheet.getLastRow()+2,1))
destinsheet.deleteSheet(newsheet)
}
}
If it has always the same name, you can try with this:
function copyMasterSheets()
{
var destinsheet = SpreadsheetApp.getActiveSpreadsheet()
var myFolder = DriveApp.getFolderById("FolderID");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var ActiveSpreadSheet = SpreadsheetApp.getActive().getSheetByName(Sheet1);
var i = 1
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
spreadSheet.getSheetByName('MasterSheet').copyTo(destinsheet).setName('MasterSheet '+i)
i++
}
}
An addendum to the answer by #Martin.
This takes the data on the various "Master Sheets" and copies it to a single sheet.
The range of data on each sheet is established dynamically, and is stacked down the page.
function copyMasters(){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var target = ss.getSheetByName('Sheet1')
// idetify the starting row
var activeStartRow = 1
// get an array of all the sheets with names like "MasterSheet"
var sheetList = new Array
var sheets = ss.getSheets()
//var sourcesheet = ss.getSheets().find(sheet => sheet.getName().includes("MasterSheet"))
var mastersheets = sheets.filter(sheet => sheet.getName().includes("MasterSheet"))
//loop through the Master sheets
for (var i=0;i<mastersheets.length;i++){
var mastername = mastersheets[i].getName()
var master = ss.getSheetByName(mastername)
var masterLC = master.getLastColumn()
var masterLR = master.getLastRow()
// calculate the start row for the target sheet
if (activeStartRow==1){
var startRow =1
}else{
var startRow=startRow+masterLR
}
activeStartRow = 0
var rangeToCopy = master.getRange(1, 1, masterLR,masterLC)
//Logger.log("DEBUG: range to copy:"+rangeToCopy.getA1Notation())
var targetRange = target.getRange(startRow, 1, masterLR,masterLC)
//Logger.log("DEBUG: target range:"+targetRange.getA1Notation())
rangeToCopy.copyTo(targetRange)
// Logger.log("DEBUG: copied the data for "+mastername)
}
}
SAMPLE

Please revise the google app script to make it concise and clear "Rows out of range" error

I have a google sheet Here. It has three subsheets. CONFIDENTIAL : MIS, CONFIDENTIAL : MSA and Collection Sheet. I need a menu button which should read all data after 4th row of the both spreadsheets. And paste in the "Collection Sheet" as a single list, together with current date in E5 to last filled column. The following code does it well but I thing it is not a smart way to do it. And sometimes if the rows are in short in number, it gives "Rows out of range" msg, Would anyone expert give / suggest me some advice to improve it?
The code is given below.
function create_submit_sheet(){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var target_sheet = SpreadsheetApp.setActiveSheet(sheet.getSheetByName('Collection Sheet'))
target_sheet.getRange('C1').setValue('');
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source_sheet = ss.getSheetByName("CONFIDENTIAL : MIS");
var Avals = source_sheet.getRange("B4:B").getValues();
var Alast = Avals.filter(String).length;
//Logger.log(Alast);
var target_sheet = ss.getSheetByName("Collection Sheet");
//var roww = target_sheet.getDataRange.length;
//var Avals = ss.getRange("A1:A").getValues();
//var Alast = Avals.filter(String).length;
//Logger.log(Alast);
var source_range = source_sheet.getRange("B4:F"+Alast+4);
//var target_range = target_sheet.getRange("A6:H");
var last_row = target_sheet.getLastRow();
//target_sheet.insertRowAfter(last_row);
var target_range = target_sheet.getRange("A"+(last_row+1)+":C"+(last_row+1));
source_range.copyTo(target_range,{contentsOnly: true});
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source_sheet = ss.getSheetByName("CONFIDENTIAL : MSA");
var Avals = source_sheet.getRange("B5:B").getValues();
var Alast = Avals.filter(String).length;
var Alast1 = Alast;
//Logger.log(Alast);
var target_sheet = ss.getSheetByName("Collection Sheet");
//var roww = target_sheet.getDataRange.length;
//var Avals = ss.getRange("A1:A").getValues();
//var Alast = Avals.filter(String).length;
//Logger.log(Alast);
var source_range = source_sheet.getRange("B5:F"+Alast+5);
//var target_range = target_sheet.getRange("A6:H");
var last_row = target_sheet.getLastRow();
//target_sheet.insertRowAfter(last_row);
var target_range = target_sheet.getRange("A"+(last_row+1)+":C"+(last_row+1));
source_range.copyTo(target_range,{contentsOnly: true});
//SpreadsheetApp.getActiveSheet().getRange('F2').setValue('Hello');
target_sheet.getRange('F4').setValue('প্রদত্ত');
target_sheet.getRange('G4').setValue('তারিখ');
var curDate = Utilities.formatDate(new Date(), "GMT+6", "MM/dd/yyyy")
Avals = target_sheet.getRange("A1:A").getValues();
Alast = Avals.filter(String).length;
target_sheet.getRange(5,7, Alast-4 ).setValue(curDate);
var sheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(sheet.getSheetByName('Collection Sheet'))
}
Try the appendRows_() utility function. You can use it like this:
function appendToSubmitSheet() {
const ss = SpreadsheetApp.getActive();
const targetSheet = ss.getSheetByName('Collection Sheet');
const values =
ss.getRange('CONFIDENTIAL : MIS!B4:F').getValues()
.concat(ss.getRange('CONFIDENTIAL : MSA!B4:F').getValues())
.filter(row => row.join(''));
appendRows_(targetSheet, values, 2);
}

Google Apps Script URL being converted to text with copy row

The following code copies a row from one sheet and adds it to the next free row of another sheet. However, one of the cells in the source range contains a hyperlink to a Google Drive folder. When the range is added to the bottom of the target sheet the hyperlink is stripped out leaving just the folder name in text. How can I retain the hyperlink during the copy process?
My Code:
function updateProjectLog() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName('Metadata');
var sourceRange = sourceSheet.getRange('metadataRecord');
var sourceValues = sourceRange.getValues();
var rowCount = sourceValues.length;
var columnCount = sourceValues[0].length;
var targetSheet = ss.getSheetByName('Project Log');
var lastRow = targetSheet.getLastRow();
var targetRange = targetSheet.getRange(lastRow + 1, 1, rowCount, columnCount);
targetRange.setValues(sourceValues);
}
Use RichTextValues to manage stylized text, including links:
function updateProjectLog() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName('Metadata');
var sourceRange = sourceSheet.getRange('metadataRecord');
var sourceValues = sourceRange.getRichTextValues();
var rowCount = sourceValues.length;
var columnCount = sourceValues[0].length;
var targetSheet = ss.getSheetByName('Project Log');
var lastRow = targetSheet.getLastRow();
var targetRange = targetSheet.getRange(lastRow + 1, 1, rowCount, columnCount);
targetRange.setRichTextValues(sourceValues);
}

Mass Edit of Cell Range in Sheets in Folder Using Script

I have used this script in the past to edit a cell or range of cells in a set of spreadsheets in a specific folder (using a source file), but when I run the script it does not work. In fact, instead of copying the range from the source sheet it clears out existing data in the destination sheets.
Here is script I have been using:
var files = DriveApp.getFolderById("1NNHFL6fMFz-LwJ4tZrvTN92foXhf7VS8").getFiles()
while (files.hasNext()) {
var file = files.next();
var shoot = SpreadsheetApp.openById(file.getId());
var sourcesheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
var sourcerange = sourcesheet.getRange('A:A');
var sourcevalues = sourcerange.getFormulas();
var destsheet = shoot.getSheetByName('Sheet1');
var destrange = destsheet.getRange('A:A');
destrange.setValues(sourcevalues);
}
}
Here is a link to the folder I have been testing this in.
Your script works fine if you change setValues() to setFormulas (if you need formulas):
function myFunction() {
var files = DriveApp.getFolderById("1NNHFL6fMFz-LwJ4tZrvTN92foXhf7VS8").getFiles()
while (files.hasNext()) {
var file = files.next();
var shoot = SpreadsheetApp.openById(file.getId());
var sourcesheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
var sourcerange = sourcesheet.getRange('A:A');
var sourcevalues = sourcerange.getFormulas();
var destsheet = shoot.getSheetByName('Sheet1');
var destrange = destsheet.getRange('A:A');
destrange.setFormulas(sourcevalues); // <------------- HERE
}
}
Try this:
function myfunc() {
var files = DriveApp.getFolderById("1NNHFL6fMFz-LwJ4tZrvTN92foXhf7VS8").getFiles()
const ss=SpreadsheetApp.getActive();
var sourcesheet = ss.getSheetByName("Sheet1");
var sourcerange = sourcesheet.getRange(1,1,sourcesheet.getLastRow(),1);
var sourcevalues = sourcerange.getFormulas();
while (files.hasNext()) {
var file = files.next();
var shoot = SpreadsheetApp.openById(file.getId());
var destsheet = shoot.getSheetByName('Sheet1');
var destrange = destsheet.getRange(1,1,sourcesheet.getLastRow(),1);
destrange.setFormulas(sourcevalues);
}
}

Copying range of values from Google Sheet to other

I want to copy the range of values from one spreadsheet to another (A1:H45). I tried the code below. In spite of copying the values of Cells A1:H45, its copying A1 Cell data in a new sheet throughout A1:H45, which means the same data getting copied 45 times.
function Copy()
{
var sss = SpreadsheetApp.openById('1IK6YsZS3_NNAlFA41d8uKriPzfZs_2Ukyh94eeBFj40');
var ss = sss.getSheetByName('CURRENT');
var range = ss.getRange('A1:H45');
var data = range.getValues();
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var yourNewSheet = activeSpreadsheet.getSheetByName("New sheet");
if (yourNewSheet != null)
{
activeSpreadsheet.deleteSheet(yourNewSheet);
}
yourNewSheet = activeSpreadsheet.insertSheet();
yourNewSheet.setName("Name of your new sheet");
yourNewSheet.getRange(yourNewSheet.getLastRow()+1,1,45,8).setValue(data);
}
Try this -
function Copy()
{
var sss = SpreadsheetApp.openById('1IK6YsZS3_NNAlFA41d8uKriPzfZs_2Ukyh94eeBFj40');
var ss = sss.getSheetByName('CURRENT');
var range = ss.getRange('A1:H45');
var data = range.getValues();
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var yourNewSheet = activeSpreadsheet.getSheetByName("New sheet");
if (yourNewSheet != null)
{
activeSpreadsheet.deleteSheet(yourNewSheet);
}
yourNewSheet = activeSpreadsheet.insertSheet();
yourNewSheet.setName("Name of your new sheet");
yourNewSheet.getRange(yourNewSheet.getLastRow()+1,1,45,8).setValues(data);
}
Your code is perfect. All you had to do was use setValues (plural) instead of setValue :)