2

私の問題は、同時アクセス中にデータが失われないようにする方法です。

スクリプトをweb-appとして公開しています。DATA_SHEETに新しい行を追加したいと思います。送信ボタンを処理する関数は次のようになります。

function onButtonSubmit(e) {
  var app = UiApp.getActiveApplication();
  var lock = LockService.getPublicLock();
  while (! lock.tryLock(1000))
    ;
  var ssheet = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ssheet.getSheetByName(DATA_SHEET);
  var lastRow = sheet.getLastRow();
  var lastCol = sheet.getLastColumn();
  var rangeToInsert = sheet.getRange(lastRow+1, 1, 1, lastCol);
  var statText = rangeToInsert.getA1Notation();
  rangeToInsert.setValues(<some data from webapp form>);
  app.getElementById('statusLabel').setText(statText);
  lock.releaseLock();
  return app;
}

しかし、これは機能しないようです。2つのフォームを開き、1秒以内に送信ボタンをクリックすると、statsLabelに同じ範囲が表示され、同じ範囲にデータが書き込まれます。そのため、1つのフォームからデータが失われます。

このコードの何が問題になっていますか?tryLock()はスクリプトをブロックしないようです。

シートへの同時書き込みアクセスを防ぐ方法は他にありますか?

4

3 に答える 3

5

/などappendRow()を使用するのではなく、を確認する価値があるかもしれません。getLastRow()setValues()

スプレッドシートへの行のアトミック追加を可能にします。スクリプトの複数のインスタンスが同時に実行されている場合でも、安全に使用できます。以前は、getLastRow()を呼び出してから、その行に書き込む必要がありました。ただし、スクリプトの2つの呼び出しが同時に実行されている場合、両方がgetLastRow()の同じ値を読み取り、互いの値を上書きする可能性があります。

于 2012-10-09T22:02:39.717 に答える
0
while (! lock.tryLock(1000))
    ;

少しひねくれているようです。代わりにこれを試してください:

  if (lock.tryLock(30000))  {
    // I got the lock!  Wo000t!!!11 Do whatever I was going to do!
  } else {
    // I couldn’t get the lock, now for plan B :(
    GmailApp.sendEmail(“admin@example.com”, “epic fail”,
        “lock acquisition fail!”);
  }

http://googleappsdeveloper.blogspot.com/2011/10/concurrency-and-google-apps-script.html

于 2012-10-09T21:34:32.627 に答える
0

getLastRow()/ setValues()をロックで使用する場合は、このコードを挿入する必要があります。

SpreadsheetApp.flush();
// before
lock.releaseLock();
于 2014-11-30T22:22:15.900 に答える