0

I am building an automated solution on Google Apps Scripts for my job that is testing my basic knowledge of HTML and JS. I would appreciate some guidance.

Context:

  • I am building a tool to automate certain tasks on Google Sheets through formulas and scripts
  • The task I'm having issues with begins with the user clicking on a button that opens a getUi() Modal Dialog
  • The main challenge is to extract data out of an HTLM table where the user makes inputs

JS code triggering the popup (just for context):

function openbrief() {
  //pull necessary values
  var supp_main = SpreadsheetApp.getActive().getSheetByName('supp_main')

  //projects
  var projrng = supp_main.getRange(2, 64, 1000);
  var projval = projrng.getValues();
  var projname = projval.filter(String)
  
  //content_category
  var catrng = supp_main.getRange(2, 65, 1000);
  var catval = catrng.getValues();
  var catname = catval.filter(String)

  //content_type
  var typerng = supp_main.getRange(2, 66, 1000);
  var typeval = typerng.getValues();
  var typename = typeval.filter(String)

  //format
  var formatrng = supp_main.getRange(2, 67, 1000);
  var formatval = formatrng.getValues();
  var formatname = formatval.filter(String)
  
  //channel
  var chanrng = supp_main.getRange(2, 68, 1000);
  var chanval = chanrng.getValues();
  var channame = chanval.filter(String)


  var widget = HtmlService.createTemplateFromFile('briefs');
  widget.projdata = projname.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
  widget.catdata = catname.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, ""); 
  widget.typedata = typename.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
  widget.formatdata = formatname.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, ""); 
  widget.chandata = channame.reduce((s, [e]) => s += `<option value="${e}">${e}<\/option>\n`, "");
  SpreadsheetApp.getUi().showModalDialog(widget.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME).setHeight(5000).setWidth(5000), 'Briefs');

}

Questions:

  1. I have a GS/JS script within the HTML that is supposed to run through the table values, push them to an array and paste them to a gSheet. However it does not do that. I'm not experience with for loops and arrays on JS, and I can't tell what's not working.
  2. Will this type of script pull the values from the dropdown menus? I suspect it won't as they seem to be sitting on top of the cell. But I'm unsure (see screenshot for more context)
  3. Any other improvements or suggestions based on both code or screenshot is very welcome

References:

HTML code

<table id="brief_table">
      <thead>
          <tr>
              <th>Content category</th>
              <th>Description</th>
              <th>Content type</th>
              <th>Format</th>
              <th>Channel</th>
              <th>Assets</th>
              <th>Start date</th>
              <th>End date</th>
              <th>Relevant links</th>
              <th>Comments</th>
          </tr>
      </thead>
      <tbody>
          <tr>
              <td>
                <select id="catname" style="Border: none;"><?!= catdata ?></select>
              </td>
              <td contenteditable='true'>Test</td>
              <td>
                <select id="typename" style="Border: none;"><?!= typedata ?></select>
              </td>
              <td>
                <select id="formatname" style="Border: none;"><?!= formatdata ?></select>
              </td>
              <td>
                <select id="channame" style="Border: none;"><?!= chandata ?></select>
              </td>
              <td contenteditable='true'>Test</td>
              <td contenteditable='true'>Test</td>
              <td contenteditable='true'>Test</td>
              <td contenteditable='true'>Test</td>
              <td contenteditable='true'>Test</td>
          </tr>
      </tbody>
</table>

<script>
function pasteBrief() {
  var table = document.getElementById("brief_table");
  var tablevalues = [];

  for (var r = 0, n = table.rows.length; r < n; r++) {
          for (var c = 0, m = table.rows[r].cells.length; c < m; c++) {
              tablevalues.push(table.rows[r].cells[c].innerHTML);
          }
      }

  alert(tablevalues);
  google.script.run.pasteBriefVal(tablevalues);
}
</script>

GS SERVER CODE

function pasteBriefVal(tablevalues){
  SpreadsheetApp.getActive().getSheetByName('supp_main').getRange('bs1:cb').setValues(tablevalues);
}

Screenshots: Dynamic table

Additional info:

  • I have managed to stringify the array, which in return allow me to paste it as a value in one single cell. This enable me to take a closer look to it (see img below) enter image description here
  • Link to copy of the spreadsheet: link - to trigger the popup "briefs.html" you want to go to "[SOW] #2-Project & deliverables" and click on the icon that says "PLAN" around D24

Edits:

  • Moved setValues out of HTML file back to GS side. Called the new GS function out from HTML via google.script.run.pasteBriefVal(tablevalues)
  • Added more information on what the array look like
  • Added the link to a copy of the original spreadsheet should anyone want to take a deeper look
A. Prats
  • 59
  • 10
  • 1
    It is unclear whether the code you show is part of a [container-bound script project](https://developers.google.com/apps-script/guides/bound) or part of a web page. If the former, see [HTML Service: Communicate with Server Functions](https://developers.google.com/apps-script/guides/html/communication). If the latter, see [Sheets API](https://developers.google.com/sheets/api). – doubleunary Jun 13 '22 at 20:45
  • Thanks for flagging. I've added a bit more flavour so it's easier for other people to understand. I will take your comment into account for future exercises. – A. Prats Jun 13 '22 at 22:24
  • 1
    Can you share a sample or copy of your spreadsheet? So we can replicate and experiment around to provide you a working solution and/or suggestions if possible. Please remove sensitive data if any. – Logan Jun 14 '22 at 00:32
  • 1
    1. Questions on this site should be specific, this means that there should be only one question per post. 2. Edits should be for improving the question i.e. adding missing relevant details, they should not change the code in such way that make an answer obsolete. – Rubén Jun 14 '22 at 02:40
  • Hey @DanF, here's a link to a copy of the spreadsheet [link](https://docs.google.com/spreadsheets/d/1AjkRrxwPZ02FSgckOunWcepBx3b4RlqdWEU7jcp9KMA/edit?usp=sharing). I have made some adjustments to the code and I can manage to paste the table data as string into one cell, which is a lot more than I could before, but it's far from what I need. Part of my problem is that I don't know how to paste an array to GSheets (I suspect via setValues, but I don't know exactly how). Also, when looking at the stringified array, I think it has too many items in it, which could also cause conflict when pasting. – A. Prats Jun 14 '22 at 06:02
  • Hey @Rubén, thanks for the feedback. Well received! I'll limit posts to one question/topic and will improve my edits. – A. Prats Jun 14 '22 at 06:03
  • By the way @DanF, to trigger the popup "briefs.html" you want to go to "[SOW] #2-Project & deliverables" and click on the icon that says "PLAN" around D24. – A. Prats Jun 14 '22 at 06:08

1 Answers1

2

Server side GS and Client side JS

The below server side code does not run in a browser: SpreadsheetApp.getActive().getSheetByName('supp_main').getRange('bs1').setValues(tablevalues);

If you wish to run server side code the use google.script.run

Cooper
  • 59,616
  • 6
  • 23
  • 54
  • That makes sense. I've looked back to previous exercises and feedback received and I have made a couple modifications to move away the "setValues" out of the HTML file. I have updated the original post with the new code. Still doesn't work though. – A. Prats Jun 13 '22 at 22:23
  • 2
    Try a console.log(JSON.stringify(tableValues));See if it's there on the serverside. If not then perhaps your array contains [illegal parameters](https://developers.google.com/apps-script/guides/html/communication#parameters_and_return_values); Date() objects cannot be sent but you can convert them to strings and then convert them back with Date() constructor. – Cooper Jun 13 '22 at 22:31
  • So it's definitely collecting some info on HTML as the alert(tablevalues) shows some stuff (see here: https://i.ibb.co/D9NrqV9/Screenshot-2022-06-14-at-00-41-44.png). But I'm not recording anything in the execution log on GS. – A. Prats Jun 13 '22 at 22:47
  • 2
    Sorry but I don't follow unfamiliar links. – Cooper Jun 13 '22 at 22:50
  • My bad. Here's the alert msg stringified: "["Content category","Description","Content type","Format","Channel","Assets","Start date","End date","Relevant links","Comments","\n – A. Prats Jun 13 '22 at 22:53
  • It basically seems not to be triggering the GS script at all... Could the array and its dimensions be linked to this? Here's a relevant post from stackoverflow where they talk about that: https://stackoverflow.com/questions/63732754/how-do-i-insert-an-array-into-a-google-doc-using-data-from-google-sheets – A. Prats Jun 13 '22 at 23:01
  • Hey, it actually does. I have added to the original post the stringified HTML table values in case it has some value to you. – A. Prats Jun 14 '22 at 06:24