Google Sheets Date Issue - google-apps-script

I'm having an issue with dates and I've been unable to find any solutions online. I've created a google sheet with a modal form to collect fleet vehicle driver info; name, dob, oln, etc., with several other date fields. The entire spreadsheet is formatted as plain text and the input types on the associated HTML pages are also text (if I format any of the date-related cells on the sheet as a date, my form won't open when I run the app script code).
When I open the form and edit a driver, the information presented is what I expect. However, if I save the record, the dob (date of birth) field in the underlying sheet turns from a date to #NUM!; surprisingly, the other date fields are not changed.
I made a copy of the spreadsheet with some dummy info, which can be viewed at https://docs.google.com/spreadsheets/d/1_trLFDh1SoIXJnmRz73ludTaT64qgXd8qJKMC6grueU/edit#gid=0
Published link is https://docs.google.com/spreadsheets/d/e/2PACX-1vSzyRgN6i0RJRjcUKxcNlnuQC0P1ZHlhPPuy19G9q-sp0XQfuMjiDWvHMnWA3_HT_QSTQEDYMgrUezV/pubhtml
Code for pulling data in from spreadsheet. Code is in ServerSideFuncs.gs
function editCustomerById(id, customerInfo){ const ss = SpreadsheetApp.getActiveSpreadsheet(); const ws = ss.getSheetByName("Drivers"); const custIds = ws.getRange(2, 1, ws.getLastRow()-1, 1).getValues().map(r => r[0].toString().toLowerCase()); const
posIndex = custIds.indexOf(id.toString().toLowerCase()); const rowNumber = posIndex === -1 ? 0 : posIndex + 2; ws.getRange(rowNumber, 2, 1, 20).setValues([[ customerInfo.firstName, customerInfo.middleName, customerInfo.lastName, +customerInfo.birthDate,
customerInfo.driverClassification, customerInfo.email, customerInfo.cellPhone, customerInfo.active, customerInfo.dpaa, customerInfo.driversLicense, customerInfo.dlState, customerInfo.deptOrg, customerInfo.dateSubmitted, customerInfo.dateReceived, customerInfo.dateExpires,
customerInfo.accepted, customerInfo.certDate, customerInfo.certClassification, customerInfo.notified, customerInfo.standing ]]); return true; }
Code from main.html
function afterEditViewLoads(params){ loadingStart(); document.getElementById("customer-id").value = params.custID; google.script.run.withSuccessHandler(function(customerInfo){ document.getElementById("first-name").value = customerInfo.firstName; document.getElementById("middle-name").value
= customerInfo.middleName; document.getElementById("last-name").value = customerInfo.lastName; document.getElementById("birth-date").value = customerInfo.birthDate; document.getElementById("driver-classification").value = customerInfo.driverClassification;
document.getElementById("email").value = customerInfo.email; document.getElementById("cell-phone").value = customerInfo.cellPhone; document.getElementById("active").value = customerInfo.active; document.getElementById("dpaa").value = customerInfo.dpaa;
document.getElementById("drivers-license").value = customerInfo.driversLicense; document.getElementById("dl-state").value = customerInfo.dlState; document.getElementById("deptOrg").value = customerInfo.deptOrg; document.getElementById("date-submit").value
= customerInfo.dateSubmitted; document.getElementById("date-received").value = customerInfo.dateReceived; document.getElementById("accepted").value = customerInfo.accepted; document.getElementById("date-expires").value = customerInfo.dateExpires; document.getElementById("cert-date").value
= customerInfo.certDate; document.getElementById("cert-classification").value = customerInfo.certClassification; document.getElementById("notified").value = customerInfo.notified; document.getElementById("standing").value = customerInfo.standing; loadingEnd();
}).getCustomerById(params.custID); } function editCustomer(){ loadingStart(); var customerInfo = {}; customerInfo.firstName = document.getElementById("first-name").value; customerInfo.middleName = document.getElementById("middle-name").value; customerInfo.lastName
= document.getElementById("last-name").value; customerInfo.birthDate = document.getElementById("birth-date").value; customerInfo.driverClassification = document.getElementById("driver-classification").value; customerInfo.email = document.getElementById("email").value;
customerInfo.cellPhone = document.getElementById("cell-phone").value; customerInfo.active = document.getElementById("active").value; customerInfo.dpaa = document.getElementById("dpaa").value; customerInfo.driversLicense = document.getElementById("drivers-license").value;
customerInfo.dlState = document.getElementById("dl-state").value; customerInfo.deptOrg = document.getElementById("deptOrg").value; customerInfo.dateSubmitted = document.getElementById("date-submit").value; customerInfo.dateReceived = document.getElementById("date-received").value;
customerInfo.dateExpires = document.getElementById("date-expires").value; customerInfo.accepted = document.getElementById("accepted").value; customerInfo.certDate = document.getElementById("cert-date").value; customerInfo.certClassification = document.getElementById("cert-classification").value;
customerInfo.notified = document.getElementById("notified").value; customerInfo.standing = document.getElementById("standing").value; var id = document.getElementById("customer-id").value; google.script.run.withSuccessHandler(function(res){ document.getElementById("save-success-message").classList.remove("invisible");
loadingEnd(); setTimeout(function(){ document.getElementById("save-success-message").classList.add("invisible"); },2000); }).editCustomerById(id,customerInfo); }
partial Code from editcustomer.html
<div class="col-md-auto">
<label for="birth-date" class="form-label">DOB</label>
<input type="text" class="form-control" id="birth-date" placeholder="Birthday">
</div>

function editCustomerById(id, customerInfo) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName("Drivers");
const custIds = ws.getRange(2, 1, ws.getLastRow() - 1, 1).getValues().map(r => r[0].toString().toLowerCase());
const posIndex = custIds.indexOf(id.toString().toLowerCase());
const rowNumber = posIndex === -1 ? 0 : posIndex + 2;
ws.getRange(rowNumber, 2, 1, 20).setValues([
[
customerInfo.firstName,
customerInfo.middleName,
customerInfo.lastName,
+customerInfo.birthDate, // <------------ I think the trouble is here
customerInfo.driverClassification,
customerInfo.email,
customerInfo.cellPhone,
customerInfo.active,
customerInfo.dpaa,
customerInfo.driversLicense,
customerInfo.dlState,
customerInfo.deptOrg,
customerInfo.dateSubmitted,
customerInfo.dateReceived,
customerInfo.dateExpires,
customerInfo.accepted,
customerInfo.certDate,
customerInfo.certClassification,
customerInfo.notified,
customerInfo.standing
]
]);
return true;
}
Reference
Unary plus (+)

Related

Tabulator - Dependent Select with Custom Editor

I need to show the list in the select box based on the another input.
On click on the SubCategory column, its showing the selected value in the dropdown. But its not showing in the table.
You can see the table in the below image. First image its not showing the data in the display, in the second image its showing the value selected
Anything missed. Any help please..
Attached the working code.
var comboEditor = function (cell, onRendered, success, cancel, editorParams) {
//Getting the other select value, based on the value this select need to show the list
let otherCellValue = cell.getData().ForumCourt;
cboData = []; //Store last values based on another cell value
var currentlyAdded = [];
var editor = document.createElement("select");
arrayOfValues2 = caselocationData.filter(function(r){return true;});
var filteredArrayOfValues = arrayOfValues2.filter(function(r){ return r[0]=== otherCellValue});
// addUniqueOptionsToDropdownList(select2_Sub, filteredArrayOfValues,1);
filteredArrayOfValues.forEach(function(r){
if(currentlyAdded.indexOf(r[0]) === -1) {
currentlyAdded.push(r[1]);
var item = {};
item.key = r;
item.name = r[1];
cboData.push(item);
}
});
for (var i = 0; i < cboData.length; i++) {
var opt = document.createElement('option');
opt.value = cboData[i].key;
opt.innerHTML = cboData[i].name;
editor.appendChild(opt);
}
editor.style.padding = "0px";
editor.style.width = "100%";
editor.style.boxSizing = "border-box";
editor.value = cell.getValue();
onRendered(function () {
editor.focus();
editor.style.css = "100%";
});
function successFunc() {
success(editor.value);
}
editor.addEventListener("change", successFunc);
editor.addEventListener("blur", successFunc);
return editor;
};

How to fix: API call to gmail.users.settings.filters.create failed with error: Empty response

I wrote a script in google apps scripts that creates two filters. I implemented it into web app and it works fine on couple of accounts that aren't that big. But when i try to use it on main account, where it supposed to work I am getting an error that can't really understand.
'API call to gmail.users.settings.filters.create failed with error: Empty response (vers 69, file„createFilter”)'
function createFitler(labelold,me){
var response = Gmail.Users.Labels.list('me');
var labelID = "";
var labelName = "";
for (var i = 0; i < response.labels.length; i++) {
var label = response.labels[i];
if(label.name == labelold)
{
labelID = label.id;
labelName = label.name;
}
}
var filter = Gmail.newFilter();
var filter2 = Gmail.newFilter();
filter.criteria = Gmail.newFilterCriteria();
filter.criteria.from = labelold;
filter2.criteria = Gmail.newFilterCriteria();
filter2.criteria.to = labelold;
filter.action = Gmail.newFilterAction();
filter.action.removeLabelIds = ['INBOX'];
filter.action.addLabelIds = [labelID];
filter2.action = Gmail.newFilterAction();
filter2.action.removeLabelIds = ['INBOX'];
filter2.action.addLabelIds = [labelID];
// Create the filter
Gmail.Users.Settings.Filters.create(filter, me);
Gmail.Users.Settings.Filters.create(filter2, me);
}
The weirdest part is that it works normal on my domain account but not on archive#mydomain.com account.

Node.js pushing data into Excel is not working

Hi I am trying to push data from my array of queries into excel but only the header seems to be displayed but the results are being pushed. When I did a console.log to see whether they would be pushed it says undefined. Any ideas as to why?
Example code:
var excel_data=[];
excel_data.push=(['Source', 'Count of thing 1', 'Count of thing 2', 'Count of thing 3']);
var database = new database(config);
var query_array = ['select count(*) as count_of_thing1 from table1', 'select count(*) as count_of_thing2 from table2', 'select count(*) as count_of_thing3 from table3'];
query_array.forEach(q => {
database.query(q)
.then(rows => {
_.each(rows, function(row){
excel_data.push([row.count_of_thing1, row.count_of_thing2, row.count_of_thing3]);
});
})
var wb = XLSX.utils.book_new();
var ws_name = "Query_Results";
var wscols = [ {width: 15} ];
var wsrows = [];
var ws = XLSX.utils.aoa_to_sheet(excel_data, {cellDates:true});
ws['!cols'] = wscols;
ws['!rows'] = wsrows;
XLSX.utils.book_append_sheet(wb, ws, ws_name);
var filenames = [
['mysql.xlsx', {bookSST:true}],
['mysql.csv', {bookSST:true}],
];
filenames.forEach(function(r) {
XLSX.writeFile(wb, r[0], r[1]);
XLSX.readFile(r[0]);
});
});

How do I set the initial day for a DatePicker

I have two DatePicker objects on a Web UI.
Initially the first should display a day in the past (like january 1st 2010), the second should display the current day (and it does).
I use
var oldDatePicker = myApp.createDatePicker();
var oldDate = new Date(2010, 1, 1);
oldDatePicker.setValue(oldDate);
but that doesn't work
How can I initialize my oldDatePicker?
EDIT 1 --> example
The lines
var zoekBeginDatum = new Date(2012, 8, 15);
pickerBeginDatum.setValue(zoekBeginDatum);
do not provide the desired result
The full (demo) code of the not working example is:
// Global CONSTANTS to be used for initialization
var globalBeginDatum = '2010/04/24';
var globalEindDatum = '';
var globalUseDatums = 'false';
function doGet()
{ // A script with a user interface that is published as a web app
// must contain a doGet(e) function.
// Create 'global' variables, accesible only by this script
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('globalBeginDatum', globalBeginDatum);
userProperties.setProperty('globalEindDatum', globalEindDatum);
userProperties.setProperty('globalUseDatums', globalUseDatums);
// Create the UiInstance object myApp and set the title text
var myApp = UiApp.createApplication()
.setTitle('Test datePicker initialvalue')
.setHeight(50)
.setWidth(100);
var breedteTextBox = 600;
var gridTexts = myApp.createGrid(3, 2);
var labelBeginDatum = myApp.createLabel('Begindatum').setId('labelBeginDatum');
var labelEindDatum = myApp.createLabel('Einddatum').setId('labelEindDatum');
var pickerBeginDatum = myApp.createDatePicker().setId('pickerBeginDatum').setName('pickerBeginDatum');
var zoekBeginDatum = new Date(2012, 8, 15); // Initial date for searching ---> does NOT work
pickerBeginDatum.setValue(zoekBeginDatum);
var pickerEindDatum = myApp.createDatePicker().setId('pickerEindDatum').setName('pickerEindDatum');
var zoekEindDatum = new Date(); // Current date
pickerEindDatum.setValue(zoekEindDatum);
var gridDatum = myApp.createGrid(2, 3);
gridDatum.setWidget(0, 1, labelBeginDatum);
gridDatum.setWidget(0, 2, labelEindDatum);
gridDatum.setWidget(1, 1, pickerBeginDatum);
gridDatum.setWidget(1, 2, pickerEindDatum);
var gridOptions = myApp.createGrid(9, 1);
var onClickChkDatums = myApp.createServerHandler('onClickChkDatums');
var chkDatums = myApp.createCheckBox('Gebruik de begindatum en de einddatum bij het zoeken')
.setId('chkDatums').setName('chkDatums')
.addClickHandler(onClickChkDatums);
gridOptions.setWidget(4, 0, chkDatums);
// Create a vertical panel called verPanel and add it to myApp
var verPanel = myApp.createVerticalPanel().setWidth('60%').setBorderWidth(2).setStyleAttribute('background', 'lightyellow');;
var horPanel = myApp.createHorizontalPanel().setWidth('100%').setStyleAttribute('background', 'lightcyan');
horPanel.add(gridOptions);
horPanel.add(gridDatum);
verPanel.add(horPanel);
labelBeginDatum.setVisible(globalUseDatums == 'true');
labelEindDatum.setVisible(globalUseDatums == 'true');
pickerBeginDatum.setVisible(globalUseDatums == 'true');
pickerEindDatum.setVisible(globalUseDatums == 'true');
// Center verPanel by adding it to another panel occupying whole browser window
var fullPanel = myApp.createVerticalPanel().setStyleAttribute('background', 'beige');
fullPanel.setHeight('100%');
fullPanel.setWidth('100%');
fullPanel.setHorizontalAlignment(UiApp.HorizontalAlignment.CENTER);
fullPanel.setVerticalAlignment(UiApp.VerticalAlignment.MIDDLE);
fullPanel.add(verPanel);
myApp.add(fullPanel); // Now verPanel will be centered
return myApp;
}
// *************** Eventhandlers
function onClickChkDatums(e)
{ // Eventhandler for chkDatums
var app = UiApp.getActiveApplication();
var chkDatums = app.getElementById('chkDatums');
var status = (e.parameter.chkDatums == 'true');
var labelBeginDatum = app.getElementById('labelBeginDatum');
var labelEindDatum = app.getElementById('labelEindDatum');
labelBeginDatum.setVisible(status);
labelEindDatum.setVisible(status);
var pickerBeginDatum = app.getElementById('pickerBeginDatum');
var pickerEindDatum = app.getElementById('pickerEindDatum');
pickerBeginDatum.setVisible(status);
pickerEindDatum.setVisible(status);
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('globalUseDatums', status);
return app;
}
I don't want to make it a habit answering my own questions, but this one might be useful for others as well.
Using BOTH setCurrentMonth() and setValue() shows the right dates in the datePicker
pickerBeginDatum.setCurrentMonth(zoekBeginDatum); // Needed !!
pickerEindDatum.setCurrentMonth(zoekEindDatum); // Needed !!
pickerEindDatum.setValue(zoekEindDatum); // Does ONLY work in combination with setCurrentMonth
pickerBeginDatum.setValue(zoekBeginDatum); // Does ONLY work in combination with setCurrentMonth

GAS - Sort a flexTable by column

I understand that cellTable in GWT performs this (Sort FlexTable Inquiry) and I was wondering if anyone knew a way to emulate some of the column sorting behaviour using a flexTable in UiApp.
In my case it is only necessary for the app to sort the column once at creation, not have it sortable by the user on click. I have included my flexTable creation code below:
var flexTable = app.createFlexTable()
.setStyleAttribute('marginTop', '10px')
.setCellPadding(5)
.setCellSpacing(2);
for(var i = 0;i<(size-1);i++){
var class = "class" + (i+1);
var classCode = classObjectsIndex[loggedInUser][class];
var text10 = statusObjectsIndex[classCode].classname;
var text11 = statusObjectsIndex[classCode].homeworkstatus;
var text12 = statusObjectsIndex[classCode].classcalendarlink;
var anchor = app.createAnchor('Calendar', text12)
.setTarget('_blank');
var calPanel = app.createAbsolutePanel()
.add(anchor);
flexTable.setText(i, 0, text10);
flexTable.setText(i, 1, text11);
flexTable.setWidget(i, 2, calPanel);
if(text11 == "No homework set for this class"){
flexTable.setRowStyleAttribute(i, "backgroundColor", "#96bcfd")
flexTable.setRowStyleAttribute(i, "color", "#000000");
}else{
flexTable.setRowStyleAttribute(i, "backgroundColor", "#eca8a3");
flexTable.setRowStyleAttribute(i, "color", "#FFFFFF");
};
}
app.add(flexTable);
Due to the way in which the table is populated sorting the array the values are pulled from will not help.
This the first question I have posted here, please be gentle. If I could ask it in a better way, I have overlooked an obvious resource to get my answer or if there is more information I need to provide please let me know!
EDIT//////////////////////////////////
I was having trouble sorting using the code provided, very helpfully, by Serge and so I approached it slightly differently and created individual objects for each row of data. The advice given by both Serge and Zig helped me end up with this working solution, many thanks!
//create flexTable
var flexTable = app.createFlexTable();
flexTable.setStyleAttribute('marginTop', '10px')
flexTable.setCellPadding(5);
flexTable.setCellSpacing(2);
//create empty table array to store rowObjects
var tableArray =[];
//create rowObjects
for(var i = 0; i<(size-1); i++){
var rowObject = {};
var class = 'class' + (i+1);
var classCode = classObjectsIndex[loggedInUser][class];
rowObject.className = statusObjectsIndex[classCode].classname;
rowObject.homeworkStatus = statusObjectsIndex[classCode].homeworkstatus;
rowObject.link = app.createAbsolutePanel().add(app.createAnchor('Calendar',statusObjectsIndex[classCode].classcalendarlink));
if(statusObjectsIndex[classCode].homeworkstatus == "No homework set for this class"){
rowObject.BGColor = "#96bcfd";
rowObject.color = "#000000";
}else{
rowObject.BGColor = "#eca8a3";
rowObject.color = "#FFFFFF";
}
tableArray.push(rowObject);
}
//sort objects in array by homework status
tableArray.sort(function (a, b) {
if (a.homeworkStatus > b.homeworkStatus)
return 1;
if (a.homeworkStatus < b.homeworkStatus)
return -1;
return 0;
});
//populate flextable
for(var i = 0;i<(size-1);i++){
flexTable.setText(i,0, tableArray[i].className);
flexTable.setText(i,1, tableArray[i].homeworkStatus);
flexTable.setWidget(i,2, tableArray[i].link);
flexTable.setRowStyleAttribute(i, 'color', tableArray[i].color);
flexTable.setRowStyleAttribute(i, 'backgroundColor', tableArray[i].BGColor);
};
app.add(flexTable);
Theres nothing that prevents you from sorting the source array first. Just store each 5 columns (3 data columns plus background/foreground colors) as rows in another array and sort that other array. After sort populate the table.
I fully agre with Zig on this, here is an example of such an implementation to help you figure out how to approach it. (code not tested but should be right)
var flexTable = app.createFlexTable()
.setStyleAttribute('marginTop', '10px')
.setCellPadding(5)
.setCellSpacing(2);
var array = [];
var t0 = [];
var t1 = [];
var t2 = [];
var color = [];
var BGcolor = [];
for(var i = 0;i<(size-1);i++){
var class = "class" + (i+1);
var classCode = classObjectsIndex[loggedInUser][class];
t0.push(statusObjectsIndex[classCode].classname);
t1.push(statusObjectsIndex[classCode].homeworkstatus);
t2.push(app.createAbsolutePanel().add(app.createAnchor('Calendar',statusObjectsIndex[classCode].classcalendarlink)));
if(statusObjectsIndex[classCode].homeworkstatus == "No homework set for this class"){
color.push("#000000")
BGcolor.push("#96bcfd")
}else{
color.push("#FFFFFF")
BGcolor.push("#eca8a3")
};
array.push(t0,t1,t2,color,BGcolor);
}
// sort the array here
array.sort();// use other sort parameter if you want, search SO for examples
for(var n in array){
flexTable.setText(i, 0, array[n][0]);
flexTable.setText(i, 1, array[n][1]);
flexTable.setWidget(i, 2, array[n][2]);
flexTable.setRowStyleAttribute(i, array[n][3])
flexTable.setRowStyleAttribute(i, array[n][4]);
}
app.add(flexTable);