스프레드시트의 풀다운 목록 연동을 GAS로 실현

배경



Google 스프레드시트에서 '풀다운 목록 연동'을 수행하는 방법을 알아보면 여러 번 HIT합니다.

내가 본 기사는 스프레드 시트의 함수(VLOOKUP라든지)로 실현하고 있는 기사였습니다만, GAS의 지식이 없어도 취급할 수 있는 점에서는 유리합니다만, 입력란이 늘어나면, 거기에 맞추어 식 의 복사나 입력 규칙의 복사가 필요하게 되는 것 같습니다.

입력 행을 늘릴 때마다 복사 실수나 실수로 식을 지워버리거나 하는 것이 싫다-라고 생각했습니다.

이게 뭐야?



「풀다운 연동」을 GAS로 실현하면 어떻게 될까,를 해 보았습니다.
더 잘하는 방법이 있으면 코멘트 란에 잘 부탁드립니다!

완성도



「카테고리1」을 선택하면, 그것에 연동하는 「카테고리2」의 선택사항만이 표시되도록 하고 싶다.



↑ 이것이 사용하는 쪽의 시트로 합니다.



↑ 이것이 설정 시트에 카테고리 1, 카테고리 2가 정의되어 있습니다.

스프레드시트에 제공



「카테고리 1」에 대해서는 통상의 「데이터의 입력 규칙」으로, 「설정 시트」의 「A2:A」를 지정해 설정해 둔다.
「사용하는 쪽의 시트」의 B2로 설정해, B3 이후는 이것을 카피해 버린다.



GAS 코드


/**
 * グローバル変数の定義
 */
const USE_SHEET_NAME     = "使う側のシート";
const SETTING_SHEET_NAME = "設定シート";
const CATEGORY1_COL_NUM  = 2; // B列

/**
 * 本体
 */
function onEdit(e) {
  if (!isTargetCol(e)) return;

  const category1Value = e.value;
  const changedRow     = e.range.getRow();
  const changedCol     = e.range.getColumn();
  const useSheet       = e.source.getSheetByName(USE_SHEET_NAME);

  // 設定シート のデータ(二次元配列)
  const settingData = e.source.getSheetByName(SETTING_SHEET_NAME).getDataRange().getValues();

  // カテゴリ1に対応するカテゴリ2を入れておくところ
  let catgory2List = [];

  // 設定シート のデータの中から、「選択されたカテゴリ1」に対応するカテゴリ2を取り出すところ
  settingData.forEach( row => {
    if (row[0] === category1Value) {
      catgory2List.push(row[1]);
    }
  });

  if(catgory2List.length === 0) return;

  // 編集されたセルの右のセルにカテゴリ2のプルダウンをセットする
  const range = useSheet.getRange(changedRow, changedCol + 1);
  const rule  = SpreadsheetApp.newDataValidation().requireValueInList(catgory2List, true);
  rule.setAllowInvalid(false).build();
  range.setDataValidation(rule);
}

/**
 * プルダウン連動をさせる列かどうかの判断
 */
function isTargetCol(e) {
  // 値が削除されたときはvalueが undefになるので無視
  if (!e.range.getValue()) return false; // ※1

  // 関係ないシートのとき
  if (e.source.getSheetName() !== USE_SHEET_NAME) return false;

  // 列が違うとき
  if (e.range.getColumn() != CATEGORY1_COL_NUM) return false;

  return true;
}
requireValueInList(values, showDropdown) 에 대해서는 공식 참조 참조.

※1 주의점


if (!e.range.getValue()) return false; // ※1

↑ 여기입니다만
if (!e.value) return false;

하고 싶어질거야! ?
하지만 이것이라면, 「붙여넣기」되었을 때에 undefined 가 됩니다.
(「사용하는 쪽의 시트」의 카테고리 1의 열에 「목관악기」라고 하는 캐릭터 라인을 copipe 해도, e.valueundefined입니다)

...라고 말하면서, 아래의 단점처럼 "코피페"에 대응할 수 없지만요.

장점


  • 아마 「입력 규칙」을 사용할 수 있는 사람은 많기 때문에, 카테고리 1의 입력 규칙만 설정할 수 있으면 나머지는 행 데이터가 아래로 증가해도 「행의 카피」로 늘릴 수 있다.
  • 「설정 시트」도 어렵지 않으므로 누구나 늘릴 수 있다. 행 데이터를 아래로 늘려도, 도중에 행을 삽입해도 OK.
  • GAS를 아는 사람에게는 스프레드시트 함수를 구사하는 것보다 알기 쉽다. (여기는 내 주관이지만)

  • 단점


  • GAS를 작성할 수 없으면 유지보수가 불가능합니다.
  • 작동이 느립니다. (onEidt에서 작동하기 때문에 작동이 완료되는 데 시간이 걸립니다.)
  • 「사용하는 쪽의 시트」의 「카테고리 1」의 열에 「코피페」했을 때에, 카테고리 2가 나오지 않는다. (★ 1)
  • 마찬가지로, 「B열의 복수행을 copipe」해도 카테고리 2가 나오지 않는다. (★ 2)

  • 개선 포인트


  • ★1은 붙여 넣은 것의 탐지를 확실히 할 수 있다, , 의일까. (지금 지금은 힘이 다했기 때문에 나중에 조사한다. 누군가 알고 있으면 가르쳐!)
  • ★2는 「편집된 복수 셀을 루프시켜 카테고리 2를 내는 처리를 넣는 것」으로 개선할 수 있을 것 같네요. 그래, 분명 할 수 있다.
  • 카테고리 2에 연동하는 카테고리 3도, ,, 할 수 있을 것 같네요!
  • 카테고리 1 설정 → 카테고리 2 설정 → 카테고리 1을 변경하면 카테고리 2가 남아 있습니다. (음, 스프레드 시트 기능으로 "경고"가 나오기 때문에 "뭔가 이상하다"는 것을 깨달을 것입니다.)

    ↓ 경고
  • 좋은 웹페이지 즐겨찾기