Print a certain range of a Google Spreadsheet using a script - google-sheets

I would like to create a button to print just a certain range of a Google Spreadsheet. I am playing arroud with .getRangeByName class but it wont work. Maybe someone can help me with some ideas?
I am playing arround with some code I found here on stackoverflow.
I am just stuck by replacing the columns and rows by a certain range name or namedRange.
All in all the result of the script below works fine for me so far.
Thanks and Regards!
function printPdf() {
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var gid = sheet.getSheetId();
var pdfOpts = '&size=A4&fzr=false&portrait=false&fitw=true&gridlines=false&printtitle=false&sheetnames=false&pagenum=UNDEFINED&attachment=false&gid='+gid;
var last_row = sheet.getLastRow(); var printRange = '&c1=0' + '&r1=0' + '&c2=34' + '&r2='+last_row // B2:APn var url = ss.getUrl().replace(/edit$/, '') + 'export?format=pdf' + pdfOpts + printRange;
var app = UiApp.createApplication().setWidth(200).setHeight(50);
app.setTitle('Verze pro tisk');
var link = app.createAnchor('Zobrazit PDF', url).setTarget('_new');
app.add(link);
ss.show(app);
}

Related

How to limit the information sent in the CSV (Google Sheets)?

I used the script below to create a submit order button which emails the current sheet as a CSV and then clears range I6:I. How can I update it so that only items with a response in range I6:I are included in the CSV? I don't want the CSV to include anything if I6:I is empty. I know the code isn't very clean. I'm new to this. Any help would be really appreciated.
function SUBMIT_ORDER() {
SpreadSheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
SheetId = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetId();
var today = new Date();
var date = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate();
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
var dateTime = date+' '+time;
var actualSheetName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
var recipients = "EMAILADDRESS"; 
var ssID = SpreadsheetApp.getActiveSpreadsheet().getId();
var sheetName = SpreadsheetApp.getActiveSpreadsheet().getName();
var email = Session.getActiveUser().getEmail();
var subject = "BMVS " +actualSheetName+ " New Purchase Order " +dateTime ;
var body = email+ " submitted a new purchase order for " +actualSheetName+ " on " +date+ " at " +time+ " ****THANK YOU****";
var requestData = {"method": "GET", "headers":{"Authorization":"Bearer "+ScriptApp.getOAuthToken()}};
var url = 'https://docs.google.com/spreadsheets/d/' + SpreadSheetId + "/export?format=csv&gid=" + SheetId;
var result = UrlFetchApp.fetch(url, requestData);
var contents = result.getContent();
RESET_QUANTITIES = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
MailApp.sendEmail(recipients, subject, body, {attachments:[{fileName:actualSheetName+'-'+dateTime+ ".csv", content:contents, mimeType:"application//csv"}]});
RESET_QUANTITIES.getRange("i6:i").clearContent();
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).activate();
spreadsheet.setCurrentCell(spreadsheet.getRange('E1'));
}
solution by script
Try
var contents = result.getContentText().split('\n').filter(r => (r.split(',')[8] != '')).join('\n')
instead of var contents = result.getContent();
solution by query
apply in a new tab
=query('Feuille 1'!A:J,"select * where I is not null",1)

How to Print sheet/range using .gs script in Google Sheets?

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?

How to find the SearchImpressionShare for a particular keyword?

One could easily find the average position for a keyword using getAveragePositon() method but the same is not available for SearchImpressionShare.
EDIT
I tried to get the SearchImpressionShare by querying the data but that gives me inconsistent data.
function main() {
var keywordId = 297285633818;
var last14dayStatsQuery = "SELECT Id, SearchTopImpressionShare FROM KEYWORDS_PERFORMANCE_REPORT WHERE Id = "+keywordId+" DURING LAST_14_DAYS"
var last14dayReport = AdWordsApp.report(last14dayStatsQuery);
var last14dayRows = last14dayReport.rows();
var last14dayRow = last14dayRows.next();
Logger.log('Keyword: ' + last14dayRow['Id'] + ' SearchTopIS: ' + last14dayRow['SearchTopImpressionShare']);
}
For example, below are the two outputs I received after running the same code twice.
Output 1:
10/16/2019 10:47:29 AM Keyword: 297285633818 SearchTopIS: 0.0
Output 2:
10/16/2019 10:47:45 AM Keyword: 297285633818 SearchTopIS: 0.17
Keywords performance report provides you those data https://developers.google.com/adwords/api/docs/appendix/reports/keywords-performance-report#searchimpressionshare
sample use:
function main () {
var query = "SELECT SearchImpressionShare, Criteria FROM KEYWORDS_PERFORMANCE_REPORT WHERE Clicks > 15 DURING YESTERDAY"
var report = AdWordsApp.report(query)
var rows = report.rows()
while (rows.hasNext()) {
var row = rows.next()
Logger.log('Keyrword %s, Impressions Share %s', row['Criteria'], row['SearchImpressionShare'])
}
}
update:
please note that if you have the same keyword within several ad group you'll get aslo several rows in report, each row for each adgroup. for the whole list of keywords use the following approach:
function main() {
var keywordId = 350608245287;
var last14dayStatsQuery = "SELECT Id, SearchTopImpressionShare FROM KEYWORDS_PERFORMANCE_REPORT WHERE Id = "+keywordId+" DURING LAST_14_DAYS"
var last14dayReport = AdWordsApp.report(last14dayStatsQuery);
var last14dayRows = last14dayReport.rows();
while (last14dayRows.hasNext()) {
var last14dayRow = last14dayRows.next();
Logger.log('Keyword: ' + last14dayRow['Id'] + ' SearchTopIS: ' + last14dayRow['SearchTopImpressionShare']);
}
}
You might find it useful to add ad group parameters to your query such as AdGroupName, AdGroupId.

Google script stops working after copying and authorizing

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

Combine two Google spreadsheet together and keep it sync

I have two sheet from others and wish to create another one which combine both sheet together.
e.g.
SheetA:
Name value
A 10
B 20
SheetB:
Name value
C 30
D 40
Then I want to create one SheetC:
Name value
A 10
B 20
C 30
D 40
And if I change SheetC, I wish data synced to SheetA or SheetB automatically.
I can implement the doc combine with below script:
function runme() {
var docA = "<Doc Id A>";
var docB = "<Doc Id B>";
var sheetName = "Sheet1";
appendSheet(docA,sheetName);
appendSheet(docB,sheetName);
}
function appendSheet(docId,sheetName) {
var sourceSpread = SpreadsheetApp.openById(docId);
var sourceSheet = sourceSpread.getSheetByName(sheetName)
var activeSpread = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = activeSpread.getActiveSheet();
var activeSheetName = activeSheet.getSheetName();
sourceRng = sourceSheet.getDataRange();
sourceRows = sourceRng.getValues(),
activeSheet.appendRow(sourceRows[0]);
for (i = 1; i < sourceRows.length; i += 1) {
activeSheet.appendRow(sourceRows[i]);
}
Logger.log("total: " + i);
}
But it seems it's difficult to sync information from docC to docA and docB.

Resources