0
function onEdit() {
var openRequests = SpreadsheetApp.getActive().getSheetByName('Open Requests');
var lastRowOpen = openRequests.getLastRow();

var closedRequests = SpreadsheetApp.getActive().getSheetByName('Closed Requests');
var lastRowClose = closedRequests.getLastRow();

var closed = openRequests.getRange(2,8,lastRowOpen,1).getValues();

for (var i = 0; i < lastRowOpen; i++)
{
    if (closed[i][0].toString() == 'Yes')
    {
        var line = i+2;
        if (closedRequests.getLastRow() == 1)
        {
            openRequests.getRange(line,1,1,9).copyTo(closedRequests.getRange(2,1,1,9));
            closedRequests.getRange(2,9,1,1).setValue(new Date());
            openRequests.deleteRow(line);
        }
        else
        {
            openRequests.getRange(line,1,1,9).copyTo(closedRequests.getRange(lastRowClose+1,1,1,9));
            closedRequests.getRange(lastRowClose+1,9,1,1).setValue(new Date());
            openRequests.deleteRow(line);
        }
    }
}

}

onEdit を実行するトリガーを設定しました。と呼ばれる列をチェックして、 と表示されClosedているかどうかを確認しますYes。列にはClosed、値を含むデータ検証ドロップダウン メニューがありますYes

したがって、ドロップダウンメニューをクリックして選択するYesと、行全体が別のシートにコピーさClosed Requestsれ、スプレッドシートからその行が削除されOpen Requestsます。

私が抱えている問題は、約 50% の確率で、選択Yesした行が削除されますが、その下の行も削除されます (これが発生した場合、約 50% の確率で、2 番目に削除された行が表示されるのは数回だけです)のClosed Requests場合、元に戻さない限り、行全体が永久に消えてしまうこともあります)。

私が知る限り、deleteRow()関数は行全体を削除し、その下のすべての行を 1 行上に移動して空白を埋めます。したがって、削除される行の下の行は同じ行にシフトされ、削除されます。ただし、関数が2回呼び出される理由はわかりません。

いくつかの遅延を追加しようとしましたが、機能していないようです。

4

4 に答える 4

5
function onEdit(e) {
  var eRange = e.source.getActiveRange();
  var openRequests = SpreadsheetApp.getActive().getSheetByName('Open Requests');
  var closedRequests = SpreadsheetApp.getActive().getSheetByName('Closed Requests');
  var nextRowClose = (closedRequests.getLastRow()?closedRequests.getLastRow()+1:2);

  if(eRange.getSheet().getName()=="Open Requests" && eRange.getColumn()==8 && eRange.getValue()=="Yes") {
    openRequests.getRange(eRange.getRow(), 1, 1, 9)
      .copyTo(closedRequests.getRange(nextRowClose, 1));
    closedRequests.getRange(nextRowClose, 9).setValue(new Date());
    openRequests.deleteRow(eRange.getRow());
  }
}
于 2013-01-16T00:07:10.833 に答える
1

@ジャック、私はあなたに似たユースケースを持っています。私のコードは、BryanP が議論している後方のものです。私のコードは多かれ少なかれここにあります: 「ステータス= '完了'のタスクアイテムのバッチ削除」。バッチでそれらを削除するため、逆方向の方法を使用します。これにより、行番号が大きい行を削除しても、行番号が小さい行の行番号が妨げられません。

ただし、バッチ モードで行を削除するわけではないため、逆方向に行っても違いはないはずです (おそらく、2 人のユーザーがシートを使用して同時に削除しない限り?)

だから私はあなたのコードを試してみると思いました。スプレッドシートに既に存在する onedit() 関数にあなたのコードをくつがえしました (これは、非アクティブな期間の後に行を赤く色付けし、タスクが実際に参加したときにタイムスタンプを挿入するために使用されます)。

次に、テストするために、既に 50 行/タスクが含まれているスプレッドシートの 1 つのコピーを使用しました。必要なセルを手動で行に入力し、セルからドロップダウンで [完了] を選択しました (「はい」ではなく「完了」を期待するようにコードを変更しました)。これを20行繰り返しました。

結果: コードは 20 回のすべての回で期待どおりに成功しました... 二重削除はなく、常にデータがコピーされます。遅延やSpreadsheetApp.flush()を導入することなく、私にとってはうまくいきました。

恐れ入りますが、確固たる提案はありません。ちなみに、スプレッドシートが適切に更新されていないため、削除された行が表示されないという既知の障害について言及します。これは、この障害が発生したときにスプレッドシートを手動で更新することで確認できます。(ただし、この障害の兆候は、2 つの連続する行の二重コピーに関するレポートと論理的に一致していないようです。)

于 2013-01-16T01:14:12.530 に答える
1

私に言及されたように、逆方向に反復してみることができます。SpreadsheetApp.flush()削除後に a を投げることも役立つ場合があります。

于 2013-01-12T14:20:45.570 に答える
0

スレッドロック?スレッドロックの問題のようです。試す:

function onEdit() {

 // ****** add lock code
 var lock = LockService.getPublicLock();
 var hasMutex = lock.tryLock(100);
 if(hasMutex==false) {
   return;
 }
 // *** end

 var openRequests = SpreadsheetApp.getActive().getSheetByName('Open Requests');
 var lastRowOpen = openRequests.getLastRow();

 var closedRequests = SpreadsheetApp.getActive().getSheetByName('Closed Requests');
 var lastRowClose = closedRequests.getLastRow();

 var closed = openRequests.getRange(2,8,lastRowOpen,1).getValues();

 for (var i = 0; i < lastRowOpen; i++)
 {
    if (closed[i][0].toString() == 'Yes')
    {
       var line = i+2;
       if (closedRequests.getLastRow() == 1)
       {
          openRequests.getRange(line,1,1,9).copyTo(closedRequests.getRange(2,1,1,9));
          closedRequests.getRange(2,9,1,1).setValue(new Date());
          openRequests.deleteRow(line);
       }
        else
       {

   openRequests.getRange(line,1,1,9).copyTo(closedRequests.getRange(lastRowClose+1,1,1,9));
        closedRequests.getRange(lastRowClose+1,9,1,1).setValue(new Date());
        openRequests.deleteRow(line);
        }
      }
  }


 // ****** add lock code
  lock.releaseLock();    

 // *** end

} 

質問:

1) その時点でスプレッドシートを使用していた人数。

2) それはどのくらいの頻度で起こりますか。

于 2013-01-17T04:14:37.120 に答える