質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Q&A

解決済

1回答

5288閲覧

GASで抽選人数をカスタマイズし、当選者が重複しない関数を作りたいです。

koroaisu

総合スコア8

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

0グッド

0クリップ

投稿2019/08/26 10:46

前提・実現したいこと

指定したシートで、行及び当選者数をカスタマイズして、抽選を行い、当選者のセルの背景色を黄色にしたいです。
しかし、当選者が重複しないようにしたいのですが、上手くできなくて質問させていただきました。

該当のソースコード

GAS

1function Roll() { 2 var sheet = SpreadsheetApp.openById("リンク先").getSheetByName("test2"); 3 var lastRow = sheet.getLastRow();  4 for (var j = 0; j < 10;j++) {  //当選者数を設定 5 var row = Math.ceil(Math.random() * (lastRow-1)) + 1; 6 var tag = sheet.getRange(row, 1).setBackground("yellow"); 7 } 8}

試したこと

抽選する際に、getvalueを使って配列に格納し、当選者をリストアップして比較したかったですが、上手く格納できなくて失敗しました。
また、getvalueの際に、背景色を設定できなくて困ってます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

抽選する際に、getvalueを使って配列に格納し、当選者をリストアップして比較したかったですが、上手く格納できなくて失敗しました。

こちらで対応してみました。

javascript

1function myFunction() { 2 function Roll() { 3 var sheet = SpreadsheetApp.openById("リンク先").getSheetByName("test2"); 4 var lastRow = sheet.getLastRow(); 5 var l = []; 6 for (var j = 0; j < 20;j++) {  //当選者数を設定 7 var row = Math.ceil(Math.random() * (lastRow-1)) + 1; 8 while(l.indexOf(row) >= 0) { 9 row = Math.ceil(Math.random() * (lastRow-1)) + 1; 10 } 11 l.push(row); 12 var tag = sheet.getRange(row, 1).setBackground("yellow"); 13 } 14 } 15 Roll(); 16}

本題とはズレますが、「Math.ceil(Math.random() * (lastRow-1)) + 1;」lastRow-1やランダム値に+1すると微妙に範囲がズレますが、意図している挙動なのでしょうか??


行番号自体は重複していないのですが、アンケートなどを回答した者が重複してアンケートに参加した場合、異なる行の番号に同じ者の名前が重複してしまいます。

追記を受けて回答を変更しました。
また、元のコードを活かすとかなり冗長になったため書き直しております。
わからない部分もあるかもしれませんが、コメントもつけてますし、よく読めばそんなに難しい事はありません。

javascript

1function myFunction2() { 2 // 重複を除去したい値が入っている列数を指定(B列だったら2) 3 var key_column_number = 2; 4 5 // 色を塗りたい数 6 var n = 5; 7 8 function Roll() { 9 var sheet = SpreadsheetApp.openById("xxxx").getSheetByName("test2"); 10 var lastRow = sheet.getLastRow(); 11 12 // 対象の値を全て取得 13 var values = sheet.getRange(1,1,lastRow, key_column_number).getValues(); 14 15 // 指定した列の値が重複した行は除く 16 var unique_values = values.reduce(function(x, y, index) { 17 if (x.names.indexOf(y[1]) < 0) { 18 x.row_nubers.push(index + 1); 19 x.names.push(y[1]); 20 } 21 return x; 22 }, {row_nubers: [], names: []}); 23 var row_numbers = unique_values.row_nubers; 24 25 // 行番号をランダムで並び替え 26 row_numbers.sort(function() {return Math.random() - .5}); 27 28 // 先頭から色を塗りたい行数分だけ行番号を取得 29 var target_row_numbers = row_numbers.slice(0,n); 30 31 // 色塗り 32 target_row_numbers.forEach(function(v) { 33 sheet.getRange(v, 1).setBackground("yellow"); 34 }); 35 } 36 Roll(); 37}

投稿2019/08/27 04:59

編集2019/08/30 02:30
yamap55

総合スコア1376

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

koroaisu

2019/08/29 01:23

ご回答、誠にありがとうございます! 「Math.ceil(Math.random() * (lastRow-1)) + 1;」につきまして、ランダムでセルを取得する関数を調べてそのまま使っていました。ご指摘ありがとうございます!
koroaisu

2019/08/29 01:38

お忙しい中すみません、ご教授の関数を試してみましたが、一つの列の中に同じ値のセルが存在した場合(例:A1、A18の値=thankyou)、当選者が重複してしまいます。indexOfではなく、もしかしたら、配列の長さに応じて、valueごとに比較した方がいいでしょうか。
yamap55

2019/08/29 01:57

保持しているものは行番号なので重複する事はないと思います。Logger.log(l)などとして値を見ていただければ確認できます。 > もしかしたら、配列の長さに応じて、valueごとに比較した方がいいでしょうか。 ここは何を言っているかわかりません。(配列とは何?valueごとに何と何を比較?)
koroaisu

2019/08/30 01:10

説明が下手で申し訳ございません。 行番号自体は重複していないのですが、アンケートなどを回答した者が重複してアンケートに参加した場合、異なる行の番号に同じ者の名前が重複してしまいます。 そのため、一度抽選した当選者は配列に格納し、抽選するたびに、すでに当選した者は配列にpushせず、再度抽選を行う形にできればと思います。
koroaisu

2019/08/30 10:04

親切で丁寧なご回答、誠にありがとうございます! ご教授頂いたコードを消化してみます。 本当に大変、助かりました。ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問