google form script exclude sundays on dates choices - google-sheets-formula

im making a script for making an apointment. I get the choices of appointmentt date from my spreadsheet using script. How to exclude sunday when i get the choices from my spreadsheet ? i cant find a way to remove the sunday.
here is the code
var ssID = "1hil07Z2wvTXH1szX9bNfPKVLDQVO36ACQFGOU6_VUI0";
var formID="1SD5BenAnNxNz-wtw0YPut6YdTf7a62zHn_z3VrTdTUU";
var wsData = SpreadsheetApp.openById(ssID).getSheetByName("DATA");
var form = FormApp.openById(formID);
function main(){
var labels = wsData.getRange(1,1,1,wsData.getLastColumn()).getValues()[0];
labels.forEach(function(label,i){
var options = wsData
.getRange(2, i+1,wsData.getLastRow()-1,1)
.getDisplayValues()
.map(function(o){return o[0]})
.filter(function(o){return o !== ""})
//Logger.log(options);
updateDropDownUsingTitle(label,options);
});
}
function updateDropDownUsingTitle(title,values) {
var title = "Tanggal Penjemputan";
var items = form.getItems();
var titles = items.map(function(item){
return item.getTitle();
});
var pos = titles.indexOf(title);
var item = items[pos];
var itemID = item.getId();
updateDropdown(itemID,values);
}
function updateDropdown(id,values) {
var item = form.getItemById(id);
item.asListItem().setChoiceValues(values);
}
this is the form
THis is my spreadsheet

There are 3 ways to achieve your goal:
Use a non-Sunday formula in sheet
Add a weekday column to sheet and filter in script
getValues and new Date instead of getDisplayValues, filter Sunday and then Utilities.formatDate

You can use the following formula:
=ArrayFormula(TODAY()+FILTER({1;2;3;4;5;6;7}, WEEKDAY(TODAY()+{1;2;3;4;5;6;7})<>1))
See on Google Sheets
This will give you the next 7 days excluding Sunday.

Related

Suitescript Saved Search Filter using other saved search results

I am trying to use the results of a specific saved search to try and filter another saved search in suitescript.
Basically, there is a button created on a project. Once the button is clicked, I need to go get all the tasks for that specific project and use each task to filter on a transaction saved search using a custom field and get whatever information is on that saved search.
This is what I have so far:
function runScript(context) {
var record = currentRecord.get();
var id = record.id;
var type = record.type;
var i = 0;
console.log(id);
var projectSearch = search.load({id: 'customsearch1532'})
var billableExpenseSearch = search.load({id: 'customsearch1533'})
var projectFilter = search.createFilter({
name:'internalId',
operator: search.Operator.IS,
values: id
});
projectSearch.filters.push(projectFilter);
var projectResults = projectSearch.run().getRange(0,1000);
while(i < projectResults.length){
var task = projectResults[i].getValue(projectSearch.columns[1]);
console.log(task);
var billableExpenseFilter = search.createFilter({
name:'custcol4',
operator: search.Operator.ANYOF,
values: task
});
billableExpenseSearch.filters.push(billableExpenseFilter);
var billableExpenseResults = billableExpenseSearch.run().getRange(0,1000);
console.log(billableExpenseResults.length);
for(var j = 0; j< billableExpenseResults.length; j++){
var testAmount = billableExpenseResults[j].getValue(billableExpenseSearch.columns[3]);
console.log(testAmount);
}
i++;
}
}
The log for the Task is correct. I have 2 tasks on the project I am trying this on but once we get to the second iteration, the billableExpenseSearch length is showing as 0, when it's supposed to be 1.
I am guessing that my logic is incorrect of the createFilter function doesn't accept changes once the filter is created.
Any help is appreciated!
EDIT:
var billableExpenseSearch = search.load({id: 'customsearch1533'});
var billableExpenseFilter = search.createFilter({
name:'custcol4',
operator: search.Operator.ANYOF,
values: task
});
billableExpenseSearch.filters.push(billableExpenseFilter);
var billableExpenseResults = billableExpenseSearch.run().getRange(0,1000);
console.log(billableExpenseResults.length);
for(var j = 0; j< billableExpenseResults.length; j++){
var taskid = billableExpenseResults[j].getValue(billableExpenseSearch.columns[0]);
console.log(taskid);
Thank you
I think your guess is correct your are keep pushing filters
billableExpenseSearch.filters.push(billableExpenseFilter);
After pushing the filter and extract the value you need to remove it before adding a new one, you can do this by pop() the last one:
billableExpenseSearch.filters.pop();
Note: You can fix this by re-loading the search every time before pushing the filter. this will reset your filters, but I do NOT recommend that since loading a search will consume more USAGE and might receive USAGE_LIMIT_EXCEEDED ERROR.
I also recommend the following:
1- Get all task ids before doing the second search, once you do that you only need to search once. Because if you have many records you might encounter USAGE_LIMIT_EXCEEDED ERROR. Since you work with a client or Suitelet script you only have 1000 USAGE.
Edit: Sample might help you.
var ids = [];
var pagedData = projectSearch.runPaged({pageSize : 1000});
// iterate the pages
for( var i=0; i < pagedData.pageRanges.length; i++ ) {
// fetch the current page data
var currentPage = pagedData.fetch(i);
// and forEach() thru all results
currentPage.data.forEach( function(result) {
// you have the result row. use it like this....
var id = result.getValue(projectSearch.columns[1]);
Ids.push(id);
});
}
Note: This search will extract all records not only first 1000.
After that add the array to the Filter
var billableExpenseFilter = search.createFilter({
name:'custcol4',
operator: search.Operator.ANYOF,
values: [ids]
});
2- Don't Use search.load use search.create it will make your script more readable and easier to maintain in the future.

Data Validation range from different spreadsheets

I have in my main spreadsheet a dropdown with data validation of a range from another tab in the same spreadsheet with data imported from another spreadsheet or with IMPORTRANGE function or imported with a script.
In both cases the main spreadsheet is very slow cause I have a lot of tab with data imported with both methods.
There is a way to do the data validation of the dropdown in the main sheet taking the data I need directly from the other spreadsheets without import them previously in the main spreadsheet with the IMPORTRANGE function or with a script?
I have tried to write a draft script but not works:
function externalSheetDataValidation() {
var cell = SpreadsheetApp.getActiveRange();
var dataValidationSheet = SpreadsheetApp.openById("xxxxxxxxxx");
var sheet = dataValidationSheet.getSheets()[0];
var range = sheet.getRange("B2:B5000");
var rule = SpreadsheetApp.newDataValidation()
.requireValueInRange(range, true)
.setAllowInvalid(false)
.build();
cell.setDataValidation(rule);
Logger.log(dataValidationSheet.getName());
}
You want to populate a dropdown based on the values of a range from a different spreadsheet.
You are currently importing those values to a sheet in your spreadsheet in order to use them via requireValueInRange.
You would like to skip the import process.
If that's the case, you can just do the following:
Create a function that returns a simple array with the values from the source range:
function importSheetA() {
return SpreadsheetApp.openById('xxxxx')
.getSheetByName('xxxxx')
.getRange('xxxxx')
.getValues()
.flat(); // This ensures a simple array is returned
}
Populate the dropdowns with requireValueInList instead of requireValueInRange, using the values returned by importSheetA:
function populateDropdown() {
var values = importSheetA();
var rule = SpreadsheetApp.newDataValidation()
.requireValueInList(values, true)
.setAllowInvalid(false)
.build();
var range = SpreadsheetApp.getActiveRange();
range.setDataValidation(rule);
}
Note:
You could update the populated options when the source range is edited if you install an onEdit trigger, and you could also specify what range of cells should be populated with dropdowns without them being necessarily selected, but I'm not sure that's what you want.
Update:
If your data has more than 500 items, value in list criteria is not an option. Your only other option would be to use List from a range instead, but as you said, this would require the source range to be on the same spreadsheet as the dropdown, which you wanted to avoid.
As a workaround, I'd suggest you to programmatically copy the data to a hidden sheet in the target spreadsheet, and use the data in this hidden sheet as your source range when creating the dropdown. For example, this:
function copyRange() {
var cell = SpreadsheetApp.getActiveRange();
var rangeNotation = "B2:B5000"; // Change according to your preferences
var sourceData = SpreadsheetApp.openById(xxxxx)
.getSheetByName(xxxxx)
.getRange(rangeNotation)
.getValues();
var targetSS = SpreadsheetApp.getActiveSpreadsheet();
var hiddenSheetName = "Hidden source data"; // Change according to your preferences
var hiddenSheet = targetSS.getSheetByName(hiddenSheetName);
if (!hiddenSheet) hiddenSheet = targetSS.insertSheet(hiddenSheetName);
var sourceRange = hiddenSheet.getRange(rangeNotation);
sourceRange.setValues(sourceData);
hiddenSheet.hideSheet();
var rule = SpreadsheetApp.newDataValidation()
.requireValueInRange(sourceRange, true)
.setAllowInvalid(false)
.build();
cell.setDataValidation(rule);
}
Reference:
requireValueInList(values, showDropdown)
Cached Dropdown Dialog
GS:
function getSelectOptions(){
const cs=CacheService.getScriptCache();
const v=JSON.parse(cs.get('cached'));
if(v){return v;}
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Options');
var rg=sh.getDataRange();
var vA=rg.getValues();
var options=[];
for(var i=0;i<vA.length;i++)
{
options.push(vA[i][0]);
}
cs.put('cached', JSON.stringify(vA), 300)
return vA;
}
function showMyselectionDialog() {
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutputFromFile('ah2'), 'Selections');
}
html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<script>
google.script.run
.withSuccessHandler(function(vA) {
updateSelect(vA);
})
.getSelectOptions();
function updateSelect(vA,id){//the id allows me to use it for other elements
var id=id || 'sel1';
var select = document.getElementById(id);
select.options.length = 0;
for(var i=0;i<vA.length;i++)
{
select.options[i] = new Option(vA[i],vA[i]);
}
}
</script>
<body>
<select id='sel1'></select>
</body>
</html>

A simple sort script on Google Sheets is not working

I have a "leaderboard"/"scoreboard", across four sheets, that I need to have auto sorting whenever updated by first Total Score (column 2) and then Total Kills (column 3). These columns are the same across all four sheets.
I've used a very simple script in the past when the scoreboard was limited to one sheet, but I have since expanded it to have Top Ten, Top Four, and Top Two on separate sheets within the same document.
The problem I'm running into: When the script updates one sheet, the other ones seem to flat out stop working entirely; in other words, the script breaks.
Can I please get some advice? I've tried several scripts already from this site, and the basic one I see some success with (but then the script seemingly breaks?) is below.
function sortOnEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("MAIN EVENT");
sheet.sort(3, false).sort(2, false);
}
function sortOnEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TOP TEN");
sheet.sort(3, false).sort(2, false);
}
function sortOnEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TOP FOUR");
sheet.sort(3, false).sort(2, false);
}
function sortOnEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TOP TWO");
sheet.sort(3, false).sort(2, false);
}
Ideally, when functioning, the sheets will literally just sort themselves by the Total Score column, with Total Kills being the "tiebreaker" for sorting.
I've included a copy of my sheet if anybody could help:
https://docs.google.com/spreadsheets/d/1a6XGv09TPt5Vnxqfcd1Xba3TGMis5OelGxlvzNDl5CY/edit?usp=sharing
try something like this instead of your scripts:
function onEdit(event){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = event.source.getActiveSheet().getName()
var editedCell = event.range.getSheet().getActiveCell();
if(sheet=="Sheet1"){
var columnToSortBy = 2;
var tableRange = "A3:C10"; //range to be sorted
if(editedCell.getColumn() == columnToSortBy){
var range = ss.getActiveSheet().getRange(tableRange);
range.sort( { column : columnToSortBy, ascending: true } );
}}
else if(sheet=="Sheet2"){
var columnToSortBy = 7;
var tableRange = "A3:C10"; //range to be sorted
if(editedCell.getColumn() == columnToSortBy){
var range = ss.getActiveSheet().getRange(tableRange);
range.sort( { column : columnToSortBy, ascending: true } );
}
else{return}
}}
try this:
function sortOnEdit(e) {
var sh=e.range.getSheet();
var name=sh.getName();
var incl=['MAIN EVENT','TOP TEN','TOP FOUR','TOP TWO'];
if(incl.indexOf(name)==-1) return;
sh.sort(3,false).sort(2,false);
}

Autosort not working anymore: Google spreadsheet

I have a working script on an old version of a Google spreadsheet that isn't working any more.
It was a sorting script which sorts out the rows each time one or more column is modified.
On the new spreadsheet that isn't working any more. I'm trying to figure out why but I can't catch where the error is.
Can anyone help?
function onEdit(e) {
Logger.clear()
Logger.log('Script Start')
var ss = SpreadsheetApp.getActiveSpreadsheet();
Logger.log('ss=%s', ss)
var sheet = ss.getSheets()[0];
Logger.log('sheet=%s',sheet)
Logger.log('SheetName=%s',sheet.getName())
if(sheet.getName()=='MembriForum'){
var editedCell = sheet.getActiveCell();
Logger.log('editedCell=%s', editedCell)
}
var columnToSortBy_1 = 4;
var columnToSortBy_2 = 6;
var range = sheet.getDataRange();
Logger.log('range=%s', range)
if(editedCell.getColumn() == columnToSortBy_1 || editedCell.getColumn() == columnToSortBy_2){
var range = sheet.getRange(range.getRow()+1, range.getColumn(),range.getNumRows()-1,range.getNumColumns() );
Logger.log('range=%s', range)
range.sort([{ column: columnToSortBy_1, ascending: true }, { column: columnToSortBy_2, ascending: true}]);
}
}
I think this is unfortunately due to an issue in new spreadsheets...
See here for details and star it to (hopefully) get more attention from Google.
Your condition will never be true since editedCell.getColumn() will always be 1.

Sorting of date-type columns when using Chartwrapper class

I am using Google chart to display some data from a Google spreadsheet. This is a segment of my code.
var queryurl = <link to the Google spreadsheet>;
function drawVisualization() {
var query = new google.visualization.Query(queryurl);
// Send the query with a callback function.
query.send(handleQueryResponse);
}
function handleQueryResponse(response) {
// Prepare the data
var data = response.getDataTable();
var table = new google.visualization.ChartWrapper({
'chartType': 'Table',
'containerId': 'chart2',
'options': {
'showRowNumber': 'true'
}
});
}
One of the columns actually contains dates, formatted as day/month/year, e.g. 15/10/2013. However, when I try to sort this particular column by clicking on the header, the sorting is carried out by treating each date as a string, so that for example if three of the dates are 01/02/1999, 01/03/1999 and 01/09/1997 then the sorted order (ascending) is 01/02/1999, 01/03/1999 and 01/09/1997 instead of the correct ordering of 01/09/1997, 01/02/1999, 01/03/1999.
My question is: is there any way to ensure the sorting in the context of dates is correct? Do I need to, for example, specify the type of data contained in each column (which was of course done in the original Google spreadsheet)?
Thanks in advance!
Here's a DataView that converts a string column in the format "MM/dd/yyyy" into a Date column.
var dateFormatter = new google.visualization.DateFormat({pattern: 'MM/dd/yyyy'});
var view = new google.visualization.DataView(data);
view.setColumns([/* list of column indices that preceed the date column */ {
type: 'date',
label: data.getColumnLabel(dateColumnIndex),
calc: function (dt, row) {
var dateArr = dt.getValue(row, dateColumnIndex).split('/');
var year = parseInt(dateArr[2]);
var month = parseInt(dateArr[0]) - 1; // adjust month to javascript's 0-indexed months
var day = parseInt(dateArr[1]);
var date = new Date(year, month, day);
return {
v: date,
f: dateFormatter.formatValue(date)
};
}
} /* list of column indices that follow the date column */]);
Here's a jsfiddle example you can play with: http://jsfiddle.net/asgallant/tggnC/

Resources