🐡

[GAS]スプレッドシートで簡易な投票機能を作成したい

2025/01/19に公開2

悩み

  • Googleフォームを使うほどでもないと思っている
  • ざっくりみんなの意見が分かれば良い

手順

スプレッドシートに投票の項目を作成する


投票ボタンは挿入>図形描画から作成して下さい。

GASを作成する

VoteCounter.gs
// 質問1の「はい」と「いいえ」をカウント
function incrementYesForQuestion1() { incrementYes(1); }
function incrementNoForQuestion1() { incrementNo(1); }

// 質問2の「はい」と「いいえ」をカウント
function incrementYesForQuestion2() { incrementYes(2); }
function incrementNoForQuestion2() { incrementNo(2); }

// 質問3の「はい」と「いいえ」をカウント
function incrementYesForQuestion3() { incrementYes(3); }
function incrementNoForQuestion3() { incrementNo(3); }

// 質問4以降も作成する場合は、上と同じ形で作成する
// これより下のコードは表の位置が変わらない場合は、変更なしでOK

// 汎用の「はい」を増やす関数
function incrementYes(questionNo) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const yesRow = getRowByQuestionNo(questionNo);
  if (yesRow) {
    const yesCell = sheet.getRange(yesRow, 8);  // H列は「はい」のカウント
    yesCell.setValue((yesCell.getValue() || 0) + 1);
  }
}

// 汎用の「いいえ」を増やす関数
function incrementNo(questionNo) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const noRow = getRowByQuestionNo(questionNo);
  if (noRow) {
    const noCell = sheet.getRange(noRow, 9);  // I列は「いいえ」のカウント
    noCell.setValue((noCell.getValue() || 0) + 1);
  }
}

// 質問番号から行番号を取得する関数
function getRowByQuestionNo(questionNo) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const dataRange = sheet.getRange("D16:D40");  // 質問番号が書かれている範囲
  const data = dataRange.getValues();
  for (let i = 0; i < data.length; i++) {
    if (data[i][0] === questionNo) {
      return i + 16;  // 実際の行番号に変換(D列が14行目から始まるため)
    }
  }
  return null;
}

スクリプトを図形に割り当てる

  1. 図形を右クリック
  2. 図形の右上に3つ黒丸が表示されるのでクリック
  3. スクリプトを割り当てをクリック
  4. incrementYesForQuestion1を入力して確定(質問1の「はい」ボタンの場合)

解説

質問ごとの処理

function incrementYesForQuestion1() { incrementYes(1); }
function incrementNoForQuestion1() { incrementNo(1); }

incrementYesForQuestion1()は「質問1」の「はい」を増やします。
中でincrementYes(1)を呼び出して、「1番目の質問だよ」と教えています。

「はい」を増やす汎用関数

function incrementYes(questionNo) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const yesRow = getRowByQuestionNo(questionNo);
  if (yesRow) {
    const yesCell = sheet.getRange(yesRow, 8);  // H列は「はい」のカウント
    yesCell.setValue((yesCell.getValue() || 0) + 1);
  }
}

スプレッドシートを取得

SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()で、現在のスプレッドシートを選択

該当の行番号を取得

getRowByQuestionNo(questionNo)で、「質問番号」に対応する行番号を取得

クリックした「はい」のセルを取得

sheet.getRange(yesRow, 8)でyesRowは行番号、8は列番号(H列)

「はい」のカウントを増やす

  • yesCell.getValue()は1つ前で取得したセルの中身を取得
  • || 0はセルが空白だったり、値がnullの場合に代わりに0を使うという安全対策
  • + 1は現在の値に+1する
  • yesCell.setValueは1つ前で取得したセルに入力

「いいえ」を増やす汎用関数

function incrementNo(questionNo) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const noRow = getRowByQuestionNo(questionNo);
  if (noRow) {
    const noCell = sheet.getRange(noRow, 9);  // I列は「いいえ」のカウント
    noCell.setValue((noCell.getValue() || 0) + 1);
  }
}

「はい」と同じ仕組みです。
ただし「いいえ」のカウントがあるI列(9列目)を使います。

質問番号から行番号を取得

function getRowByQuestionNo(questionNo) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const dataRange = sheet.getRange("D16:D40");  // 質問番号が書かれている範囲
  const data = dataRange.getValues();
  for (let i = 0; i < data.length; i++) {
    if (data[i][0] === questionNo) {
      return i + 16;  // 実際の行番号に変換(D列が14行目から始まるため)
    }
  }
  return null;
}
  • sheet.getRange("D16:D40")で質問番号が書かれている範囲を取得
  • dataRange.getValues()で取得した範囲の値を取得
  • data[i][0] === questionNoで該当する行番号を探す
  • return i + 16で行番号は16行目から始まるので、i + 16で行番号を返す

あとがき

これは実際の実務で遭遇した場面です。
Googleフォームの回答率が激低だったので、どうやってみんなの意見を集めようかなと思って辿り着いたものになります。クリックし放題の仕様なので、ユーザーの判別や二重回答を防ぐは無理です。そこは社会人なのだから、常識はあるよねで進めました。結果的にグラフにすると良い感じになり、無事乗り越えることができました。

Discussion

こじまるこじまる

はじめまして。
私も仕事で同じような場面に出くわしました。

コピー大変ですよね…
(私も20個くらいコピーしました。)

すこしでも見た目を面白くするためにREPT関数を使って、★を増やして見栄えするようにしてました(=REPT("★", セル番地))。

投票数が増えると横の星が増えていく感じです。

もし、もうひと味加えたくなった際にはご参考まで。

wateruwateru

丁寧にありがとうございます!
複製する作業が一番大変でした・・・。

視覚的に分かりやすくする発想は無かったですね。
見栄え良くするならアリですね!