見出し画像

GAS学習note:Day3 if文を極める(条件分岐・比較演算子・空セル判定)

はじめに

Day2ではセルの読み書きと for文での複数処理を学びました。
Day3のゴールは「if文を自在に書ける」こと。これができると、条件で処理を分ける=実務の自動化の核が作れます。


if文の基本形と比較演算子

if (条件) {
  // 条件が true のとき実行
} else {
  // それ以外のとき実行
}

よく使う比較演算子

  • === 等しい(型も値も一致)※推奨

  • !== 等しくない

  • > / < / >= / <= 大小比較

基本は === を使う(== は型変換が起きてバグの元)


実践1:点数で「合格/要改善」を判定

スプレッドシートの A列:点数B列:判定 とします(1行目は見出し)。

function judgeScore() {
  const sheet = SpreadsheetApp.getActive().getActiveSheet();
  const last = sheet.getLastRow();
  for (let r = 2; r <= last; r++) {
    const score = sheet.getRange(r, 1).getValue(); // A列
    if (typeof score !== 'number') continue;       // 数値以外はスキップ
    if (score >= 80) {
      sheet.getRange(r, 2).setValue('合格');       // B列
    } else {
      sheet.getRange(r, 2).setValue('要改善');
    }
  }
}

💡ポイント

  • 見出しを避けるため r = 2 から開始

  • typeof score !== 'number' で安全にガード(空や文字列を弾く)


実践2:三段階評価(else if)

スプレッドシートの A列:点数、B列:判定、C列:評価 とします(1行目は見出し)
80点以上:A、60〜79:B、59以下:C

function gradeScore() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const last = sh.getLastRow();
  for (let r = 2; r <= last; r++) {
    const v = sh.getRange(r, 1).getValue();
    if (typeof v !== 'number') { sh.getRange(r, 3).setValue('—'); continue; }
    if (v >= 80) {
      sh.getRange(r, 3).setValue('A');
    } else if (v >= 60) {
      sh.getRange(r, 3).setValue('B');
    } else {
      sh.getRange(r, 3).setValue('C');
    }
  }
}


実践3:複合条件(AND/OR/NOT)

  • &&(かつ)

  • ||(または)

  • !(ではない)

例:在庫が10以下 かつ 発注済みでない行を警告
E列:在庫数、F列:発注済み(TRUE/FALSE)、G列:メモ

function stockAlert() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const last = sh.getLastRow();
  for (let r = 2; r <= last; r++) {
    const qty = Number(sh.getRange(r, 5).getValue());   // 在庫数
    const ordered = sh.getRange(r, 6).getValue();       // チェックボックス(TRUE/FALSE)
    const isOrdered = (ordered === true);               // 論理値として扱う

    if (qty <= 10 && !isOrdered) {
      sh.getRange(r, 7).setValue('⚠ 補充要');
      sh.getRange(r, 5, 1, 3).setBackground('#fff2cc'); 
    } else {
      // ★条件に当てはまらなければ、メモと背景色をリセット
      sh.getRange(r, 7).setValue('');
      sh.getRange(r, 5, 1, 3).setBackground(null);
    }
  }
}

💡F列の発注のセルはチェックボックス形式に変更

F列の発注のセルのチェックボックスにチェックを入れ、実行するとG列のメモの色付け、⚠ 補充要が消える。


空セル・文字列の“落とし穴”回避術

1) 空セル判定は === "" が安全

const v = sh.getRange(r, 1).getValue();
if (v === "") { /* 空セル */ }

if(!v){} は 0 も偽と判定してしまうので NG。

2) 数値に変換してから比べる

const raw = sh.getRange(r, 1).getValue();   // "100" のような文字列の可能性
const num = Number(raw);
if (Number.isNaN(num)) { /* 数値でない → スキップ */ }
if (num >= 80) { /* OK */ }

3) 文字列比較は 全角/半角・大文字小文字 に注意

const flag = String(sh.getRange(r, 2).getValue()).trim();
if (flag.toLowerCase() === 'ok') { /* … */ }

早期リターン(ガード節)で読みやすく

ネストを浅くしてバグを減らします。

function processRow(r) {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const v = sh.getRange(r, 1).getValue();
  // 前提を満たさないならすぐ返す
  if (v === "" || typeof v !== 'number') return;

  if (v >= 100) {
    sh.getRange(r, 2).setValue('達成');
    return;
  }
  sh.getRange(r, 2).setValue('未達');
}

よくあるエラー&対処(ミニ辞典)

  • == を使ってしまう → 予期せぬ型変換で判定ミス。=== を使う

  • 空セルを !v で判定 → 0 も偽になる。v === "" で判定

  • 文字列数値をそのまま比較 → "100" > 80 は true になるが混在は危険。Number() で揃える

  • 見出し行まで処理 → for (let r = 2; …) のように2行目から

  • TRUE/FALSE の表記ゆれ → データをチェックボックス(TRUE/FALSE)にするか toLowerCase() で吸収


今日の仕上げ課題(コピペでOK)

課題1:売上ランク

  • I列:売上

  • J列:ランク(100,000以上=S / 50,000以上=A / それ以外=B)

function rankSales() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  for (let r = 2; r <= sh.getLastRow(); r++) {
    const num = Number(sh.getRange(r, 9).getValue());
    if (Number.isNaN(num)) { sh.getRange(r, 10).setValue('—'); continue; }
    if (num >= 100000) sh.getRange(r, 10).setValue('S');
    else if (num >= 50000) sh.getRange(r, 10).setValue('A');
    else sh.getRange(r, 10).setValue('B');
  }
}


課題2:期限警告

  • L列:期限(日付)

  • M列:ステータス(空 or 済)

  • ルール:今日より前 & ステータス空ならN列に「期限切れ」+行を赤背景

function dueAlert() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const last = sh.getLastRow();

  // 今日を0時にそろえる(今日スルー仕様)
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const todayMs = today.getTime();

  for (let r = 2; r <= last; r++) {
    let due = sh.getRange(r, 12).getValue();           // L列:期限
    const rawStatus = sh.getRange(r, 13).getValue();   // M列:ステータス(チェックボックス)

    // ステータス判定:未チェック or 空文字 → 未処理
    const isTodo = (rawStatus === false) || (String(rawStatus).trim() === "");
    // 「済」にしている場合の互換(テキスト運用にも対応)
    const isDone = (rawStatus === true) || (String(rawStatus).trim() === "済");
    if (isDone) { // 完了は常にリセットしてスキップ
      sh.getRange(r, 14).setValue("");
      sh.getRange(r, 12, 1, 3).setBackground(null);
      continue;
    }

    // 日付でなければスキップ(文字列でも new Date で変換を試す)
    if (!(due instanceof Date)) {
      due = new Date(due);
    }
    if (!(due instanceof Date) || isNaN(due)) {
      // 変換不可ならクリアだけして次へ
      sh.getRange(r, 14).setValue("");
      sh.getRange(r, 12, 1, 3).setBackground(null);
      continue;
    }

    // 期限も0時にそろえて数値比較
    due.setHours(0, 0, 0, 0);
    const dueMs = due.getTime();

    if (isTodo && dueMs < todayMs) {
      // 期限切れ:今日より前 & 未処理(未チェック/空)
      sh.getRange(r, 14).setValue("期限切れ");       // N列
      sh.getRange(r, 12, 1, 3).setBackground("#f4cccc"); // L〜N列 赤背景
    } else {
      // 条件外はリセット
      sh.getRange(r, 14).setValue("");
      sh.getRange(r, 12, 1, 3).setBackground(null);
    }
  }
}


まとめ

  • if / else if / else の基本と**比較演算子(=== 推奨)**を理解

  • 空セル/数値/文字列の扱いを安全に

  • AND/OR/NOT で複合条件を表現

  • 早期リターンで読みやすくバグを減らす

👉 Day4 は「for文 × if文で“実務ミニツール”を作る」。
実データを一括クリーニング&判定する実戦レシピを作ります。

いいなと思ったら応援しよう!

この記事が参加している募集