I have an apps script that creates a new Google workbook each time a new entry is made in Column A of sheet1 of a Master workbook and renames that new workbook to the last entered data in column A of sheet1 of the Master workbook. It also pastes the URL of the newly created workbooks in Column J of sheet1 of the master workbook.
The apps script code is run by an onEdit trigger I set manually. Each time a new workbook is created, the last row that was edited gets copied (from A to J) to the newly created workbook. Every workbook both the master workbook and the newly created workbooks gets shared with a list of emails typed in Column B of Sheet 2 of the master workbook (as editors). Below is the code.
function myFunction() {
// Creating new Spreadsheet.
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
const lastRow = sh.getLastRow();
const values = sh.getRange(`A${lastRow}:J${lastRow}`).getValues()[0];
const nss = SpreadsheetApp.create(values[0]);
const url = nss.getUrl();
sh.getRange(lastRow, 10).setValue(url);
values[9] = url;
nss.appendRow(values);
// Sharing Spreadsheets.
const sheet2 = ss.getSheetByName("Sheet2");
const emails = [...new Set(sheet2.getRange("B1:B" + sheet2.getLastRow()).getValues().reduce((ar, [b]) => {
if (b && b.includes("#")) ar.push(b);
return ar;
}, []))];
ss.getEditors().forEach(e => ss.removeEditor(e));
ss.addEditors(emails);
nss.addEditors(emails);
}
I have been trying to make the master workbook copy a template sheet (by ID), but I haven't done so successfully. I need your help on this. Your help is appreciated.
Copy sheet from Master to new Spreadsheet:
const MasterSpreadsheet = SpreadsheetApp.getActiveSpreadsheet()
const NewSpreadsheetId = SpreadsheetApp.create(`New`).getId()
const NewSpreadsheet = SpreadsheetApp.openById(NewSpreadsheetId)
MasterSpreadsheet.getSheetByName(`TargetSheet`)
.copyTo(NewSpreadsheet)
.setName(`CopiedSheet`)
Copy Spreadsheet to new Spreadsheet:
const MasterSpreadsheet = SpreadsheetApp.getActiveSpreadsheet()
const NewSpreadsheetId = MasterSpreadsheet.copy(`Copy of ${MasterSpreadsheet.getName()}`).getId()
const NewSpreadsheet = SpreadsheetApp.openById(NewSpreadsheetId)
Note: Copying a Spreadsheet will place the new Spreadsheet file in your Drive 'root' folder. You can however, use DriveApp to get the file using NewSpreadsheetId and move it to a specified folder.
If neither of these help, or you need further explanation, please let me know!
Related
The table (master) has links that point to cells within the table.
When creating a copy of this table (master copy), these links lead to the original table (master).
How can I automatically change the links so that they in the copy (master copy) refer to cells inside the copy (master copy)?
I'll link the script to the "fix links" button.
Link to table - https://docs.google.com/spreadsheets/d/1Jrpjm7Yjwp-3WTFKyBz87laPeq6ksjwPaaiWWNcIoow/edit?usp=sharing
I think it can be done by replacing #gid (sheetID) in the links. I found information how to get #gid (sheetID) - Google Apps Script, Google Sheets - Getting Spreadsheet ID and Sheet ID programmatically
But I don't know how to automatically find and replace all #gid (sheetID) in the current table in the links.
You can do it manually using Find and Replace. But it needs to be automated.
I believe your goal is as follows.
From your provided sample Spreadsheet, you want to change the hyperlinks in the range of "I6:I10" with the active sheet instead of the original sheet.
In this case, how about the following sample script?
Sample script 1:
Please copy and paste the following script to the script editor of Spreadsheet and save the script. And, as a test, please copy master, and please open the copied sheet. And then, please run this script. By this, the hyperlinks in the range of "I6:I10" are changed from the original sheet to the currently active sheet.
function myFunction() {
const checkRange = "I6:I10"; // This is from yoru sample Spreadsheet.
const sheet = SpreadsheetApp.getActiveSheet();
const sheetId = sheet.getSheetId();
const range = sheet.getRange(checkRange);
const richTextValues = range.getRichTextValues().map(r => r.map(c => {
const link = c.getLinkUrl();
return link ? c.copy().setLinkUrl(link.replace(/#gid\=.*&/, `#gid=${sheetId}`)).build() : c;
}));
range.setRichTextValues(richTextValues);
}
Sample script 2:
In this sample script, "master" sheet is copied to the same Spreadsheet with the specific sheet name, and the hyperlinks in the range of "I6:I10" are changed from the original sheet to the currently active sheet.
function myFunction2() {
const newSheetName = "sample"; // Please set the new sheet name by copying "master" sheet.
const checkRange = "I6:I10"; // This is from yoru sample Spreadsheet.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sourceSheet = ss.getSheetByName("master");
const newSheet = sourceSheet.copyTo(ss).setName(newSheetName);
const sheetId = newSheet.getSheetId();
const range = newSheet.getRange(checkRange);
const richTextValues = range.getRichTextValues().map(r => r.map(c => {
const link = c.getLinkUrl();
return link ? c.copy().setLinkUrl(link.replace(/#gid\=.*&/, `#gid=${sheetId}`)).build() : c;
}));
range.setRichTextValues(richTextValues);
}
References:
getRichTextValues()
setRichTextValues(values)
I have written a script that duplicates an entire google sheet to a new document and saves it in a folder when a button is pressed, however, I only want it to copy a specific range (A1:F52).
Every attempt I make at modifying the script to only have .getRange("A1:F52") throws an error that getrange is not a function, what am I doing wrong and how should it actually be?
This script functions perfectly as it is, but I just want it to only take the range across, any help would be greatly appreciated.
// SAVE INVOICE
function copyRowsWithCopyTo() {
// SET VALUES IN CELL
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A1:F60').activate();
spreadsheet.setCurrentCell(spreadsheet.getRange('F3'));
spreadsheet.getRange('A1:F60').copyTo(spreadsheet.getActiveRange(),
SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
//COPY CONTENTS TO INVOICE SHEET
let spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
let sourceSheet = spreadSheet.getSheetByName('DO NOT EDIT');
// SET SPREADSHEET MONTH
let targetSheet = spreadSheet.getSheetByName('JANUARY 2023');
let row = sourceSheet.getActiveRange().getRow();
let activeRow = sourceSheet.getRange( 2,1,1,20);
let last_row = targetSheet.getLastRow();
activeRow.copyTo(targetSheet.getRange('A'+(last_row+1)+':H'+(last_row+1)),{contentsOnly:true});
// REPLICATE INVOICE SHEET TO NEW DOCUMENT AND SAVE IN INVOICE FOLDER
var sheet = SpreadsheetApp.getActiveSheet(); // Get current active sheet.
//GET SHEET NAME
var sheet_name1 = sheet.getRange("F4").getValue(); // Get the value of cell F4, used to name the new spreadsheet.
var sheet_name2 = " - "
var sheet_name3 = sheet.getRange("A9").getValue(); // Get the value of cell A9, used to name the new spreadsheet.
var sheet_name = sheet_name1 + sheet_name2 + sheet_name3
var folder = DriveApp.getFolderById("1DVdganPrCfePk41kteKnXSqKmL4Pivu5");
// Get the ID of the folder where you will place a copy of the spreadsheet.
var newSS = SpreadsheetApp.create(sheet_name); // create new blank spreadsheet in a root folder
var asFile = DriveApp.getFileById(newSS.getId()); // get new spreadsheet as a file
folder.addFile(asFile); // add this file to destination folder
DriveApp.getRootFolder().removeFile(asFile); // remove a file from root folder
var copiedSheet = sheet.copyTo(newSS).getRange("A1:F52"); // copy active sheet to new spreadsheet
copiedSheet.setName(sheet_name); // rename copied sheet
newSS.deleteSheet(newSS.getSheetByName('Sheet1')); // remove "Sheet1" sheet which was created by default in new spreadsheet
// run Clear function
clear()
}
I am clearly mistyping the .getrange parameter as it throws an error, but I cannot work out what im doing wrong.
I have an app script code that Creates a new workbook when new data is entered in Google Sheet. The code is below.
function myFunction() {
// The code below creates a new spreadsheet "New Sheet Name" and logs the URL for it
var ssNew = SpreadsheetApp.create();
Logger.log(ssNew.getUrl());
}
I want the new spreadsheet name to be the last data entered in Column A and also the URL for the new workbook to be pasted in Column J of the same row as the last data in Column A
From I have an app script code that Creates a new workbook when new data is entered in Google Sheet., I thought that you might be running the script with the installable OnEdit trigger. But from your showing script, I thought that you might have wanted to directly run with the script editor. If my understanding is correct, how about the following modification?
Modified script:
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = sheet.getLastRow();
var title = sheet.getRange("A" + lastRow).getValue();
var ssNew = SpreadsheetApp.create(title);
sheet.getRange("J" + lastRow).setValue(ssNew.getUrl());
}
When this script is run, the title is retrieved from the column "A" of the last row. And, the URL of created Spreadsheet is put in the column "J" of the same row.
Reference:
getLastRow()
Creating a new Spreadsheet
function myFunction() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
const nss = SpreadsheetApp.create(sh.getRange(sh.getLastRow(), 1).getDisplayValue())
sh.getRange(sh.getLastRow(), 10).setValue(nss.getUrl());
}
trying to figure out how to give a new sheet that is copied into a folder a specific name each time from a button script. The specific name would come from a specific cell each time.
Here's the current code being used and the New Sheet is what I'm trying to have named from cell B3 on a specific spreadsheet each time. No idea how to do this, it just names it NEW SHEET each time and then errors out when I try to do B3.
function cloneGoogleSheet() {
var destFolder = DriveApp.getFolderById("Folder Name");
DriveApp.getFileById("Folder Name").makeCopy('NEW SHEET', destFolder);
SpreadsheetApp.getActive().getSheetByName('NEW SHEET').setName('Specific Sheet!B3')
}
Any help is appreciated!
function cloneGoogleSheet() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
const name = sh.getRange('A1').getDisplayValue();
const destFolder = DriveApp.getFolderById("Folder Id");
DriveApp.getFileById("file id").makeCopy(name, destFolder);
}
Get used to using file id's and not names.
I am trying to find a way of creating a script that will copy a GoogleSheet, which is the Master file, into a new location with a new name. The name of the file would be located in Cell A1 with the folder location in Cell A2. With Excel it was relatively easy, but I just can't seem to get anything to work with GoogleSheets.
Assuming this is the Master file:
Replace cell A2 with the folder id of the destination folder, choose the name of the copy in cell A1 and change Sheet1 to your specific case.
Copy and execute this function from the script editor:
function myFunction() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet1");
const new_name = sh.getRange('A1').getValue();
const dest_folder_id = sh.getRange('A2').getValue();
const dest_folder = DriveApp.getFolderById(dest_folder_id);
DriveApp.getFileById(ss.getId()).makeCopy(new_name, dest_folder);
}
References:
makeCopy(name, destination)
getRange()
Class Spreadsheet