I have a script that creates a new file, names it and copies data from a template. The problem I am having is getting all of the formatting over such as merged cells. Here is the code I have so far.
function createNewSheet(e) {
const sh = e.range.getSheet();
var name = sh.getRange(e.range.rowStart, 1).getValue();
var crNew = SpreadsheetApp.create("Job Traveler-" + name);
var ssNew = SpreadsheetApp.openByUrl(crNew.getUrl()).getId();
importRange("1X4iOzc_shcOR8UM7OEM4F1-eR62YZmwKWyyEuu59Pf4","Job!A1:D", ssNew,"Sheet1!A1");
copiedFormat();
}
function importRange(sourceId,sourceRange,destinationID,destinationRangeStart){
const sourceSS = SpreadsheetApp.openById(sourceId);
const sourceRng = sourceSS.getRange(sourceRange);
const sourceVals = sourceRng.getValues();
// Get formatting data
const sourceFontStyle = sourceRng.getFontStyles();
const sourceFontWeight = sourceRng.getFontWeights();
const sourceFontBackgroundColor = sourceRng.getBackgrounds();
const destinationSS = SpreadsheetApp.openById(destinationID);
const destStartRange = destinationSS.getRange(destinationRangeStart);
const destSheet = destinationSS.getSheetByName(destStartRange.getSheet().getName());
destSheet.clear();
const destRange = destSheet.getRange(
destStartRange.getRow(),
destStartRange.getColumn(),
sourceVals.length,
sourceVals[0].length
);
destRange.setValues(sourceVals);
// Set formatting
destRange.setFontStyles(sourceFontStyle);
destRange.setFontWeights(sourceFontWeight);
destRange.setBackgrounds(sourceFontBackgroundColor);
SpreadsheetApp.flush();
}
Best
Description
I've only provided the addtional steps to duplicate merged cells from one range to another. I leave it to you to incorporate the relavent code to your script. I've included a debugging step 'merged.forEach()' which you can remove for production.
Script
function createNewSheet() {
try {
// in my case source and destination are the same spreadsheet but different sheets
// and I have made the ranges arbitrary
importRange("Sheet5","Sheet5!C6:L11","Sheet6","Sheet6!E11")
}
catch(err) {
console.log(err)
}
}
function importRange(sourceId,sourceRange,destinationID,destinationRangeStart) {
try {
var sourceSS = SpreadsheetApp.getActiveSpreadsheet();
var sourceRng = sourceSS.getRange(sourceRange);
var sourceVals = sourceRng.getValues();
var destinationSS = sourceSS;
var destStartRange = destinationSS.getRange(destinationRangeStart);
var destSheet = destinationSS.getSheetByName(destStartRange.getSheet().getName());
var row = destStartRange.getRow();
var col = destStartRange.getColumn();
var rows = sourceVals.length;
var cols = sourceVals[0].length;
destSheet.getRange(row,col,rows,cols).setValues(sourceVals);
var merged = sourceRng.getMergedRanges();
merged.forEach( range => console.log(range.getA1Notation()));
var rowOffset = destStartRange.getRow()-sourceRng.getRow();
var columnOffset = destStartRange.getColumn()-sourceRng.getColumn();
for( var i=0; i<merged.length; i++ ) {
row = merged[i].getRow()+rowOffset;
col = merged[i].getColumn()+columnOffset;
rows = merged[i].getNumRows();
cols = merged[i].getNumColumns();
destSheet.getRange(row,col,rows,cols).merge();
}
}
catch(err) {
console.log(err)
}
}
Reference
https://developers.google.com/apps-script/reference/spreadsheet/range#getMergedRanges()
https://developers.google.com/apps-script/reference/spreadsheet/range#merge()
Related
I am working on a script to copy all the all data from sheets saved in a folder and concatenate them to a single spreadsheet.
The variable combinedData is not returning any data when I run it through the logger outside the while loop. Any ideas why this is happening?
// DATA CONCATINATION
function Data_concat() {
var folder = DriveApp.getFolderById("1Rky5tOyrTMJ15uhTog1ltBMwONap7Rx1");
var filesIterator = folder.getFiles();
var file;
var filetype;
var ssID;
var combinedData = [];
var data;
while(filesIterator.hasNext()){
file = filesIterator.next();
filetype = file.getMimeType();
if(filetype === "application/vnd.google-apps.spreadsheet"){
ssID = file.getId();
data = getDatafromSS(ssID);
combinedData = combinedData.concat(data);
}//end of if
}//end of while
Logger.log(combinedData)
//var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("raw_Data");
//ws.getRange("A2:J").clearContent();
//ws.getRange(2,1,combinedData.length, combinedData[0].length).setValues(combinedData)
}//end of Data_concat
//GET DATA FROM TARGET SHEET
function getDatafromSS(ssID){
var ss = SpreadsheetApp.openById(ssID);
var ws = ss.getSheets()[0];
var data = ws.getRange("A2:G" + ws.getLastRow()).getValues();
return data;
}
Save Data in all Spreadsheets in a folder
On Different Sheets:
function saveDataInAllSheetsInAFolder() {
const tss = SpreadsheetApp.getActive();
const tssnames = tss.getSheets().map(sh => sh.getName()).flat();
const fldr = DriveApp.getFolderById("Folderid");
const files = fldr.getFilesByType(MimeType.GOOGLE_SHEETS);
while(files.hasNext()) {
let file = files.next();
let ss = SpreadsheetApp.openById(file.getId());
ss.getSheets().forEach((sh,i) => {
let vs = sh.getDataRange().getValues();
let nsh = tss.insertSheet(ss.getName() + "-" + sh.getName() + "-" + Utilities.formatDate(new Date(),tss.getSpreadsheetTimeZone(),"yyyyMMdd HH:mm:ss.S"));
nsh.getRange(1,1,vs.length,vs[0].length).setValues(vs)
})
}
}
google-apps-script reference
Learn More
On Same Sheet:
function saveDataInAllSheetsInAFolder() {
const tss = SpreadsheetApp.getActive();
const nsh = tss.insertSheet(Utilities.formatDate(new Date(),tss.getSpreadsheetTimeZone(),"yyyyMMdd HH:mm:ss.S"));
nsh.getRange(1,1).setValue("Data Sheet " + Utilities.formatDate(new Date(),tss.getSpreadsheetTimeZone(),"yyyyMMdd HH:mm:ss.S") );
tss.setActiveSheet(nsh);
const tssnames = tss.getSheets().map(sh => sh.getName()).flat();
const fldr = DriveApp.getFolderById("Folderid");
const files = fldr.getFilesByType(MimeType.GOOGLE_SHEETS);
while(files.hasNext()) {
let file = files.next();
let ss = SpreadsheetApp.openById(file.getId());
ss.getSheets().forEach((sh,i) => {
let vs = sh.getDataRange().getValues();
nsh.getRange(nsh.getLastRow() + 1,1,vs.length,vs[0].length).setValues(vs);
})
}
}
I'm trying to paste rows A3:M from XLE, XLF, XLU, XLI, and downwards into the sheet Calendar.
The code below works perfectly for pasting XLE A3:M but I can't figure out how to do the same with the other sheets and append the data at the end of the previous data pasted.
Below is the code:
function copyRowsWithSetValues() {
const id = '113-_bKJT9GkbXBGmB3sOQYhNMrAdQ2xx_oPmAPJrxHA';
const spreadsheet = SpreadsheetApp.openById(id);
const XLE = spreadsheet.getSheetByName('XLE');
const XLF = spreadsheet.getSheetByName('XLF');
const XLU = spreadsheet.getSheetByName('XLU');
const XLI = spreadsheet.getSheetByName('XLI');
const XLK = spreadsheet.getSheetByName('XLK');
const XLV = spreadsheet.getSheetByName('XLV');
const XLY = spreadsheet.getSheetByName('XLY');
const XLP = spreadsheet.getSheetByName('XLP');
const XLC = spreadsheet.getSheetByName('XLC');
const XLB = spreadsheet.getSheetByName('XLB');
const XLRE = spreadsheet.getSheetByName('XLRE');
const COUNTRY = spreadsheet.getSheetByName('COUNTRY');
const Calendar = spreadsheet.getSheetByName('Calendar');
var lastRow = Calendar.getLastRow();
var lastColumn = Calendar.getLastColumn();
var range_to_copy = XLE.getRange("A3:M");
var range_to_paste = Calendar.getRange(lastRow + 1, 2);
range_to_copy.copyTo(range_to_paste, SpreadsheetApp.CopyPasteType.PASTE_FORMAT);
}
I thought I could copy the data from each sheet using this code: var range_to_copy = XLE.getRange("XLE!A3:M, XLF!A3:M, XLU!A3:M"); and then paste that into the main sheet Calendar.
Try is this way
function copyRows() {
const ss = SpreadsheetApp.openById("id");
const shts = ['XLE','XLF','XLU','XLI','XLK','XLV','XLY','XLP','XLC','XLB','XLRE'];
const cal = ss.getSheetByName('Calendar');
shts.forEach((n,i) => {
let sh = ss.getSheetByName(n);
let src = sh.getRange("A3:M" + sh.getLastRow());
let des = cal.getRange(cal.getLastRow() + 1,2);
src.copyTo(des, SpreadsheetApp.CopyPasteType.PASTE_FORMAT);
});
}
I currently have a script on Google Sheets that auto deletes rows after a certain date. However, I would like to change it so that it auto archives the rows to another sheet instead. I added in the target sheet , but I'm at a loss on how to move the rows, before it deletes.
function ArchiveOldEntries() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Form Responses 1");
var datarange = sheet.getDataRange();
var lastrow = datarange.getLastRow();
var values = datarange.getValues();
var targetSheet = ss.getSheetByName("Archive");
var currentDate = new Date()//today
var yesterday = new Date();//yesterday
yesterday.setDate(currentDate.getDate() - 1);
for (i=lastrow;i>=2;i--) {
var tempDate = values[i-1][2];
if (tempDate <= yesterday)
{
sheet.deleteRow(i)
}
}
}
Archive and Delete rows one day old or more
function ArchiveOldEntries() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");//source sheet
const vs = sh.getDataRange().getValues();
const tsh = ss.getSheetByName("Sheet1");//archive sheet
const dt = new Date();
const ytdv = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate() - 1).valueOf();//yesterday value
let d = 0;
vs.forEach((r,i) => {
let cdv = new Date(r[2]).valueOf();//date is in column3
if(cdv <= ytdv) {
tsh.getRange(tsh.getLastRow() + 1,1,1,r.length).setValues([r])
sh.deleteRow(i + 1 - d++)
}
});
}
I have a script that creates a new Google Sheet file and names it based on a variable in a different sheet. After the sheet is created I am trying to copy all data from a template sheet, including merged cells and formatting. The scrip currently works in all aspects except the formatting. I am having a very hard time to get it to work. I would even be fine with just duplicating the sheet and having it rename based on my previous criteria.
function createNewSheet(e) {
const sh = e.range.getSheet();
var name = sh.getRange(e.range.rowStart, 1).getValue();
var crNew = SpreadsheetApp.create("Job Traveler-" + name);
var ssNew = SpreadsheetApp.openByUrl(crNew.getUrl()).getId();
importRange("1X4iOzc_shcOR8UM7OEM4F1-eR62YZmwKWyyEuu59Pf4","Job!A1:D", ssNew,"Sheet1!A1");
}
function importRange(sourceId,sourceRange,destinationID,destinationRangeStart) {
var sourceSS = SpreadsheetApp.openById(sourceId);
var sourceRng = sourceSS.getRange(sourceRange);
var sourceVals = sourceRng.getValues();
var destinationSS = SpreadsheetApp.openById(destinationID);
var destStartRange = destinationSS.getRange(destinationRangeStart);
var destSheet = destinationSS.getSheetByName(destStartRange.getSheet().getName());
var row = destStartRange.getRow();
var col = destStartRange.getColumn();
var rows = sourceVals.length;
var cols = sourceVals[0].length;
destSheet.getRange(row,col,rows,cols).setValues(sourceVals);
var merged = sourceRng.getMergedRanges();
var rowOffset = destStartRange.getRow()-sourceRng.getRow();
var columnOffset = destStartRange.getColumn()-sourceRng.getColumn();
for( var i=0; i<merged.length; i++ ) {
row = merged[i].getRow()+rowOffset;
col = merged[i].getColumn()+columnOffset;
rows = merged[i].getNumRows();
cols = merged[i].getNumColumns();
destSheet.getRange(row,col,rows,cols).merge();
}
}
Any advice would be much appreciated. I am no expert so I do apologize.
Best
Here is a snippet from one of my projects where I set the border and fill color
for (i = 0; i < numCount; i++) {
sheet.getRange(i + row2SetValues, col2SetValues).setValue(randNumbers[i]);
}
sheet.getRange(row2SetValues, col2SetValues, numCount, 1).setBorder(true, true, true, true, true, true, 'black', SpreadsheetApp.BorderStyle.SOLID_LIGHT);
sheet.getRange(row2SetValues, col2SetValues, numCount, 1).setBackground("#bdd4f9");
}
I tried to fill it with my sheet data, but that
var dataRange = sheet.getDataRange();
get an error. What should I do?
function RefreshImports() {
var lock = LockService.getScriptLock();
if (!lock.tryLock(5000)) return; // Wait up to 5s for previous refresh to end.
var id = "1r7TgCWXfjmcjufT0yz9qcFDlr482SdHDHlZYblXyAt0"; // [YOUR SPREADSHEET ID]
var ss = SpreadsheetApp.openById(id);
var sheet = ss.getSheetByName("crypto"); // sheet name
var dataRange = sheet.getDataRange();
var formulas = dataRange.getFormulas();
var content = "";
var now = new Date();
var time = now.getTime();
var re = /.*[^a-z0-9]import(?:xml|data|feed|html|range)\(.*/gi;
var re2 = /((\?|&)(update=[0-9]*))/gi;
var re3 = /(",)/gi;
for (var row=0; row<formulas.length; row++) {
for (var col=0; col<formulas[0].length; col++) {
content = formulas[row][col];
if (content != "") {
var match = content.search(re);
if (match !== -1 ) {
// import function is used in this cell
var updatedContent = content.toString().replace(re2,"$2update=" + time);
if (updatedContent == content) {
// No querystring exists yet in url
updatedContent = content.toString().replace(re3,"?update=" + time + "$1");
}
// Update url in formula with querystring param
sheet.getRange(row+1, col+1).setFormula(updatedContent);
}
}
}
}
// Done refresh; release the lock.
lock.releaseLock();
// Show last updated time on sheet somewhere
sheet.getRange(7,2).setValue("Rates were last updated at " + now.toLocaleTimeString())
}
I set up the trigger.
Not sure what you trying to do and you explanation leaves a lot to be desired.
So this is a simple way to put your formulas into a sheet named "Destination".
function RefreshImports() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("crypto");
const rg = sh.getDataRange();
const formulas = rg.getFormulas();
sh.getRange(1,1,formulas.length,formulas[0].length).setFormulas(formulas);
}