Google Apps Scriptで重複しないレコードだけ取り出す【GAS】
時々、teratailなどのサイトを巡って、回答できそうな内容に回答してたりするのですが、現場ならではの質問や要望が出てきたりするので、とても参考になります。
さて、そんな中、データの塊に於いて、A列の記号が重複していないレコードだけを取り出すというテーマがあり、挑戦してみました。月間売上データの中であまり売れていないものだけを取り出すといったケースで使えそうです。
図:これが求める結果
リンク
よくある勘違い
通常、配列内で重複する値があった時に、ユニークな値を取り出すのには、配列.filterなどのメソッドを使ったり、ループ回してindexOfで調べるといった事があります。ただ、問題なのはこれ「ユニークな値として取り出す」のであって、「重複していない値を取り出す」わけじゃない点。
1 2 3 4 5 6 7 8 9 10 |
//配列 var array = [1,2,2,3,4,4,4,5,6,6,7,8,9] //filterで取り出すと array.filter(function (x, i, self) { return self.indexOf(x) === i; }); //出てくる値は。。。2,4,6は必要ないのに・・・・ [1,2,3,4,5,6,7,8,9] |
しかもこれは1次元配列で出来ることで、スプレッドシートのデータの塊である2次元配列でやるにはこのまま出来るわけじゃない。
必要なのは、[1,3,5,7,8,9]の値を取り出し、それを含むレコードだけを取り出すこと。
サンプルファイル
※メニューに出てくる🍄取り出し⇒非重複抽出を実行すると、E列にそのレコードが取り出される仕組みです
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
//実際に出力してみる function hikaku(){ //スプレッドシートのデータを取得する var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1"); //シートデータを取得する var ss = sheet.getRange("A1:C6").getValues(); //A列だけ取得する var array = sheet.getRange("A1:A6").getValues(); //A列を1次元配列で取り出す const list = array.reduce((pre,current) => {pre.push(...current);return pre},[]); //重複要素だけ取り出す let result = list.filter(function(x, i, self) { return self.indexOf(x) !== i; }); //ssの塊から重複していないレコードだけ、配列に取り出す var singleman = []; for(var i = 0;i<ss.length;i++){ //重複リストにいるかどうか判定 var ret = result.includes(ss[i][0]); //falseの場合配列にレコード単位でpush if(ret == false){ singleman.push(ss[i]); } } //スプレッドシートのE列辺りに出力 var lastColumn = singleman[0].length; //カラムの数を取得する var lastRow = singleman.length; //行の数を取得する sheet.getRange(1,5,lastRow,lastColumn).setValues(singleman); } |
- スプレッドシートのデータの塊、A列だけの塊が必要なデータ群
- A列だけの塊は1次元配列に変換(list)⇒重複してる要素だけ取り出す(result)
- forループでスプレッドシートの塊を回し、A列の値をresultの塊に対してincludesで調査し、trueが返ってくれば重複、falseが返ってくれば対象のレコードとなります。
- 最後に書き込み用配列にpushして、E列に書き込み
- このコードはV8 Runtimeで動作します。
- ユニークな値を取り出してるわけじゃないのがポイントです。
- ret == trueで判定式を変更すれば重複するものだけを抽出も出来ます。便利!!