同じ日付範囲内の列値に基づいてデータの行が挿入されないようにするにはどうすればよいですか?

Aug 21 2020

ユーザー入力からシートにデータを挿入しています。挿入する前に、指定された日付範囲内に同じ電子メールアドレスを持つ行(列3、コードの値e + k3)がすでに存在することを確認したいと思います。すでに存在する場合、その行は挿入されませんが、他の入力は処理されます。それを解決する方法は?タナイケに感謝します。

function onePeriodm(){
  
  const srcSheetName = "Dashboard";
  
  // 1. Retrieve values from the source sheet.
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const srcSheet = ss.getSheetByName(srcSheetName);
  const [[,,,,,k3],,[f5,g5,...h5i5j5k5]] = srcSheet.getRange("F3:K5").getDisplayValues();
  
  // 2. Convert the values for putting to the destination sheet.
  const dstValues = h5i5j5k5.reduce((ar, e) => {
    if (e != "") ar.push([g5, Number(e), e + k3, , , f5]);
    return ar;
  }, []);
  
  // 3. Put the converted values to the destination sheet.
  const dstSheet = ss.getSheetByName(f5);
  const dstCurrentValues = dstSheet.getRange(`A2:A${dstSheet.getLastRow()}`).getDisplayValues().flat();
  const index = dstCurrentValues.lastIndexOf(dstValues[0][0]) + 2;
  dstSheet.insertRowsAfter(index, dstValues.length);
  dstSheet.getRange(index + 1, 1, dstValues.length, dstValues[0].length).setValues(dstValues);
}

回答

1 dwmorrin Aug 21 2020 at 16:18

reduce既存のデータセットに入力日と学生IDの行が既にある場合に新しい行が生成されないように、関数を更新する必要があります。

これには、現在の値を取得する場所をステップ2にシフトアップし、取得する値を展開して電子メール列を含め、reduce関数でそれらの値にアクセスできるようにする必要があります。また、使用することはできません.flat()我々は複数の列を見ているので、今のトリックを、私たちは持っているので、の細かいこと.find().map()それは同じようにうまく動作します。

これでreduceステップ#3になり、要件を追加します。私たちは.find()、指定された日付と学生の電子メールで既存のレコードを取得しようとするために使用します。find戻ってundefined、それが失敗した場合、私たちは私たちの更新できるreduceだけで唯一のプッシュに条件をstudentId != ""しますstudentId != "" && !existingEntry

の形状を変更しdstCurrentValuesて展開し、メール値を取得.flat().map(row => row[0])たため、の形状を同じにするためにに変更する必要がありlastIndexOfます。

すべての読者の利益のために、変数名は「A1」表記からそれらに含まれる値を反映する名前に更新されました。

function onePeriodm() {
  const srcSheetName = "Dashboard";

  // 1. Retrieve values from the source sheet.
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const srcSheet = ss.getSheetByName(srcSheetName);
  const [
    [, , , , , emailPattern],
    ,
    [courseCatalogId, dateString, ...studentIds],
  ] = srcSheet.getRange("F3:K5").getDisplayValues();

  // 2. Retrieve current values
  const dstSheet = ss.getSheetByName(courseCatalogId);
  const dstCurrentValues = dstSheet
    .getRange(`A2:C${dstSheet.getLastRow()}`) // expanded to include email column
    .getDisplayValues(); // not flattening since we have multiple columns now

  // 3. Convert the values for putting to the destination sheet.
  //    Do not include if there is already an email for this date in current values
  const dstValues = studentIds.reduce((array, studentId) => {
    const existingEntry = dstCurrentValues.find(
      (row) => row[0] === dateString && row[2] === studentId + emailPattern
    );
    if (studentId != "" && !existingEntry)
      array.push([
        dateString,
        Number(studentId),
        studentId + emailPattern,
        ,
        ,
        courseCatalogId,
      ]);
    return array;
  }, []);

  // 4. Put the converted values to the destination sheet.
  const index = dstCurrentValues.map((row) => row[0]).lastIndexOf(dateString);
  const row = index + 2;
  dstSheet.insertRowsAfter(row, dstValues.length);
  dstSheet
    .getRange(row + 1, 1, dstValues.length, dstValues[0].length)
    .setValues(dstValues);
}