Lock a sheet then export URL - google-apps-script

Absolute noobie here, just trying to automate a process we currently do manually between google sheets.
I'd like to have a script attached to a button that does the following when pressed -
"lock" a vlookup or freeze a cell's contents. (I use a separate sheet of prices for materials that changes over time. When a quote gets accepted, I want to be able to "lock" the data that's already been pulled across from the other sheet, so the customer only pays what they've been quoted.
export the current sheet URL (or ID) to another sheet. I've got a "dashboard" sheet that we use as an overview of all the other sheets. Once the button is pressed I want to add the current sheet to the list of sheets we are monitoring on the dashboard sheet. Essentially I want to be able to extract the url of the sheet where we've just pressed the button, and add that url (or ID) to a list on another sheet.
Hope that makes sense! Any help is greatly appreciated.

This will get you started. The copyUrl function will paste the url to the first empty row in column B, you can change the column by changing the 2 on codeline 12.
function freeze(){
const ss = SpreadsheetApp.getActiveSpreadsheet();
const activeSheet = ss.getActiveSheet();
activeSheet.getDataRange().copyTo(activeSheet.getDataRange(),{contentsOnly:true});
}
function copyUrl(){
const targetSheetId = 'xxxxxx';
const targetSheetName = 'sheetname';
const currentUrl = SpreadsheetApp.getActiveSpreadsheet().getUrl();
const target = SpreadsheetApp.openById(targetSheetId).getSheetByName(targetSheetName);
target.getRange(target.getLastRow()+1,2).setValue(currentUrl);
}
References
copyTo(spreadsheet)
getLastRow()

Related

Can i have a simple script on sheet1 and sheet2?

I have made a script that automatically sorts data when i make a change. It workds fine on the one sheet but i cannot find a way to apply it on sheet2 too.
So i need it to sort both sheet1 and 2 (the sheets are simular so the same sort range and everything needs to be the same - i just need it to apply on sheet2 also-
I have tried to make a copy of the code and change sheet_name to sheet2.
I Insert picture of the code. I would be very happy if you could help.
Explanation:
Take advantage of the event object. This will give you very important information regarding the edit/event which took place.
The idea is to use the script for multiple sheets. One way to do that is to construct an array of the sheet names you want to include:
const sheet_names = ["Management Associate","Finance Associate"];
and check if the name of the active sheet is included in this list:
if(sheet_names.includes(sheet.getName())){
// the rest of the code here
}
As a more complete implementation, I modified the last line of your code to include the name of the sheet that was edited. To do that, I used template literals but of course this approach is optional:
ss.toast(`Sort complete in ${sheet.getName()}`);
Solution:
function onEdit(e) {
const sheet_names = ["Management Associate","Finance Associate"]; // add sheets here
const sort_data_range = "A2:H999";
const sort_order = [{column:6, ascending:true}];
const ss = e.source;
const sheet = ss.getActiveSheet();
if(sheet_names.includes(sheet.getName())){
const range = sheet.getRange(sort_data_range);
range.sort(sort_order);
}
ss.toast(`Sort complete in ${sheet.getName()}`);
}

Script that adds new row to sheets in selected AND another Google Spreadsheet

I'm working on a Spreadsheet to keep track of team member's project hours. I've created a Spreadsheet per team member for them to fill out weekly, and a project overview Spreadsheet that takes in all data through IMPORTRANGE.
To be able to quickly add a new project I want a macro to insert a new row in the Project overview + the separate Spreadsheets per team member. However I can't figure out how to write the correct code for the separate team member Spreadsheets. What's going wrong here?
If possible I'd also like to make a macro to DELETE a row in the project overview + team member spreadsheets, and one to HIDE a row...
Project overview
Team member Kate
Team member David
My current code:
function InsertRow() {
var ss = SpreadsheetApp.getActive();
var allsheets = ss.getSheets();
var row = SpreadsheetApp.getActiveRange().getRow();
// Array holding the names of the sheets to exclude from the execution
// I only managed to make it work when I exclude the sheet that I actually want to affect instead of the other way around?
var exclude = (["PROJECTS"] ||
SpreadsheetApp.openById("1xjR3lx5_KAA9nqiD3YsjZnulQaMyWGPQqgYsjtzQ0xI").getSheets() ||
SpreadsheetApp.openById("1Q5gtZlqf41of1Zwi8pvZbDx4NN5LcDh5SxfwasLUDMU").getSheets())
for(var s in allsheets){
var sheet = allsheets[s];
// Stop iteration execution if the condition is meet.
if(exclude.indexOf(sheet.getName())==-1) continue;
sheet.insertRowBefore(row);
}
}
As I see it you have a couple of options, which I'll be listing here as A, B, and C. Please note that you might need two different .GS files as you are linking to two sheets
A
Try code found on google app script documentation
I found the google apps script documentation for this command found here, so you might want to check that for this questions and others , but here is the exact code included
// The code below opens a spreadsheet using its ID and logs the name for it.
// Note that the spreadsheet is NOT physically opened on the client side.
// It is opened on the server only (for modification by the script).
var ss = SpreadsheetApp.openById("abc1234567");
Logger.log(ss.getName());
B
use open by url instead of open by id
Your issue might be that your current id isn't correct, I have no way of knowing, so here is some alternate code here (link to documentation here)
// The code below opens a spreadsheet using its id and logs the name for it.
// Note that the spreadsheet is NOT physically opened on the client side.
// It is opened on the server only (for modification by the script).
var ss = SpreadsheetApp.openByUrl(
'https://docs.google.com/spreadsheets/d/abc1234567/edit');
Logger.log(ss.getName());
C
Tie the google script to one sheet
This last option doesn't require any code, just an explanation. Instead of trying to link your script to two separate sheets, you might be able to automatically link it to a single google sheet and create two pages in the sheets file that you treat as two different sheets but are one thing. This might not be what you want, but I included it anyways. You link the sheet to the code automatically by:
1 opening your sheet
2 going to "tools"
3 clicking script editor
4 copy and paste your code (except for the "open by id" part)
5 success!
Your exclude variable doesn't contain what you think it does. You're using an "or" operator (||), which will take the first "truthy" value and skip the rest.
console.log((["PROJECTS"] || 'something else')); // ["PROJECTS"]
Moreover, you don't have a good way of telling which spreadsheet belongs to which team member. To solve that problem, you can create an object.
const teamSpreadsheetIds = {
'DAVID': 'ABC',
'KATE': '123',
};
console.log(teamSpreadsheetIds['DAVID']); // ABC
With the teamSpreadsheetIds object, you can now go about updating your team member sheets locally as well as their individual spreadsheets. The "PROJECTS" sheet is unique, so there's only one check for it.
function InsertRow() {
const ss = SpreadsheetApp.getActive();
const allSheets = ss.getSheets();
const row = SpreadsheetApp.getActiveRange().getRow();
const teamSpreadsheetIds = {
'DAVID': '1Q5gtZlqf41of1Zwi8pvZbDx4NN5LcDh5SxfwasLUDMU',
'KATE': '1xjR3lx5_KAA9nqiD3YsjZnulQaMyWGPQqgYsjtzQ0xI',
};
for (let sheet of allSheets) {
const sheetName = sheet.getName();
const memberSpreadsheetId = teamSpreadsheetIds[sheetName];
const isSkippable = memberSpreadsheetId === undefined && sheetName !== 'PROJECTS';
if (isSkippable) { continue };
// Insert a row in the local sheet
sheet.insertRowBefore(row);
// Get the member sheet and insert a row
if (memberSpreadsheetId) {
const memberSpreadsheet = SpreadsheetApp.openById(memberSpreadsheetId);
const memberSheet = memberSpreadsheet.getSheets()[0]; // Assumes the first sheet is the one to modify
memberSheet.insertRowBefore(row);
}
}
}

Insert new row at top of sheet based on new rows in another tab

I have a Google sheet with a listing of job candidates in one tab (Primary candidates sheet). What I would like to do is paste a daily export of candidates into another tab and have new candidates from the latest export inserted up top of the primary candidates sheet.
I've tried to search this methodology online which typically leads to success after some research. However, I can't seem to find any documentation on macros, scripts, or formulas which could accomplish this.
Wanted to see if anyone had any resources for additional research.
You can use below code to copy data from source sheet into top of destination sheet. Enter sheet names accordingly. Save. From script editor menu, Run > Function > Test, to test. It'll insert new rows in destination sheet and source sheet data will stay as is.
function test() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getSheetByName('source sheet name here'); // change here
var des = ss.getSheetByName('destination sheet name here'); // change here
var sv = source
.getDataRange()
.getValues();
sv.shift();
des.insertRowsAfter(1, sv.length);
des.getRange(2, 1, sv.length, source.getLastColumn()).setValues(sv);
}

How to duplicate a sheet on a user-selected target spreadsheet and copy data

I’m very new to Google Apps Script, and I’m having trouble trying to accomplish my goal.
I have a Google Sheets Workbook that allows users to:
Select a name from a drop down (each name has a unique/individual
google workbook URL associated with it)
Type in a desired spreadsheet name
Press a “Push Sheet” button
Once the user presses the button, I’m trying to accomplish the following things:
Duplicate the sheet 'Template - Do Not Modify’ that already exists on target workbook (the URL associated with the selected name)
Rename the duplicated sheet to the desired spreadsheet name
Copy the range A7:D150 from the sheet “Tracker” on the original workbook to the range A7:D150 newly created sheet on the target workbook
The original sheet is set up to have the user authorize the workbook connection prior to running the script.
Here's my code:
function cloneGoogleSheet() {
var sheet = SpreadsheetApp.getActiveSheet();
var name = sheet.getRange("B10").getValue();
var url = sheet.getRange("f5").getValue();
var tss = SpreadsheetApp.openByUrl(url);
tss.setActiveSheet(tss.getSheetByName('Template - Do Not Modify'));
tss.duplicateActiveSheet();
var activesheet = tss.getActiveSheet();
activesheet.setName(name);
}
My issues are:
It doesn't seem like utilizing ActiveSheets is a safe way to do all of this and that there's a better way.
When attempting to use the URL variable (the script runs fine with a hardcoded URL value), I get an invalid argument: URL error. The cell F5 updates to a new URL based on what name is selected from the drop down, using a lookup which references names with unique URLs:
=lookup(B4,
{P71,P72,P73,P74,P75,P76,P77},
{Q71,Q72,Q73,Q74,Q75,Q76,Q77}
)
Given the fact that I'm using all these ActiveSheet variables, I'm not sure how to get back to my original sheet to copy the ranges.
I would very much appreciate someone showing me the correct way to do this. Thanks!
Have you tried using "getSheetByName"?
Try Armit Agarwal's tutorial on Duplicate a Sheet in Google Spreadsheets:
function cloneGoogleSheet() {
var name = "labnol";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Template').copyTo(ss);
/* Before cloning the sheet, delete any previous copy */
var old = ss.getSheetByName(name);
if (old) ss.deleteSheet(old); // or old.setName(new Name);
SpreadsheetApp.flush(); // Utilities.sleep(2000);
sheet.setName(company);
/* Make the new sheet active */
ss.setActiveSheet(sheet);
}

Google Sheets script to copy/paste from one sheet to another

Could someone help me with creating a script that does the following:
Function: Upon adding a new sheet to my already existing workbook, I would like it to copy Column "E" from Sheet 1 and (Paste Special > Conditional formatting only) to the newly introduced Sheet "X"
Where can I learn more on how to write code? I have never used Stackoverflow by the way someone just recommended me to come here. I believe I just answered my own question somehow on the post, which I am sure was wrong to do but I couldn't comment on an already existing answer without exceeding the limit.
// Adds custom menu
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('CustomMenu').addItem('Copy format', 'copyFormat') //Add function to menu.'GIVE NAME HERE', 'functionName'
.addToUi();
}
function copyFormat() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh1 = ss.getSheets()[0]; //Gets the first sheet of the workbook. Can use ss.getSheetByName('Name of sheet here'); If it is not the first sheet
var activeSh = ss.getActiveSheet(); //Get the active sheet, you should be on the sheet just added
var rowEnd = activeSh.getLastRow(); //Last row of active sheet
sh1.getRange("E1:E").copyFormatToRange(activeSh, 5, 5, 1, rowEnd); //Copy format, including conditional, to column E of active sheet
}
This just adds a button that allows you to select a cell and give it the same conditions has in the original sheet.
Example: Sheet 1: Column E1:E100 has a given condition.. which needs to apply in the exact same way to any new incoming sheets since they all come in the same format. Right now its at a point of which when a new sheet arrives in the workbook: I can enter the new sheet > Select the cell which requires the conditions > Select the custom menu > Cell gets conditioned. So the next step would be automate the process I just mentioned since there is several sheets added daily to the workbook.