I am copying a new instance of my spreadsheet without formulas into a folder. I found a script that works great here:
Copy an entire Spreadsheet, Just Preserve the Values.
I was trying to define a specific tab to copy but no luck.
var sheet = ss.getSheetByName('tab to dowload');
and
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheets()[2]);
function myFunction() {
var spreadsheetId = "###"; // Please set the source Spreadsheet ID.
var destFolderId = "###"; // 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) {
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);
}
Explanation:
Your goal is to pass selected sheets, based on their name, to the newly created file.
You can do that by defining a list with the selected sheets:
var selected_sheets = ['Sheet1','Sheet5'];
and then instead of using ss.getSheets() which gets every sheet, use this to get the sheet object of the selected sheet names:
var tempSheets = selected_sheets.map(sn=>ss.getSheetByName(sn))
.map(function(sheet) {
var dstSheet = sheet.copyTo(ss).setName(sheet.getSheetName() + "_temp");
var src = dstSheet.getDataRange();
src.copyTo(src, {contentsOnly: true});
return dstSheet;
});
Solution:
Please modify this list: var selected_sheets = ['Sheet1','Sheet5']; and replace Sheet1, Sheet5 to the name of your sheets. You can also have one sheet: e.g. var selected_sheets = ['Sheet1'];.
function myFunction() {
var spreadsheetId = "###"; // Please set the source Spreadsheet ID.
var destFolderId = "###"; // 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 selected_sheets = ['Sheet1','Sheet5']; // Add the sheets you want to copy here!
var tempSheets = selected_sheets.map(sn=>ss.getSheetByName(sn))
.map(function(sheet) {
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);
}
Related
function onEdit(e)
{
var datum = Utilities.formatDate(new Date(), "GMT+1", "dd.MM.YYYY");
var ss = SpreadsheetApp.getActive();
var newas = SpreadsheetApp.create("Sperren");
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sperren');
sheet.activate();
var temp = ss.duplicateActiveSheet();
range = temp.getDataRange();
range.copyTo(range, {contentsOnly: true});
temp.copyTo(newas);
ss.deleteSheet(temp);
newas.getSheetByName('Sperren');
newas.deleteActiveSheet();
var folderID = "Sperr Material";
var folderID2 = "Prozess";
var datei = newas.getRange("C3").getValues();
// var dateid = newas.getRange("G6").getValues();
var folder = DriveApp.getFoldersByName(folderID);
var theblob = newas.getBlob().setName(datei +" "+ datum);
var newFile = folder.next().createFolder(folderID2 +" "+ datei + " "+ datum).createFile(theblob);
}
/* #Process Form */
function processForm(formObject)
{
var url = "https://https://docs.google.com/spreadsheets/d/1v03Se_BaW-SqFJpN8TU9oEhT2eSvMRHvqwnh3s14lPY/edit#gid=645028893";
var as = SpreadsheetApp.openByUrl(url);
var ws = as.getSheetByName("Test");
/*ws.appendRow([formObject.material,
formObject.stückzahl,
formObject.label,
formObject.datum,
formObject.grund,
formObject.lgort,
formObject.name,
formObject.sgrund]);*/
ws.getRange("A2").setValue(formObject.material);
ws.getRange("B2").setValue(formObject.stückzahl);
ws.getRange("C2").setValue(formObject.label);
ws.getRange("D2").setValue(formObject.datum);
ws.getRange("E2").setValue(formObject.grund);
ws.getRange("F2").setValue(formObject.lgort);
ws.getRange("G2").setValue(formObject.name);
ws.getRange("H2").setValue(formObject.sgrund);
}
Can anyone help me here, i have Html Formular which sends the values to Google Sheet and Sheet should save on one column.
After that it should be transfer the value to another sheet, where is a specific Table, after that it should be save this table to Drive App with informations.
The first column will be changed by either request and by new change should Google Sheet save a new Datei.
but my OnEdit code will not work
if there is a new change should Google save it to a Folder in Drive APP.
But this onEdit code will not work :)
This question already has answers here:
Export Single Sheet to PDF in Apps Script
(3 answers)
Closed 2 years ago.
I am aware that similar type of question has being asked earlier under the Using Google Apps Script to save a single sheet from a spreadsheet as pdf in a specific folder
The code that was used is working for me and is mentioned below:
function generatePdf() {
// Get active spreadsheet.
var sourceSpreadsheet = SpreadsheetApp.getActive();
// Get active sheet.
var sheets = sourceSpreadsheet.getSheets();
var sheetName = sourceSpreadsheet.getActiveSheet().getName();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
// Set the output filename as SheetName.
var pdfName = sheetName;
// Get folder containing spreadsheet to save pdf in.
var parents = DriveApp.getFileById(sourceSpreadsheet.getId()).getParents();
if (parents.hasNext()) {
var folder = parents.next();
} else {
folder = DriveApp.getRootFolder();
}
// Copy whole spreadsheet.
var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(sourceSpreadsheet.getId()).makeCopy("tmp_convert_to_pdf", folder))
// Delete redundant sheets.
var sheets = destSpreadsheet.getSheets();
for (i = 0; i < sheets.length; i++) {
if (sheets[i].getSheetName() != sheetName) {
destSpreadsheet.deleteSheet(sheets[i]);
}
}
var destSheet = destSpreadsheet.getSheets()[0];
// Repace cell values with text (to avoid broken references).
var sourceRange = sourceSheet.getRange(1, 1, sourceSheet.getMaxRows(), sourceSheet.getMaxColumns());
var sourcevalues = sourceRange.getValues();
var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
destRange.setValues(sourcevalues);
// Save to pdf.
var theBlob = destSpreadsheet.getBlob().getAs('application/pdf').setName(pdfName);
var newFile = folder.createFile(theBlob);
// Delete the temporary sheet.
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
}
The problem that I encounter is that my source sheet has a few fields which are auto populated in the sheet using vlookup. These fields are exported in the temp file which is created by this script as I have checked the trash and the field values are present but the PDF generated by the code is missing all the vlookup data.
The sample image of PDF is as below in which the vlookup missing entries are marked in yellow:
While the temp google sheet which is in trash has the values in the respective cells. Screenshot of the same is below the vlookup fields are highlighted in red.
Kindly help me with the solution.
Add the contentOnly: true in line 38. See the code. Hope this solves the problem. This will clear all the formula's. (im not sure the setValues() accept this extra parameter. the copyTo does, so you can make a copy of the sheet to a contentOnly sheet and then use that for the pdf)
function generatePdf() {
// Get active spreadsheet.
var sourceSpreadsheet = SpreadsheetApp.getActive();
// Get active sheet.
var sheets = sourceSpreadsheet.getSheets();
var sheetName = sourceSpreadsheet.getActiveSheet().getName();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
// Set the output filename as SheetName.
var pdfName = sheetName;
// Get folder containing spreadsheet to save pdf in.
var parents = DriveApp.getFileById(sourceSpreadsheet.getId()).getParents();
if (parents.hasNext()) {
var folder = parents.next();
} else {
folder = DriveApp.getRootFolder();
}
// Copy whole spreadsheet.
var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(sourceSpreadsheet.getId()).makeCopy("tmp_convert_to_pdf", folder))
// Delete redundant sheets.
var sheets = destSpreadsheet.getSheets();
for (i = 0; i < sheets.length; i++) {
if (sheets[i].getSheetName() != sheetName) {
destSpreadsheet.deleteSheet(sheets[i]);
}
}
var destSheet = destSpreadsheet.getSheets()[0];
// Repace cell values with text (to avoid broken references).
var sourceRange = sourceSheet.getRange(1, 1, sourceSheet.getMaxRows(), sourceSheet.getMaxColumns());
var sourcevalues = sourceRange.getValues();
var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
destRange.setValues(sourcevalues, {contentsOnly:true});
// Save to pdf.
var theBlob = destSpreadsheet.getBlob().getAs('application/pdf').setName(pdfName);
var newFile = folder.createFile(theBlob);
// Delete the temporary sheet.
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
}
Just needed to add a line to flush the app did the work. Updated code:
function generatePdf() {
// Get active spreadsheet.
var sourceSpreadsheet = SpreadsheetApp.getActive();
// Get active sheet.
var sheets = sourceSpreadsheet.getSheets();
var sheetName = sourceSpreadsheet.getActiveSheet().getName();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
// Set the output filename as SheetName.
var pdfName = sheetName;
// Get folder containing spreadsheet to save pdf in.
var parents = DriveApp.getFileById(sourceSpreadsheet.getId()).getParents();
if (parents.hasNext()) {
var folder = parents.next();
}
else {
folder = DriveApp.getRootFolder();
}
// Copy whole spreadsheet.
var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(sourceSpreadsheet.getId()).makeCopy("tmp_convert_to_pdf", folder))
// Delete redundant sheets.
var sheets = destSpreadsheet.getSheets();
for (i = 0; i < sheets.length; i++) {
if (sheets[i].getSheetName() != sheetName){
destSpreadsheet.deleteSheet(sheets[i]);
}
}
var destSheet = destSpreadsheet.getSheets()[0];
// Repace cell values with text (to avoid broken references).
var sourceRange = sourceSheet.getRange(1,1,sourceSheet.getMaxRows(),sourceSheet.getMaxColumns());
var sourcevalues = sourceRange.getValues();
var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
destRange.setValues(sourcevalues);
SpreadsheetApp.flush();
// Save to pdf.
var theBlob = destSpreadsheet.getBlob().getAs('application/pdf').setName(pdfName);
var newFile = folder.createFile(theBlob);
// Delete the temporary sheet.
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
}
I have been trying to combine two scripts to create a script that i can run on demand by using a custom menu. I would like the script to do the following:
Make a copy with values and format only (no formulas and importrange), of a existing spreadsheet.
Name the copy the same as the original spreadsheet + timestamp in "yyyy-mm-dd" format.
Place the copy in a specific subfolder.
Also to be able to create the copy on demand, using a custom menu button to do so.
And lastly to have a custom menu button for easy access to said subfolder.
So far i have found two scripts that can do parts of this task but have not been able to combine them to a single script. Is this possible?
See the code below for the two scripts:
SCRIPT 1
// Program: Archive GSheet with Date Stamp
// Programmer: Michael Fryar
// Date: 19 September 2017
// Google Apps Script to copy Google Sheet to subfolder with date stamp in name
// Add Custom Menu
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Archive')
.addItem('Archive a copy with timestamp', 'archiveCopy')
.addItem('Open folder', 'openArchive')
.addToUi();
}
// Define function to copy sheet to subfolder with date stamp in name
// Building on https://gist.github.com/abhijeetchopra/99a11fb6016a70287112
function archiveCopy() {
// Replace "spreadsheetId" with the ID of the Google Sheet you wish to copy
var file = DriveApp.getFileById("ID")
// Replace "folderId" with the ID of the folder where you want the copy saved
var destination = DriveApp.getFolderById("ID");
// Get timezone for datestamp
var timeZone = Session.getScriptTimeZone();
// Generate datestamp and store in variable formattedDate as year-month-date
var formattedDate = Utilities.formatDate(new Date(), timeZone , "yyyy-MM-dd");
// Replace "file_name" with the name you want to give the copy
var name = formattedDate + " Copy";
// Archive copy of "file" with "name" at the "destination"
file.makeCopy(name, destination);
}
// Define function to open archive folder in new tab
// Building on https://www.youtube.com/watch?v=2y7Y5hwmPc4
function openArchive() {
// Replace "folderId" with the ID of the folder where you want copies saved
var url = "https://drive.google.com/drive/folders/"
// HTML to open folder url in new tab and then close dialogue window in sheet
var html = "<script>window.open('" + url + "');google.script.host.close();</script>";
// Push HTML into user interface
var userInterface = HtmlService.createHtmlOutput(html);
SpreadsheetApp.getUi().showModalDialog(userInterface, 'Opening Archive Folder');
}
SCRIPT 2
function copyEntireSpreadsheet() {
var id = "ID"; // Please set the source Spreadsheet ID.
var ss = SpreadsheetApp.openById(id);
var srcSheets = ss.getSheets();
var tempSheets = srcSheets.map(function(sheet, i) {
var sheetName = sheet.getSheetName();
var dstSheet = sheet.copyTo(ss).setName(sheetName + "_temp");
var src = dstSheet.getDataRange();
src.copyTo(src, {contentsOnly: true});
return dstSheet;
});
var destination = ss.copy(ss.getName() + " - " + new Date().toLocaleString());
tempSheets.forEach(function(sheet) {ss.deleteSheet(sheet)});
var dstSheets = destination.getSheets();
dstSheets.forEach(function(sheet) {
var sheetName = sheet.getSheetName();
if (sheetName.indexOf("_temp") == -1) {
destination.deleteSheet(sheet);
} else {
sheet.setName(sheetName.slice(0, -5));
}
});
}
UPDATE!
I found another script that could do the parts that i needed and was finally able to combine them together. Posting script below to benefit others in search of something similar:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Archive')
.addItem('Archive copy with timestamp', 'Archive')
.addItem('Open folder', 'openArchive')
.addToUi();
}
function Archive() {
var spreadsheetId = "###"; // Please set the source Spreadsheet ID.
var destFolderId = "###"; // 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) {
var dstSheet = sheet.copyTo(ss).setName(sheet.getSheetName() + "_temp");
var src = dstSheet.getDataRange();
src.copyTo(src, {contentsOnly: true});
return dstSheet;
});
// Get timezone for datestamp
var timeZone = Session.getScriptTimeZone();
// Generate datestamp and store in variable formattedDate as year-month-date
var formattedDate = Utilities.formatDate(new Date(), timeZone , "yyyy-MM-dd");
// Copy the source Spreadsheet.
var destination = ss.copy(ss.getName() + " " + formattedDate);
// 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);
}
// Define function to open archive folder in new tab
// Building on https://www.youtube.com/watch?v=2y7Y5hwmPc4
function openArchive() {
// Replace "folderId" with the ID of the folder where you want copies saved
var url = "https://drive.google.com/drive/folders/folderid"
// HTML to open folder url in new tab and then close dialogue window in sheet
var html = "<script>window.open('" + url + "');google.script.host.close();</script>";
// Push HTML into user interface
var userInterface = HtmlService.createHtmlOutput(html);
SpreadsheetApp.getUi().showModalDialog(userInterface, 'Opening Archive Folder');
}
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.
I am stuck here. I would like to create a sheet with a name of a given cell in my main sheet (this part works). Then, I would like to copy the values from cells G4:I26 into the new sheet that was just created (not working). Here is what I have so far:
function newSheetLast() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = ss.getRange("J1").getDisplayValue();
ss.insertSheet(sheetName, ss.getSheets().length);
var source = ss.getRange('G4:I26');
source.copyTo(sheetName.getRange('A1'), {contentsOnly: true});
source.clear();
Try the following script code:
function newSheetLast() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1');
var newSheetName = ss.getRange('J1').getDisplayValue();
var newSheet = ss.insertSheet(newSheetName, ss.getSheets().length);
var source = sheet.getRange('G4:I26');
source.copyTo(newSheet.getRange('A1'), {contentsOnly: true});
source.clearContent();
};
Change the Sheet name "Sheet1" in the above code with the sheet's name in which you have the cell "J1" containing the new sheet's name.