Google script to copy and paste - google-apps-script

I'm trying to work out if it's possible to write a script that will copy and paste special all the values in a tab with the same name across multiple workbooks in a file?
This is what I have so far but I just can't seem to get it to work properly? Any help would be most appreciated.
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Copy and Paste')
.addItem('Copy and paste sheet with new name', 'copyAndPasteSheetWithNewName')
.addToUi();
}
function copyAndPasteSheetWithNewName() {
var sheetName = Browser.inputBox('Enter the name of the sheet to copy and paste:');
var folder = DriveApp.getFileById(SpreadsheetApp.getActive().getId()).getParents().next();
var files = folder.getFilesByType(MimeType.GOOGLE_SHEETS);
while (files.hasNext()) {
var file = files.next();
var workbook = SpreadsheetApp.open(file);
var sheet = workbook.getSheetByName(sheetName);
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
}
}
}

From your following reply,
What I'm trying to do is just have the final part of the script hard code the worksheet. It's full of formulas and I want the results of those formulas not the formulas themselves.
In this case, how about the following modification?
From:
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
To:
var range = sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn());
range.copyTo(range, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false); // or range.copyTo(range, {contentsOnly: true});
By this modification, the last row of each sheet is converted to only the values without the formulas.

Related

Google Sheets - App Script (copyTo - cell content & format)

I have a tracker to count daily productivity.
This is appended to a weekly tracker, in which the sum of the two serves as a running total.
The weekly tracker is appended to a separate sheet to serve as historical data.
TRACKER
DATA
As you can see in the 'DATA' screenshot, the formula is being copied from K12:O12
see function copyTT / source.copyTo
I want to retain cell formatting, and copy only the cell data, not it's formula.
Script;
function mergeTT() {
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var source = ss.getRange("NEW_TTRACKER!J3:O3");
var destSheet = ss.getSheetByName("NEW_TTRACKER");
var lastRow = destSheet.getRange("J7:J11").getValues().filter(String).length;
var destRange = destSheet.getRange(lastRow+7,10,1,6);
source.copyTo(destRange, {contentsOnly: true});
var ws = ss.getSheetByName("NEW_TTRACKER")
ws.getRange('K3:O3').clearContent();
}
function copyTT() {
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var source = ss.getRange("NEW_TTRACKER!J5:O12");
var destSheet = ss.getSheetByName("NEW_TDATA");
var destRange = destSheet.getRange(destSheet.getLastRow()+1,1);
source.copyTo(destRange, {contentsOnly: false});
var sheet = SpreadsheetApp.getActive().getSheetByName("NEW_TTRACKER");
sheet.getRange('J7:O11').clearContent();
}
Thanks in advance.
I've been attempting to get around it playing with different CopyPasteType properties and I'm really not getting anywhere.
About I've been attempting to get around it playing with different CopyPasteType properties, I think that your approach is correct. In your script, how about modifying your script as follows?
From:
source.copyTo(destRange, {contentsOnly: true});
To:
source.copyTo(destRange, { contentsOnly: true });
source.copyTo(destRange, SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false); // Added
By this modification, the format is also copied.
Reference:
copyTo(destination, copyPasteType, transposed)

Google Apps Script that aligns all cells in all sheets

At the moment, I have to go through every sheet and use this macro to align it vertically and horizontally. Is there a way of tweaking this script to align all sheets instead of having to do each one manually?
function Alignment() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).activate();
spreadsheet.getActiveRangeList().setHorizontalAlignment('center')
.setVerticalAlignment('middle');
};
Get all sheets and iterate over each sheet:
function Alignment() {
var spreadsheet = SpreadsheetApp.getActive();
var sheets = spreadsheet.getSheets();
sheets.forEach(sheet=>{
sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn()).activate();
spreadsheet.getActiveRangeList().setHorizontalAlignment('center')
.setVerticalAlignment('middle');
});
};
If you want to get more performance but you won't be able to see the changes as they are hapenning in the sheets, then try this:
function Alignment() {
const spreadsheet = SpreadsheetApp.getActive();
const sheets = spreadsheet.getSheets();
sheets.forEach(sheet=>{
let rg=sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn());
rg.setHorizontalAlignment('center')
.setVerticalAlignment('middle');
});
};

Add a IF (Background Color) conditional to Copyto Function

So Tanaike was kind enough to make a Copyto function for me previously, which basically took a snapshot of a spreadsheet I had and copied it to a new location without bringing along the respective formulas of each cell:
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('Master Menu')
.addItem('Archive Report', 'Archiver')
.addToUi();
}
function Archiver() {
var spreadsheetId = "File_ID"; // Please set the source Spreadsheet ID.
var destFolderId = "File_ID"; // Please set the destination folder ID.
// Copy each sheet in the source Spreadsheet by removing the formulas as the temporal sheets.
var ss = SpreadsheetApp.openById(spreadsheetId);
var tempSheets = ss.getSheets().map(function(sheet, i) {
var dstSheet = sheet.copyTo(ss).setName(sheet.getSheetName() + "_temp");
var src = dstSheet.getDataRange();
src.copyTo(src, {contentsOnly: true});
return dstSheet;
});
// Copy the source Spreadsheet.
var destination = ss.copy(ss.getName() + " - " + new Date().toLocaleString());
// Delete the temporal sheets in the source Spreadsheet.
tempSheets.forEach(function(sheet) {ss.deleteSheet(sheet)});
// Delete the original sheets from the copied Spreadsheet and rename the copied sheets.
destination.getSheets().forEach(function(sheet) {
var sheetName = sheet.getSheetName();
if (sheetName.indexOf("_temp") == -1) {
destination.deleteSheet(sheet);
} else {
sheet.setName(sheetName.slice(0, -5));
}
});
// Move file to the destination folder.
var file = DriveApp.getFileById(destination.getId());
DriveApp.getFolderById(destFolderId).addFile(file);
file.getParents().next().removeFile(file);
}
I am grateful for this function, but there is one last thing I would like to do with this if possible: I would like to make it so that ONLY cells that are highlighted green ("#0D7813") have their respective formulas removed (contents only), while all other cells have their formulas preserved, when the sheet containing them is copied over. I tried my hand at making this working but I don't know how to make a boolean statement for this, here was my attempt:
// Copy each sheet in the source Spreadsheet by removing the formulas as the temporal sheets.
var ss = SpreadsheetApp.openById(spreadsheetId);
var tempSheets = ss.getSheets().map(function(sheet, i) {
var dstSheet = sheet.copyTo(ss).setName(sheet.getSheetName() + "_temp");
var src = dstSheet.getDataRange();
var backgrounds = tempSheets.getDataRange().getBackgrounds()
if(backgrounds === "#0D7813"){
src.copyTo(src, {contentsOnly: true});
}
else{
src.copyTo(src, {contentsOnly: false});
}
return dstSheet;
I don't know how to make a boolean for individual cells for the process since it seems to be copying the whole sheet. Any help would be appreciated, thank you.
Here you go Lamb, thank you for all your help by they thusfar :) :
Here is a link to a sample of the spreadsheet: https://docs.google.com/spreadsheets/d/1NcS22owCLKOrx5ZU1zyuBEJPgHZfmtn55oh6R_uUkMQ/edit?usp=sharing
Here is a link to a sample of the sheet it references: https://docs.google.com/spreadsheets/d/10vX8cT1d8OCRXsB9rWtdSvVv4HTN3jCuo-96ZnNp2g4/edit?usp=sharing
Please bear in mind that getBackgrounds returns a two-dimensional array of color codes, not just one value. So the condition backgrounds === "#0D7813" can never return true. You have to check each cell individually.
In this case, I would (1) copy all the spreadsheet as it is, with formulas, and after that (2) loop through each cell (with content) of each sheet, and remove the formula if the background color is the specified one.
So you could change this:
// Copy each sheet in the source Spreadsheet by removing the formulas as the temporal sheets.
var ss = SpreadsheetApp.openById(spreadsheetId);
var tempSheets = ss.getSheets().map(function(sheet, i) {
var dstSheet = sheet.copyTo(ss).setName(sheet.getSheetName() + "_temp");
var src = dstSheet.getDataRange();
src.copyTo(src, {contentsOnly: true});
return dstSheet;
});
// Copy the source Spreadsheet.
var destination = ss.copy(ss.getName() + " - " + new Date().toLocaleString());
// Delete the temporal sheets in the source Spreadsheet.
tempSheets.forEach(function(sheet) {ss.deleteSheet(sheet)});
// Delete the original sheets from the copied Spreadsheet and rename the copied sheets.
destination.getSheets().forEach(function(sheet) {
var sheetName = sheet.getSheetName();
if (sheetName.indexOf("_temp") == -1) {
destination.deleteSheet(sheet);
} else {
sheet.setName(sheetName.slice(0, -5));
}
});
To this:
// Copy all the spreadsheet (formulas included)
var ss = SpreadsheetApp.openById(spreadsheetId);
var destination = ss.copy(ss.getName() + " - " + new Date().toLocaleString());
var backgroundColor = "#0d7813"; // The background color you want to check for
destination.getSheets().forEach(function(sheet) { // Iterating through each sheet in the destination
var backgrounds = sheet.getDataRange().getBackgrounds(); // Getting 2-dimensional array with background colors for each cell in the sheet
for (var i = 0; i < backgrounds.length; i++) { // Iterating through each row
var rowBackgrounds = backgrounds[i];
for (var j = 0; j < rowBackgrounds.length; j++) { // Iterating through each cell for that specific row
var cellBackground = rowBackgrounds[j];
if (cellBackground === backgroundColor) { // Checking if the cell background color is the same as the specified one
var cell = sheet.getRange(i + 1, j + 1);
cell.copyTo(cell, {contentsOnly: true}); // Removing formulas from the cell
}
}
}
});
Check the comments I added in the code to see what the script is doing line by line.
I hope this is of any help.

Replace formulas with static values

The script copies all cells in column V and pastes them one column to the right.
When this is done it should replace the cells with a formula in Column V with static values.
function newsprint() {
var sheet = SpreadsheetApp.getActiveSheet();
var rangeToCopy = sheet.getRange(1, 22, sheet.getMaxRows(), 1);
rangeToCopy.copyTo(sheet.getRange(1, 23));
}
You can do this with
function newsprint() {
var sheet = SpreadsheetApp.getActiveSheet();
var rangeToCopy = sheet.getRange(1, 22, sheet.getMaxRows(), 1);
rangeToCopy.copyTo(sheet.getRange(1, 23), {contentsOnly: true});
}
as shown here in the Google Apps Script Documentation. You need to use the copyTo(destination, options) method to use the contentsOnly parameter rather than
copyTo(destination).

Copy and paste a Row and delete certain cells

I am trying to copy paste a row (A3:S3) to the next free row of my sheet.
This works fine with the following code.
What I am now trying to do is to delete the cells C3-K3.
function copypastescript() {
var reference = 'Definitionstabelle!A2';
var rng = SpreadsheetApp.getActiveSpreadsheet().getRange(reference);
rng.setValue(rng.getValue()+1);
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var source = ss.getRange ("Definitionstabelle!A3:S3");
var destSheet = ss.getSheetByName("Definitionstabelle");
var values = source.getValues().filter(function(e) {return e.some(function(f) {return f})});
destSheet.getRange(destSheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);
}
Answer for Q1:
You want to delete the cells "C3:K3" of the sheet of Definitionstabelle after the values of "A3:S3" are copied.
If my understanding is correct, how about this modification?
Modified script:
Please add the following script after destSheet.getRange(destSheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);.
ss.getRange ("Definitionstabelle!C3:K3").clearContent();
or
ss.getRange ("Definitionstabelle!C3:K3").clear();
References:
clearContent()
clear()
If I misunderstood your question and this was not the result you want, I apologize.
Answer for Q2:
some code to copy K3 and paste it into J3 before deleting C3:I3 and K3
You want to copy the value of "K3" to "J3" of the sheet "Definitionstabelle".
You want to copy before the vaues of cells "C3:K3" are deleted.
In your situation, should the copy from "K3" to "J3" be done before the copy of "A3:S3"?
If my understanding is correct how about this modification?
Please put the following script before ss.getRange ("Definitionstabelle!C3:K3").clear();.
Modified script:
function copypastescript() {
var reference = 'Definitionstabelle!A2';
var rng = SpreadsheetApp.getActiveSpreadsheet().getRange(reference);
rng.setValue(rng.getValue()+1);
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var source = ss.getRange ("Definitionstabelle!A3:S3");
var destSheet = ss.getSheetByName("Definitionstabelle");
// Added
destSheet.getRange("K3").copyTo(destSheet.getRange("J3"), {contentsOnly:true}); // or destSheet.getRange("K3").copyTo(destSheet.getRange("J3"))
var values = source.getValues().filter(function(e) {return e.some(function(f) {return f})});
destSheet.getRange(destSheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);
// Added
ss.getRange ("Definitionstabelle!C3:K3").clearContent(); // or ss.getRange ("Definitionstabelle!C3:K3").clear()
}
Reference:
copyTo(destination, options)