Translate

2021年1月31日

カクレクマノミとハタゴイソギンチャクの長期飼育

カクレクマノミとハタゴイソギンチャク

上写真のカクレクマノミのペアは、象と散歩: カクレクマノミの飼育は簡単? の中で2013年春に購入と書いているので、飼育開始から8年近くになります。ADW: Amphiprion ocellaris: INFORMATION によると自然下での平均寿命は、6-10年とあります。しかし、飼育下では20年というの記事もありますので、まだまだ長生きしてもらいたいです。

一方、ハタゴイソギンチャクの平均寿命については、Stichodactyla gigantea - Wikipedia に3-5年とありますが、こちらも同じく8年を迎えようとしています。水槽の掃除のときに手を刺されるとちょっと痛いですが、長く飼育しているとイソギンチャクにも愛着が湧いてきます。

しかし、愛着とは裏腹に飼育開始の頃と比べると、飼育方法はだいぶ手抜きとなりました。逆に言えばこれがカクレクマノミとイソギンチャクに必要最小限な機器と飼育ではないかと思っています。


カクレクマノミとハタゴイソギンチャクに必要なもの

過去のブログでは、カクレクマノミとハタゴイソギンチャクの共生には下記の4つが必要だと記載しています。これはより飼育が難しいハタゴイソギンチャクの生態に合わせて飼育環境を考えてのことでした。

  1. 光(LEDスポットライト)
  2. 水質(ろ過装置&プロテインスキマー)
  3. 水温(ヒーター)
  4. 水流(小型ポンプ)

しかし、下の写真のように4番目の水流(小型ポンプ)は、現在は使っていません。またヒーターは真冬のみ利用しています。

必要なアクアリウム器具

水流は不要?

ハタゴイソギンチャクは浅瀬に生息するイソギンチャクなので波(水流)が必要ではないかということで、小型ポンプを使って水流を作っていましたが、小型ポンプのモーターが故障をして使用を止めましたが、ハタゴイソギンチャクに大きな変化はありません。

小型ポンプで発生させる水流は、自然の波と比べるとあまりにも貧弱で意味がなかったようです、、、、。


水温は25℃が最適?

リビングで飼育しているので冬でも水温があまり下がらないということもあり、冬の寒い時期(12月中旬から3月上旬頃)だけヒーターを使っています。

ヒーターの設定温度は20℃です。夏は水温が30℃になるので、20-30℃の中での飼育です。カクレクマノミもハタゴイソギンチャクも水温の変化に思った以上に強いですし、低温にも適応します。しかし、個体差もあると思いますので水温と生体の様子を観察しながらヒーターを使ってください。

カクレクマノミが、日中でもイソギンチャクの中に身を潜めて、じっとしていているのであれば水温を上げましょう。ハタゴイソギンチャクは水温が下がると小さくなりますが、この冬の時期に水温を下げていることで大きくなるハタゴイソギンチャクの成長を抑制できているのかもしれません。

この冬は、ずっと家にいるので部屋が暖かく、リビングに設置している水槽の水温も下がりません。水温計で確認すると18−19℃なのでヒーターをまだ使っていません。カクレクマノミも元気に餌を欲しがって上がってくるので、今の冬はヒーターなしで飼育できそうです。


天然海水とプロテインスキマー

以前、ハタゴイソギンチャクに元気がなくなってしまったときに、天然海水がいいと聞き、釣りに行ったときにポリタンクに汲んできた海水を水槽に入れると徐々に元気になりました。それ以来、人口海水ではなく天然海水を使っています。

水換えは積極的にはしていません。プロテインスキマーのタンクに溜まった分の海水を補給して、蒸発した水は、浄水器の水を足しています。海水も臭くはないのでろ過装置とプロテインスキマーで水質は維持できているようです。時折、水槽のガラス面をメラミンスポンジで汚れを落としていますが、その時に網でかき回して大きなゴミは網ですくい、残りはプロテインスキマーに任せています。

以前は、ハイドロメーターで塩分濃度を確認し、試験紙で水質をチェックしていましたが、今や海水や浄水の水も目分量ですし、水質チェックはまるきっりしていません。あまり神経質にならなくてもカクレクマノミもハタゴイソギンチャクも元気です。


長期飼育からわかった共生飼育の重要な要素

ということで、カクレクマノミとハタゴイソギンチャクの長期共生飼育には、

  • 光合成のための光
  • 適当な水質

を年間を通して維持し、寒くなったらヒーターで水温を上げればいいというのが結論です。

機材的には

  • LEDスポットライト(光合成)
  • エーハイム アクアコンパクト(水質維持)
  • マメデザイン マメスキマー3(水質維持)

という3種の神器と必要に応じてヒーターです。


LEDスポットライト(光合成)

象と散歩: 初心者のイソギンチャクとカクレクマノミの共生飼育 で、カクレクマノミ と共生するイソギンチャクについて書いていますが、ハタゴイソギンチャク、センジュイソギンチャクなど褐色の ”褐虫藻” で光合成をして栄養を得るイソギンチャクには光が必要です。

水槽でこの褐虫藻が光合成するためには、青色LEDスポットライトが最適です。

なぜ青色LEDスポットライトが最適かと言えば、象と散歩: イソギンチャクの飼育には青色LEDスポットライト からの再掲となりますが、

  • 光合成に必要な波長は400nm-500nm(青色)と600nm-700nm(赤色)
  • 海中では赤色光は吸収されてしまう
  • 褐虫藻には青色の光を吸収する光合成補助色素のペリジニンがある
  • 海中の褐虫藻が光合成を行うには青色以外の光は不要
  • 高輝度青色LEDは効率的に青色のみ発光できる
  • 光合成光量子束密度を高めるため光を分散させないスポットライト型

という理由からです。イソギンチャクの飼育に青色LEDより効率的なアクアリムライトはありません。

イソギンチャクの飼育に何度か失敗したあとに「アクシーファインスポット LED 20W ブルー」に辿り着きましたが、青の世界はイソギンチャクには快適な環境だったようです。その後、象と散歩: ハタゴイソギンチャクとカクレクマノミの共生は紫色の世界で大丈夫? で書いた青8赤2白2灯に、そして、現在は、青8赤4灯へと変遷しています。

水槽照明 アクアリウムライト 24W 青8 赤4灯

2代目から46z8(よろずや)が扱っている、お財布に優しいLEDスポットライトにしましたが、残念ながら、青8赤2白2灯は8ヶ月間と短命でした、、、。

46z8(よろずや)で扱っている青色系LEDスポットライトは合計LEDランプ12個で24Wです。青色だけで考えるとLEDライト8個で16Wと、最初に購入した「アクシーファインスポット LED 20W ブルー」より青色の光が弱くなっています。それでもハタゴイソギンチャクは成長を続けているのと、観賞という観点ではブルーよりも紫色の世界の方がカクレクマノミも綺麗に見えるので良しとしています。

青色を中心とするのであれば、こちらです。

メインビジュアルの写真のように紫の世界であれば、青8灯、赤4灯となります。

46z8(よろずや)では上記以外にも、

があります。

LEDスポットライトとして水槽の淵にかけて固定する「AXY FINE SPOT」を使っています。

アームでスポットライトを当てる位置を動かせるのでハタゴイソギンチャクが移動してしまった場合にも追っかけることができます。

またライトの点灯/消灯にアナログ式のプログラムタイマーを使っていましたが、現在は、スマート家電化の一環として購入したスマートプラグに変えました。

スマートプラグでアクアリウムライトをコントロール

アナログ式のタイマーでは「ジジジジ」という時を刻む音がしていましたが、スマートプラグにしてから無音となりました(笑。また時間にも正確です。現在は、8:30点灯、20:00消灯と設定していますが Amazon Echoで、

Alexa, 水槽のライトを点けて/消して

と音声で点灯/消灯のコントロールもできます。

EchoがなくてもスマホとWiFi環境があればスマートプラグは使えます。


エーハイムアクアコンパクト(水質維持)

餌やカクレクマノミ の排出物により小さな海水の世界では分解能力が少ないので ”ろ過装置” は必須です。

エーハイム アクアコンパクトは、"物理ろ過"、"生物ろ過"、"吸着ろ過(活性炭フィルター)" の3種類が組み合わさったコンパクトな外部フィルターです。ポンプ部も水槽にかけるだけなのでセッティングも簡単で初心者向けです。アクアコンパクトには2004と2005の二種類があります。2005の方5cm背が高く、その分、ろ材を多く入れられますが、30cm水槽であれば2004で十分です。

アクアコンパクト 2004 2005
ろ過槽容量 1.0ℓ 1.5ℓ
ろ材容量 0.8ℓ 1.3ℓ
本体寸法 128×(H)191mm 128×(H)241mm

ろ過装置のモーターは6万時間以上連続稼働していますが、異音も故障もなく動作し続けています。しかし、水槽に水を供給するノズルは塩が付着して取れなくなってしまいましたので、見た目からそろそろ替え時かもしれません。

アクアコンパクト2004

生物ろ材

バクテリを繁殖させるために細かい穴がたくさんある多孔質ろ材が使われています。バクテリアの働きにより有害物質を無害化します。エーハイム 純正ろ材の ”エーハイム サブストラット プロ レギュラー” を使っています。掃除は結構な大仕事になるので年に2回、フィルターを交換するタイミングで水で濯ぎ洗いしています。ろ材は7年間で数回しか交換していません、、、。


物理ろ過

エーハイム アクアコンパクト 2004/2005用フィルターパッドセットは、下記のセットとなっています。

  • 細目フィルターパッドx3(1ヶ月毎に交換)
  • 粗目フィルターパッドx1(2〜3回の洗浄、若しくは6ヶ月)
  • ストレーナー用スポンジフィルターx1(2〜3回の洗浄、若しくは6ヶ月)

純正品として販売されているのに交換時期の目安とセットの枚数が異なるのが疑問ですが、ろ過装置を開いて掃除をするのは面倒です。なので、細目フィルターを4ヶ月毎に交換して、その時に粗目フィルターと多孔質ろ材も洗浄しています。粗目フィルターとストレーナー用スポンジフィルターは年に1回の交換です。これでセットの枚数とも合致します。


吸着ろ過

アクアコンパクトは別売の活性炭フィルターパッドが使えます。「活性炭の力によってにごり、悪臭を吸着して水を透明にします。」とあり、最初の頃は使っていましたが、水の匂いも気にならないのでいまは使っていません。


マメデザイン マメスキマー3(水質維持)

象と散歩: ハタゴイソギンチャクの飼育にはプロテインスキマーが必要? でプロテインスキマーについて記載していますが、プロテインスキマーは、泡を発生させてタンパク質の汚れが泡に吸着させて水質を維持するための装置です。

エアレーションでカクレクマノミ、ハタゴイソギンチャクといった生物だけではなく、ろ過装置の生物ろ過をするバクテリアに酸素供給をする効果もあります。

マメデザイン マメスキマー3

"マメデザイン マメスキマー3” は、細いガラス管の中のウッドストーンにエアポンプで空気を送り細かい泡を発生させて泡の力で浮き上がったゴミと海水を外に置いた容器に貯めて行きます。デザインもシンプルで小型水槽にピッタリです。

エアーポンプには "アデックス エアーポンプ X101” を使っています。

アデックス エアーポンプ X101

ウッドストーンは消耗品で、定期的な交換が必要です。

マメデザイン ウッドストーン

プロテインスキマーは、イソギンチャク飼育の水質維持には必須です。


ガラス管を割ってしまった、、、

掃除をしているときにマメスキマー3のガラス管を割ってしまいました。「結構な出費に、、、」とショックを受けましたが、交換部品としてガラス管本体だけで販売されていました。

それでも痛い出費でした。

マメスキマー 交換部品 ガラス菅本体

飼育をこれから始めるなら

水槽、底砂、ライブロックなどについては、象と散歩: カクレクマノミの飼育は簡単? を参考にしてみてください。

イソギンチャクは同時に購入せずにカクレクマノミ が定着してから購入しましょう。アクアリウム店に行かなくてもネットで共に購入できます。ネットで生き物を購入することには躊躇いもありましたが、charm 楽天市場店 で購入したカクレクマノミとハタゴイソギンチャクが長生きしています。カクレクマノミはなるべく成長した4cm以上の個体を選びましょう。

カクレクマノミとハタゴイソギンチャク

自宅で過ごすことが多くなったいまアクアリムを始めるいいチャンスです。

ハードルが高いと言われる海水熱帯魚のカクレクマノミとハタゴイソギンチャクもちょっとしたコツで長く飼育することができます。

2021年1月16日

GASでGoogleフォームの値を取得する(フォームを指定)

ゾウでもわかる Google Apps Script

Googleフォームでの回答内容をGAS(Google Apps Script)で参照する方法です。

Googleフォームの値を取得するには2種類の方法があります。

  1. フォームが実行されたときに値を取得
  2. フォームを指定して回答内容を取得

今回は、「フォームを指定して回答内容を取得」する方法についての説明です。


フォームオブジェクトの取得

フォームオブジェクトを取得する方法には2つあります。


アクティブなフォームを開く

フォームからスクリプトエディタを開いてスクリプトを作成する場合には、アクティブなフォームが取得できます。

変数 = FormApp.getActiveForm()

フォームID/フォームURLを指定してフォームを開く

もうひとつが、フォームIDかフォームURLを指定する方法です。

変数 = FormApp.openBy(フォームID)
変数 = FormApp.openByUrl(フォームURL)

フォームの編集URLが下記の場合にフォームIDは、赤字の部分となります。

https://docs.google.com/forms/d/1234567890abcdefghijklmnopqrstuvwxyz/edit

実際のコードでは下記のように書きます。

function formObject() {
  //フォームID
  var formId = '1234567890abcdefghijklmnopqrstuvwxyz'

  //フォームオブジェクトの取得
  var form = FormApp.openById(formId)
}

フォームURLは、青字の部分で、最後のスラッシュは必要です。

https://docs.google.com/forms/d/1234567890abcdefghijklmnopqrstuvwxyz/edit

URLを指定した場合のサンプルコードです。

function formObject() {
  //フォームURL
  var formUrl    = 'https://docs.google.com/forms/d/1234567890abcdefghijklmnopqrstuvwxyz/'

  //フォームオブジェクトの取得
  var form  = FormApp.openByUrl(formUrl)
}

フォームの回答を取得する

フォームの回答を取得するには3段階の手順が必要です。

  1. フォームの全回答を取得
  2. ひとつの回答を選択
  3. 質問と回答内容を取得

フォームの全回答を取得

上で取得したフォームオブジェクトを指定して全回答を取得します。取得した回答は配列([1件目の回答, 2件目の回答, 3件目の回答, .....])となっているので回答数はlengthでわかります。

※ 実行する際には、var formId = 'フォームID' のフォームIDの部分を書き換えてください。

function formObject() {
  //フォームID
  var formId = '1234567890abcdefghijklmnopqrstuvwxyz'

  //フォームオブジェクトの取得
  var form = FormApp.openById(formId)
  
  //全回答の取得
  var formResponses = form.getResponses()
  
  //全回答数
  Logger.log('回答数 = ' + formResponses.length)
}

現在の回答数が3件であることがわかります。

回答数 = 3

ひとつの回答を選択

上のサンプルコードで全回答を取得した変数formResponsesは配列になっています。いま3件の回答があるので下記のようにして各々を取得できます。

  • formResponses[0] ・・・ 1件目の回答
  • formResponses[1] ・・・ 2件目の回答
  • formResponses[2] ・・・ 3件目の回答

そして、getItemResponses()で回答内容が取得できます。

変数 = formResponses[n番目].getItemResponses()

取得した回答内容にいくつの質問があるのかは、lengthで求められます。サンプルで使用しているフォームの質問は「日付」「時刻」「氏名」と3つです。

Google Sheets(フォーム回答内容)

結果が3となるかを確認します。

function formObject() {
  //フォームID
  var formId = '1234567890abcdefghijklmnopqrstuvwxyz'

  //フォームオブジェクトの取得
  var form = FormApp.openById(formId)
  
  //全回答の取得
  var formResponses = form.getResponses()
  
  //1件目の回答を取得
  var itemResponses = formResponses[0].formResponse.getItemResponses()

  //質問件数
  Logger.log('質問項目数 = ' + itemResponses.length)
}

質問項目数 = 3

質問と回答内容を取得

これでやっと回答内容を取得する準備が整いました。

フォームの質問を取得するには

変数 = n番目の項目.getItem().getTitle()

フォームの回答を取得するには

変数 = n番目の項目.getResponse()

で、取得できます。

下記のコードでで1件目の回答の1つ目の質問と回答内容が取得できます。

function formObject() {
  //フォームID
  var formId = '1234567890abcdefghijklmnopqrstuvwxyz'

  //フォームオブジェクトの取得
  var form = FormApp.openById(formId)
  
  //全回答の取得
  var formResponses = form.getResponses()
  
  //1件目の回答を取得
  var itemResponses = formResponses[0].getItemResponses()
  
  //1件目の回答の1つ目の質問と回答を取得
  var title = itemResponses[0].getItem().getTitle()
  var response = itemResponses[0].getResponse()

  Logger.log('質問内容 = ' + title)
  Logger.log('回答内容 = ' + response)
} 

質問内容 = 日付
回答内容 = 2021-01-10

全回答内容の取得

回答数、質問数はlengthで求められるので、全回答内容を表示するサンプルです。

function formObject() {
  //フォームID
  var formId = '1234567890abcdefghijklmnopqrstuvwxyz'

  //フォームオブジェクトの取得
  var form = FormApp.openById(formId)
  
  //全回答の取得
  var formResponses = form.getResponses()
  
  //i件目の回答を取得
  for (var i = 0; i < formResponses.length; i++)  {
    //回答を格納する配列
    var arr = []
    //i件の回答を取得
    var itemResponses = formResponses[i].getItemResponses()

    for (var j = 0; j < itemResponses.length; j++)  {
      //i件目の回答のj番目の質問と回答を取得
      var title = itemResponses[j].getItem().getTitle()
      var response = itemResponses[j].getResponse()
      arr[j] = '【' + title + '】 ' + response
    }
    Logger.log(i+1 + '件目の回答 = ' + arr)
  }
}

1件目の回答 = 【日付】 2021-01-10,【時刻】 10:10,【氏名】 象と散歩
2件目の回答 = 【日付】 2021-01-11,【時刻】 11:11,【氏名】 キリンと散歩
3件目の回答 = 【日付】 2021-01-12,【時刻】 12:12,【氏名】 イルカと散歩

フォームから回答内容が一致するものを探す

formの回答内容検索して回答内容が一致するものを探すサンプルプログラムとなります。(2022/6/19追記)

一致させる内容については、サンプルを簡単にするために変数としています。

    一致条件
  • 質問内容='氏名'
  • 回答内容='象と散歩'

変数で指定した条件と一致する回答があれば、質問内容と回答内容を出力して、一致するものがなければ '一致なし' と出力します。

複数一致するものがあれば複数回出力されます。

function formObject() {
  //一致条件
  var questionTitle = '氏名'
  var costomerName ='キリンと散歩'

  //フォームID
  var formId = '1234567890abcdefghijklmnopqrstuvwxyz'

  //フォームオブジェクトの取得
  var form = FormApp.openById(formId)
  
  //全回答の取得
  var formResponses = form.getResponses()

  var ans = 0 //一致する回答を見つけた場合に1にする 
  for (var i = 0; i < formResponses.length; i++)  {
    //i件目の回答を取得
    var itemResponses = formResponses[i].getItemResponses()

    for (var j = 0; j < itemResponses.length; j++)  {
      //i件目の回答のj個目の質問と回答を取得
      var title = itemResponses[j].getItem().getTitle()
      var response = itemResponses[j].getResponse()

     //質問項目が questionTitle で 回答内容が costomerName かを確認
      if (title == questionTitle && response == customerName) {
        Logger.log('質問内容 = ' + title)
        Logger.log('回答内容 = ' + response)
        ans = 1
      }
    }
  }
  if (ans == 0) {
    Logger.log('一致なし')
  }
}

タイムスタンプを指定して回答を取得

getResponses(タイプスタンプ)でタイムスタンプが一致するフォームの回答を取得できます。

以下の例は、シートのタイプスタンプ(A列)と一致する回答編集用のURLを取得してシートのE列に書き込む例です。シートIDはフォームIDと同様に取得して変更してください。

function formObject() {
  //フォームID
  var formId = '1234567890abcdefghijklmnopqrstuvwxyz'
  //シートID
  var sheetId = 'abcdefghijklmnopqrstuvwxyz1234567890'
  //シート名
  var sheetName = 'フォームの回答 1'
 
  //フォームオブジェクトの取得
  var form = FormApp.openById(formId)
  var formResponses = form.getResponses()

  //シートオブジェクトの取得
  var sheet = SpreadsheetApp.openById(sheetId).getSheetByName(sheetName)
  var lastRow = sheet.getLastRow() // 最終行の取得

  //シートの2行目から最終行までを処理
  for (var i =2; i <= lastRow; i++)  {
    //A列からタイムスタンプを取得
    var timeStamp = sheet.getRange('A' + i).getValue()
  
    //タイムスタンプが一致するフォームの回答を取得
    var formResponses = form.getResponses(timeStamp)
    //編集用URLの取得
    var editUrl = formResponses[0].getEditResponseUrl()

    //編集用URLをハイパーリンク形式に
    var strEditUrl = '=HYPERLINK("' + editUrl + '","編集用URL")'

    //編集用URLをE列に書き込む
    sheet.getRange('E' + i).setValue(strEditUrl)
  }
}

シートのA列にあるタイムスタンプを取得して変数timeStampに格納して、タイムスタンプが一致する回答を取得しているのがこの部分です。

var formResponses = form.getResponses(timeStamp)

タイムスタンプが一致した回答は配列の0番目に格納されています。getEditResponseUrl()で編集用URLが取得できます。

var editUrl = formResponses[0].getEditResponseUrl()

タイムスタンプはミリ秒まであるので通常は問題ないと思いますが、タイムスタンプが一致する回答が複数あった場合の挙動はわかりません。

シートが下記のように更新されます。回答編集用URLは長いのでハイパーリンクにしました。

Google Sheets(回答編集URLを追加)

GASの基礎を学べる参考図書

ある程度プログラミンがわかっていれば、WEBやYoutubeでも十分に調べられると思いますが、初歩的なところからであれば参考図書は有効な学習手段です。

詳解! Google Apps Script完全入門 [第3版]」は、プラグラミング初心者にわかりやすく説明されています。GASを最初に学ぶ一冊として良書です。

2021年1月11日

GASでGoogleフォームの値を取得する(トリガー編)

ゾウでもわかる Google Apps Script

Googleフォームでの回答内容をGAS(Google Apps Script)で参照する方法です。

Googleフォームの値を取得するには2種類の方法があります。

  1. フォームが実行されたときに値を取得
  2. フォームを指定して回答内容を取得

今回は、「フォームが実行されたときに値を取得」についての説明です。


Googleフォーム実行時に値を取得

Apps Scriptはトリガーを設定することができるのでフォームが送信されたときに実行することができます。

スクリプトは、フォームから直接か、

GoogleフォームでGoogle Scriptを書く

回答先のシートから記述します。

 GoogleシートでGoogle Scriptを書く

トリガーの設定

トリガーの設定は、スクリプトの左側にあるメニューの時計のアイコンからです。

スクリプトからトリガーを設定

下例では、後述するサンプルプログラムの getFormValue を選択しています。イベントの種類は「フォーム送信時」を選んでください。

トリガーの設定 

function(e)とは?

フォーム送信時のトリガーで関数が実行されると、フォームの回答内容が関数の()内に指定した引数に渡されます。

function(e) のように引数をeとしている例が多いですが、これはイベントオブジェクトの表記に基づいているからだと思いますが、別に引数は e でなくても問題ありません。


連想配列で取得する(namedValues)

namedValue を使うと {キー:} という形でデータを取得できます。pythonではディクショナリー(辞書型)と呼ばれている配列です。

実際のデータで説明するのがわかりやすいと思います。

① 下記のフォームで送信します

サンプル フォーム

② トリガーでフォーム送信時に getFormValue を実行するように設定

getFormValue関数には、下記のコードを記載します。

namedValues でキーに質問名、値に回答内容を連想配列として取得したものをログに出力します。

function getFormValue(e) {
  console.log(e.namedValues)
}

フォームの質問項目は、日付、時刻、氏名ですが、namedValues で取得すると、時刻、氏名、日付の順番となっています。タイムスタンプは、回答を送信したときの時間です。

{ '時刻': [ '11:11:00' ],
  '氏名': [ 'キリンと散歩' ],
  '日付': [ '2021/01/11' ],
  'タイムスタンプ': [ '2021/01/10 12:25:19' ] }

質問名で値を取得する

namedValues['質問名'][0]

で、質問の回答を取得できます。[0]は、質問名の0番目(最初)の値を意味しますが、値がひとつしかないので省略可能です。

下記のコードで、質問名が氏名の内容を出力します。

function getFormValue(e) {
  var name = e.namedValues['氏名'][0]
  console.log('氏名 = ' + name)
}

氏名 = キリンと散歩

一次元配列として取得する(values)

values を使うと一次元配列で取得できます。

function getFormValue(e) {
  console.log(e.values)
}

こちらはフォームの順番に従っています。

[ '2021/01/10 12:25:19', '2021/01/11', '11:11:00', 'キリンと散歩' ]

namedValuesでのサンプルコードと同じく氏名の値を取得するのであれば、4番目の項目となるのでvalues[3]とします。

※配列は0からの指定なので、上記のデータであれば

  • values[0]    タイムスタンプ
  • values[1]    日付
  • values[2]    時刻
  • values[3]    氏名

となります。

function getFormValue(e) {
  var name = e.values[3]
  console.log('氏名 = ' + name)
}

氏名 = キリンと散歩

通常の配列なので、lengthを使ってforループで回して全ての項目を出力することも可能です。

function getFormValue(e) {
  for (var i = 0; i < e.values.length; i++)  {
    console.log(e.values[i])
  }
}

2021/01/10 12:25:19
2021/01/11
11:11:00
キリンと散歩

分割代入で変数にフォーム値を代入

分割代入を使うと配列から値を取り出して個別の変数に代入することが可能です。

function getFormValue(e) {
  var [timeStamp, date, time, name] = e.values
  console.log(name)
}

キリンと散歩

実行する上での注意事項

フォームの値を取得する関数は、スクリプトエディタからは実行できません。

トリガー起動関数を手動で実行する

getFormValueをスクリプトから実行すると、eの引数に何も渡されていないので、e.namedValues で 'namedValues' of undefined とエラーとなります。


「送信後に編集」は変更項目のみ取得可能

フォームの設定で「送信後に編集」をオンにしておくと、回答者は回答を編集をすることができます。

回答を編集して送信された場合は、変更された内容しか取得できません。何も回答を変更せずに送信されると取得できる項目はタイムスタンプだけとなります。

function getFormValue(e) {
  console.log(e.namedValues)
  console.log(e.values)
}

{ '氏名': [ '' ],
  'タイムスタンプ': [ '2021/01/10 12:50:40' ],
  '時刻': [ '' ],
  '日付': [ '' ] }

[ '2021/01/10 12:50:40', '', '', '' ]

GASの基礎を学べる参考図書

ある程度プログラミンがわかっていれば、WEBやYoutubeでも十分に調べられると思いますが、初歩的なところからであれば参考図書は有効な学習手段です。

詳解! Google Apps Script完全入門 [第3版]」は、プラグラミング初心者にわかりやすく説明されています。GASを最初に学ぶ一冊として良書です。

2021年1月9日

掃除の基本は「掃いて」「拭く」(吾妻箒)

手編み箒 アズマ 匠125 匠箒 短柄

Amazonの初売りでアズマ工業の 匠125 匠箒 短柄 が特選タイムセールになっていたので、思わずポチリと。

年末に、

『US103 床を優しく掃けるほうきS』も、まだまだ現役として頑張れそうなので、くたびれてきたら次を考えたいと思います。

【引用】象と散歩: 掃除の基本は「掃いて」「拭く」(ホーキ編)

と書いたばかりでしたが、物欲には勝てませんでした。

匠125 匠箒 短柄 は、最初の1本としてお勧めした「短柄 手編みホーキ 匠」よりワンランク上の商品ですが、特選セールで 短柄 手編みホーキ 匠 よりも安くなっていました。


カーバー箒と手編み箒を比べてみる

下写真の左が以前から使っていたカバー箒「US103床を優しく掃けるほうきS」、右が新しく購入した手編み箒「匠125 匠箒 短柄」です。

カバー箒(左)と手編み箒(右)

写真からもわかるように明らかに違うのは穂の量です。

穂幅の4cmの差よりも、厚さ2cmの差で穂の量に大きな差があります。手編みという特性上、全体的に穂の量が多く、その分、重さでも130gの違いがあります。

 
床を優しく掃ける
ほうきS
匠125 匠箒 短柄
長さ 77cm 82cm
穂幅 29cm 33cm
厚さ 3cm 5cm
重量 270g 400g
通常価格 1,560 円
1,880円
3,750 円
5,280円

手編みの美しさ

アズマ工業の「匠125 匠箒」は、タイで生産されています。手編み箒という日本の伝統文化が、タイの職人によって脈々と引き継がれています。

タイの箒職人による編み上げは、丁寧でしっかりしていています。

この素晴らしい技術を日本でも絶やさないようにしてもらいたいと願う次第です。

TRADITIONAL CORN BROOM – Libman.com をみると、米国でもBroomcorn(ホウキモロコシ)の箒が伝統的な箒とあります。和のデザインとコシとしなやかさを持つ高品質のホウキモロコシを使った長柄箒であれば、エコやSDGsといった観点からも欧米でも室内掃除用具として受け入れらるのではないでしょうか。


掃き心地の違い

130gは、片手での掃き掃除では結構感じる重さです。アズマ工業が、カバー箒を作った理由のひとつが「軽い箒」というのが頷けます。

その重さの違いから、カバー箒では「サッ、サッ、サッ、サッ」というテンポで掃いていましたが、手編み箒では「サーッ、、、サーッ」とゆっくりとなります。

穂の量が多い分、1回で掃き出せる量も多いですが、掃くペースが異なるのでトータル的には同じように思えます。しかし、カーペットなど敷物の上を掃くときには、穂の密度が高い分、隙間に入り込んでいる細かいゴミをしっかりと掃き出してくれます。

総合的に考えると、手軽さではカバー箒、丁寧な掃除では、手編みに軍配が上がります。


座敷箒の使い方

座敷箒は、フローリング、畳、絨毯(じゅうたん)、カーペットと、どこにでも使えます。

力を入れずに穂先を立てて優しく掃くことで、座敷箒の「しなやかさ」を生かすことができ、埃やゴミをしっかり捉えます。柄を軽く持つと力を入れずに掃けます。

  • 柄を軽く持つ
  • 穂を立てる
  • 力を入れずに優しく掃く

この3つが座敷箒を使った掃き掃除の基本です。

あとは、フローリングや畳の目に沿って掃き掃除をしていきます。


サスティナブルな座敷箒

説明書きに「箒は正しく扱っていただく事で、何十年もの間使い続けることができます。どうぞ大切にご使用ください。」とあります。

「手編み箒ってそんなに長持ちするの?」と驚きですが、正しく扱うのひとつに収納があります。

穂先が床に着いてた状態で収納していると穂先に癖がついてしまうので、吊り下げて収納します。また穂先に癖がついてしまったときには、穂全体を水(ぬるま湯)に浸して形を整えて乾かせば再生します(カバー箒で実践済み)。

手編み箒は、大切に使おうという気持ちにさせてくれますし、長く使っていれば愛着も湧いてきそうです。


シールはドライヤーで剥がす

匠125は、Amazonの製品紹介の写真にあるように柄の部分に緑色のシールが貼られています。そんなに自己アピールしなくてもと剥がそうとしましたが、粘着力が強いシールで、手ではキレイに剥がせそうにありません。

アズマ 匠125 匠箒 短柄
アズマ 匠125 匠箒 短柄(Amazon)

ドライヤーを使うとキレイに剥がれます。柄にシールのベタベタが少し残りますが、中性洗剤をティッシュに付けて擦れば落とせます。

ドライヤーを使うときは、シールを熱して無理せず剥がせるようになってから、少しづつゆっくりと剥がしていけば、下記のようにシールを破らずに剥がすことができます。


商品タグ止め

「US103 床を優しく掃けるほうきS」も同じでしたが、商品タグが太いステープラーで箒に打ち込まれています。

これは、マイナスドライバーを差し込んでテコの原理で引き抜けます。


掃除を見直そう

「なぜ掃除機を使うのか?」ということに疑問を持つこともなく、掃除機を使い続けていました。掃除の基本である「掃いて」「拭く」を改めて考えるきっかけとなったのは、コロナ禍の新しいライフスタイルからです。

時間のない生活下では、ロボット掃除機という選択肢は考えましたが、箒で掃き掃除をしようという発想はありませんでした。

しかし、実際に箒を使ってみると「掃除=掃除機」という固定概念がなくなり、掃除機の必然性も感じなくなりました。

下記のブログも併せて読んで、フローリングワイパー、粘着式クリーナーと組み合わせて、テレワーク前の朝の掃除時間を楽しんでください。


2021年1月7日

Google Apps Script タイムゾーンの設定

ゾウでもわかる Google Apps Script

GAS(Google Apps Script)で文字型の日付時間をDate型にしてGoogleスプレッドシートにあるタイムスタンプと比較しようとしたら、なぜか一致してくれない、、、。

「何で?」と日時を格納した変数をログに出力してみると、

function myFunction() {
  d = new Date(`2020/01/01 10:10:10`)
  console.log(d)
}
Wed Jan 01 2020 10:10:10 GMT-0500 (Eastern Standard Time)

と表示されます。

GASがアメリカ東部標準時で表示

GMT-0500 (Eastern Standard Time) とは、 アメリカ東部標準時です。

シートの日時は日本時間(JST)で設定されていたので、同じ時間でもアメリカ東部標準とは14時間の時差があるので一致しないわけです。


Apps ScriptエディタでTimeZoneを設定する

GASでのTimeZone(タイムゾーン)を変更しようと思い、新しいApps Scriptエディタの「プロジェクトの設定」を見ましたが、タイムゾーンという設定項目がありません。

「appsscript.json」マニフェスト ファイルをエディタで表示する という項目には、チャックが入っていなかったので、確認のためにチェックを入れてみました。

新エディタでタイムゾーンの設定

エディタに戻ると、appsscript.jsonが表示されました。コードを見ると、timeZone(タイムゾーン)が "America/New_York" となっていました。

appsscript.json の内容

下記が、appsscript.json のソースになります。

{
  "timeZone": "America/New_York",
  "dependencies": {
},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}

この timeZoneの値を、"Asia/Tokyo" に変更して保存。

{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}

もう一度、下記のコードを実行すると、

function myFunction() {
  d = new Date(`2020/01/01 10:10:10`)
  console.log(d)
}
Wed Jan 01 2020 10:10:10 GMT+0900 (Japan Standard Time)

GMT+0900 (Japan Standard Time) 日本標準時に変わりました。

タイムゾーンを変更したら、プロジェクトの設定の『「appsscript.json」マニフェスト ファイルをエディタで表示する』のチェックを外すとエディタに表示されなくなります。


旧エディタなら簡単にタイムゾーンの変更が可能

新エディタにしていたので設定項目がありませんでしたが、旧エディタならタイムゾーンの変更がUIでできることが後からわかりました。

① ファイル→プロジェクトのプロパティを選択

旧エディタでのタイムゾーンの設定

② タイムゾーンを(GMT+09:00)東京 に変更して保存

プロジェクト プロパティ

こちらの方が簡単でしたね。


日時の比較

ちなみにDate型の変数は、そのまま等符号では比較できません。

function myFunction() {
  var d1 = new Date('2021/01/01 10:00:00')
  var d2 = new Date('2021/01/01 10:00:00')
  if  (d1 == d2)  {
    console.log('d1=',d1)
    console.log('d2=',d2)
    console.log('一致')
  } else  {
    console.log('d1=',d1)
    console.log('d2=',d2)
    console.log('不一致')
  }
}

これを実行すると

d1= Fri Jan 01 2021 10:00:00 GMT+0900 (Japan Standard Time)
d2= Fri Jan 01 2021 10:00:00 GMT+0900 (Japan Standard Time)
不一致

と、同じ日時を代入した変数なのに一致しません。

日時の比較は、getTIme()でミリ秒に変換して比較するのが一番簡単な方法です。

function myFunction() {
  var d1 = new Date('2021/01/01 10:00:00')
  var d2 = new Date('2021/01/01 10:00:00')
  if  (d1.getTime() == d2.getTime())  {
    console.log('d1 msec=',d1.getTime())
    console.log('d2 msec=',d2.getTime())
    console.log('一致')
  } else  {
    console.log('d1 msec=',d1.getTime())
    console.log('d2 msec=',d2.getTime())
    console.log('不一致')
  }
}

d1に代入した日時をmsec(ミリ秒)で表示させると一致していることがわかります。

d1 msec= 1609462800000
d2 msec= 1609462800000
一致

GASの基礎を学べる参考図書

ある程度プログラミンがわかっていれば、WEBやYoutubeでも十分に調べられると思いますが、初歩的なところからであれば参考図書は有効な学習手段です。

詳解! Google Apps Script完全入門 [第3版]」は、プラグラミング初心者にわかりやすく説明されています。GASを最初に学ぶ一冊として良書です。

アクセス上位(過去7日間)