I have a Google Sheet which hides some sheets from most users, but when an admin user is identified, has a menu option to show all the sheets. It calls my function showAllSheets, as follows:
function showAllSheets() {
var sheets=SpreadsheetApp.getActiveSpreadsheet().getSheets();
for(var i = 0; i < sheets.length; i++){
//Show each sheet
sheets[i].showSheet();
console.log('Showing Sheet: ' + sheets[i].getName())
}
}
But this function doesn't always work. I get very mixed results. Sometimes it shows all sheets as expected. Sometimes it shows some of the sheets. Sometimes it eventually shows all or some of the sheets but only after a long delay (1 minute+) and sometimes, it does nothing at all.
I'm checking my execution time in the "Executions" section of Apps Script. This function typically executes in about 2-3 seconds and the console log contains all expected messages. It will say "completed" and still my sheets aren't showing. Sometimes it will eventually show the sheets some time after it says execution is complete and again, sometimes they never show.
I have an onOpen installable trigger and an onSelectionChange simple trigger, so at first I was concerned maybe my scripts are running into each other. However, I've confirmed I still have this issue even if I make sure all other scripts have completed before I run it.
I have no issues with .hideSheet() in my functions that hide the sheets (one being RestoreDefaultView, the other in my onOpen trigger.). They always get hidden immediately.
Here is the menu code I'm using:
var ui = SpreadsheetApp.getUi();
if (thisuser.group == 'admin') {
ui.createMenu('MyProject(Admin)')
.addSubMenu(
ui.createMenu('View')
.addItem('Restore Default Sheet View', 'restoreDefaultView')
.addItem('Show All Sheets', 'showAllSheets')
)
.addToUi();
}
What is going on and what can I do to fix it?
EDIT: Per request, here is the function that is hiding some of the sheets:
function restoreDefaultView() {
const name_Master = 'PROJECT MASTER';
const name_Lists = 'LISTS';
const name_Guide = 'GUIDE';
const name_Access = 'ACCESS';
const name_ActionForm = 'frm_Action';
const name_ProjectForm = 'frm_Project';
const name_NotesForm = 'frm_Notes';
const name_AdminForm = 'frm_Admin';
const name_GroupAdmin = 'admin_Groups';
//const id_ProjectList = '(redacted)'; // Google Drive file ID of Project List'
//const id_TaskList = ''; //Google Drive file ID of Task List
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sht_Master = ss.getSheetByName(name_Master);
var sht_Guide = ss.getSheetByName(name_Guide);
var sht_Lists = ss.getSheetByName(name_Lists);
var sht_Access = ss.getSheetByName(name_Access);
var sht_ActionForm = ss.getSheetByName(name_ActionForm);
var sht_ProjectForm = ss.getSheetByName(name_ProjectForm);
var sht_NotesForm = ss.getSheetByName(name_NotesForm);
var sht_AdminForm = ss.getSheetByName(name_AdminForm);
var sht_GroupAdmin = ss.getSheetByName(name_GroupAdmin);
//Sheets Normally Displayed
//Immediately activate Master sheet after making visible to minimize confusion
sht_Master.showSheet();
sht_Master.activate();
sht_Guide.showSheet();
//Sheets Normally Hidden
sht_Lists.hideSheet();
sht_Access.hideSheet();
sht_ActionForm.hideSheet();
sht_ProjectForm.hideSheet();
sht_NotesForm.hideSheet();
sht_AdminForm.hideSheet();
sht_GroupAdmin.hideSheet();
}
Try this:
function showAllSheets() {
var sheets=SpreadsheetApp.getActiveSpreadsheet().getSheets();
for(var i = 0; i < sheets.length; i++){
sheets[i].showSheet();
SpreadsheetApp.flush();
console.log('Showing Sheet: ' + sheets[i].getName())
}
}
Related
I am trying to have my function use three sheets within its embedded spreadsheet: two fixed sheets and one active/open sheet. I need it to read the sheet I have open because that is the sheet I am changing week to week, but it is automatically defaulting to using the first sheet rather than the sheet I have opened. I altered this function from an existing function I have that works, and on this new one I only changed the message and its assigned variables. I really know absolutely nothing about coding but have been learning so I can create a custom message from a code a previous coworker wrote. I appreciate all of the help I can get x10000
function createMessage(address, dirtrider, day, window, outby, phone) {
{ var message = 'Hello ' + address + ', welcome to IVCC\'s composting program! You\'ll be receiving weekly automated reports from this number (a weekly reminder to put your bucket out and a notification if any incorrect items were discarded into your bucket). To stop receiving these messages, reply STOP. We are currently restructuring our biking routes, therefore you may be receieving a new Dirtrider according to this message. Starting next week, you\'re assigned Dirtrider will be ' + dirtrider + ', and you\'re new bucket will arrive weekly on ' + day + '\'s sometime between ' + window + '. Please have your bucket outside your front door by ' + outby + ' on this day weekly unless notified of a change. This is an automated messaging service, so please reach out to your Dirtrider directly at ' + phone + ' with any questions or concerns about your service. Thanks for composting with us! -IVCC Team';
}
return message;
}
// function to verify numbers and messages before sending //
function PrintMessages() {
var mainsheet = SpreadsheetApp.getActiveSheet();
var data = mainsheet.getDataRange().getValues();
var contactsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Contact Sheet");
var contacts = contactsheet.getDataRange().getValues();
var messageLog_sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Message Log");
var messageLog = messageLog_sheet.getDataRange().getValues;
var mLrow = 2 //row to start at on Message Log spreadsheet
// runs through every row of active spreadsheet, i = row //
for (var i = 2; i < data.length; i++) {
// set variables based on values in sheet and create message//
var address = data[i][0];
var day = data[i][1];
var window = data[i][2];
var outby = data[i][3];
var dirtrider = data[i][4]
var phone = data[i][5]
var message = createMessage(address, dirtrider, day, window, outby, phone);
// reference seperate contact sheet, j = column //
var nresidents = contacts[i][2];
for (var j = 1; j <= nresidents; j++) {
// log address, phone number, and message function //
var address = contacts[i][0];
var number = contacts[i][j+2];
var messageArray = [[address, number, message]];
var range = messageLog_sheet.getRange(mLrow, 1, 1, 3); //ENTER COMMENTS
range.setValues(messageArray);
var mLrow = mLrow + 1;
}
}
}
I have a Google ads script that will find any ad groups with on active RSA's, and export the campaigns and ad group name to a Google Sheet.
But sometimes then it runs it says it "Failed due to system errors" and gives the following error message:
7/11/2022 3:50:02 PM Exception: Call to GoogleAdsService.Search failed: The request took too long to respond.
at adsapp_compiled:18112:138
at adsapp_compiled:18123:9
at sa (adsapp_compiled:227:15)
at Object.search (adsapp_compiled:235:20)
at iI.search (adsapp_compiled:18238:36)
at SH.search (adsapp_compiled:17815:19)
at TH.search (adsapp_compiled:17910:20)
at $H.search (adsapp_compiled:18002:19)
at fd (adsapp_compiled:1041:32)
at fd.next ()
I think it is a runtime error, because it doesn't receive any response from the server.
i have been told it might have something to do with the syntax order, but i don't know how to fix that if that is the case.
I have tried to do the export to a new clear sheet, just to see if the sheet i used had to many formulas in it which could slow it down, but it still gave the same error message.
I have also tried to do it on an entirely different account that is smaller but still same issue.
/**********************
RSA Checker
**********************/
var SPREADSHEET_URL = 'INSERT SPREADSHEET URL HERE';
var Sheet_name = 'INSERT SHEET NAME HERE';
function main() {
var sheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL).getSheetByName(Sheet_name);
var range = sheet.getRangeList(['A1:A', 'B1:B'])
range.clearContent();
sheet.getRange("A1").setValue("Campaign");
sheet.getRange("B1").setValue("Ad groups");
var GetAdGroups = AdWordsApp.adGroups()
.withCondition('Status = ENABLED')
.withCondition('CampaignStatus = ENABLED')
.withCondition("AdvertisingChannelType = SEARCH")
.withCondition("CampaignName DOES_NOT_CONTAIN_IGNORE_CASE 'dsa'")
.withCondition("AdGroupName DOES_NOT_CONTAIN_IGNORE_CASE 'dsa'")
.withCondition("campaign.experiment_type = BASE")
.get();
for (var row = 2; GetAdGroups.hasNext(); row ++) {
var AdGroups = GetAdGroups.next();
var RSACount = AdGroups.ads().withCondition('Type=RESPONSIVE_SEARCH_AD').withCondition('Status = ENABLED').get().totalNumEntities();
if ((RSACount < 1)) {
sheet.appendRow( [AdGroups.getCampaign().getName(), AdGroups.getName()] );
}
}
}
I am running the following script as its own .gs file
/**
* TITLE:
* Hide a row if a value is inputted.
*/
//**GLOBALS**
// Sheet the data is on.
var SHEET = "Norm Adam";
// The value that will cause the row to hide.
var VALUE = "Yes";
// The column we will be using
var COLUMN_NUMBER = 11
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
//Ensure on correct sheet.
if(SHEET == activeSheet.getName()){
var cell = ss.getActiveCell()
var cellValue = cell.getValue();
//Ensure we are looking at the correct column.
if(cell.getColumn() == COLUMN_NUMBER){
//If the cell matched the value we require,hide the row.
if(cellValue == VALUE){
activeSheet.hideRow(cell);
};
};
};
}
It works fine on a computer browser but on iOS device it doesn't work through the google sheets app and I actually can't even get the editable through safari. I read that only the onEdit function will work on a mobile device so I figured this should work. Is there another piece to this puzzle?
Thanks
Mike
(credit for script creation goes to: https://yagisanatode.com/2018/05/26/how-to-hide-a-row-based-on-a-cell-value-in-google-sheets-with-filter-or-google-apps-script/ )
Script V2:
I commented below on this still not working in iOS. I figured the simpler it was the more likely to work?
function onEdit(e) {
if (e.range.getColumn() == 11 && e.value == 'Yes') {
e.range.getSheet().hideRows(e.range.getRow());
}
}
getActive calls, especially ss.getActiveCell() should be avoided on mobile apps. Consider alternatives like e.range to get the edited range from event objects.
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?
I know there are a lot of questions out there related to Google Scripts and some of them touch on my issue but I can't seem to figure out the full answer.
I only want to be able to run 1 or 2 scripts in the same project file for 1 spreadsheet. How do I allow permission for everyone with whom the sheet is shared WITHOUT forcing each user to go through the process of allowing Authorization? Is this possible?
Maybe there is an alternative script? Here is my script (in case this helps):
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{name:"Go to active row", functionName:"Go to active
row"}];
sheet.addMenu("Scripts", entries);
myFunction();
};
function gotoend() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastRow = sheet.getDataRange().getValues();
lastRow.forEach(function (row,index) {
if (row[3] == "") { // row[0] is the same as Column A. row[1] = B
lastRow.length = index;
}
});
var newRange = sheet.getRange(lastRow.length,1);
sheet.setActiveRange(newRange);
}
/**
* #OnlyCurrentDoc
*/