如何从 HTML/Javascript 发送一整套表单回复,而不是一次发送一个?

How can I send an entire array of form responses from HTML/Javascript instead of one at a time?

我正在做一个map painter programme, that takes in X, Y and colour data from user input and stores in a Google spreadsheet

紧接着 solution,数据将以表格形式发送到电子表格。在我的代码中,一个数组填充了 X、Y 和颜色数据,然后当我点击 Save All 按钮时,表单通过循环填充,并一个接一个地发送到我的电子表格的 DoPost() 函数.

编辑:这是 Octavia

请求的循环
document.getElementById('paintButton').onclick = function () {

            console.log('')
            console.log('+++++++++ SAVING PAINT DATA ++++++++++')
            console.table(paintArray)
            console.log(paintArray.length + ' rows to save.')

            try{

            for (let i = 0; i < paintArray.length; i++) {
        
    //AUTOMATICALLY FILL EDITOR AS PAINTING
            
    uniqueID =  parentID +'-'+  paintArray[i].x +'-'+ paintArray[i].y +'-'+  paintArray[i].z 

    let saveMessage = 'Saving row ' + (i + 1) + '/' + paintArray.length + ': ' + '' +  uniqueID + ' at ' + paintArray[i].x + ',' + paintArray[i].y
    
    //document.getElementById('paintLabel').innerHTML = saveMessage
    
    console.log(saveMessage)


            document.getElementById('testLocation').value =  ''
            document.getElementById('testCategory').value = ''

            document.getElementById('testX').value = paintArray[i].x
            document.getElementById('testY').value = paintArray[i].y
            document.getElementById('testZ').value = paintArray[i].z

            document.getElementById('uniqueID').value = uniqueID
            document.getElementById('parentID').value = parentID

            document.getElementById('testFill').value = paintArray[i].fill
            document.getElementById('TextA').value = ''
            document.getElementById('TextB').value = ''
            document.getElementById('TextC').value = ''
            document.getElementById('TextD').value = ''
            document.getElementById('TextE').value = ''

             sleep(5000)
                  
            //AUTOMAGICALLY SUBMIT FORM DATA
            document.forms['mapData'].dispatchEvent(new Event('submit'));

       
  
}

console.log('+++++++++ PAINT DATA SAVED SUCCESS ++++++++++')

paintArray = []

alert("+++++++++ PAINT DATA SAVED SUCCESS ++++++++++")

}catch{

console.log('+++++++++ PAINT DATA SAVE FAILED ++++++++++')

}

}

所以,正在发生的事情是接收到表单数据并将其粘贴到 中的下一行实际发生的事情是我画了一堆正方形,点击 Save All 并等待一遍又一遍地填写、发送和存储表格。

我遇到的问题是这个过程很慢,而且容易出错。我在循环中有一个 sleep(5000) 以尽量减少错误,但这会增加保存时间!

我找到了 this solution for the spreadsheet side of the problem, which basically pastes an array in bulk rather than row after row. The video shows that this is a much faster, slicker way to transfer lots of data. However, the data is being sent row after row from my painter programme。我想弄清楚的是是否有任何方法可以将整个 paintArray 发送到我的 Google Sheet doPost().

我有一些想法。

首先,我可以保留 painter programme as it is and in the doPost() in my spreadsheet's appscript store the incoming entries into an array, and then once it is filled using the method here;但是,我不确定如果 doPost() 被多次调用,这将如何工作,而且我也不确定如何告诉 Google Sheets 一次执行数组的批量粘贴所有表格已提交。

编辑:这是 doPost() 的修订版,其中包含批量粘贴代码。但现在我需要一种方法来检索批量数据。

    function doPost (e) {

  const lock = LockService.getScriptLock()
  lock.tryLock(10000)

  try {

    const doc = SpreadsheetApp.openById(scriptProp.getProperty('key'))
    const sheetName = doc.getSheetByName(e.parameter['sheetName'])
    const headers = sheetName.getRange(1, 1, 1, sheetName.getLastColumn()).getValues()[0]
    

    const nextRow = sheetName.getLastRow() + 1

    const newRow = headers.map(function(header) {
     
    return header === 'timestamp' ? new Date() : e.parameter[header]
    
    })

  paintArray.push(newRow)
  
  sheetName.getRange(nextRow,1,paintArray.length, paintArray[0].length).setValues(paintArray);

    
  
} catch(e) {    
  } finally {
    lock.releaseLock();
  }
}

第二个想法是以某种方式改变 painter programme 的方法,从通过循环发送单个表单到将 paintArray 作为整个数组发送,然后可以通过 doPost() 函数在 Google 表结束。但是,我正在努力寻找在线解决方案。

我们的想法是,您首先使用选定的分隔符(例如 ,)整理数据,然后通过在 doPost(e) 内拆分数据来处理它。此解决方案将对您当前的代码进行最少的修改。

html:

try {
  // initialize them to blank if needed
  array = [ 'testLocation', 'testCategory', 'testX', 'testY', 'testZ', 'uniqueID',
            'parentID', 'testFill', 'TextA', 'TextB', 'TextC', 'TextD', 'TextE' ];

  array.forEach(element => document.getElementById(element).value = '');
  
  for (let i = 0; i < paintArray.length; i++) {
    uniqueID = `${parentID}-${paintArray[i].x}-${paintArray[i].y}-${paintArray[i].z}`

    // append each item and have them delimited by a comma
    document.getElementById('testX').value += `${paintArray[i].x},`
    document.getElementById('testY').value += `${paintArray[i].y},`
    document.getElementById('testZ').value += `${paintArray[i].z},`
    document.getElementById('uniqueID').value += `${uniqueID},`
    document.getElementById('parentID').value += `${parentID},`
    document.getElementById('testFill').value = `${paintArray[i].fill},`
  }
  // submit them all at once
  document.forms['mapData'].dispatchEvent(new Event('submit'));
  paintArray = []
}

doPost(e):

...
const nextRow = sheetName.getLastRow() + 1;

// start of sample values 
headers = ['key1', 'key2', 'key3']
// emulating an event object, assuming these are the values sent to doPost
var e = {};
e.parameter = { 'sheetName': 'Global', 
                'key1': 'a,b,c,d,e',
                'key2': '',
                'key3': '!,@,#,$,%'}
// end of sample values

// tokenize your values per header
var paintArray = headers.map(function (header) {
  return e.parameter[header].split(',');
});

console.log('before transpose:')
console.log(paintArray)
// transpose 2d data
paintArray = paintArray[0].map((_, colIndex) => paintArray.map(row => row[colIndex] || ''));
console.log('after transpose:')
console.log(paintArray)

// then proceed to use setValues
sheetName.getRange(nextRow, 1, paintArray.length, paintArray[0].length).setValues(paintArray);
...

输出(paintArray):

获得转置数组后,您现在应该可以将其批量写入电子表格。

注:

  • 我只包含了代码的重要部分,展示了它是如何完成的。随意将此代码合并到您现有的代码中。