【问题标题】:Server-side function does not want to run服务器端功能不想运行
【发布时间】:2020-12-08 23:14:02
【问题描述】:

我正在使用 Apps 脚本为 Google 表格构建一个侧边栏,它是一个从 Google 日历导入数据的工具。脚本没那么复杂:

  • 用于选择日历、开始和结束日期以及包含标题的复选框的表单
  • 一些客户端javascript
  • 一些服务器端函数

1.我有一个文件 Code.gs 负责创建自定义菜单并呈现侧边栏

function onOpen() {
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .createMenu('Custom Menu')
      .addItem('Show sidebar', 'showSidebar')
      .addToUi();
}

function showSidebar() {
  var html = HtmlService.createTemplateFromFile('index').evaluate()
      .setTitle('Extract data from calendar')
      .setWidth(300);
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .showSidebar(html);
}

function include(filename){
  return HtmlService.createHtmlOutputFromFile(filename).getContent();
}

2。 index.html:侧边栏的内容

<!DOCTYPE html>
<html>
<head>
</head>
<body style="margin: 10px;">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">

<!-- Compiled and minified -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
            
  <div class="row">
    <form class="col s12">
<!--    CHOOSE CALENDAR ROW    -->   
    <div class="row">
      <div class="input-field col s12">
       <select id='calendar'>
       <? var calendars = CalendarApp.getAllOwnedCalendars();
          calendars.forEach((calendar) => { ?>
         <option value="<?= calendar.getId() ?>"><?= calendar.getName() ?></option>
         
         <? }) ?>
       </select>
       <label>Calendar</label>
       </div>
    </div>

<!--    START TIME ROW    -->
      <div class="row">
        <div class="input-field col s12">
          <input placeholder="Start date" id="startDate" type="date" class="validate">
          <label for="startDate">Start date</label>
        </div>
      </div>
      
<!--    END TIME ROW    -->
      <div class="row">
        <div class="input-field col s12">
          <input placeholder="End date" id="endDate" type="date" class="validate">
          <label for="endDate">End Date</label>
        </div>
      </div>
      
<!--    INCLUDE HEADER    -->
      <div class="row">
         <label>
           <input type="checkbox" class="filled-in" checked="checked" id="includeHeader" />
           <span>Include Header</span>
         </label>
      </div>
      
<!--    EXTRACT BUTTON    -->
      <div class="row">
        <button class="btn waves-effect waves-light" id="extractBtn">EXTRACT</button>
      </div>
    </form>
  </div>
  <?!= include('index-js') ?>
  <script>
      document.addEventListener('DOMContentLoaded', function() {
    var elems = document.querySelectorAll('select');
    var instances = M.FormSelect.init(elems, {});
  });
  </script>
</body>
</html>

3. index-js.html:为提取按钮添加事件并调用服务器端函数

<script>
var extractBtn = document.getElementById('extractBtn'); 

extractBtn.addEventListener('click', function(e) {
    e.preventDefault();
    
    var calendarId = document.getElementById('calendar').value;
    var startDate = new Date(document.getElementById('startDate').value);
    var endDate = new Date(document.getElementById('endDate').value);
    var includeHeader = document.getElementById('includeHeader').checked;
   
    if(startDate.getTime() < endDate.getTime()) {
      e.target.textContent = 'Extracting...';
      google.script.run.withSuccessHandler(extractCompleted).writeData(calendarId, startDate, endDate, includeHeader);
    } else {
      M.toast({html: "Please enter an end date starting after the selected start date"});
    }
});

function extractCompleted(){
    M.toast({html: 'Extract completed'});
    extractBtn.textContent = 'Extract';
}

</script>

4. extractCalendar.gs 负责获取数据并将其添加到 Google 表格中

function extractCalendar(calendarId, startDate, endDate) {
  var calendar = CalendarApp.getCalendarById(calendarId);
  var events = calendar.getEvents(startDate, endDate);
  
  
//  Initialize variables that will hold information
  var rows = [];
  
  events.forEach((event) => {
                 // Get basic information
                 var eventTitle = event.getTitle();
                 var startTime = event.getStartTime();
                 var endTime = event.getEndTime(); 
                 var description = event.getDescription();
                 var isRecurring = event.isRecurringEvent();
  
  
   // Get the guest list
   var guests = event.getGuestList();
   var emailsParticipantsArray = [];
   var emailsParticipants = '';
  
   // Add each guest email to the array
   guests.forEach(guest => emailsParticipantsArray.push(guest.getEmail()));
   
  // Convert the array to a string
  emailsParticipants = emailsParticipantsArray.join(',');
   
  
   rows.push([eventTitle, startTime, endTime, emailsParticipants, description, isRecurring]);
  
 }
  );

   return rows;

 }
 
 function writeData(calendarId, startDate, endDate, includeHeader=True){
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  var rows = extractCalendar(calendarId, startDate, endDate);

  var numRows = rows.length;
  var lastRow = sheet.getLastRow();
  
  (includeHeader) && rows.unshift(['Title', 'Start Date', 'End Date', 'Participants Email', 'Description', 'Recurring']);
  sheet.getRange(lastRow + 1, 1, numRows, 6).setValues(rows);

 }

以下行不运行并生成错误消息:Uncaught TypeError: Failed due to invalid value in property: 12769757186-mae_html_user_bin_i18n_mae_html_user.js:61

google.script.run.withSuccessHandler(extractCompleted).writeData(calendarId, startDate, endDate, includeHeader);

这里发生了什么,为什么服务器端功能没有运行?

感谢您的帮助!

【问题讨论】:

  • 您无法在客户端和服务器之间传递日期以检查 Google 脚本运行的限制
  • 有这个限制是有原因的吗?

标签: javascript google-apps-script


【解决方案1】:

Parameters and Return Values

您可以传递标准字符串格式的年月日或日期,并使用 Date() 构造函数重新创建日期。

【讨论】:

  • 您还可以在将对象传递给 Javascript 之前,在 Apps 脚本端 JSON.stringify() 对象,然后再次 JSON.parse() 它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-14
  • 1970-01-01
  • 1970-01-01
  • 2023-01-16
相关资源
最近更新 更多