Альтернативный способ передачи данных (например, значений массива) через обработчик без использования свойств скрипта

#google-apps-script #google-sheets

#google-apps-script #google-sheets

Вопрос:

Я создал приложение, в котором я использую ScriptProperties для хранения данных из обработчика в его but(e) функцию. Это работало хорошо, пока другие люди не начали использовать ту же электронную таблицу одновременно. Так часто бывает, что один человек тратит время на размышления о том, какой пункт выбрать из меню флажков, а другой человек использует ту же функцию, изменяя данные, хранящиеся в ScriptProperties, и влияя на использование функции первым человеком. Каков наилучший способ исправить это, используя альтернативный способ передачи информации через обработчик? Вот один пример одной из этих функций (в которой я использую ScriptProperties для передачи значений letterSpreadsheetId и recipientArray ):

 function letter(letterSpreadsheetId){
  ScriptProperties.setProperty('letterSpreadsheetId', letterSpreadsheetId); // different people may have different letterSpreadsheetId;
  ScriptProperties.setProperty('letter', 1); // to be used in another function
  var activeSheet = ss.getActiveSheet();
  var app = UiApp.createApplication().setHeight(400).setWidth(600);
  var panel = app.createVerticalPanel(); // you can embed that in a form panel
  var label = app.createLabel("Choose a receiver").setStyleAttribute("fontSize", 18);
  app.add(label);  
  var sheet = SpreadsheetApp.openById(letterSpreadsheetId).getSheetByName("receivers");
  var recipientArray = sheet.getRange(2, 1, sheet.getLastRow(), sheet.getLastColumn()).getValues();  
  var item3Panel = app.createHorizontalPanel();
  item3Panel.add(app.createLabel("receiver"));
  var listBox = app.createListBox().setName('item3');  
      for(var i = 0; i < (recipientArray.length); i  ){
           listBox.addItem(recipientArray[i][1]);
    }
  item3Panel.add(listBox);
  var recipientArrayStr = JSON.stringify(recipientArray);
  ScriptProperties.setProperty('recipientArr', recipientArrayStr);
  var handlerBut = app.createServerHandler("butAnswerLetter").addCallbackElement(panel);
  var but = app.createButton("submit").setId("submitButton2").addClickHandler(handlerBut);
  panel.add(item1Panel)
       .add(item2Panel)
       .add(item3Panel)
       .add(but)
       .add(app.createLabel().setId("answer"));  
  var scroll = app.createScrollPanel().setPixelSize(600, 400).setTitle("My title 1");
  scroll.add(panel);
  app.add(scroll);
  ss.show(app);
}

function butAnswerLetter(e){
  var letterSpreadsheetId = ScriptProperties.getProperty('letterSpreadsheetId');
  var recipient = e.parameter.item3;
  ScriptProperties.setProperty('recipient', recipient);
  var recipientArrayRecovery = ScriptProperties.getProperty('recipientArr');
  var recipientArray = JSON.parse(recipientArrayRecovery);
  for(var i=0;i<recipientArray.length;i  ){
    if(recipient == recipientArray[i][1]){
        var usedRecipientArray = recipientArray[i];
    }
  }
 

Ответ №1:

У вас есть 2 возможности (которые я знаю): либо использовать свойства UserProperties вместо свойств скрипта, поскольку они связаны с пользователем, но для этого потребуется, чтобы пользователь вошел в систему и авторизовался, либо — и это будет работать в любом случае, даже если доступ к приложению осуществляется анонимно, используйте теги, которые вы можете написатьпрактически на любом виджете.

синтаксис довольно прост, вот небольшой пример кода :

 function doGet(){
  var app = UiApp.createApplication().setTitle('test_TAG');
  var list = app.createListBox(true).setVisibleItemCount(5).setPixelSize(30,450).setName('list');
  var handler = app.createServerHandler('show').addCallbackElement(list);
  list.addChangeHandler(handler);
  var data = [];
  for(var n = 0;n<20;n  ){
    list.addItem(n ' ');
    data.push('available value = ' Number(n 1));
  }
  list.setTag(data.toString());
  app.add(list);
  return app
}

function show(e){
  var app = UiApp.getActiveApplication();
  var data = e.parameter.list_tag.split()
  var selected = e.parameter.list;
  app.add(app.createTextBox().setText(selected).setPixelSize(200,20));
  app.add(app.createTextArea().setText(data.join()).setPixelSize(200,300));
  return app;
}
 

тестируемый здесь


Редактировать

следуя соответствующему комментарию Zig :

Я забыл упомянуть скрытый виджет (или текстовое поле / область, для которых установлено значение невидимый, полезно для отладки, когда вы хотите проверить, что в нем содержится! ) это, конечно, тоже можно использовать… Комментарий о том, что у пользователя несколько окон, отображающих одно и то же приложение, также заслуживает упоминания!

В целом, у вас есть 3 возможности!

(спасибо Зигу Манделю)

Комментарии:

1. Или просто сохраните необходимые данные внутри «скрытого» в пользовательском интерфейсе. Свойства совсем не для этого. Даже в случае одного пользователя он сломается, если у пользователя открыто несколько окон одного и того же приложения.

2. Спасибо, я действительно забыл упомянуть об этом — ответ обновлен