Google 表单提交按钮的 onClick 事件

onClick event for Google Forms Submit button

这快把我逼疯了,我有一个简单的 Google 表格可以接受订户代码和他们的时隙时间。我的目的是通过 Google 表格获取数据并将其保存到 Google 工作表 而不会在插槽时间 .

中发生任何冲突

为了向您展示一个示例,我附上了我的表格和 sheet 的图片。完成第一个条目后,如果要将另一个时隙分配给同一订阅者,我们需要确保时隙时序不会与分配给同一订阅者的 google sheet 中保存的时序冲突订户。如果您看到第二个条目,它只是接受它,为此我们需要一个不可用的验证检查。我的问题是,是否有可能在提交按钮上进行 onClick 验证?我一直在 google 上疯狂地搜索它,但没有找到解决方案。如果无法以 Google 形式执行此操作,我有哪些替代方案或是否有任何可用的解决方法?

热切等待对我的查询的回复。谢谢。

您可以在当前设置上尝试的另一个想法是,您可以使用 onFormSubmit 触发器。提交响应后,会将其与添加到 sheet 的先前行进行比较,以检查是否与您的数据有任何冲突。

确认有后,去掉最后一条回复即可。如果没有冲突,那就让它结束吧。

Sheet 脚本:

function checkConflict(e) {
  var sheet = e.range.getSheet();
  var lastRow = sheet.getLastRow();
  // exclude the last submitted response
  var timeSlots = sheet.getRange(2, 3, lastRow - 2, 2).getValues();
  var lastResponse = e.values;
  var lastStart = new Date(lastResponse[2]).getTime();
  var lastEnd = new Date(lastResponse[3]).getTime();

  // convert timeslots to comparable data type
  timeSlots = timeSlots.map(timeSlot => [timeSlot[0].getTime(), timeSlot[1].getTime()]);
  // get conflicts
  var conflict = timeSlots.filter(timeSlot => (timeSlot[0] <= lastStart && timeSlot[1] >= lastStart) || 
                                              (timeSlot[0] <= lastEnd && timeSlot[1] >= lastEnd));
  // remove lastRow if conflict is 1
  if(conflict.length) {
    sheet.deleteRow(lastRow);
    MailApp.sendEmail(lastResponse[4], 
                      "Time Slot conflict", 
                      "Your recent response was removed due to a conflict. Your submitted time slot is the following:\n" + 
                      "From: " + new Date(lastStart) + "\n" + 
                      "To: " + new Date(lastEnd));
  }
  else {
    MailApp.sendEmail(lastResponse[4], 
                      "Time Slot confirmed", 
                      "Your time slot is now confirmed. Confirmed time slot is the following:\n " + 
                      "From: " + new Date(lastStart) + "\n" + 
                      "To: " + new Date(lastEnd));
  }
}

示例数据:

触发器:

电子邮件确认:

电子邮件冲突:

输出:

注:

  • 此方法不会在提交前检查您的输入。它只是删除了之后的最后一个响应 IF 与之前的时隙时间冲突。
  • 此外,发送回复的人不会知道他的广告位是否已确认,除非您在表格中要求他的电子邮件并在检查后发送确认(他提交的回复是否由于以下原因被删除)冲突,或者因为没有冲突而被批准)
  • 如果您有 9:00 - 10:00 的时间段,它不会接受另一个包含 9:00 的响应,因为 (>=, <=) 包含在内。您可以选择开始时间为 1/31 分钟(例如 9:01-10:008:31-9:30)或结束时间为 59/29 分钟(例如 9:00-9:598:30-9:29).
  • 如果这很麻烦,那么您需要调整检查冲突的条件。你应该能想出来。

正如@Cooper 指出的那样,您最好创建自己的网络应用程序。

经过几个小时的工作,我制作了一个 web app that will work for you using Google Apps Script. Here 电子表格和脚本文件。

服务器端代码:

var ss = SpreadsheetApp.getActiveSheet()

function doGet() {
  return HtmlService.createTemplateFromFile('form').evaluate()
}

function submitData (data) {
  
  ss.appendRow([new Date(),data.ssCode, new Date(data.startDateTime), new Date(data.endDateTime)])
}

function isAvailible (start, end) {
  var data = ss.getDataRange().getValues()
  var isAvailible = true;
  var message = '';

  data.forEach(row => {

    if(start > row[2].valueOf() && start < row[3].valueOf() || end > row[2].valueOf() && end < row[3].valueOf()) {
      isAvailible = false;
      message = new Date(row[2].valueOf()) +'<br> to ' + new Date(row[3].valueOf()) + '<br> isn\'t availible.'
    }
  })

  var response = {status: isAvailible, message: message}

  return response;
  
}

客户端代码:

M.FormSelect.init(document.querySelectorAll('select'));

var dps = document.querySelectorAll('.datepicker');
var dpsInstances = M.Datepicker.init(dps, {
  showClearBtn: true,
  autoClose: true
});

dpsInstances[0].options.onSelect = function(day) {
  dpsInstances[1].setDate(day);
  endDate.value = dpsInstances[1].toString()
  M.updateTextFields();
}

var tps = document.querySelectorAll('.timepicker');
var tpsInstances = M.Timepicker.init(tps, {
  twelveHour: false,
  showClearBtn: true,
  autoClose: true
});

function formSubmit(data) {

  var startDate = new Date(data.startDate.value);
  var startTime = data.startTime.value.split(':');
  startDate.setHours(startTime[0]);
  startDate.setMinutes(startTime[1]);

  var endDate = new Date(data.endDate.value);
  var endTime = data.endTime.value.split(':')
  endDate.setHours(endTime[0]);
  endDate.setMinutes(endTime[1]);
  
  if (startDate.valueOf() >= endDate.valueOf()) {
    M.toast({html: 'End date should be greater then start date.'})
    return;
  }
  
  var dataToSubmit = {
    ssCode: data.ssCode.value,
    startDateTime: startDate.valueOf(),
    endDateTime: endDate.valueOf()
  }

  google.script.run.withSuccessHandler(function(response) {
    if (response.status) {
      google.script.run.withSuccessHandler(function() {
        myForm.reset()
        M.toast({
          html: "Successful"
        })
      }).submitData(dataToSubmit)
    } else {
      M.toast({
        html: response.message
      })
    }

  }).isAvailible(dataToSubmit.startDateTime, dataToSubmit.endDateTime)


}
body {
  background: rgb(244, 235, 234)
}

.outer-field {
  border-radius: 15px;
  background: white;
  height: 150px;
  margin: 10px;
  padding: 20px;
}

.title {
  padding-left: 2%;
  font-weight: bold;
}
<html>
  <head>
    <base target="_top">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

  </head>
  <body>
  
    <div class="row">
      <div class="col s10 offset-s1 l4 offset-l4">
        <div class="outer-field" style="height: 100px">
          <h4>Slot Timings</h4>
        </div>
        <form id="myForm" onsubmit="event.preventDefault(); formSubmit(this) ">
          <div class="outer-field">
            <div class="title">Subscriber Code</div>
            <div class="input-field col s6 l6">
              <select form="myForm" name="ssCode" required>
                <option value="001">001</option>
                <option value="002">002</option>
                <option value="003">003</option>
              </select>
            </div>
          </div>
          <div class="outer-field">
            <div class="title">From</div>
            <div class="col s6 l6">
              <div class="input-field">
                <input type="text" id="startDate" name="startDate" class="datepicker validate" form="myForm" required>
                <label for="startDate">Date</label>
              </div>
            </div>
            <div class="col s6 l6">
              <div class="input-field">
                <input type="text" id="startTime" name="startTime" class="timepicker validate" form="myForm" required>
                <label for="startTime">Time</label>
              </div>
            </div>
          </div>
          <div class="outer-field">
            <div class="title">To</div>
            <div class="col s6 l6">
              <div class="input-field">
                <input type="text" id="endDate" name="endDate" class="datepicker" form="myForm" required>
                <label for="endDate">Date</label>
              </div>
            </div>
            <div class="col s6 l6">
              <div class="input-field">
                <input type="text" id="endTime" name="endTime" class="timepicker" form="myForm" required>
                <label for="endTime">Time</label>
              </div>
            </div>
          </div>
          <button class="btn waves-effect waves-light" type="submit" name="action" style="margin-left: 3%" >Submit
            <i class="material-icons right">send</i>
          </button>
        </form>
        
      </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
  </body>
</html>