简体   繁体   中英

Is there any way to simplify various function calls from code.gs in a google.script.run.withSuccessHandler? Google Apps Script

I have created a modal dialog in my google sheet where you can see the data obtained from the sheet. This modal is only to read the data of the sheet in an orderly way and more aesthetically pleasing to the eye than with the cells of the sheet of google sheets.

The modal works fine but I have 1 question and it is the following:

There are several functions in my coge.gs to obtain the data from my google sheet. At the same time, I have to call these functions in my html file with google.script.run.withSuccessHandler to be able to get the data in my template.

Is there any way to simplify the process of function calls in a single google.script.run.withSuccessHandler ?

This is my code html:

google.script.run.withSuccessHandler(function (value) {document.getElementById('nombreclientePE').textContent = value;} ).clientePedidoPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('numeropedidoPE').textContent = value;} ).numeroPedidoPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('fechapedidoPE').textContent = value;} ).fechaPedidoPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('estadopedidoPE').textContent = value;} ).estadoPedidoPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('logometodopagopedidoPE').src = value;} ).logoMetodoPagoPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('metodopagopedidoPE').textContent = value;} ).metodoPagoPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('gastosenviopedidoPE').textContent = value;} ).gastosEnvioPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('metodoenviopedidoPE').textContent = value;} ).metodoEnvioPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('subtotalpedidoPE').textContent = value;} ).subtotalPedidoPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('decuentocantidad%pedidoPE').textContent = value;} ).descuentoCantidadPorcentajePedidoPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('decuentocantidad€pedidoPE').textContent = value;} ).descuentoCantidadEurosPedidoPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('decuentototalpedidoPE').textContent = value;} ).descuentoTotalPedidoPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('totalpedidoPE').textContent = value;} ).totalPedidoPE();
google.script.run.withSuccessHandler(function (value) {document.getElementById('direccionpedidoPE').textContent = value;} ).direccionEnvioPE();

Link to a google sheet document with the live demo. To open the modal window, the active cell must be positioned in any cell of any customer row. Then, click on the "View order" button.

Google Sheets Demo Live

Code.gs

const o = {
  'nombreclientePE': () => clientePedidoPE(),
  'numeropedidoPE': () => numeroPedidoPE(),
  'fechapedidoPE': () => fechaPedidoPE(),
  'estadopedidoPE': () => estadoPedidoPE(),
  'logometodopagopedidoPE': () => logoMetodoPagoPE(),
  'metodopagopedidoPE': () => metodoPagoPE(),
  'gastosenviopedidoPE': () => gastosEnvioPE(),
  'metodoenviopedidoPE': () => metodoEnvioPE(),
  'subtotalpedidoPE': () => subtotalPedidoPE(),
  'decuentocantidad%pedidoPE': () => descuentoCantidadPorcentajePedidoPE(),
  'decuentocantidad€pedidoPE': () => descuentoCantidadEurosPedidoPE(),
  'decuentototalpedidoPE': () => descuentoTotalPedidoPE(),
  'totalpedidoPE': () => totalPedidoPE(),
  'direccionpedidoPE': () => direccionEnvioPE()
};

function PE(input) {
  const output = [];
  for (const id of input) {
    const value = o[id]();
    output.push([id, value]);
  }
  return output;
}

function formVerPedido2(numPedido) {
  var hoja = SpreadsheetApp.getActiveSheet();
  var fila = hoja.getCurrentCell().getRow();
  var numPedido = hoja.getRange(fila,3,1,1).getValue();
  var template = HtmlService.createTemplateFromFile('PedidosIndex');
  template.input = Object.keys(o);
  var pedidoContendido = template.evaluate()
    .setWidth(800)
    .setHeight(1300);


  //var logoMetodoPago = logoMetodoPagoPE();
  //htmlOutput = logoMetodoPago;

 SpreadsheetApp.getUi().showModalDialog(pedidoContendido, 'Pedido #' + numPedido + '');
}

index.html

    <script>const input = <?!= JSON.stringify(input) ?>;</script>
    <?!= include('PedidosJavaScript'); ?> <!-- See PedidosJavaScript.html file -->

js.html

google.script.run.withSuccessHandler(onSuccess).PE(input);
function onSuccess(output) {
  for (const [id, value] of output) {
    document.getElementById(id).textContent = value;
  }
}

If informations are coming from a form : code html

  function formSubmit() {
    var data = document.forms[0]
    var tab = []
    for (var i=0;i<data.length;i++){
      if (data[i].type != "button"){
        tab.push(data[i].value)
      }
    }
    google.script.run.addData(tab);
    document.forms[0].reset()
  }

code gs

function addData(tab) {
  mySheet.getRange(getLastDataRow(bdd) + 1,1,1,tab.length).setValues([tab])
}

What I suggest is : replace all the functions as numeroPedidoPE(), fechaPedidoPE() ... by only one (assuming that data are in the same row)

function transferPedidoData() {
  var hoja = SpreadsheetApp.getActiveSheet();
  var fila = hoja.getCurrentCell().getRow();
  var pedidoData = hoja.getRange('B'+fila+':S'+fila).getValues();
  return pedidoData;
}

then, in the html file, add this script

<script>
  <? 
    var pedido = transferPedidoData();
  ?>
</script>

and finally, call for the different data in your PedidosHTML.html file as following, x as needed

<?= pedido[0][x] ?>

This definitely needs to be simplified. On the client side you need something like this:

function gscriptRun(fnName) {
  google.script.run
    .withSuccessHandler(function (value) {
      document.getElementById(fnName).textContent = value;
    })
    .runFunc(fnName);
}

const fnsToRun = ['clientePedidoPE', 'numeroPedidoPE'];
fnsToRun.forEach(fn => gscriptRun(fn));

We wrapping all google.script.run calls in a function. Then we create an array of function names we want to call on the server side and call them all with Array.prototype.forEach() .

On the server side you need to have this function:

function runFunc(fnName) {
  return globalThis[fnName]();
}

It will just execute the functions by their names.

However, this doesn't look like a great approach as there are so many API calls. You probably want to re-write your code so that you can extract all data with just one call.

You could follow this type of structure if you want to grab the values from various locations in a spreadsheet. Personally I would put them right next to each other in a row and use getValues() instead of getting each value separately.

gs:

function getMyData(tA) {
  const ss = SpreadsheetApp.getActive();
  const sh = ss.getSheetByName("Sheet0");
  const rgObj = {'nombreclientePE':'A1','numeropedidoPE':'A2','fechapedidoPE':'A3','estadopedidoPE':'A4','logometodopagopedidoPE':'A5','metodopagopedidoPE':'A6','gastosenviopedidoPE':'A7','metodoenviopedidoPE':'A8','subtotalpedidoPE':'A9','decuentocantidad%pedidoPE':'A10','decuentocantidad€pedidoPE':'A11','decuentototalpedidoPE':'A12','totalpedidoPE':'A13','direccionpedidoPE':'A14'}
  let obj = {pA:[]}
  tA.forEach(p => {
    obj.pA.push(p);
    obj[p] = sh.getRange(rgObj[p]).getValue();
  });
  return obj;
}

html:

<!DOCTYPE html>
 <html>
   <head>
     <title>My Title</title>
   </head>
   <body>
     <!-- You provide the body -->
     <script>
       window.onload = getData()
       function getData() {
         const tA = ['nombreclientePE','numeropedidoPE','fechapedidoPE','estadopedidoPE','logometodopagopedidoPE','metodopagopedidoPE','gastosenviopedidoPE','metodoenviopedidoPE','subtotalpedidoPE','decuentocantidad%pedidoPE','decuentocantidad€pedidoPE','decuentototalpedidoPE','totalpedidoPE','direccionpedidoPE'];
         google.script.run
         .withSuccessHandler((obj) => {
           obj.pA.forEach(p => {
             document.getElementById(e).textContent = obj[p];
           })
         })
         .getMyData(tA) 
       }
     </script>
   </body>
 </html>

I think the easiest way of doing this from what you already have is use a single google.script.run call to a wrapper function which returns all the data and then setting the values in JavaScript.

List your elements in an array and then loop through them on Success, rather than using a google.script.run call for each element:

const elements = [
      'nombreclientePE',
      'numeropedidoPE',
      'fechapedidoPE',
      'estadopedidoPE',
      'metodopagopedidoPE',
      'gastosenviopedidoPE',
      'metodoenviopedidoPE',
      'subtotalpedidoPE',
      'decuentocantidad%pedidoPE',
      'decuentocantidad€pedidoPE',
      'decuentototalpedidoPE',
      'totalpedidoPE',
      'direccionpedidoPE',
    ]
    
    const logoId = 'logometodopagopedidoPE'
    
    function callGasFn() {
      google.script.run.withSuccessHandler(setData).getAllValues()
    }
    
    function setData(data) {
      elements.forEach((x, i) => document.getElementById(x).textContent = data[0][i])
      document.getElementById(logoId) = data[1]
    }
   
    callGasFn()

Then in Apps Script you have your getAllValues() function:

function getAllValues() {
  return [
    [
      clientePedidoPE(),
      numeroPedidoPE(),
      fechaPedidoPE(),
      estadoPedidoPE(),
      metodoPagoPE(),
      gastosEnvioPE(),
      metodoEnvioPE(),
      subtotalPedidoPE(),
      descuentoCantidadPorcentajePedidoPE(),
      descuentoCantidadEurosPedidoPE(),
      descuentoTotalPedidoPE(),
      totalPedidoPE(),
      direccionEnvioPE(),
    ],
    logoMetodoPagoPE()
  ]
}

I separated the logo out of the main array as it has src set as opposed to textContent .

In the sheet you provided, Maria del Campo is missing from the client sheet - I don't know if this is intened but it does cause direccionEnvioPE() to fail as her data isn't available in the sheet.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM