I am trying to develop a WebApp in which user enters his/her id and script will search that ID in the Google sheet and retrieve the respective data row from sheet which contains that ID. Now script is searching the ID in sheet and retrieve the specific row as an array. But I want to import that data in Table in WebApp. But couldn't find any reasonable solution. Following is the script:
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
function FetchData(val) { //'val' is entered by user in WebApp
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Sheet1");
var lc=formSS.getLastColumn();
var lr=formSS.getLastRow();
for (var i=2;i<=lr;i++)
{
var UID = formSS.getRange(i, 1).getValue();
if (val==UID) //Searching Google Sheet ID's and User Entered ID
{
var res=formSS.getRange(i, 1, 1,lc).getValues()[0];
return res; //contains the data of specific row which we want to put in WebApp Table
}
}
}
This is HTML Code
<body>
<script>
document.getElementById("btn").addEventListener("click",SearchID);
function SearchID() //Searching ID in Google Sheet
{
var id=document.getElementById("userid").value;
google.script.run.FetchData(id);
document.getElementById("userid").value="";
}
</script>
</body>
</html>
Is there any way that we can put this data in the table of WebApp HTML page. Any Guidance would be much appreciated. This is sheet Link:
https://docs.google.com/spreadsheets/d/119wJ3sBY3coGpEo2CHDnW1hPv_WQbgRaQKUwv7HxyFY/edit?usp=sharing
As others mentioned, you need to construct a HTML table based on the results received from the server. getValues() returns Object[][], but in your case, the function returns when it finds the first result, so you have only one row.
After receiving that, your useData() function should create a TABLE element using HTML syntax, so you need to add tags like <TABLE>, <TR>, <TH> and <TD>. These tags can be added to a variable that is used to construct the table, appending tags and their contents as you iterate over the data received:
function useData(data) {
var output = document.getElementById('OutPut');
// Start building table
var html = '<table>';
// Add table header
html += `<tr>
<th>Unique ID</th>
<th>Student name</th>
<th>Course</th>
<th>Issued on</th>
<th>certificate link</th>
</tr>`;
// Add table row, assuming there's only one row based on what is being done by Apps Script
html += '<tr>';
for (var col = 0; col < data[0].length; col++) {
html += '<td>' + data[0][col] + '</td>';
}
html += '</tr>';
// Stop building table
html += '</table>';
// Add table to existing element
output.innerHTML = html;
}
Related
I am trying to adapt Zack Akil's script to generate a Google Form from a Google Sheet using App Script, but one thing that I am struggling with is to make the sheet's input parsed as HTML. I generate a form based on my sheet, all the text on cells is placed in Forms as plain text, the HTML is not parsed (see figure below).
I pasted the script from Zack and I kindly ask you to point out where should I modify in order to have this parsed on the form.
function getSpreadsheetData(sheetName) {
// Return an list of objects (one for each row) containing the sheets data.
var arrayOfArrays = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName || 'Sheet1').getDataRange().getValues();
var headers = arrayOfArrays.shift();
return arrayOfArrays.map(function (row) {
return row.reduce(function (memo, value, index) {
if (value) {
memo[headers[index]] = value;
}
return memo;
}, {});
});
}
function create_ranges_for_data(form, data, data_section_name){
// loop throughh each row
data.forEach(function (row) {
// create a new question page
form.addPageBreakItem()
// add page title
form.addSectionHeaderItem()
.setTitle(data_section_name);
// create number range input with the title being the document to be labeled
form.addScaleItem()
.setTitle(row[data_section_name])
.setBounds(1, 10)
.setRequired(true);
});
}
function make_form_using_column(column_name) {
// create a new Google Form document
var form = FormApp.create('Data labelling - ' + column_name)
desc = "Thank you for taking the time to label this data!";
form.setDescription(desc);
form.setProgressBar(true);
form.setShowLinkToRespondAgain(false)
var data = getSpreadsheetData();
create_ranges_for_data(form, data, column_name);
}
function gen_form(){
var COLUMN_TO_USE = 'Input text'
make_form_using_column(COLUMN_TO_USE);
}
You can't use HTML text formatting. most sites block it because it poses a security risk. You might need to install an add-on or, like fullfine said, use bold text.
I have a Google spreadsheet in which I record my freelance jobs. I have it set up that each line calculates whether it is paid for. (Payments are pulled from a separate sheet.)
What I would like to do is to generate an invoice, where I would select the customer and I get a listing of all unpaid entries for that customer.
Using a arrayed filter function does the job, but I can't use that as an invoice because I need the total line underneath, and would prefer the table format matching the count of entries.
Is it possible to insert such information into a Google Doc as a table, or within Sheets, to push the lines following an array down?
I thought this would be a simple enough concept but I can't find anything that does the full deal.
You could try this script. I'm not sure if the final results is what you are looking for. In case it is not, it can be easily modified:
function onEdit(e) {
//If you change the Customer in the Invoice sheet, it runs the code
if (e.range.getA1Notation() == 'A1' && e.source.getSheetName() == 'Invoice'){
var sprsheet = SpreadsheetApp.getActiveSpreadsheet();
var invoice = sprsheet.getSheetByName("Invoice");
var times = sprsheet.getSheetByName("Times");
var in_customer = invoice.getRange("A1").getValue(); //Name you selected in the dropdown menu
var data = times.getRange("A1:H").getValues(); //All the data from the Time sheet
var total = 0;
//Loops through all the data looking for unpaid subtotals from that customer
for (var i = 0; i < data.length; i++){
/*> "i" represents the row, the second number is the column
> The rows start at 0 since it is the first array position.
*/
if (in_customer == data[i][2]) {
if (data[i][7] == 'N'){
total += Number(data[i][5]); //Accumulates each subtotal into total
invoice.appendRow([data[i][0], data[i][1], data[i][3], data[i][5]]);
}
}
}
invoice.appendRow(["Total: ","","", total]);
}
}
This results in (I changed some values to test it):
As you see I added some headers.
References:
Range Class
onEdit Trigger
I'm a beginner at this so apologies. I'm trying to have a sheet with data in column A be the options in a specific list in a form. Ultimately I would like many columns of data be the reference of specific lists. The form doesn't need to sync with the list. I'd prefer to do that by running script in sheet.
This is how far I am but it's only pulling cell A1.
Right now the form is simple and only has one drop down question.
Many thanks for any help.
var FORM_ID = '1Edo3yPmfPLQXPRff6z8oDsYW0Hp-Mm5SYLISPnyTXfo';
var LIST_SHEET_NAME = 'List';
var range = 'A:A';
var ITEM_ID = '983918997';
function updateListInForm() {
var values_ = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName(LIST_SHEET_NAME)
.getRange(range)
.getValues();
values_[0][0] = values_[0][0].toString();
for (var i = 1; i < values_.lenght; i++) {
values_[0].push(values_[i][0].toString())
}
var form = FormApp.openById(FORM_ID);
var list = form.getItemById(ITEM_ID);
list.asListItem().setChoiceValues(values_[0]);
function getitemsofform() {
var form = FormApp.openById(FORM_ID);
var items = form.getItems(FormApp.ItemType.LIST);
for (var i in items) {
Logger.log('id: ' + items[i].getId() + ' title: ' + items[i].getTitle());
}
}
}
One more thing. Can anyone point me to a program or app that teaches google script? I would like to start from scratch. ie. this is what var means, this is how to write a simple function
I'm trying to create a dynamic HYPERLINK formula that will automatically create the link based on the sheet name in Column A, but I'm not sure how (or if it's possible) to get the URL of the sheet based on the name.
Here's the setup:
Single Google Spreadsheet with multiple tabs
Tab names: 1500, 1501, 1502, Consolidated
On the Consolidated tab, I have two columns: Column A is the Sheet Name, and Column B is a HYPERLINK formula, that when clicked should open the corresponding sheet.
Is there a way to programmatically get the URL for the sheet based on the sheet name in Column A? Perhaps I could use a script to populate Column C with the URL, then use the following formula: =HYPERLINK(C2,A2)?
Thanks for the help!
Surprised to see this as a top search on Google but with no answer.
Anyway, here's the method I found that works for me: combine Hyperlink with values from a different column using the &, a basic example is shown below:
If you are trying to automatically generate direct URL's to specific sheets based on their name, and do not want to use scripts, you are out of luck. Currently, the only way to link directly to specific sheets is by appending the correct gid number to the spreadsheet URL. A gid must be either copied manually from the active sheet's URL, or automatically extracted with a custom function, created using scripts.
Since you're open to using scripts, it looks like i found a detailed tutorial of how to do this. https://www.benlcollins.com/spreadsheets/index-sheet/
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Index Menu')
.addItem('Create Index', 'createIndex')
.addItem('Update Index', 'updateIndex')
.addToUi();
}
// function to create the index
function createIndex() {
// Get all the different sheet IDs
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var namesArray = sheetNamesIds(sheets);
var indexSheetNames = namesArray[0];
var indexSheetIds = namesArray[1];
// check if sheet called sheet called already exists
// if no index sheet exists, create one
if (ss.getSheetByName('index') == null) {
var indexSheet = ss.insertSheet('Index',0);
}
// if sheet called index does exist, prompt user for a different name or option to
cancel
else {
var indexNewName = Browser.inputBox('The name Index is already being used,
please choose a different name:', 'Please choose another name',
Browser.Buttons.OK_CANCEL);
if (indexNewName != 'cancel') {
var indexSheet = ss.insertSheet(indexNewName,0);
}
else {
Browser.msgBox('No index sheet created');
}
}
// add sheet title, sheet names and hyperlink formulas
if (indexSheet) {
printIndex(indexSheet,indexSheetNames,indexSheetIds);
}
}
// function to update the index, assumes index is the first sheet in the workbook
function updateIndex() {
// Get all the different sheet IDs
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var indexSheet = sheets[0];
var namesArray = sheetNamesIds(sheets);
var indexSheetNames = namesArray[0];
var indexSheetIds = namesArray[1];
printIndex(indexSheet,indexSheetNames,indexSheetIds);
}
// function to print out the index
function printIndex(sheet,names,formulas) {
sheet.clearContents();
sheet.getRange(1,1).setValue('Workbook Index').setFontWeight('bold');
sheet.getRange(3,1,names.length,1).setValues(names);
sheet.getRange(3,2,formulas.length,1).setFormulas(formulas);
}
// function to create array of sheet names and sheet ids
function sheetNamesIds(sheets) {
var indexSheetNames = [];
var indexSheetIds = [];
// create array of sheet names and sheet gids
sheets.forEach(function(sheet){
indexSheetNames.push([sheet.getSheetName()]);
indexSheetIds.push(['=hyperlink("#gid='
+ sheet.getSheetId()
+ '","'
+ sheet.getSheetName()
+ '")']);
});
return [indexSheetNames, indexSheetIds];
}
Happy new year, folks,
Currently, I'm accessing and loading a Google Sheets worksheet using the following, default way:
URL metafeedUrl = new URL(SPREADSHEET_URL);
SpreadsheetEntry spreadsheet = service.getEntry(metafeedUrl, SpreadsheetEntry.class);
URL cellFeedUrl = ((WorksheetEntry) spreadsheet.getWorksheets().get(0)).getCellFeedUrl();
// Get entries as cells
feed = (CellFeed) service.getFeed(cellFeedUrl, CellFeed.class);
Then I work with it, etc. Everyting works just fine.
The problem:
I'm about to deploy the application and have it work with a Worksheet that has several hundred, if not thousand rows of cells. To me, the only relevant rows are usually the 100-200 bottom ones.
Is there a way to partially load a CellFeed, preferrably from the bottom up? Does the API provide such a way?
Looking at the API itself, you can do it with cell feed or list feed.
in cell feed, look at https://developers.google.com/google-apps/spreadsheets/#fetching_specific_rows_or_columns
you can specify there the minimum/maximum row/columns to get, and there is also a java example in there.
a more efficient way to get your data, is the row feed as it sends less bytes in return:https://spreadsheets.google.com/feeds/list/
with the undocumented "start-index' parameter so it only reads starting at that row.
I use this and works for the "old" and "new" sheets.
The first time you will need to get all rows (or attempt some sort of binary lookup to find the last spreadsheet row).
I have not used the java api library, it probably does not allow for that undocumented parameter. You can always do a url "get" directly from java or any language and use the spreadsheet api directly by https.
I got this tip a long time ago from here:
https://groups.google.com/forum/#!topic/google-spreadsheets-api/dSniiF18xnM
and use it on this github project (javascript ajax call example)
https://github.com/zmandel/Plus-for-Trello/blob/master/source/sql.js
I don't know any CellFeed, but you can create an HTML feed that retrieves a number of ROWS from any Spreadsheet, then treat that HTML, would that work for you? What are the goals when retrieving the information?
Eg.
Code.gs
function doGet() {
return HtmlService.createTemplateFromFile("form").evaluate().setSandboxMode(HtmlService.SandboxMode.NATIVE);
}
function getLastLines( numLines, ssId, sheetName ){
var sheet = SpreadsheetApp.openById(ssId).getSheetByName(sheetName);
return JSON.stringify(sheet.getRange(sheet.getLastRow() - numLines, 1, numLines, sheet.getLastColumn()).getValues());
}
in form.html
<div id="arrayPlace"></div>
<script>
function changeDiv( res ){
document.getElementById("arrayPlace").innerHTML = res;
}
function getUrlParameter(sParam)
{
var sPageURL = window.location.search.substring(1);
var sURLVariables = sPageURL.split('&');
for (var i = 0; i < sURLVariables.length; i++)
{
var sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] == sParam)
{
return sParameterName[1];
}
}
}
var numLines = getUrlParameter("numLines");
var ssId = getUrlParameter("ssId");
var sheetName = getUrlParameter("sheetName");
google.script.run.withSuccessHandler( changeDiv ).getLastLines( numLines, ssId, sheetName );
</script>
And the URL would have the additional parameters:
https://script.google.com/macros/s/AKfycbwFLN-qqTcXXAVgR-aDa9h61yTa39kVhE2MwX9htRbIm2NN5I4/exec?numLines=5&ssId=1dJlNmtvcsWixEDnUz7GxnyLMZKXHwA-9uopYPUC8I4E&sheetName=Sheet1