I am writing a Google Sheets Script to save as Sheet file to a PDF. I want the File Name to be Cell A11 (which is a combination of texts from other cells). So I wrote this:
file.setName(Cell + '.pdf');
My question is: how can I define "Cell" to pull data from A11 from inside the spreadsheet.
Here. Add this function to your script.
function getFilename() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName('Sheet1');
// Edit the sheet name as necessary
var cell = sheet.getRange('A11');
var filename = cell.getValue();
return filename;
}
Then change
file.setName(Cell + '.pdf');
to
file.setName(getFilename() + '.pdf');
Related
I have two sheets
Sheet1
and sheet2
What I want to do is one by one copy the values of each row from sheet 1 to sheet 2. whenever one row is copied from sheet1 to sheet2 (i.e values from cell A to F). the cell G2 and H2 (in sheet2) get values ( based on multiple different formulas filter function, pivit tables etc from other sheets ) When I get the updated values in sheet 2 I want to copy the values form G2 and H2 to the respective row back in sheet 1
basically I want to use the sheet2 as a custom function where cell A2, B2, C2, D2, H2, F2 are inputs and cell G2 and H2 are outputs.
I tried using macros but what is required is a combination of both Absolute and Relative referencing and that doesn't seem to be possible
gif of the process I am doing manually
Did it with appscript and menue items
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('AERON')
.addItem('Calculate Single Cabnets', 'menuItem1')
.addSeparator()
.addItem('Calculate Multiple Cabnets', 'menuItem2')
.addToUi();
}
function menuItem2() {
var sheet = SpreadsheetApp.getActiveSheet();
var selection = sheet.getSelection();
if(selection.getActiveRange().getA1Notation()==null)
ui.alert('No range selected');
else{
//get the inputs
var sheetname = SpreadsheetApp.getActiveSheet().getName();
// SpreadsheetApp.getUi().alert(sheetname);
var range = SpreadsheetApp.getActiveSpreadsheet().getRange(selection.getActiveRange().getA1Notation());
var input = range.getValues();
var ac = SpreadsheetApp.getActiveSpreadsheet().getActiveRange()
SpreadsheetApp.getUi().alert(ac);
// get sheet name
sheetname = SpreadsheetApp.getActiveSheet().getName()
const numRows = ac.getNumRows();
for (let i=1; i<= numRows;i++ ){
var cell = ac.getCell(i, 1).offset(0, 0,1,6).getA1Notation();
var cell1 = ac.getCell(i, 1).offset(0, 7,1,2).getA1Notation();
// SpreadsheetApp.getUi().alert(cell + " " +sheetname + " " + cell1);
single_row(sheetname, cell, cell1 );
}
SpreadsheetApp.getUi().alert("All values updated")
}
}
function single_row(sheetName, inputRange, outputRange ) {
var fnSheetName = "Main";
var fnInputRange = 'A2:F2';
var fnOutputRange = 'G2:H2';
var input = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName).getRange(inputRange).getValues();
SpreadsheetApp.getActiveSpreadsheet().getSheetByName(fnSheetName).getRange(fnInputRange).setValues(input);
var output = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(fnSheetName).getRange(fnOutputRange).getValues();
SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName).getRange(outputRange).setValues(output);
}
This creates a menue item on the top which one by one copies the values to the other sheet then copies the result back
I need to enable edition in more than one sheet to 60 users (using e-mail).
The user need to edit a few cells and all the other the edition need to be blocked.
Example: all the user should have the edition enable in sheets X, Y and Z, and the range of cells enabled to edition is B6:Q50. All the other cells need to be blocked and only the owned can edit.
Is it possible?
Solution:
On your main Google spreadsheet file, you can create a bound script and try this tweaked script below:
This script was based from Protect spreadsheet then unprotect specific cells and ranges with script & article of addEditors() method.
Script:
function main() { //Main function to run
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
addEditors();
for(var x=0; x<sheets.length; x++){
unlockCertainRanges(sheets[x]);
}
}
function addEditors(){ //Function to add editors
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var emails = [
'test1#example.com',
'test2#example.com',
'test3#example.com'
];
sheet.addEditors(emails);
}
function unlockCertainRanges(currentSheet){ //Function to unlock certain ranges on your sheets
var sheet = currentSheet;
// Remove all range protections in the spreadsheet
var protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
var protection = protections[i];
protection.remove();
}
var protection = sheet.protect();
//restrict editors to owner
protection.getRange().getA1Notation();
var eds = protection.getEditors();
protection.removeEditors(eds);
//set unprotected ranges
var ranges = protection.getUnprotectedRanges();
var data = ["B6:Q50"]; // ADD YOUR RANGES HERE TO BE EDITABLE
data.forEach(res => { //LOOPS INTO EVERY ARRAY CONTAINING SPECIFIC RANGES
ranges.push(sheet.getRange(res));
protection.setUnprotectedRanges(ranges); //REMOVES THE PROTECTION ON THE RANGE
});
}
Sample Result:
After running the main function, the emails added on addEditors function are automatically added as editors of the file & they'll be abe to edit range B6:Q50 and the rest of the cells will be protected (only the owner of the spreadsheet file will be able to edit):
Sample Images:
Image 1: A user is not allowed to edit cell A1 (outside of B6:Q50 range on all sheets)
Image 2: User is allowed to edit cell B6 (within B6:Q50 range on all sheets)
Please help with Google sheets macro. Trying simple stuff as a start. Macro needs to clear B2 cell and paste formula (importhtml) as shown below. Then it has to do the same for cell B43 (Potentially will do this in multiple cells on this sheet if it ever works).
Google sheets link:
https://docs.google.com/spreadsheets/d/1O0AJJEd0tGyFXlEPhih8HG9YOWcZNRot_Z7FXPdQrx8/edit?usp=sharing
Strangely it works in B43, but leaves B2 empty.
function Untitledmacro() {
// Clear B2 and then paste formula
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('DATA'), true);
spreadsheet.getRange('B2').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
};
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('DATA'), true);
spreadsheet.getRange('B2').activate();
spreadsheet.getCurrentCell().setFormula('=IMPORTHTML("https://www.investing.com/commodities/real-time-futures","table",1)');
// Clear B43 and then paste formula
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('DATA'), true);
spreadsheet.getRange('B43').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('DATA'), true);
spreadsheet.getRange('B43').activate();
spreadsheet.getCurrentCell().setFormula('=IMPORTHTML("https://www.investing.com/indices/indices-futures","table",1)');
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('DATA'), true);
Added Sheets API, not sure it's needed here though
See if this helps
function clearAndSetformula() {
const sheet = SpreadsheetApp.getActive().getSheetByName('DATA');
const cells = ["B2", "B43"];
const formulas = [
'=IMPORTHTML("https://www.investing.com/commodities/real-time-futures","table",1)',
'=IMPORTHTML("https://www.investing.com/indices/indices-futures","table",1)'
];
cells.forEach((cell, i) => sheet.getRange(cell).clear({ contentsOnly: true, skipFilteredRows: true }).setFormula(formulas[i]));
};
If you need to add more cells/formulas, add them in the proper arrays. Make sure the positions line up so that the first cell in the array cells will have the first formula in the array formulas etc...
I hope that helps?
I am trying to create a script in Google Sheets that select a range and print it. I am trying to print some information based on some parameters. I have the following script that sets the desired range, but I do not see a way to print it using script.
function printInvoice() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange("A1:H46");
range.activate();
}
Any suggestions? Thanks!
You can use the following script:
var PRINT_OPTIONS = {
'size': 7, // paper size. 0=letter, 1=tabloid, 2=Legal, 3=statement, 4=executive, 5=folio, 6=A3, 7=A4, 8=A5, 9=B4, 10=B
'fzr': false, // repeat row headers
'portrait': true, // false=landscape
'fitw': true, // fit window or actual size
'gridlines': false, // show gridlines
'printtitle': false,
'sheetnames': false,
'pagenum': 'UNDEFINED', // CENTER = show page numbers / UNDEFINED = do not show
'attachment': false
}
var PDF_OPTS = objectToQueryString(PRINT_OPTIONS);
function onOpen(e) {
SpreadsheetApp.getUi().createMenu('Print...').addItem('Print selected range', 'printSelectedRange').addToUi();
}
function printSelectedRange() {
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getActiveRange();
var gid = sheet.getSheetId();
var printRange = objectToQueryString({
'c1': range.getColumn() - 1,
'r1': range.getRow() - 1,
'c2': range.getColumn() + range.getWidth() - 1,
'r2': range.getRow() + range.getHeight() - 1
});
var url = ss.getUrl().replace(/edit$/, '') + 'export?format=pdf' + PDF_OPTS + printRange + "&gid=" + gid;
var htmlTemplate = HtmlService.createTemplateFromFile('js');
htmlTemplate.url = url;
SpreadsheetApp.getUi().showModalDialog(htmlTemplate.evaluate().setHeight(10).setWidth(100), 'Print range');
}
function objectToQueryString(obj) {
return Object.keys(obj).map(function(key) {
return Utilities.formatString('&%s=%s', key, obj[key]);
}).join('');
}
You will also need to create an html file in your project (File>New>HTML File) with the name js, and paste in the following code:
<script>
window.open('<?=url?>', '_blank', 'width=800, height=600');
google.script.host.close();
</script>
This will create a button in your Sheets menu that will open a PDF with the selected range. You can modify some settings such as the print orientation, its size, or whether to show the gridlines or not on top of the script. If you still want to automatically print the ranges without having to manually go through the print dialog, you can either:
Send the document to your printer using GmailApp API class, if your printer supports such functionality.
Use Google Cloud Print. The following blog post may help you with that: https://ctrlq.org/code/20061-google-cloud-print-with-apps-script
I stumbled on your code quite by chance from an "unallowed question to stack overflow which actually seems to be exactly what I want - could not get any detail on how to print from App Script for sheets.
I have been trying it out but it falls over at the line in your sample
"var htmlTemplate = HtmlService.createTemplateFromFile('js');"
where the service cannot find 'js'. Afraid I do not understand what an html template is anyway - are you able to explain?
After making a copy of my perfectly working google sheet, together with the script that comes with it; the script itself does not work anymore in the copy.
I go through the steps of authorizing it as an app but it seems to hang when i run it on the copy. It times out after 540 odd seconds. It seems to be having trouble with DriveApp.createFolder (exectution time 540 seconds). Yet i have not changed anything in the script, works fine on the original one.
Here is the script, im pretty sure everything is fine here, it just doesn't want to work as soon as you make a copy of it. I need to make copies of this sheet for each person in my team but i can't at the moment.
function saveAsCSV() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var date = SpreadsheetApp.getActiveSheet().getRange(3,2).getValue();
var time = SpreadsheetApp.getActiveSheet().getRange(4,2).getValue();
var site = SpreadsheetApp.getActiveSheet().getRange(2,2).getValue();
// iterate through all sheets in the spreadsheet and rename them according to cell B2
for( var j = 0 ; j < sheets.length; j++) {
var sourceSheet = sheets[j];
// get contents of cell B2
var newSheetName = sourceSheet.getRange("B2").getValue();
// rename sheet
sourceSheet.setName(newSheetName);
}
// create a folder from the named SNOWSURVEYS with date
var folder = DriveApp.createFolder('SNOWSURVEYS' + '_' + date + '_'+ site);
// append ".csv" extension to the sheet name
fileName = SpreadsheetApp.getActiveSheet().getName() + ".csv";
// convert all available sheet data to csv format
var csvFile = convertRangeToCsvFile_(fileName);
// create a file in the Docs List with the given name and the csv data
folder.createFile(fileName, csvFile);
var folderID = folder.getId();
var folderName = folder.getName();
var ui = UiApp.createApplication().setTitle('Your files have are in your google drive in a folder called ' + folder);
var p = ui.createVerticalPanel();
ui.add(p);
p.add(ui.createAnchor('Click here to go straight to your files ',folder.getUrl()));
SpreadsheetApp.getActive().show(ui)
}
Execution transcript printscreen