LoginSignup
0
1

More than 3 years have passed since last update.

【Google Apps Scriptとスプレッドシートで在庫管理】選択範囲の中で取得した値を使って、別シートで計算する

Last updated at Posted at 2020-06-19

はじめに

この動画を見ていただけると、大体何をやるのか理解していただけるかと。。

経緯

Google Apps Script 入力された文字を別シートにて検索し、その隣にある文字を書き出す
こちらの続き:sweat_smile:

スプレッドシートでアクセサリーの在庫管理をしていると、とてもめんどくさいのが以下の作業!
在庫として保有している材料の数 ー 今回使った材料の数 = 現在の在庫の数

アクセサリー作りで使う材料の数は多いようで、それを毎回手動でスプレッドシートを使い引き算するのが面倒だということですね。。。

用意するもの

在庫をまとめたシート

スクリーンショット 2020-06-19 17.33.59.jpg

作ったアイテムをまとめたシート

スクリーンショット 2020-06-16 21.37.07.jpg

全体の流れ

①「作ったアイテム」のシートで使った材料を範囲選択(動画参照)
②カスタムメニューでボタンを作っておいて、それを押すことで発動し、①で選択した範囲を2次元配列で取得
③「在庫」シートにて同じ名前の材料を検索し、2つ横のセルの値(各材料の在庫数)を取得
④②と③で取得した在庫数を引き算して、残った在庫数を書き出す

大体の処理の流れはこんな感じ。

全てのコード

コード.gs
// Spreadsheetが開かれた時に自動的に実行されます.
function onOpen() {
  // 現在開いている、スプレッドシートを取得します.
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

  // メニュー項目を定義します.
  var entries = [
    {name : "在庫から使った数を減らす"  , functionName : "menuItem1"},
  ];
  // 「Custom」という名前でメニューに追加します.
  spreadsheet.addMenu("Custom", entries);
}

 // menuItem1をクリックした時の処理
function menuItem1() {
 //現在アクティブなシートの名前を取得
 var nowSheet = SpreadsheetApp.getActiveSheet().getName();
     //シート「作ったアイテム」以外で実行したらアラート
  if (nowSheet === '作ったアイテム') {
     var data = getData();
     matchData(data);
    } else {
    alert();
    }
}

function getData() {
    //現在のスプレットシートを取得する
    var sheet1 = SpreadsheetApp.getActiveSheet();
    var values = sheet1.getActiveRange().getValues();
    var numRows = sheet1.getActiveRange().getNumRows();

    return [values, numRows];
}

function matchData(data) {
    //現在のスプレッドシートを取得
 var ss = SpreadsheetApp.getActiveSpreadsheet();
   //シート「在庫」を取得
 var stockSheet = ss.getSheetByName('在庫');

  //使った材料の配列「values」をdataの中から取り出す
  var items = data[0];

 // ループする回数「numRows」をdataの中から取り出す
  var dataNumRows = data[1];
  var stopSetCount = dataNumRows - 1;

  for(var i = 0; i <= stopSetCount; i++){
    var item = items[i];

    var itemName = item[0];
    var usedCount = item[2];

    //シート「在庫」で材料名を探す
    var textFinder = stockSheet.createTextFinder(itemName);
    var ranges = textFinder.findAll();
    //材料名のセル範囲を取得
    var textPos = ranges[0].getA1Notation();
    //材料名の位置を取る
    var textPosCell = stockSheet.getRange(textPos);
    //材料名の2つ右隣のセルの値を取る
    var targetValue = textPosCell.offset(0, 2).getValue();
    //在庫の数から使った数を引く
    var afterUsedCount = targetValue - usedCount;
    textPosCell.offset(0, 2).setValue(afterUsedCount);
  }
}

function alert() {
  var ui = SpreadsheetApp.getUi();
  var title = '「作ったアイテム」のシートで実行してよ';
  var text = 'おかしくなるから!';
  ui.alert(title, text, ui.ButtonSet.OK_CANCEL);
}

軽く解説

なぜループする回数を-1するのか?

// ループする回数「numRows」をdataの中から取り出す
  var dataNumRows = data[1];
  var stopSetCount = dataNumRows - 1;

 for(var i = 0; i <= stopSetCount; i++){

範囲選択した部分が何行か?を取得して、ループを回す回数を決めているんだが、なぜ−1するのか?
結論を言うと、−1しないとループする回数が1回増えてしまうからだ。

もし範囲選択した部分が4行だったとする。すると4回ループしないといけない。
しかし、for分はvar i = 0;で0から始まってる。だから−1しないと、1回ループする回数が増えてしまいエラーが起こる。

なので、var i = 0;var i = 1;としても良い。

matchDataで受け取るdataは何?

 // menuItem1をクリックした時の処理
function menuItem1() {
 //省略
     var data = getData();
     matchData(data);
  //省略
}


function matchData(data) {
//省略
//使った材料の配列「values」をdataの中から取り出す
  var items = data[0];

 // ループする回数「numRows」をdataの中から取り出す
  var dataNumRows = data[1];

}

ここで受け取ってるのはgetData()で返されている値。
1つ目の配列(つまりvalues)が範囲選択した部分のデータが2次元配列で入っている。
2つ目の配列(つまりnumRows)が「範囲選択した部分は何行あったか?」と言うデータが入っている。

function getData() {
    //現在のスプレットシートを取得する
    var sheet1 = SpreadsheetApp.getActiveSheet();
    //getValueではなくgetValues。複数形のsがあるよ!
    var values = sheet1.getActiveRange().getValues(); 
    var numRows = sheet1.getActiveRange().getNumRows();

    return [values, numRows];
}

カスタムメニューはこの部分で作られてる

// Spreadsheetが開かれた時に自動的に実行されます.
function onOpen() {
  // 現在開いている、スプレッドシートを取得します.
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

  // メニュー項目を定義します.
  var entries = [
    {name : "在庫から使った数を減らす"  , functionName : "menuItem1"},
  ];
  // 「Custom」という名前でメニューに追加します.
  spreadsheet.addMenu("Custom", entries);
}

 // menuItem1をクリックした時の処理
function menuItem1() {
 //現在アクティブなシートの名前を取得
 var nowSheet = SpreadsheetApp.getActiveSheet().getName();
     //シート「作ったアイテム」以外で実行したらアラート
  if (nowSheet === '作ったアイテム') {
     var data = getData();
     matchData(data);
    } else {
    alert();
    }
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1