How to retrieve values from the last row - forms

I created a Form for requesting new student Google account. I want a Sheets Script to email the person who submits the Form the new account information, which is created via a formula on a "Results" sheet.
function Notification() {
// Send email notice for accounts
var lastRow = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Results").getLastRow();
var range = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Results").getRange("A" + lastRow);
if (range.getValue() !== "") {
return lastRow;
} else {
return range.getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
var AccountName = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Results").getRange("H" + lastRow);
var Password = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Results").getRange("I" + lastRow);
var PW = Password.getValue();
var Account = AccountName.getValue();
// Fetch the email address
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Results").getRange("G" + lastRow);
var emailAddress = emailRange.getValues();
// Send Alert Email.
var message = 'Account Request - Account Name: ' + Account + ' Password: ' + PW; // Second column
var subject = 'Google Account Request';
MailApp.sendEmail(emailAddress, subject, message);
}
This script is triggered on a new Form Submit. Attempting to pull the values from the last created row queried to a "Results" sheet, using lastRow to find the latest entries row, from select columns. Script runs without error, but no email is sent, telling me that it's not getting the values, or returning null values.
This is the sheet its pulling data from

You are only sending row 2 because you are retrieving only one value (Password.getValue() and AccountName.getValue()). Consider the difference between getValue versus getValues.
On the other hand, by declaring a range such as getRange("H2:H") ("Account Name") you are including every row in the spreadsheet, including rows with and without content.
How would I make it pull the values from the last created row?
There are two options:
getlastRow() (the "Sheet" versus "Range" version) "returns the position of the last row that has content" doc ref here. In fact, that item of documentation has a good example of how to declare a Range using the command.
there is another (very useful) utility described on StackOverflow that is a favourite of mine. This describes the number of contiguous rows, in a column, with content.
I suggest that you declare the range using getRange(row, column, numRows, numColumns).
"row" having been determined using one of the methods described above, "numRows"=1. Then getValues for that range will include only the values in that row, and your email will be sent only in relation to that row.

Related

How to get the current active table (where currently the cursor is positioned) in Word using Office.js api?

I want to get the content of a table ,by just clicking on the table(not selecting the table) i.e placing the cursor on the table, in Word Add-in using Office Js Api.
The Word JS API has (since release of Requirement Set 1.3) the parentTable and the ParentTableOrNullObject properties of the Range object.
Since document.GetSelection() returns a Range object, code like the following sample will evaluate whether the current selection is in a table. (It also counts the number of rows and selects the table.)
const range = context.document.getSelection();
range.load("parentTableOrNullObject");
await context.sync();
var isInTable = range.parentTableOrNullObject;
if (isInTable.isNullObject) {
messageText = "The selection is not in a table."
}
else {
var tblRows = isInTable.rowCount;
isInTable.load("rowCount");
await context.sync();
var messageText =
"The selection is in a table with " + tblRows.toString() + " rows.";
isInTable.select();
}
console.log(messageText);

How to use database data on Event OnBeforeCreate

I want to get the last data created on my database, more specifically the field called: "Saldo Atual" and after this get the form data field "Valor" and make a sum between this fields (the Old one "Saldo Atual" and the new "Valor") before create a new record and add this "Valor" and the sum of "Saldo Atual"+"Valor".
I don't know how to get the database last record
var saldoAtual =
record.saldoAtual = saldoAtual + record.valor;
And I want to know if the second line it's correct to save the sum of "Saldo Atual"+"Valor"
Based on my comment, I think that your records will need to have a Date_Created field. Then in your onBeforeCreate event the following script should work (this is untested, so you need to do your own testing):
var query = app.models.YourModelTheSameAsYourEventModel.newQuery();
query.sorting.Date_Created._descending();
query.limit = 1;
var lastrecord = query.run();
record.saldoAtual = lastrecord.saldoAtual + record.valor; //You may need to use lastrecord[0].saldoAtual
record.Created_Date = new Date();
Try that and do some testing to see if this yields your desired output.

using email addresses as keys in firestore

I want to create "invitations" based on email addresses so that when a user with that email would arrive to the system his invitations would already be waiting for him.
so I wanted to create an invitations collection with key based on groupId + '_' + invited_user_email but if the user is test#test.com this the .com is interpreted as a subkey :(
I tried groupId + '_' + invited_user_email.replace(/[.]/g,'\\.') but it did not help either.
What am I missing? Is there no way to include a '.' in a firestore document's ID ?
EDIT:
per Doug Stevenson's request here is the code I use now:
var invitedUserEmailAsKey=invitedUserEmail.replace(/[.]/g,'\\.')
var batch = db.batch();
var groupRef = db.collection("groups").doc(groupId);
var invitationRef = db.collection("invitations").doc( groupRef.id + '_' + invitedUserEmailAsKey);
var groupUpdates = {};
groupUpdates['invited.' + invitedUserEmailAsKey + '.user_name'] = invitedUserName;
groupUpdates['merge'] = true;
batch.update(groupRef, groupUpdates);
The problems are with the updated document on the groups collection.
It ends up looking like this:
instead of having someone#gmail.com as a key
Using update() with "dot" in a key is interpreted as a nested field as documented here.
Notice that you're updating a document fields (groupRef) and not really doing anything with the "invitations" collection. I don't think that creating a new field on the group doc for every invitation is what you really mean to do.
As Dror mentioned, adding users with update() and a dot in the key won't work.
I use the set method with merge true:
addUserToGroup(id,email,type){
this.log("id",id,"email",email,"type",type);
let obj = {};
obj[email] = type;
this.angularFireStore.collection("Users").doc(id).set(obj, { merge: true }).then(() => {
this.log("addedUser",email);
}).catch((error) => {
this.log("failed to add user",error)
})
}
From the documentation: https://firebase.google.com/docs/firestore/manage-data/add-data#web-v8_1
"To create or overwrite a single document, use the set() method"
"If you're not sure whether the document exists, pass the option to merge the new data with any existing document to avoid overwriting entire documents."

Adding a row and copying the information from the original row for every day in a date range in Google Sheets

I have a Google Sheet where information from a Google Form is dumped. Two of the columns create a date range and I would like for the sheet to automatically create a new row of information for every date of the range and copy all the other information from the original row for every row that is created. In the end, every date in the range has it's own row regardless of it being 2 days or 25 and all the the information gathered through the form be present for each day
Here is an example
Here's a function that will do the trick for you. My spreadsheet is below after running. I just append it to the bottom of the starting data.
function convertDateRangetoRows()
{
var ss=SpreadsheetApp.getActive();
var sht=ss.getActiveSheet();
var rng=sht.getDataRange();
var rngA=rng.getValues();
var rngB=[];
var day=86400000;
rngB.push(rngA[0]);
for(var i=1;i<rngA.length;i++)
{
rngB.push(rngA[i]);
if(rngA[i][0] && rngA[i][1] && rngA[i][0]!=rngA[i][1])
{
var dt0=new Date(rngA[i][0]);
var dt1=new Date(rngA[i][1]);
var days=(dt1.valueOf()-dt0.valueOf())/day;
var dt=dt0.valueOf();
for(j=0;j<days;j++)
{
dt+=day;
rngB.push([Utilities.formatDate(new Date(dt), Session.getScriptTimeZone(), "MM/dd/yyyy"),'',rngA[i][2],rngA[i][3],rngA[i][4]]);
}
}
var intermediate='nothing';
}
var rngb=sht.getRange(sht.getLastRow()+1,1,rngB.length,rngB[0].length);
rngb.setValues(rngB);
var end='the end is near';
}

How to get values from input in sap.ui.table.Table?

In sap.ui.table.Table I have input field in one column. It will get nearly 300 records of data from back-end and binded in other columns.
User manually enters in the input field. Further, when he clicks on submit button I have to take all values from all input as array. Please give suggestions.
You can do it using data binding of table, as invoking getRows() on Table control to access Input fields of each row would not help in this case;it only returns only currently visible rows and you have around 300 records to access.
Here is the solution:
Get all data from back-end in JSONModel.
Add one property say inputValue to each item in model's data by iterating over it.
Bind this model to table and use inputValue property in table's template to bind column containing Input fields.
As JSONModel supports two-way binding, all the values which user has entered in an Input fields are available in your model.
And, lastly iterate over model's data to get inputValue for each row.
Above steps in action:
Step 1 and 2:
setModelForTable: function() {
var oModel = sap.ui.model.json.JSONModel( < URLToLoadJSON > );
var length = oModel.getData().results.length;
for (var i = 0; i < length; i++) {
var path = "/results/" + i + "/inputValue";
oModel.setProperty(path, "");
}
}
Step 3:
Now, that you have model with inputValue property in all the items of data, set the model on table; which will show all the Input fields in columns empty initially and will update the corresponding model entry as user modifies it.
<t:Column>
<t:label>
<Text text="User Input" />
</t:label>
<t:template>
<Input value="{inputValue}" />
</t:template>
</t:Column>
Finally, get all entered values in array.
var length = oModel.getData().results.length;
var aInputvalues = []
for (var i = 0; i < length; i++) {
var path = "/results/" + i + "/inputValue";
aInputvalues.push(oModel.getProperty(path));
}
I had the case which is a bit similar and I did it in the following way. Will work if you really do not need records which are not changed.
have a variable to store [] of changed records
Attach change to input field
on change push changed record to a variable
var source = event.getSource();
source.getModel().getProperty(source.getBindingContext().getPath());
or the value of the input field.
event.getSource().getValue();
In case you have a record Id you can just push this ID and input value.
4. on submit iterate through an []