見出し画像

【チェックボックス1】一括 ON/OFF切り替えテクニック 【GASもあるでよ】

小ネタが幾つか溜まってるので、少しずつ記事にして放出していこうかなと。でも、いろいろ関連するネタを盛り込みたくなっちゃうから結局シリーズ化して小ネタじゃなくなる。。

雑談ばっかで面白いけど、授業が脱線しまくって本来やるべきことが終わらない先生みたいなw

今回はスプレッドシートで扱う チェックボックスネタです。



Googleスプレッドシートの チェックボックスを理解する

まず、Googleスプレッドシートにおける チェックボックスとはどのようなものか?という基本部分を理解しましょう。Excelとはかなり違います

メリット:チェックボックスは セルの入力規制の一つの型である
特徴:ExcelとGoogleスプレッドシートの チェックボックスは 互換性がない
デメリット:チェックボックスの制御は GASでやるしかない
デメリット:チェックボックス自体を消されるリスクがある



チェックボックスは 入力規制の 一つの型である

EXCELのチェックボックスと同じ感覚で使おうとすると、Googleスプレッドシートのチェックボックスは最初は違和感があります。

セルの上から被せて セルより上のレイヤーのオブジェクト扱いとなる Excelのチェックボックスに対して、Googleスプレッドシートのチェックボックスは セル内の値って扱いになります。

プルダウンと同じように、セルに対して データの入力規制で「チェックボックス」を選択することで、指定範囲のセルが チェックボックスになります。

チェック ON、チェックOFFは、基本は TRUE、FALSE という扱い。カスタムでこの値を変えることも可能です。

最初はEXCELとの勝手の違いに戸惑うかもしれませんが、このセルの値であるってのがEXCEL以上に便利だったりします。

セル扱いなんでセル範囲のコピーはもちろん、オートフィルで チェックボックスを容易に増やせますし、セル内の文字や背景と同じ感覚で色付けも簡単

表示形式で、TRUEFALSEチェックのあり・なし に見えているという理解がしっくりくるかも。

チェックあり、なしを 関数で利用する際も、そのままセル参照にすれば良いだけです。

GASで使う場合も onEditと組み合わせて実行ボタンとして利用できるし、処理のターゲットとする 行、列 を取得したい場合も、 変化のあったチェックボックスのセル位置を取得することで対象を指定できます。



ExcelとGoogleスプレッドシートの チェックボックスは 互換性がない

上記の通りGoogleスプレッドシートとEXCELのチェックボックスは、扱い(仕組み)がまったくの別モノです。当然、互換性もありません

チェックボックス入りの Excelを Googleドライブで開くと、チェックボックスは消えてしまいます。

一方、チェックボックス入りGoogleスプレッドシートをExcel形式でダウンロードして開くと、チェックボックス箇所は TRUE,FALSEといった 文字列に変換されています。

この部分はなんともなりません。諦めましょう。



チェックボックスの制御は GASでやるしかない

Googleスプレッドシートは警告出てもエンター突破できちゃうのが困る

Googleスプレッドシートの チェックボックスは 「データの入力規制」の一つであるため、残念ながら他の データの入力規制 が適用できません。

「データの入力規制」は、1つのセルに複数同時設定はできないのです。

例えば、「1つ目のチェックボックスにチェックが付いている時だけ、2つ目のチェックをつけられる」といった条件付けをしたくても無理です。

対応策として、上記のような「条件付き書式」を使って ある条件の時にチェックボックスを見た目上 消す(実際はセルの背景色と文字色を同じにして見えなくする)といった手もありますが、チェックボックス自体は存在するので マウスクリックしちゃうと画像のような警告が出ます。

当然、手動でチェックのON/OFFも出来つつ、ある条件の時だけ自動でチェックが入るとか、ラジオボタン(チェックボックスグループの中で 1つだけしか選択できない)といったことも、基本機能では対応できません

効力よわー

チェックボックス自体に「データの入力規制」が追加できないのなら、チェックボックスを関数で集計した他の計算セルにたいして 規制をかけたらどうか? と試してみても 画像のような結果です。

一応 セルに赤い注意マークが出て、マウスをあてれば「無効」とは出ていますが、チェック自体は制限できてないですし、ポップアップが出るわけでもありません。

国連決議くらい 効力がよわよわですw

チェックボックスを制御する為にはGASを使うしかないのです。



チェックボックス自体を消されるリスクがある

これが一番大きいデメリットかな。

意外とあるあるなのが、チェックボックス自体を Delete されちゃうってケース。これが結構困ります。

ユーザーに チェックの ON/OFF を許可するということは、ユーザーに 編集権限を与える必要があり、さらにそのセルを保護できないわけです。そうすると ユーザーの中には チェックを外す感覚でDeleteしちゃう人もいるんですよね。

残念ながら防止する為のよい方法はなく、これも GASで対応が必要です。

onOpenトリガー + insertCheckboxes で更新した(ページを開いた)ら 強制的に毎回復活させるとかですかね。


Googleスプレッドシートの チェックボックスの特徴、良い点、悪い点は理解できたでしょうか。



一括チェック ON/OFF を制御する2つの方法

「チェックボックスの制御はGASでやるしかない」と言いましたが、実は例外があって、この 一括 ON/OFFだけは 機能(キーボードショートカット)でサクッとできちゃったりします。

今回は

  1. 一括チェック ON/OFF をショートカットで実現する

  2. 一括チェック ON/OFF をGASで実現する

この2つを紹介しましょう。



1.一括チェック ON/OFF をショートカットで実現する

スペースキーで一括操作

いきなり答えですが、一括チェック ON/ OFF は スペースキーで出来ます。

全選択してから スペースキーを押すだけ。これだけで チェックあり・なし(ON/OFF)が切り替わります

挙動と注意点は以下の通り。
あくまでも チェックの反転ではなく、一括ON/OFFです。

■スペースキーによる チェックボックス制御
日本語入力はオフとなっている必要がある
・選択した範囲に チェックボックス以外が含まれていても影響ない
 ※チェックボックスにだけ作用する

選択した範囲にチェック OFF のチェックボックスがある?
→ YES  スペースキーで チェックON
→ NO  スペースキーで チェックOFF

この「範囲内の チェックボックスにだけ作用する」って点が便利ですね。

数式や文字、空白セルが選択範囲内にあっても、まったく影響を受けないので その点を気にせず 一括ON/OFFが出来るわけです。

さらに範囲選択の部分もショートカットで対応すれば、キーボード操作だけでさくっと 範囲を指定した 一括 ON/OFF出来ちゃいます。


Ctrl + A で範囲(リージョン)選択 → 全選択

範囲選択、全選択は ショートカット Ctrl + A で出来ます。

■ Ctrl+A による範囲選択
1回目 アクティブセルの範囲選択
2回目 全セル選択
※アクティブセルが 単独状態の場合は 1回目で全選択


リージョンを理解する

「範囲」という考え方は、少しわかりにくいので解説しておきましょう。

リージョンが4つある状態

ここで言う「範囲」は、GAS上では リージョン と呼ばれるもので、言葉の通り 独立した地域(区画)というイメージです。

上の画像だと A11の塗りつぶし以外の 4色エリアが、それぞれ4つの 範囲(リージョン)となっているのがわかります。

※起点が全て左上のケース。

基本的には何らかの値がセルに入力されたセルが隣接している塊がリージョンとなります。隣接は 縦・横のみです。斜めはダメ

2番目のケースですが、リージョンは四角形である必要があり、2番目のリージョンのように一部が欠けていても、そこを含めた四角形がリージョンとなります。

3番目のリージョンは A11という スペース5つが入ったセルが隣接していますが、スペースや 空文字("")が入ったセルは 隣接と見なさない特徴があります。

4番目(パープルリージョン)は、かなりわかりにくいので別図で説明します。

連鎖的に拡大するリージョン例

「た」(A12)を選択した状態、つまりA12を 起点として Ctrl + A した場合、①の「たちつてと」リージョンと 「な」(A15) が接していることで、②の「なにぬね」リージョンが 1つのリージョンになり、その際欠けている部分 ③もリージョンに加わります。さらに③に隣接している「の」セルもリージョンに含まれる為、その上下も含めた ④がリージョンも合わせて 一つのリージョン A12:D17(パープルリージョン) となっているわけです。

4連コンボ(ぷよぷよだと「ダイアキュート」)って感じですね。


リージョンは 起点によって変化する

面白い(難しい)のが、起点によって リージョンは変わってくるという点です。

先ほどのパープルリージョンは「た」A12を起点としたので、A12:A17がリージョンとなりました。

これがパープルリージョン内でも 「な」(A15)を起点として Ctrl + Aした場合は A15:B17がリージョンとなります。これは A15:B17が いずれの値の入ったセルにも隣接していない為、これ以上範囲が広がらないからです。

同じくパープルリージョン内の「の」(D16)を起点とした場合は、上下に値の入ったセルが無いので 、どのリージョンにも属さない単体セルという扱いになります。

ちなみに 単体セル(空白もしくはなにかしらの値が入っているセル)を選択した状態で Ctrl+A とした場合は、一発で全選択になります。


結合セルは一塊という扱い

ScreanToGifはキーボード操作を表示できるのをいまさら知った

結合セルの場合は、一つの塊として処理されます。

上記のように 本来入力されているのは 「は」(A22)であったとしても、A22:A25が結合セルで一塊になっているので、A26を起点とした場合にA22:A25が接しているという扱いになり、そこから連鎖的に「ひ」結合セル、「ふ」結合セル、「へ」結合セル がリージョンに加わり 最終的に A22:F29 が一つのリージョンという扱いになります。

これが何に使えるか?というと、以下のようなケースです。

見栄えの都合上、つまり 選択肢が連続していない、1行(または1列)空けてチェックボックスがある場合、本来はリージョンとしてはバラバラになってしまいます。

これらを なにかしらを入力した結合セルに接するようにすることで、一つのリージョンにすることが出来ます。

上の画像だと 質問1 は A3:A12の結合セルを使うことで A3:C12 の1つリージョンにしています。同様に質問2は E3:U3 の結合セルを使って E3:U4 を1つのリージョンにしています。

こうすることで 質問ごとに 一括ON/OFFの制御が可能となり、さらに次回以降で触れる「チェックボックスのラジオボタン化」でも 質問ごとにリージョンという単位で制御が出来るようになるのです。


スペースキー一括チェック ON/OFF 実践

実際の 例を見てみましょう。(結合セルは使わない事例です)

複数のチェックボックスがあって、以下のように各設問がリージョンになっている(繋がっていない)場合の動きをです。

すしちぇっく

■上記画像の操作の流れ

  1. チェックボックスを制御したいリージョン内の適当なセルを選択

  2. Ctrl + A  → その設問のリージョン全体がアクティブになる

  3. スペースキー → 全てチェックが入ってる状態なので 全OFF状態に

  4. そのまま再度 Ctrl + A → 全セルがアクティブに

  5. スペースキー → 一部チェックが外れているので、 全部ONに

  6. 再度スペースキー → 全ON状態なので、全部OFFに


このように、キーボードだけで特定の範囲のチェックボックスの ON/OFF、さらに シート全体のチェックボックス ON/OFF切り替えができました。

設問内の文字には影響がないこともわかりますね。
これならわざわざ GAS化する必要はないと思うんですが・・・。

自分がやる分にはいいけど、 ITリテラシー低めの 普段ショートカットってなに??というレベルの ユーザーにこれを使ってもらうには、手間とリスク(なんか不安)があるんですよね。

というわけで この動きをGAS化して、誰もがボタンで実行できるようにコーディングしてみましょう。



2.一括チェック ON/OFF をGASで実現する

とりあえず 要件は以下でやってみましょう。

■対象とする範囲
 選択されているセル(アクティブセル)が、
  あるリージョン内であれば、そのリージョン(DataRegion
  どのリージョンにも属さないセル シート全体(DataRange

■チェック挙動
 範囲内の チェックボックスで
  1つでもチェックOFFがあるなら 全チェックボックス ON
  全てのチェックボックスが ONなら 全チェックボックス OFF

で、コード書こうと色々検証してみたんですが・・・。

スペースキーを押した時の挙動が いまいちわからないw


チェックボックス制御で 使用するメソッド

一括チェックの ON、OFF は rangeクラスのメソッド checkuncheck で出来るってのはわかるんですが

■chek

■unchek

範囲に チェックの入ってないチェックボックスが存在するか否かという判定が難しい。。


isChecked で判定するのかと思ったら、範囲内に チェックボックス以外が含まれていても、チェックのON/OFFが混在していても、どちらも null を返すみたいで「チェックOFFがあるから nullなのか?」って判別が結構難しいです。

範囲内の個々のセルがチェックボックスであるか?を判定してから、 チェックボックスなら  isChecke でさらに判定して・・・って処理は出来なくはないけど、なんか面倒な処理だし本当にこんな挙動なのか??

とりあえず、isChecked は使わず、簡単そうな getValuesで 取得した値で 判定しちゃいましょう。(mirは すぐ楽な方に逃げる系です)



一括チェックボックス ON/OFFコード(簡易版)

ややチェック判定は やや甘めのコードになります。

function allcheck(){
  const sheet = SpreadsheetApp.getActiveSheet()

  //アクティブセルの所属するリージョンを取得
  let region = sheet.getActiveRange().getDataRegion();

  //リージョンのA1表記の範囲情報を取得
  const add = region.getA1Notation();

  //リージョンが複数セルなら A1:B2 といった形で ":" が含まれる。
  //含まれない = 単体セルの場合は DataRnage に差し替え
  region = add.includes(":")? region : sheet.getDataRange();

  //範囲の値を取得して 一次元配列に変換
  let values = region.getValues().flat();

  //値の一次元配列に false が1つでもあったら チェックON、1つもなければ チェックOFF
  values.some(value => value === false) ? region.check() : region.uncheck(); 
}

コード自体は結構短いし、丁寧めにコメント入れたんで上記でわかりますかね?

選択しているセルの 範囲(リージョン)を取得するのが getDataRegion メソッドです。

getA1Notation で セル範囲をA1表記で取得した 文字列に対して、":" を含んでいるか否かで セルが単体か リージョンかを判別しています。

":"が含まれるか? という部分は 含まれる・含まれないで true,falase が返る includes が適切でしょう。


ここまでが範囲の定義部分。
その下 let values 以下が チェック状態の確認です。

まず、getValues で取得した 範囲内の値の二次元配列を 一気に処理できるように flat で一次元配列化。

その配列から 一つずつ値を取り出し  Boolean型 の false か?を  === (厳密な一致)で 確認し、false が一つでもあれば check、 falseが一つもなければ uncheck という処理をしています。

「 配列内に1つでもあれば」 という判定は someを使っています。

GAS部分は 興味ない人、苦手な人は なんとなく理解できればOK。


チェックボックス 一括 ON/OFFボタンで 動きを確認

ボタンにスクリプトを割り当てて動きを確認してみましょう。

重要なのは、ボタンを押す際のアクティブ(選択している)セルと対象範囲のチェック状態です

■対象とする範囲
 選択されているセル(アクティブセル)が、
  あるリージョン内であれば、そのリージョン(DataRegion
  どのリージョンにも属さないセル シート全体(DataRange

■チェック挙動
 範囲内の チェックボックスで
  1つでもチェックOFFがあるなら 全チェックボックス ON
  全てのチェックボックスが ONなら 全チェックボックス OFF

この要件の動きになってますね。

細かいことを言えば、シート全体 と DataRange別モノですが、チェックボックスが存在するセルは DataRangeに確実に含まれるので、ここは気にしなくてもよいでしょう。

ただ、全チェック ON/OFFどちらを実施するか? という判定部分は、上記では 問題なく動いていますが、処理としては FALSE 一致で判定しているので、

  • チェックボックスにカスタム セル値 が使われているケース

  • シート内に FALSE と直接入力された セルが含まれるケース

では、正しく動きません。

カスタムセル値のチェックボックスは getValues で値を取得しても TRUEやFALSE ではないので、チェックOFFが存在しても FALSE は一つもない という判定になってしまいます。

何度ボタンを押しても uncheck を繰り返すだけで、全チェック ONが作動しません。

FALSEとか置くなよと

同じく チェックボックスではない FALSE が 範囲内のセルに含まれる場合は、毎回 FALSEが存在する という判定になり、 しかも このFALSEはチェックボックスではないので、checkメソッドで切り替わりません

ボタンを押しても ひたすら checkを実行してしまい、全チェック OFFが一向に作動しません。

どちらも例外的なケースなので普通に利用するには問題ないと思いますが、スペースを使ったショートカットによる 一括 ON/OFFだと 上記のケースでも問題なく作動する ので、やっぱ 微妙ですね。

今回のコードは スペースキーによる 一括 ON/OFF の劣化コピーだと思ってくださいw



うーん、これで次に行こうかと思いましたが、なんか劣化版ってのが気に入らんですね。例外的なケースとは言え、正しく動かないってのも不安があるし。。

やっぱり 面倒だけど、ちゃんと チェックボックスとしてチェック状態を判定して一括処理するコードも書きましょう。

mir動きますw
(そんなたいしたことではない)

というわけで、来週の更新、スペースキー一括チェック ON/OFF GAS化 完全版(たぶん)まで 震えて眠れ!



■このシリーズの次の記事


この記事が気に入ったらサポートをしてみませんか?