This question already has an answer here:
using a forEach loop to build html table and date/time comes through as null
(1 answer)
Closed 2 years ago.
Trying to populate the sheet data in HTML web app, my data consists Time(24 hrs format) but in web apps, it's reflecting in a different format.
Attached Image for reference
function doGet() {
var t = HtmlService.createTemplateFromFile('index');
t.data = SpreadsheetApp
.openById('1ZPbCZWvEIJ7rpYxyfD4yiWrnC11RT9I_96kCndAJmdI')
.getActiveSheet()
.getDataRange()
.getValues();
return t.evaluate();
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<table>
<? for (var i = 0; i < data.length; i++) { ?>
<tr>
<? for (var j = 0; j < data[i].length; j++) { ?>
<td><?= data[i][j] ?></td>
<? } ?>
</tr>
<? } ?>
</table>
</body>
</html>
How about a following modification? getDisplayValues() was used for this situation.
From :
function doGet() {
var t = HtmlService.createTemplateFromFile('index');
t.data = SpreadsheetApp
.openById('1ZPbCZWvEIJ7rpYxyfD4yiWrnC11RT9I_96kCndAJmdI')
.getActiveSheet()
.getDataRange()
.getValues();
return t.evaluate();
}
To :
function doGet() {
var t = HtmlService.createTemplateFromFile('index');
t.data = SpreadsheetApp
.openById('1ZPbCZWvEIJ7rpYxyfD4yiWrnC11RT9I_96kCndAJmdI')
.getActiveSheet()
.getDataRange()
.getDisplayValues(); // Modified
return t.evaluate();
}
Related
I have a code that sends a summary of a sheet in an email. However, I want to add a summary table from another sheet to that email. The sheet that I want to add to the email looks like this: [![Sheet][1]][1]. This sheet is a filter from another sheet and it filters only the rows where the date is equal to the date in B1.
I would like to have a copy of this table that contains only the rows that are not empty and add it to the email.
I tried this code:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var responses = ss.getSheetByName("cambios mail");
var mail = ss.getSheetByName("MAILS");
var active_range = responses.getActiveRange();
var cambio = responses.getRange(active_range.getRowIndex(), 5).getValue();
var nuevo = responses.getRange(3, 11).getValue();
var cancelados = responses.getRange(3, 12).getValue();
var fecha =responses.getRange(3, 8).getValue();
var date = Utilities.formatDate(fecha, "GMT+2", "dd/MM/YYYY")
var sheet = ss.getSheetByName('cambios drop');
var values = sheet.getRange("A2:I" + sheet.getLastRow()).getValues();
var tabla= JSON.stringify(values);
var subject = "CAMBIOS REFERENCIAS: Resumen refes canceladas/añadidas";
var body = "Los siguientes modelos fueron modificados en el Master Doc ayer fecha " +date +".\n\n" + "Refes añadidas:" + nuevo + "\n\nRefes canceladas:"+ cancelados+ "\n\nCualquier consulta podéis contestar a este mail."+"\n\nAdjunto una tabla con los cambios de drops de ayer. Si no hubo cambios, la tabla aparecerá vacía."+"\n\nTabla"+ tabla+ "\n\nArchivo: https://docs.google.com/spreadsheets/d/";
var mailCorrecto = mail.getRange(1,2).getValues()
GmailApp.sendEmail(mailCorrecto, subject, body);
And this is what the table looks like on the email:
[![email][2]][2]
Does anybody know how I can format the range to be able to see it as a table on the email?
Thank you in advance!
[1]: https://i.stack.imgur.com/Tt3b9.png
[2]: https://i.stack.imgur.com/pZMEd.png
A templated html file for sending a table to an email
html:
<!DOCTYPE html>
<html>
<head>
<title>My Title</title>
</head>
<body>
<div id="myimages">
<? for(var i = 0;i < filename.length; i++) { ?>
<br /><img src="cid:img<?= i ?>" /><br />File Name: <?= filename[i] ?><hr />
<? } ?>
</div>
This is the div for the table
<div id="tabledata">
<? var vs = getBullSheetData(); ?>
<table>
<? vs.forEach((r,i)=>{ ?>
<tr>
<? r.forEach((c,j)=>{ ?>
<? if(i == 0) { ?>
<th style="padding:2px 5px;font-weight:bold;border:1px solid black;"><?= c ?> </th>
<? } else { ?>
<td style="padding:2px 5px;border:1px solid black;"><?= vs[i][j] ?> </td>
<? } ?>
<? }); ?>
</tr>
<? }); ?>
</table>
</div>
This is the end
</body>
gs:
function getBullSheetData() {
Logger.log('entering getBullSheetData')
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet2');
const vs = sh.getDataRange().getValues();
return vs;
}
templated html
I've got JS form validation code and have to write HTML to it. Unfortunately, something is wrong. Could you please tell me what I am doing wrong? When I click submit button there is no change.
window.onload = init;
function validateForm() {
var user = document.forms["myForm"]["user"].value;
var password = document.forms["myForm"]["password"].value;
if (user == "") {
document.getElementById("poleUser").innerHTML = "<img src='./unchecked.gif'/> Proszę podać nazwisko";
} else {
document.getElementById("poleUser").innerHTML = "<img src='./checked.gif'/>";
}
if (password.lenght < 6) {
document.getElementById("poleHasla").innerHTML =
"<img src='./unchecked.gif'/> Hasło musi zawierać co najmnej 6 znaków";
} else {
document.getElementById("poleHasla").innerHTML = "<img src='./checked.gif'/>";
}
return false;
}
function init() {
document.getElementsByName('myForm').onsubmit = validateForm;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form name="myForm">
Name: <input type="texts" name="user"><span id="poleUser"></span><br>
Password: <input type="password" name="password"><span id="poleHasla"></span>
<br>
<input type="submit" value="Submit">
</form>
</body>
</html>
You need to properly format the function calls
document.getElementsByName('myForm').onsubmit = validateForm;
should be
document.getElementsByName('myForm').onsubmit = validateForm();
(Notice the parentheses at the end).
However, I'd just like to address how you're doing this. In most cases, assigning the onSubmit property statically makes more sense than doing it dynamically. In this case, there really doesn't seem to be any reason for initializing the property using JS.
I have a webapp form and I'm looking for a way to push the value of the form into google spreadsheet.
My current attempt is to assign a name to each form input (a1,a2,a3...) then attempt to iterate the form values into an array like this:
Code.gs
function doGet(e) {
return HtmlService
.createTemplateFromFile('Index')
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.NATIVE)
}
function writeForm(form) {
var ss =
SpreadsheetApp.openById('1bKrGjBV*****');
var sheet = ss.getSheets()[0];
var data = ss.getDataRange().getValues();
var input = [''];
var ndata = form
for(var j=0;j<data.length;j++){
var value = form.a+j
input.push(value)
}
for(var k=0;k<data.length;k++){
sheet.getRange(k+1,4).setValue(ndata[k]);
}
var range = sheet.getRange(1, 5);
}
function getData(){
return SpreadsheetApp
.openById('1bKrGjBV*****')
.getSheets()[0]
.getDataRange()
.getValues();
}
Index.html
<body>
<center><h1>Produce Inventory Form </h1></center>
<style>
table,th,td{border:1px solid black;}
</style>
<? var data = getData(); ?>
<form id="invform">
<input type = "submit" value="Submit" onclick
="google.script.run.writeForm(this.parentNode)">
<table align="center">
<tr><th>Code</th><th>Name</th><th>ChName</th><th>On Hand</th></tr>
<? for(var i=0;i<data.length;i++){ ?>
<tr>
<th><?= data[i][0] ?></th>
<th><?= data[i][1] ?></th>
<th><?= data[i][2] ?></th>
<th><input type = "text" style="width:40px" min="0" maxlength="3" name=a<?
=i ?>>
</tr>
<? } ?>
</table>
</body>
With this method, the problem I'm getting into is
var value = form.a+j
Doesn't do what I was hoping for, which is to assign a variable to form.a1, form.a2, form.a3, ... then push it into an array.
I'm pretty sure there's a better way but I have yet to find a solution. Apologize for the messy code, but I was focused on getting the result.
How about a following modification?
Modification points :
For Index.html, </form> is missing.
About form.a+j, you can retrieve the values using form["a" + j].
ndata is JSON like {a1: "value", a2: "value"}. So when ndata is imported to cells, it becomes undefined.
When several values are imported to cells, the importing efficiency becomes higher by using setValues().
When these are reflected to your script, the modified script is as follows. The values inputted to forms are imported to "D1:D" of spreadsheet.
Modified script :
Code.gs
function doGet(e) {
return HtmlService
.createTemplateFromFile('Index')
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.NATIVE)
}
function writeForm(form) {
var ss = SpreadsheetApp.openById('1bKrGjBV*****');
var sheet = ss.getSheets()[0];
var data = ss.getDataRange().getValues();
var input = []; // Modified
// var ndata = form
for(var j=0;j<data.length;j++){
var value = form["a" + j]; // Modified
input.push([value]) // Modified
}
sheet.getRange(1, 4, input.length, input[0].length).setValues(input); // Added
// for(var k=0;k<data.length;k++) {
// sheet.getRange(k+1,4).setValue(ndata[k]);
// }
// var range = sheet.getRange(1, 5);
}
function getData(){
return SpreadsheetApp
.openById('1bKrGjBV*****')
.getSheets()[0]
.getDataRange()
.getValues();
}
Index.html
<body>
<center><h1>Produce Inventory Form </h1></center>
<style>
table,th,td{border:1px solid black;}
</style>
<? var data = getData(); ?>
<form id="invform">
<input type = "submit" value="Submit" onclick="google.script.run.writeForm(this.parentNode)">
<table align="center">
<tr><th>Code</th><th>Name</th><th>ChName</th><th>On Hand</th></tr>
<? for(var i=0;i<data.length;i++){ ?>
<tr>
<th><?= data[i][0] ?></th>
<th><?= data[i][1] ?></th>
<th><?= data[i][2] ?></th>
<th><input type = "text" style="width:40px" min="0" maxlength="3" name=a<?= i ?>>
</tr>
<? } ?>
</table>
</form> <!-- Added -->
</body>
If I misunderstand your question, I'm sorry.
I am trying to insert newly created elements (rows and cells) into a table (via javascript) above a row that has an ID of "dynPop". When I attempt to do this, I get the following error
TypeError: target is null
Here is the HTML of the table...
<table>
<tr id="dynPop">
<td style="color:white">
blah blah blah blah blah
</td>
</tr>
</table>
And here is the code to insert the new row and cell before it...
$rownumber = 1;
var target = document.getElementById('dynPop');
//Populate member table with chapter image row
var $CHAP_IMAGE = $out[1];
var olr1 = document.createElement('tr');
var old1 = document.createElement('td');
var olt1 = document.createTextNode($CHAP_IMAGE);
old1.appendChild(olt1);
olr1.appendChild(old1);
$rowname = 'row' + $rownumber;
olr1.setAttribute('name', $rowname);
target.insertBefore(olr1, target);
$rownumber++;
Any thoughts as to why this javascript code is not working ?
Thanks!
I"m not sure without seeing the rest of your HTML, but I think the main problem is that your JavaScript is executing before the DOM loads.
You might try putting your JavaScript into a function that gets called on the body element's onload event:
<!DOCTYPE html>
<html>
<head>
<title>asdf</title>
<script type="text/javascript">
function doThing() {
$rownumber = 1;
var target = document.getElementById('dynPop');
var $CHAP_IMAGE = "$out[1]; ";
var olr1 = document.createElement('tr');
var old1 = document.createElement('td');
var olt1 = document.createTextNode($CHAP_IMAGE);
old1.appendChild(olt1);
olr1.appendChild(old1);
$rowname = 'row' + $rownumber;
olr1.setAttribute('name',$rowname);
target.insertBefore(target, olr1);
$rownumber++;
}
</script>
</head>
<body onload="doThing()">
<table>
<tr id="dynPop">
<td style="color:white">
blah blah blah blah blah
</td>
</tr>
</table>
</body>
</html>
I have a HTML form in JSP page, and in the I have a JavaScript validation. The user must enter one field: name or id or year, and a java file will search the student in database by name or by id or by year. The JavaScript alerts when no field is filled and performs the action if one field is filled.
<html>
<head>
<title>Student to search into database</title>
<script language="javascript">
function validate2(objForm){
int k = 0;
if(objForm.name.value.length==0){
objForm.name.focus();
k++;
}
if(objForm.year.value.length==0){
objForm.year.focus();
k++;
}
if(objForm.id.value.length==0){
objForm.year.focus();
k++;
}
if(k == 0){
return false;
}
return true;
}
</script>
</head>
<body bgcolor=#ADD8E6><center>
<form action="FoundStudents.jsp" method="post" name="entry2" onSubmit="validate2(this)">
<input type="hidden" value="list" name="seek_stud">
...........................................................................................
The problem is I want to process the parameter which I receive in FoundStudents.jsp: If I get the year, I look in DB which student(s) are in that year and display all that student(s)' data(do that in a java file). How could I do that in FoundStudents.Jsp without checking again which field is filled(I've done that in JavaScript from SearchStudent.jsp). I mean the FoundStudents.jsp calls a method in the java file for searching and displaying.
I tried by now with the input hidden that worked, but that is for more forms. I have only 1.
FoundStudent.jsp
<%#page import="stud.diploma.students.StudentsManager"%>
<%#page import="stud.diploma.students.Student"%>
<%#page import="java.util.ArrayList"%>
<%#page import="stud.diploma.database.ConnectionsManager"%>
<%# page language="java" import="java.sql.*, java.lang.*" %>
<%
Student search = null;
if(request.getParameter("seek_stud") != null){
//reading params from the SearchStudent form
String name = request.getParameter("name");
String year_prime = request.getParameter("year");
int year, id;
try{
year = Integer.parseInt(year_prime);
}catch(Exception e1){
year = 0;
}
String id_prime = request.getParameter("id");
try{
id = Integer.parseInt("id");
}catch(Exception e2){
id = 0;
}
if(name.length() != 0){
search = StudentsManager.getInstance().studByName(name);
}
if(year > 0){
search = StudentsManager.getInstance().studByYear(year);
}
if(id > 0){
search = StudentsManager.getInstance().studById(id);
}
if(search != null){
%>
<html>
<body bgcolor=#4AA02C>
<center>
<h2>Student's data</h2>
<table border="1" cellspacing="1" cellpadding="8" bgcolor= #EBDDE2>
<tr>
<td bgcolor= #FF9966><b>ID</b></td>
<td bgcolor= #FF9966><b>Name</b></td>
<td bgcolor= #FF9966><b>Year</b></td>
</tr>
<tr>
<td><%= search.getId()%></td>
<td><%= search.getName()%></td>
<td><%= search.getYear()%></td>
</tr>
</table>
</center>
</body>
</html>
<%}else{%>
<%
String redirectURL = "MainMenu.html";
response.sendRedirect(redirectURL);
%>
<%}%>
<%}%>
This FoundStudent.jsp is for the version of multiple forms (using hidden input) that worked. (the javascript test was just a little bit different, I typed it insted of what I had in the beginning)
It searched by name and by year only. Didn't search by ID (I had exception here <td><%= search.getId()%></td> I'm still trying to see how to deal with it. ID is a AUTO_INCREMENT PRIMARY KEY)
Lines like : search = StudentsManager.getInstance().studByName(name);
Search is a Student type object. (Object Student is creaded in a java file)
StudentsManager is a java class that receives calls to it's methods from JSP. getInstance() creates an instance of StudentsManager. Method studByName(name) receives the parameter name from the form and searches it in the database.
So I changed the (java)script to:
<script language="javascript">
function validateSea(){
if(document.entry2.name.value != ''){
return true;
}
else
if(document.entry2.year.value != ''){
return true;
}
alert('Please fill one field.');
return false;
}
</script>
</head>
which is for 1 form. I'm not sure if I did the correct thing, but in FoundStudents.jsp, where I receive the parameters of the form, I test:
if((request.getParameter("year") != null)||(request.getParameter("name") != null)){
//reading params from the SearchStudent form
................}
It works this way.