kintone Café 神奈川 Vol.13を開催しました


六月のkintone café 高知 Vol.16 & SORACOM UG 四国に呼んでいただいた事は、私に複数の気づきと学びを与えてくれました。

・サイボウズ社が築いたkintoneエコシステムの理念に通ずる文化をSORACOM社に感じたこと。
・互いがAPIで簡単に繋げられたので、ハードウエアが苦手な私でも取り扱える手応えを得られたこと。
・kintoneを取り扱うにあたって、入力をもっと考えねばならないこと。

そしてご縁も。

次のkintone Café 神奈川をSORACOM UGさんと共催しようと決めたのは、高知での懇親会の場です。
そこで仲良くなったSORACOM UGのなっちゃんこと藤田さんとコンタクトを取り、後日なっちゃんの会社にもお伺いして打ち合わせを行い、イベントの趣旨を固めました。

一方、次のkintone Café 神奈川の開催地は鎌倉でやると決めていました。そこで私は、鎌倉でkintone Caféを行える場所の選定を始めました。
私は鎌倉とさまざまなご縁でつながっています。カマコンにも参加しました。カヤックさんが運営する「まちの社員食堂」で食事もいただきました。鎌倉商工会議所で登壇したこともあります。
今回、ヒトノコトという屋号で活動している渡辺みさきさんに開催に良い場所がないか相談したところ、推薦していただいたのが安国論寺さんです。
ヒトノコトウェブサイト
みさきさん、ありがとうございました。

早速、安国論寺さんとアポイントを取り、七月の某日にお寺を訪問しました。
同行してくださったのは、一緒にkintone café 神奈川を運営してくださっている藤村さんです。そこで、施設の設備面や接続環境に問題ないことを確認しました。
安国論寺ウェブサイト

そこまで決まったので、あとは登壇者やセッションです。
高知のイベントは完全にオフライン限定でした。そのため、内容が参加者のみしか知らなかったことは好都合でした。
実は高知のイベントとは登壇者が何人か重なっています。が、登壇者が被ってもさほど支障はないと判断しました。
コロナ感染対策も含めて何度も打ち合わせを重ね、登壇内容を徐々に固めていきました。
コロナ感染患者数が増加した際は、完全オンラインに移行することも覚悟しました。ハンズオンもすべてオンラインで行うことも含めて準備を進めました。
告知

ツイートまとめ [~開催前]



当日、曇り時々雨だった予報は外れ、見事に晴れました。
お寺に行くと、安国論寺の平井住職がご用意くださった案内看板が二つも設置されていました。それがお寺の雰囲気に溶け込み、とても良い感じを出していました。
中世からの古都でありながら、ITでも多くの先進的な企業を擁する鎌倉にふさわしいお出迎えです。
kintone Caféでも例のないお寺Café。参加して下さったみなさんの期待に応えなければ。

境内には蝉時雨が響いています。三方を崖に囲まれた安国論寺の境内にはリスが生息しています(視察で訪問した際に何匹も見かけました)。自然の癒しに満ちた場所です。
今回、イベントを開催する場所は、本堂の裏手をぐるりと巡った場所に建つ観音堂です。

観音堂はまだ新しい建物です。Wi-Fi完備。電源や机、椅子もそろっています。
調光も可能で冷暖房も十分に行き渡ります。パントリーも備わっているし、トイレも広い。
堂内には南無幸福観世音菩薩様が安置され、悩める衆生の営みを静かに見守ってくださっています。

ただ一つだけ問題が。
それは夏の陽射しが堂内に差し込み、投影したプロジェクターの映像が鮮明に見えなかったことです。この問題は、光量を最大にし、コントラストを調整しても解決できませんでした。
これによってリアル参加の方々にとって少し画面が見にくかったのが残念でした。

ツイートまとめ [開催前~当日]


他には音声をオンラインと会場にどう配分するかでうまくいかず、ぎりぎりまで調整を重ねました。
13時10分がやってきました、開会の発声を行う時間です。
今回の司会進行は私。
kintone Caféの理念とkintoneの目指す目標を語り、まずは始まり。

ツイートまとめ [当日~kintone Caféとは]





続いてトップをお願いするのはJOYZOの四宮さん。今回、四宮さんに登壇していただいたことによって、kintone café 神奈川にkintone界の三巨頭が揃いました。
ラジカルブリッジの斉藤さんはリアルとオンラインで一回すつ。アールスリーインスティテュートの金春さんにはオンラインで一回。そして、Mr.kintoneの四宮さん。

そもそも今回のイベントをやろうと思った理由は、高知で登壇した四宮さんのセッションをより多くの人に聞かせたいと言う思いでした。
kintoneは概念を座学で聞くより、実例を出した方がよく理解してもらえます。四宮さんによるセッションは、kintoneと IoTをどうつなぐかを実例のイメージとして皆さんに理解してもらえたのではないでしょうか。
なぜIoTが必要なのか。その理由の一つは人のケアレスミスを防ぐためにあります。
冷蔵庫の締め忘れをデバイスで検知し、それを通知する。JOYZOさんが星野リゾートさんで実装されたこの実例は、IoTをどうビジネスや日常に活かすかの良い例となるでしょう。

高知で私は四宮さんのセッションを聴き、kintoneとIoTをどうつなげ、提案するかの知見を得ました。弊社がIoTに可能性を感じる上で励みになりました。目標にしたいと思います。
また、後に登壇する私の話す内容を補強するように、無尽蔵のレコード追加はkintoneの本分ではない、との点を述べてくださったこともありがたかったです。
IoTによって大量レコードを取り扱うことは、今のkintoneには幾分荷が重い部分です。ですが、要件とデバイスの組み合わせによっては、十分kintoneでもIoTと組み合わせて案件がこなせるのです。

四宮さんありがとうございました。

ツイートまとめ [kintone Caféとは~四宮さん]





さて、四宮さんのセッションは質疑も含めて用意していた時間より5分ほど早く終わりました。そこで私は、自分のセッションを少し伸ばそうと決めました。もともと48枚のスライドを作っていたため、伸ばそうと思えば伸ばせます。

今回、私が語ったのは大きく3つです。

・kintoneに関わる方は、そろそろkintoneに入力する手段や方法を考えた方が良いよ。
・kintoneには1アプリごとに1日1万リクエストの制限があって、対策を考える必要があるよ。
・kintoneには1サブドメインごとに同時接続数100の制限があって、対策を打たないと止まるよ。

今回はIoTをkintoneにつなげる上では理解しておいてもらいたい点だったので、ちょっと真面目に。
でも、笑いは高知で登壇した時に比べると、ちょっと取れなかったなあ。
その理由もわかっています。私の登壇の後にMaxさんが立ったまま話しているのを見た瞬間に。
あ、座ったまま喋ってた、と自分のミスに気づきました。悔やまれます。まだまだ未熟です。

質疑の時間も若干余ってしまいました。そこで、愚にもつかない話で場をつなぎました。それがあとあとのペース配分を狂わせました。
まだ私には精進が必要です。

ツイートまとめ [四宮さん~長井]




続いて、Maxさんとなっちゃんによる「SORACOM User Groupのご紹介」と、 「つながっている社会へ!IoTとSORACOM」をMaxさんから。

今回、弊社メンバーやパートナー技術者にも安国論寺に来てもらいました。その狙いの一つこそ、Maxさんのセッションを直に聞いてもらうことでした。

なぜ、コミュニティに私が肩入れするのか。粛々と案件をこなすだけではなぜいけないのか。
その気づきをMaxさんの語りの中から感じ取って欲しかったのです。
どこかの小人さん達がいつのまにか案件や仕事を用意してくれるわけではないこと。こうした場で発信する繰り返しがなければ、今の弊社は案件をもらえていないこと。
エバンジェリストやアドボケイターとはどんな人か。それは、私が何度も内部に向けて話すだけでは伝わっていなかったでしょう。だから、私以外の方が実践する生きた手本を見てほしかったのです。
なっちゃんのようなSORACOMの外側の方がSORACOMを語る。そのコミュニティのあり方は、kintoneでも盛んです。

そのためには、どういう理念のもとでSORACOMさんが活動しているのか。 それを理解しないとコミュニティは成長しません。
私が感じたSORACOMさんとkintoneの相性の良さはどこにあるのか。
四宮さんとMaxさんのセッションから汲み取ってもらいたかったのは、こうした技術以外の部分にもありました。

もはや一部の人たちが技術を独占する時代ではありません。技術は民主化に向かっています。
その流れを読みそこなうと、会社や組織として先細る未来が待っていることでしょう。

エバンジェリストとは、技術を民主的に広めていく存在であるべき。私がサイボウズさんやSORACOMさんに肩入れする理由もそうです。私がエバンジェリストとしてコミュニティに肩入れする理由もそう。
民主化に向けて活動を続けていくと、やがて独占する特権は失います。が、その活動によって民主化された社会は、それを広めた方を放ってはおかないはずです。
民主主義の手続きにのっとり、その立役者にさまざまな役割を期待します。つまり仕事となって戻ってくるのです。
技術を独占すると、かえって衰えていく。これは人類の歴史が証明しています。

高知でも今回もMaxさんはこういう言葉をおっしゃられました「IoTとの言葉は使われなくなる」。
IoTがコモディティ化した時、当たり前になった時。それがエバンジェリストとしてのゴールです。それを教えてくれたセッションでした。

Maxさん、なっちゃんありがとうございました。

ツイートまとめ [長井~Maxさん&なっちゃん]


さて、ここで一度休憩タイムとネットワーキングタイムを挟みました。
せっかく皆さんに来ていただいた以上、ご縁をつないでいただかなければ。

そして続いてはSORACOM UG 東京の三人様にお話ししてもらいました。


まずは和田さんから。

「GPSマルチユニットの紹介 ーいざ鎌倉ー」と題したセッションで紹介されたデバイスは、まさにIoTの王道を往くものでした。
温度と湿度と加速度センサーを備え、GPSも備えたデバイス。それがGPSマルチユニットです。
つまり、これ一台で色んなことができてしまう優れもの。

例えば位置情報を組み合わせて現在地の情報を取得できます。また、その情報をLINEなどで簡単に知らせることができます。
鎌倉に到着し、「いざ鎌倉」を高らかに世界に宣言することができるのです。それを例に挙げて示してくれました。

SORACOMのダッシュボードではそれらの連携を簡単に行えます。それが理解できました。

和田さん、ありがとうございました。

ツイートまとめ [Maxさん&なっちゃん~和田さん]



続いて前嶋さんからは、「簡単にIoTをはじめる方法 (SORACOM LTE-M Button for Enterprise / Button Plusの応用例)」と題したセッションで、ArduinoとSORACOM Buttoを組み合わせ、その場でIoTのセンサーの動きを見せてくださいました。
農家の熱中症防止デバイスや、見守り デバイス。どれもIoTの活用事例として参考になるものばかり。

電子回路図が出てくるあたりで、私の理解力は飽和しそうになりました。
こうした電子回路に普段触れない私のようなソフトウエア・エンジニアはハードウエアにとっつきにくい印象を持ってしまいます。
むしろ、だからこそ私は、この両者をつなげられる技術者が必要とされると思いました。クラウドはそれを可能にします。この両者を結びつける提案ができれば、今後の生き馬の目を抜く情報業界を生きていけるはずです。
ハードウエアに強い方にはハードウエアをまかせてしまう。そこから出てきたデータをどのように加工し、活用するのかを示してあげられれば、お客様のニーズは満たせられます。この道筋が見えました。

前嶋さん、ありがとうございました。

ツイートまとめ [和田さん~前嶋さん]



最後に大口さんからは「SORACOMデバイスで遊ぶ」というタイトルのセッション。
ボタンを使い、ポストに投函されたことを知らせるシステムの実例を示してくださいました。

フレップボードとかジャンパ・スイッチとか、割り込みとかレジスタとか。私が名前ぐらいしかしらない単語が飛び出します。
ですが、こうした高度な部分を見ておかないと、座学や独学を始めたときに先が見えません。すると挫折してしまうのです。

大口さんの処理で実装する部分のうち、AWS以降の処理については想像ができました。それは、私が理解できていない弱点がどこかも明らかにしてくれました。
目指す高みを見せてくれた意味でも、大口さんのこのセッションは参考になりました。
そして、概念を理解した上で、ハードウエア・エンジニアにお任せしたほうがよいという気づきも得ました。まずは私も学ばなくては。

大口さん、ありがとうございました。

ツイートまとめ [前嶋さん~大口さん]



続いては高知でも盛り上がったハンズオンです。
高知から島根経由で駆けつけてくださった片岡幸人さんが事前にkintone・SORACOMの試用環境をご用意していただき、準備は万端。
また、今回もSORACOMさんより事前に人数分のボタンをご用意くださいました。

いざハンズオンのスタートです。kintoneエバンジェリストであり、IoTをビジネスに活用する幸人さんの本領が発揮されます。今回は遠距離の異動にも関わらず、パトランプまで運んできてもらい、本当に頭が下がります。

今回は会場にいる皆さんがハンズオンに参加するだけではありません。同時に、オンラインでもハンズオンを実施しました。
仮想的なボタンを用意することで、オンラインの方にもIoTとkintoneの連携を行ってもらえる。それは、リアルでなければIoTのハンズオンはできないという常識を打ち破る壮挙です。
それだけでも凄いのに、リアル側と同時進行する離れ業は幸人さんが事前にシナリオを作りこんでいてくれたおかげです。

このハンズオンが盛り上がったこと!
皆が一生懸命にチャレンジする姿に主催者の本望が満たされました。

私は高知では真っ先に完走し、ボタン押下回数でも一位を獲ってしまいました。自分の大人げのなさに恥ずかしい思いをしました。
今回、私のノートパソコンはZoom配信用に使っており、私はハンズオンにiPadで参加しました。ツイートもしながら、サポートもしながらのハンズオンでしたが、なんとか完走ができました。
完走した後は、遅れている皆さんのサポートに回りました。
今回のハンズオンは、私や四宮さんやSORACOMのDaisukeさんやDaiさんなど多くの方がフォローを行ってくださいました。
それもあって、会場にパソコンを持ってきている方はほぼ全員が完走できました。スマホしか持ってきていない方はPC版しか用意していなかったため、画面を操作の度にズームする必要があり、参加を諦めた方もいました。

そうした方もいらっしゃいましたが、成功でした。
私の中の印象では、ハンズオンに取り組む皆さんの熱意は高知よりも上回っていた気がします。主催者バイアスがかかっていることは承知ですが。

片岡幸人さん、ありがとうございます。そしてご参加の皆さんも。

ツイートまとめ [大口さん~片岡さん(連携ハンズオン)]


さて、ここからはLTコーナー。


まずは原田さんから。

「サイボウズ災害支援チームとの取り組み(経過報告)」
前々々回のkintone Café 神奈川 Vol.10で語ってくださった、サイボウズ社との防災協定の取り組みの続報です。
カンタンマップとの連携なども含め、災害情報をkintoneで管理する仕組みが出来上がりつつある現状を語ってくださいました。

わが国はこの夏も災害が頻発しました。これから先も同じような事態が各地を襲うことでしょう。
今回のこの協定を基に、災害にあたってのさまざまな情報共有が進むことを願っています。
そして、IoTとkintoneの連携がますます必要になるはずです。

原田さん、ありがとうございました。

ツイートまとめ [片岡さん(連携ハンズオン)~LT(原田さん)]



続いては山崎さんです。
災害協定に続いては、災害についてのソリューションのネタがよいだろうと考え、話してもらいました。

山崎さんは昨年のCybozu Days 2021の弊社ブースにおいて、雨量計をkintoneと連携する出展物を提供してくださいました。
この出展物は、制作した雨量計に水を入れると、センサーからRaspberry Piを通して、その雨量データや緯度経度や時間をkintoneに飛ばします。
それによってkintoneで雨量を管理する仕組みです。

まさに今回のイベントの趣旨にふさわしい内容です。
この秋に予定されているCybozu Days 2022でも山崎さんには何かを作ってもらう予定です。

山崎さん、ありがとうございました。

ツイートまとめ [LT(原田さん)~LT(山崎さん)]



続いては藤村さんです。
藤村さんは安国論寺の視察からイベントに至る部分でご協力をいただきました。
会場の入り口にデジタルサイネージによるウェルカムボードを設置したのも藤村さん。
会場の皆さんが来場した際のアンケートフォームを作ったのも藤村さん。そこでは設置した体温計を書き込み、コロナ感染があった場合の連絡先の取得も含めていました。

藤村さんからはまず、kintone Café 神奈川のメンバー内で立ち上がったkintone Café METAVERSE支部のご紹介。
さらに、安国論寺のお堂内にいるということで、マンダラ思考法をご紹介くださいました。kintoneの画面をカスタマイズし、マンダラ思考法のツールとしてしまうHackです。

これまた、お寺Caféにふさわしい内容でした。

藤村さん、ありがとうございました。

ツイートまとめ [LT(山崎さん)~LT(藤村さん)]





最後にMaxさんがLTネタを二つ持ち込んでくださったので、
締めをMaxさんにお願いしました。

まず「”電波”のちょっとイイ話」です。
私もそうですが、クラウド・エンジニアの多くはWi-Fiをただ単に享受するだけです。
何も意識せずに使っている方がほとんどではないでしょうか。

ですが、当然IoTを実装するにあたっては、デバイスの設置位置が重要です。きちんと正確なデータが定時に飛ばせるように設置しなければなりません。
電波の特性を説明していただくことで、kintone界隈の方にもより具体的な実装方法のTIPSとして届いたと思います。

この電波についてが一番よかったという嬉しいツイートもいただきました。

続いて「アウトプットって、なにそれ美味しいの?ブログとLTのすゝめ」です。

このLTが私にとってはとても刺さりました。上にも書きましたが、なぜアウトプットするとよいのか。
会社のためでもなく、誰のためでもない。自分のためにアウトプットする。

私が弊社メンバーやパートナーさんに伝えたかったことが、このLTに詰まっていました。
もちろん、私にとって学びになったのはもちろんです。というか、私にとってこのMaxさんのLTは何度も聴き直そうと思っています。
「座右のLT」として。

Maxさん、ありがとうございました。

ツイートまとめ [LT(藤村さん)~LT(Maxさん)]



この後、皆さんで集合写真を撮りました。
なっちゃんが音頭をとり、和田さんがセルフタイマーで二枚。kintoneとSORACOMのそれぞれのハンドサインを。

そして無事に撤収作業も終わり、安国論寺の皆さんにもお礼を言いまして。

夜は鎌倉駅前まで移動して懇親会をしました。参加をご希望する方が22名ほどまで膨れ上がってしまったため、収容できるお店が限られてしまいました。
結果、神奈川で展開しているチェーン店に落ち着きましたが、皆さん、三つのテーブルで話に花を咲かせていました。盛り上がってましたねぇ!

さらに10名ほどは二次会の懇親会へ。ここでも百戦錬磨の皆さんにしかできないディープな話が。
こういうバックボーンが明らかになるのも懇親会をやる面白さですね。

リアルとオンラインで参加された皆さん、すばらしい内容を発表してくださった登壇の皆さん、素敵な会場と案内板をご用意くださった安国論寺の皆さん、安国論寺をご紹介くださったみさきさん、スタッフの皆さん、本当に本当にありがとうございました。
とても盛り上がりました。

ツイートまとめ [LT(Maxさん)~それ以降]

皆さんから現時点で四つのブログが!
福井さん
渋屋さん
SORACOMさん
SORACOM UGさん



kintoneアソシエイト試験合格ロードマップ


弊社メンバーが先ごろ、kintone アソシエイト試験に合格しました。
IT業界が未経験で面談時にkintoneの名前すら知らなかった状態で弊社にジョインしたメンバーが、何度も不合格になりながら、頑張ってkintoneアソシエイト試験の合格を勝ち取ってくれたロードマップを書いてくれました。

kintoneアソシエイト試験合格ロードマップ

  Topへ↓

kintoneの知識ゼロからアソシエイト試験取得までのロードマップを自分なりにまとめました。

まず試験の全体像を理解する必要があります。(テスト範囲)
問題の構成は9ヶのポイントに分かれているので、一つづつ点で覚えていき、最終的に線で理解する必要が出てきます。
覚える項目がおおすぎるので、必要最低限合格に必要な箇所のみに絞り込みます。

ステップ1

  Topへ↑

ではまず、全体像の把握のためのステップ1です。

ステップ1
まずは公式サンプル問題に挑戦します。
どのような問題がどんな風に出題されるかを把握します。

こちら(https://cybozu.co.jp/kintone-certification/aa_practice/questions.html)から3パターンで挑戦できます。

おそらくある程度kintoneを触ったことがある方でも半分も取れないと思います。
ステップ1で足りない知識をステップ2で補います。

ステップ2

  Topへ↑

ステップ2は基本的に暗記です。
大きく分けると9ケに分かれています。

ステップ2
1、kintoneの契約プランの特徴
2、Cybozu.com
3、kintoneシステム管理
4、ポータル
5、スペース
6、ゲストスペース
7、通知
8、アプリ
9、モバイル版での挙動

基本的にCybozu.com共通管理者、kintoneシステム管理者、アプリ管理者、スペース管理者、一般ユーザー、ゲストの目線で考えます。

Cybozu.com共通管理者は何ができて何ができないか、
kintoneシステム管理者は何ができて何ができないか、
といった目線で覚えていきます。

1、kintoneの契約プランの特徴

  Topへ↑

1、kintoneの契約プランの特徴
スタンダードコースとライトコースの違い。
ゲストユーザーの料金などを全て覚えます。
こちらのページ(https://kintone.cybozu.co.jp/price/)を丸暗記します。

2、Cybozu.com

  Topへ↑

2、Cybozu.com
ここは覚えることが多いですが、要点をまとめておきます。
最低限下記の5つのやり方は覚えます。
①、ユーザーの登録方法(表示名、ログイン名は必須)
②、一括操作(一括操作でできること、できないこと)
③、アクセス制限(有料なアクセス制限と無料のアクセス制限の種類)
④、監査ログ(監査ログで確認できる内容)
⑤、カスタマイズ(カスタマイズできる範囲)

参考ページ(https://jp.cybozu.help/general/ja/)

3、kintoneシステム管理

  Topへ↑

3、kintoneシステム管理
ここも必ず出題されますので、全て覚えます

①アプリ
アプリ管理、アプリテンプレート
②スペース
スペース管理、スペーステンプレート、スレッドのアクション
③ゲストユーザー
ゲストユーザーの管理、ゲストユーザーの認証
④権限
アクセス権、アプリグループ
⑤カスタマイズ
JavaScript / CSSでカスタマイズ
ヘッダーの色
⑥その他
アップデートアプション
利用する機能の選択
プラグイン
スマートフォンでの表示

参考ページ(https://jp.cybozu.help/k/ja/admin/permission_admin/permissions/set_admin.html)

4、ポータル

  Topへ↑

4、ポータル
ここではポータルでできる機能が重要になります。
お気に入り機能、検索機能、モバイルでの挙動。
この3つは確実に出題されます。
特にkintoneの検索機能はクセがあります。
添付ファイルの内容まで検索対象に入っているなど、
細かい箇所まで出題されますので、しっかり把握しておきます。

参考ページ(https://jp.cybozu.help/k/ja/user/portal.html)

5、スペース

  Topへ↑

5、スペース
スペースも問題数が多いのでしっかり覚えておきます。
スペースの作り方、スペースペンプレート、スレッドアクション、スレッドのフォロー
特にスペースの参加/退会、スレッドのフォロー/フォロー解除を禁止する箇所は確実に覚えます。

参考ページ(https://jp.cybozu.help/k/ja/admin/space_admin.html)

6、ゲストスペース

  Topへ↑

6、ゲストスペース
ゲストスペースの招待の仕方、ユーザーがゲストスペースでできる操作、ゲストができる操作
kintoneアカウントと共通化する箇所は応用問題でよく出題されます。

参考ページ(https://jp.cybozu.help/k/ja/user/guest.html)

7、通知

  Topへ↑

7、通知
どのタイミングで誰に通知されるか、通知の特徴
自分宛の通知と全ての通知の違いを把握しておけばここはそこまで重くはありません。

参考ページ(https://jp.cybozu.help/k/ja/user/notifications.html)

8、アプリ

  Topへ↑

8、アプリ
ここが一番覚えることが多いです
出題箇所も多いので、実際に操作して体で覚えることをお勧めします。

①アプリの作り方
ファイルを読み込んで作る方法(CSVやExcel)
拡張子まで覚えておきます。
②フォーム
フィールドの種類と特性
特にルックアップ、関連レコード、リンク、ラベル、はよく出題されます。
CSVに書き出したときのデータの動きなど、実際に見ておいた方が良いです。
③一覧
アプリ管理者と一般ユーザーで操作の違い
④グラフ
アプリ管理者と一般ユーザーで操作の違い
⑤設定
ここも項目が多いので、よく出る箇所をまとめます。
・プロセス管理
・通知
・アクセス権
・カテゴリー
・高度な設定
・アクション

カスタマイズ・サービス連携は深いところまでは出題されません。
カスタマイズ・サービス連携がアプリの設定でできて、プラグイン、JavaScript/CSSでカスタマイズ、APIトークン、Webhookで何ができるかだけ把握しておけば大丈夫です。

参考ページ(https://jp.cybozu.help/k/ja/user/app_settings.html)

9、モバイル版での挙動

  Topへ↑

9、モバイル版での挙動
モバイル版を使わない方もいらっしゃると思いますが、必ず出題されますので
モバイル版ではできないこと、できることを把握しておきます。
モバイル版に関する出題は項目も少ないので覚えやすいと思います。

参考ページ(https://jp.cybozu.help/k/ja/user/mobile_access/smartphone.html)

繰り返す

  Topへ↑

ステップ2が終わりましたら、ステップ1に戻りサンプル問題を受けます。
この流れを何度か繰り返し頭に定着させます。

何回か繰り返し、自信がついてきたら本番に挑戦することをお勧めします。
受験料金も安くはないので自信を持った状態で受けたいですね。
幸いにもサンプル問題の再現度はかなり高いので、実際の試験とのギャップに苦しむことはないと思います。


kintone Café 神奈川 Vol.12を開催しました


2022/6/21に今年に入ってから二回目のkintone Café 神奈川を実施しました。

会場は東戸塚駅そばの横浜市東戸塚地区センター会議室です。

kintone Café 神奈川は、神奈川のあちこちで開催することを目指しています。今までに関内、新横浜、上永谷、鷺沼、横浜、オンライン限定×3、武蔵小杉/オンライン、向ケ丘遊園/オンライン、茅ケ崎/オンラインと開催してきました。今回は東戸塚/オンラインということで、リアルでは14名の、オンラインでは最大で22名の方に参加していただきました。

告知

昨年の初めに三カ月おきに開催すると宣言してから、今のところ6回目の開催で、何とかペースを保てています。これもスタッフの皆さんのおかげです。

今回のテーマは「あなたの会社のkintone活用事例」としました。
kintoneもすっかりお茶の間に浸透し始めています。さまざまな活用例が多くの記事やブログで紹介されています。
それでは、実際にkintoneを使ってシステムを提供する会社は、自社でどのようにkintoneを使っているのか。それを掘り下げるテーマとしました。正直にいうとこのテーマはすでに何度か、取り上げられています。ですが、私にとってなかなか語ったことのないテーマだったこともあり、やってみようと思いました。

今回も山田さんが司会を買って出てくれました。ありがとうございます。
さらに、渋屋さんが会場を確保してくださいました。他にも当日の配信用PCやスピーカーなどを御用意と、懇親会の会場の手配まで。合間にはカメラマンとして写真撮影も。末尾の集合写真は渋屋さんが写してくださったものです。ありがとうございます。

そしていつもの通り、私が最初にkintone Café 神奈川の理念を。
実は今回もYouTube Liveの配信に失敗してしまいました。YouTubeで事前に配信予約を設定していたはずなのに、なぜかZoomからYouTube Live配信の設
定ができず。これは反省点として次回までに改善しておきます。

まず初めにエミック社の松尾さんより「kintoneと連動したWebフォームの作成」というタイトルで話していただきました。
Form Data to kintoneを使った連携のデモを実施していただきました。
システムに関する問い合わせなど、ウェブフォームで受け付ける会社も多いと思います。が、問い合わせ管理についてはなるべく省力化して、kintoneで管理してしまいたいですよね。
そうした事例を公開してくださった松尾さん、ありがとうございました。


続いてはキンスキ松井さんこと、サイボウズ社の松井さんから「kintone コミュニティ案内板の裏側で使うkintone×Zapierの紹介」というタイトルで語っていただきました。
キンコミはkintone界隈にあまたあるコミュニティのポータルを支えたいとの思いで立ち上げられています。その中には今回のkintone Café 神奈川の開催告知をはじめ、秀逸なブログ、発信などを紹介するページもあります。それらの記事の追っかけと取込の作業は大変です。
そうした作業を松井さんはZapierを使って省力化されています。その実例を紹介してくださいました。その事例は、ノンコーディングでもここまでできてしまう素晴らしいモデルケースだと思います。
私も今のZapier契約プランを上位に切り替えようと思いました。松井さん、ありがとうございました。

続いては休憩をはさみ、私です。

今回は、テーマに沿って「うちの会社のkintoneは三世帯同居・別荘もあり」というタイトルにしました。何を意味しているのか、わからん、という突っ込みもいただきつつ。

スライド

内容については上記のUrlに書いている通りです。アーリーユーザーゆえの失敗といいますか。それがいまだに三世代同居として使い続けている原因になってしまっています。
それでも、あまり使われていないアプリグループの活用事例としては、お役立てていただけるのではないかかと。
あとは松井さんの内容に続いてとなりましたが、Zapierを使った連携事例などもお話しました。

質疑の際に松井さんからは、今のkintoneはアプリの所属スペース間を移動できる機能が実装されたが、当時にその機能があってもアプリグループを使ったか、という質問が。さすがの切り口ですね。

多分、私はこの事例に関してはアプリグループを使ったように思います。機能の更新や外部連携もそれほど頻繁ではないお客様なので、テナントとしてはアプリグループで十分だからです。ただ、今となってはお客様にはスペースを使ってもらっていますけどね。


続いてはオンラインから参加の大竹さんによる「kintoneによるWordPressの表示コンテンツとログ管理」というタイトルです。
kintoneからWordPressの表示コンテンツを呼び出すにあたり、複数カテゴリーが重なった場合の制御を行うことで、kintoneのレコード上に設定したカテゴリーを基にWordPressのページとして呼び出す事例を語ってくれました。
表示ページのデータはkintoneで管理し、それを制御してWordPressのページを入れ替えたいニーズはありそうです。特に自社サイトやオウンドメディアを運営している企業さんには良い事例になりそうですね。大竹さん、ありがとうございました。

さて、最後のトリを飾るのは藤村さんによる「kintone caféでこんなタクラミ始めます」というタイトルのLTです。まさにLightning Takuramiにふさわしい、意表を突いた内容でした。kintone Café メタバース支部の立ち上げ!なんという斬新な。
その一方で、kintone界隈の人にとっては二年前のkintone Hack本選でWillさんが披露された、VR上の振る舞いをkintoneに反映させるセッションでもおなじみです。そのため、kintoneとVR/ARは全く無縁ではないのです。その親和性の高さを知っている私にとって、興味が尽きないテーマでした。
しかも今のVRゴーグルはあまり酔わないそうです。かつて酔っぱらってしまい、苦手意識を感じた私にとっては再び初めて見る良いきっかけとなるかもしれません。藤村さん、ありがとうございました。

最後にオンラインの皆さんとリアルの皆さんとで写真を撮影。うーん、充実!

ちなみに私のセッションの中で、次回の9月のkintone Café 神奈川 Vol.13はSORACOM UGさんと共催する旨も発表しました。これから日程や場所やテーマは決めていきます。

夜の懇親会も10名の方に参加してもらい、とても楽しく飲めました。リアルでやるっていいですよね!

ちなみにその場で次回の開催は鎌倉か逗子、その次は小田原と今年のスケジュールが決まりました。こういう事が決まってしまうスピードもリアルで会える良さですよね。

今回、集まっていただいた皆様と登壇の皆様。ありがとうございました!また3カ月後にお会いしましょう!


kintone café 高知 Vol.16 & SORACOM UG SHIKOKUで登壇しました


およそ32年ぶりの高知市への訪問。
私にとって久しぶりの高知は、kintone café 高知 Vol.16とSORACOM UG SHIKOKUの共催イベントへの登壇として実現しました。
告知ページ

三日間に及ぶ高知の旅は、友人との再会や、2日連続での交流会でのさまざまなご縁、自然の豊かさなど、語ることに事欠かない旅でした。
本稿では、kintone Café 高知とSORACOM UGのイベントについてのみに絞ります。

イベント当日はあいにくの雨でした。とは言え、私が泊まっていた紺碧の湯 ドーミーイン高知からイベント会場のオーテピアまでは、帯屋町通りのアーケードを通ればすぐ。今回、じゅんちゃんこと片岡淳さんに教えてもらった宿に泊まって満足でした。

会場には事前に押さえておいた時間の5分前にならないと入れず、設営の関係で開催時間が少しだけ遅れました。とは言え、会場の広さやAV機器の豊富さと会場全体の新しさは、5分の遅れを補って余りあるものでした。
オーテピアは高知市の再開発の主軸とも言える施設です。すぐそばにある「ひろめ市場」とともに、人々の流れと賑わいを高知城の周辺に取り戻すことに貢献しています。

イベントは、じゅんちゃんによる開会の宣言から始まりました。じゅんちゃんが今回のイベントの企画者だと聞いています。
昨年の冬、向ケ丘遊園でkintone Café 神奈川を開催しました。そこに高知から駆けつけてくれたのがじゅんちゃんです。であれば、私も高知に行かねば。行かない選択などありえません。それはkintoneエバンジェリスト、いや、人の道に反します。じゅんちゃんからのお誘いを受け、行くと即答しました。
並走する複数の案件の間を縫って参加することになった私ですが、今回のイベントはとても楽しめました。登壇者としてだけでなく、参加者としても。これは参加者や登壇者が豪華だったからでしょう。じゅんちゃんありがとうございました。

じゅんちゃんに続いて登壇したのは、サイボウズの毛海さんです。毛海さんとは昨年のCybozu Days 2021でご挨拶して以来です。
全国で20数名しかいない毛海エバンジェリストとしての自己紹介のつかみもばっちり。
kintoneを中心としたサイボウズのサービスの数々や、毛海さん自身が手掛けられた構築事例などの紹介がありました。
事前にいただいていた登壇スケジュールでは、私の前に話すのが毛海さんだったので、私も毛海さんがkintoneのご紹介をしてくださる前提で登壇スライドを組み立てました。
毛海さんがkintoneの良さをコンパクトに伝えてくれたので、私もやりやすかったです。ありがとうございました。

続いて私の登壇です。

登壇にあたってのネタはすでに5月の半ばにめどをつけていました。6月の初めにはスライドもほぼ書き終えていました。
それでも、小心者の私は心配していました。SORACOMボタンを押してもkintoneに飛ばなかったらどうしよう、と。
そこで、じゅんちゃんが話している際にボタン押下。うむ、問題なし。

スライドは以下のURLをベースに話しました。

スライドでデモする順番を間違えたり、ボタンを押したら押した座標をGoogle Mapに表示するはずが、ピンが立った場所がオーテピアではなく窓の外に見える追手前高校の時計台だったり、投下したネタの数々に皆さんが笑ってくれたのは良かったです。
私、二年半前からボタンを袋に大切にしまっており、袋の上から壇上でボタンをポチッと押しました。あとでSORACOMさんからは、いやせめて袋から出そうよ、という突っ込みが。しまった!ここで笑いとれたんやった。

私もテストの時点で、Googleの座標がずれるのは気になっていました。これ、懇親会の時に聞こうかなと思っていたのですが、次の斎藤さんのセッションが始まる前に、SORACOMの伊佐さんからご指摘をいただきました。
伊佐さんによると簡易座標取得を使った場合は、近隣の基地局の位置、つまり時計台に依存してしまうそうです。
伊佐さんとお会いするのは、伊佐さんがサイボウズからSORACOMに移ってからは初めてのはず。さすがのご指摘が嬉しかったです。これぞリアルイベントの良さですね。ありがとうございました。


さて、私の次に登壇したのは札幌からやってきたクラウドおじさんこと斎藤さん。斎藤さんのセッションは、完全にkintoneに特化した内容でした。SORACOMさんには一切忖度せず、kintone一本で勝負するところはさすがです。
じゅんちゃんもSORACOMさんには気遣わず、kintoneの事を話してもらって大丈夫、というスタンスだったようです。私はその真意を汲み取れずにSORACOMさんに寄せてしまいましたが。

斎藤さんのセッションは、今までにkintoneが出した全てのバージョンアップを順におさらいするもの。これがなかなか興味深く面白い内容でした。
私はkintoneのβテスターで、当初からkintoneの歴史には参加していたつもりでした。が、すっかり忘れているバージョンアップばかり。次々と繰り出されるバージョンアップに、あらためてこの10年のkintoneの歴史を振り返ることができました。kintoneも最初はあまり機能が入っていなかったのですね。フィールドの初期値設定がなかったり、CSV読込による更新ができなかったり。
今となってはもう異世界のサービスのよう。

斎藤さんとはイベントの前夜の交流会でもご一緒し、当日夜の交流会でも、さらに宿に帰った後も夜中の2時半近くまでお風呂の中でお話させていただきました。
法人を立ち上げた今でも一人で運営されていることなど、私の目標とするワークスタイルを実現していることが素晴らしい。筋の通し方に今さらながらに感銘を受けました。ありがとうございました。

さて、斎藤さんの次に登壇したのはミスターkintoneこと、JOYZOの四宮さんです。
私は事前に四宮さんのセッションタイトルだけ聞いていました。そのため、四宮さんのセッション内容は私の内容と被るのではないかと心配していました。私は最初だからよいけど、四宮さんには迷惑にならないかな、と。そこでじゅんちゃんには事前に私のスライドの内容を送ろうか?とお伝えしていました。ですが、私の心配は杞憂でした。
私のセッションの内容など軽く凌駕してくるあたり、さすがJOYZOさんであり、四宮さんです。私がセッションでやったこととほぼ同じような連携を以前に運用されていたそうです。それだけでなく、さらに高度な連携の事例を見せてくださいました。SORACOM連携プラグインの画面や、それを使った連携事例など、私にとってはどれもがとても参考になりました。弊社も早くSORACOM案件をとれるようにならないと。ありがとうございました。

あと、四宮さんのセッションの中でめっちゃ役に立ったのは、高知に宿泊すると5000円がキャッシュバックされる情報です。これは!と思ってメモしていたのですが、宿に申請するのを忘れてしまいました。5000円どころか30000円以上は高知県に、しかもチェーン店でないお店に還元したはずなのに。

ここで休憩、いや、ネットワーキングタイムが入りました。休憩の合間に皆さんと交流を深めてほしい、とあえて休憩といわずネットワーキングタイムと呼ぶあたり、交流を重視するじゅんちゃんの心意気を感じます。
私もさまざまな方と名刺交換をしました。その日の夜の交流会でも。

さて、再開してすぐ登壇してくださったのは、SORACOM UGのなっちゃんこと藤田さんとMaxこと松下さん。
「推しエバンジェリスト」という新たなワードも登場したそのセッションは、SORACOMさんのオープンかつフラットな企業風土が感じられるセッションでした。
SORACOMさんはお互いにニックネームで呼び合っているようです。松下さんはMax、伊佐さんはMartin。
弊社も外の商談の場でも身内を呼び捨てにせず、さんづけで呼ぶようにしています。ですが、ニックネームの方がさらにフラットな感じになってよいですね。

その風通しの良さは、SORACOM UGのなっちゃんとMaxさんのやりとりからも感じられました。ユーザー会も含めたフラットな関係が築けている証しですね。
そもそも今回のイベント、企画者こそじゅんちゃんですが、発案者はなっちゃんだと聞いています。オープンかつ、外部との交流を良しとする価値観。サイボウズさんやkintoneのそれに合致しています。もちろん私の価値観にも。

また、Maxさんが説明するSORACOMさんのビジネスモデルやビジョンなどにも興味を持ちました。
特に「「IoT」という言葉は早晩なくなる。なぜならモノに回線が通じることは当たり前になるから」との言葉にはしびれました。IoTの分野もkintoneとの連携の可能性は無限にありそうです。

夜の交流会でもMaxさんやMartinさんとは語る機会を持ちました。SORACOMさんとは早速、kintone Café 神奈川で共催しようという話につながりました。詳細はまたご連絡できると思います。とても楽しみです。引き続きよろしくお願いいたします。ありがとうございました。

その後はハンズオンの時間です。SORACOMのボタンの実機を全員に配り、皆さんにSORACOM コンソールにログインし、操作してもらいながら、kintoneとの連携を皆さんに体験してもらおうという企画です。これがとてもよかった。

このハンズオンですが、私が登壇して説明した内容とほぼ一緒。つまり、私のセッションの内容を皆さんに追体験してもらえるのです。登壇者としてこれほどありがたいことはありません。一部、私が使ったSORACOMコンソールのサービスとは違うサービスを利用していましたが、それさえも私にとっては学びでした。私もまだSORACOMコンソールの機能に関しては知らないことが多く、可能性を感じます。

ハンズオンを司会した片岡幸人さんからは、皆さんがハンズオンを最後までやり遂げられるよう、サポートしてほしいという話を事前にもらいました。私もハンズオンに参加しつつ、サポート役を担いました。皆さんはフライングしてましたが、私は順序を守ってフライングもしませんでした。本当ですよ。
ここで面白かったのは、パトランプを使ったところです。皆さんの押した内容に応じてパトランプが点滅する。しかもプロンプトにImsiの番号が流れるので、自分のボタンが押されたエビデンスが画面に出てくる。ハンズオンに参加する実感をビジュアルで見せる趣向はリアルハンズオンならではです。さすがです。幸人さん、ありがとうございました。

ハンズオンはこれだけでは終わりません。さらに、ハンズオンの理解度を試してみましょう、と言う余興が。
私はすぐに答えがわかったので、一番にボタンを押すことができました。その後も、合間にボタンをポチポチ押していたら、なぜか私が連打回数でぶっちぎりの一位になってしまいました。ハンズオンではフライングしなかったのに、ここではフライアウェイ。自分の大人げのなさにきまり悪い思いをしたのも良い思い出です。

賞品としてSORACOMさんのバンダナをいただいたので、私もこれを機会にSORACOMさんにも何か恩返しせねば。と思いました。
実際、SORACOMさんの掲げるビジョンには共鳴するところも多いので。私にとってもやりがいのある分野になりそうです。

さて、続いては三名の方によるLT祭りです。
最初は、M-SOLUTIONS社の岸田さんから、M-SOLUTIONSさんが展開するプラグインのご紹介でした。
実は前日の夕方にカミノバさんが運営するCafé NOVAで岸田さんによるプラグイン勉強会があり、私も参加させてもらっていました。参加だけでなく、質問までさせていただきまして。
弊社もkintoneの内部カスタマイズについては自社で内製するよりも、プラグイン活用の方向に進もうと考えています。それもあって岸田さんの勉強会はとても参考になりそうです。ありがとうございました。

続いては、STNet社の野口さんから。
野口さんは以前、kintone Café 香川を立ち上げられたとのこと。そして今はSORACOMさんのIoT機器を使って多様なご研究をされているそうです。タニシを電気で集めたり、豚の健康状態をIoTのデータから調べたり。そうした研究内容にとても興味を惹かれました。
研究者の現場にもkintoneやSORACOMが活用される。そんな時代がやってきたことに感慨もひとしおでした。
また機会があれば、野口さんの実験の今後を知りたいと思いました。IoTの取り組みとしても良いモデルケースになりそうな感じ。ありがとうございました。

LTの最後を締めたのは、kintoneエバンジェリストの沖さんです。沖さんにリアルでお会いするのは多分数年ぶりのはず。最初はエバンジェリストポロシャツを着ている沖さんが誰だか分かりませんでした。そのぐらいスリムな体形に変身しておられました。
そのダイエットに関する知見が盛り込まれたLTは、システム開発者側としての姿勢とユーザーの関係を、顧客である沖さんと沖さんがお金を払うRIZAPさんの関係に置き換えていました。その視点の切り取り方がとても斬新でした。
確かに私たちシステム提供者は、システムを内製のみに限定するのではなく、きちんと投資すべきところに投資する事を薦めます。それなのに、自分の体については内製でなんとかしようと足がきます。その矛盾に気付かされました。

沖さんには夜の交流会の二次会でもその部分について深掘りさせてもらいました。システム提供者として学ぶところが多く、勉強になりました。ありがとうございました。

夜の懇親会では、葉牡丹へ。ここは、なかなか風情のあるお店です。ここでも多くの方とお話をさせていただきました。高知の習わしや風土、ポテンシャルなどは、現地に行かねば聞けません。そうした話を伺えたのはリアルのイベントならではです。前日は三次会、この日も四次会まで長く楽しい夜を過ごしました。

今回のkintone Café 高知はオンライン配信をせず、その内容も一切録画していません。現地に来た人のみが、現地の空気や熱気を体験できる。それがじゅんちゃんのポリシーです。筋が通っています。
地名をつけるのなら、その地でやる。旅を愛する私としても賛成です。
オンラインの環境がここまで整った今、リアルを見直し、リアルでしかできないことを考える時期にきています。その上でリアルとオンラインの真の価値が実現できるはず。
これはイベント運営者の端くれとして、とても参考になりました。

私がなぜこうした無償の活動に力を注げるのか。ここできれいごとを述べても仕方がありません。
私や弊社にとってこうした活動が、巡り巡って何年後かの仕事のご依頼につながっていることは事実です。ですが、旅が何よりも好きな私が、こうした活動を通して各地を訪問できる。それこそが、最大のモチベーションてす。

仕事と旅を絡めたい。それが実現できる手段こそ、お客様への案件で地方に行ったり、kintone Caféで登壇したりすることです。
案件で伺う旅は、ともすれば仕事モード一色になってしまいます。行ったけれども、観光も何もせずに帰るなんてこともあります。
ですが、kintone Caféは案件よりもゆるいため、旅に気持ちを集中できます。
さらに、kintone Caféで登壇することで地方に知識を還元し、夜の懇親会では地方にお金を還元できます。そして、自分自身には知見がたまり、私の知名度も上がります。その観点からのメリットは見逃せません。
今回の高知でもそのことを再認識しました。

私にとって仕事とは何か。人生とは何か。今回のkintone café 高知 Vol.16とSORACOM UG SHIKOKUの共催イベントは、それを考える良い機会となりました。
今後もこうしたイベントに呼ばれれば、なるべく参加できるようにしたいと思います。そして、私も何か還元できるような価値を提供できるよう、切磋琢磨したいと思います。

今回運営してくださったじゅんちゃんや片岡幸人さん、スタッフの皆様、カミノバ社の皆様、SORACOM社やSORACOMUGの皆様、また登壇者の皆様、さらに参加者の皆様、会場や飲み会やその他、旅の中でご縁をいただいた皆様、本当にありがとうございます。


kintone Café 神奈川 Vol.11を開催しました


三月二十五日にkintone Café 神奈川 Vol.11を開催しました。

qloba上の公式サイトでの開催報告。
https://kintonecafe-kanagawa.qloba.com/activities/12153

昨年の春先より、これからはkintone Café 神奈川は3カ月おきに開催すると宣言し、達成することができました。
今年もそれを継続したいと思います。まず、ご参加者の皆様やスタッフの皆様に感謝いたします。

今回のVol.11は、コロナが始まってから味わう機会が激減していたリアルイベントの醍醐味を感じさせる内容でした。
オンライン参加者数と会場の参加者数が拮抗するkintone Caféも久々。そうしたリアルの会場からは、参加した皆さんからの反応が直接感じられ、運営側としてもとてもやりがいを感じました。それはまさにコミュニケーションの相乗効果。

今回のkintone Caféは、リアル開催の復活を宣言するように「kintoneで何ができるの?」をテーマとしました。
まさに原点回帰です。

今回の司会はけいんさんに担っていただきました。
そして、お約束のkintone Caféの理念を述べる前口上は代表の長井が担当しました。

さて、最初のセッション「kintoneで何ができるの?入門編」は藤村さん。
今回のkintone Caféは、藤村さんを抜きにして考えられません。場所の選定からリアル参加者の集客、そして会場にkintoneベースのデジタルサイネージを設置し、ウェルカムボードの代わりとしてくださったのも藤村さん。さらに「イベントチャット」というツイートを集約するツールを作っていただいたのも藤村さん。

セッションの内容も、今回のkintone Caféへの藤村さんの熱い思い、チガラボの皆さんにkintoneの魅力を伝えたいという思いがあふれていました。冒頭のアイスブレイクで皆さんのkintoneへの理解度や知識などを把握し、その上で会場の雰囲気をつかみます。

kintoneを知らない方にkintoneに興味を持ってもらえるように組み立てられた内容は、冒頭のセッションとして素晴らしいものでした。「ゆるい」というキーワードは、まさにkintoneの敷居の低さを表した言葉。
ありがとうございました。

さて、続いてのセッションはけいんさんによる「Excelから顧客リストを作ってみよう」。
藤村さんによってkintoneへの興味を掻き立てられた皆さん。kintoneの実際の画面が見たい。そんな皆さんの思いをくみ取るために実際のデモをお見せする。藤村さんからけいんさんへの見事なバトンリレーです。

けいんさんはExcelで用意した顧客データをもとに、kintoneの標準機能であるアプリをExcelから作成する機能を使い、一瞬でアプリにしてしまいました。この素早い動きには会場の皆さんも心が動かされていました。目の前でこのような反応が返ってくると嬉しくてしょうがありません。これこそがリアルイベントのうれしさです。やってよかったと思える瞬間です。

さらにけいんさんは、そのように作ったアプリを参加者の皆さんにスマホでログインしてもらえるようQRコードとログイン情報を用意してくださいました。それにより、会場の皆さんが一斉にスマホを取り出し、ログインを試す姿はこれぞリアルイベントのダイレクトな反応。けいんさんのたくらみが見事にチガラボさんで炸裂しました。素晴らしい。ありがとうございました。

続いては、代表の長井によるアプリのライブ作成です。
正直、業務が忙しいため、今回のkintone Caféでは当初登壇する予定はありませんでした。十日前にLTやりましょうか、といったものの、20分のセッションは考えておらず。一週間前になって私の枠が20分とられていることにきづき、おや?と。

その後も準備する時間が取れず、当日も13時にチガラボさんにはいったものの、打ち合わせが四つ続き、ようやく17時になって冒頭の「kintone Caféとは」を作った次第。結局、事前にkintone環境に入ってRepotone Uをインストールするのが精いっぱいでした。しかも藤村さんとけいんさんのセッションでは、私の端末をディスプレイにつなぎ、Zoomの画面共有で皆さんにお見せする形態をとったため、お二方のセッションの裏で準備する時間もなく。

その分、正真正銘のガチライブ感は出せたかもしれません。Webから適当に持ってきた問診票をアプリにf実装しようとしたところで、その問診票のチェックボックスの項目が多く、とても時間内に実現できませんでした。ですが、repotone uを使ってその場で入力した内容を帳票にアップできたことは、皆さんにkintoneのリアルなゆるさとスピード感が伝えられたのではないかと思っています。

今回の開催にあたっては、私と藤村さんがそれぞれkintone関連のパンフレットを多数持ち込み、それを皆さんの机に置いておきました。けいんさんと私のセッションの間の休憩では、皆さんがそれらを興味深そうにめくり、それぞれが意見交換を交わしていました。そこに藤村さんが適宜からんで補足を加えていました。
まさにこれはコワーキングの実例。こうした場の雰囲気はkintone Caféやコミュニティでもファシリテーターさんの手腕によっては見られることもよく見られます。が、チガラボさんの場合、その協働のあり方がファシリテーターの手を借りずとも皆さんの中で自然と出来上がっていました。これぞコワーキングスペースの正しいあり方でしょうね。そしてリアルイベントのあるべき姿。

そうした雰囲気にとても感銘を受けた私たちは、夜の懇親会へ。蕎麦厨房水火さんで美味しい料理を頂きつつ、そうした茅ケ崎の街やチガラボの雰囲気について意見を交換しました。
私にとって今まで茅ケ崎といえば、サザン・オールスターズや開高健、そして懇意にしているTouch is Loveジーンズストアさん、そして浜降祭ぐらいでした。
ですがチガラボさんで感じた自然と協働やたくらみが成り立つ様子は、新たな茅ケ崎の魅力を教えてくれました。
皆さんありがとうございました。


事例:株式会社ライライ様


既存システムのコスト削減が喫緊の課題に

  Topへ↓

ライライ様は、さまざまな撮影現場で活躍されているスタッフと映像プロダクションの間に立ち、両者をマッチングする業務を主に担っておられます。
映像の撮影現場はさまざまなスキルが臨機応援にスタッフに求められる場です。現場によって必要な作業を見定め、その作業に長じたスタッフを迅速に現場に紹介できるライライ様のビジネスは、映像プロダクションに高い価値をもたらします。
ただし、その分、作業指示や報告や請求書の発行作業に煩雑な事務作業が発生していました。それらを管理するための既存のシステムでは膨大な運用コストがかかっており、今回、kintoneを中心とした仕組みに切り替えることで、コストの削減を実現しました。

コスト削減を踏まえた業務要件のヒアリング

  Topへ↑

お客様(映像プロダクション)からのご発注を請け、それを案件として作成する。さらにスタッフの空き状況を見ながら案件にスタッフを割り当てる。スタッフはその案件の現場に入り、作業が終われば交通費や経費や作業内容を報告する。その報告内容を基にライライ社はスタッフの支払い書を発行し、映像プロダクションに対する請求書を発行する。
ご発注から請求までの流れは単純に書くとこのような感じです。

一方、映像撮影の現場の業務は多種多様です。ライライ様はそれらの業務や作業による金額設定を細かく定めています。たとえば、スタッフの習熟度による単価設定も二十種類以上の段階を設けるなど。
そうした業務を基にした金額は支払書や請求書に確実に反映させなければなりません。

ライライ様はそれまで、Salesforce+SVF Cloudを使った仕組みでビジネスを回しておられました。
その仕組みを回すために、各撮影現場に派遣されたスタッフは各々で作業報告を行わなければなりません。作業報告のプラットフォームとして、ライライ様はSalesForceを採用されていました。そのため、Salesforceにスタッフの数だけアカウントを作成し、スタッフはSalesforceにログインして報告を行っていたのです。
すると当然、月々のコストは相当な額にのぼります。
月々の支払額が負担になっていたこと。Salesforceの年次契約の更新日が迫っていたこと。さらにSalesForceの中で多くのカスタマイズが必要になっていて、その費用の見積もりももらっていたこと。それらを考えた結果、システム刷新の判断をくだしました。そこから、弊社へのご依頼につながりました。

この時点でライライ様はkintoneを採用すると決めておられました。まずkintoneを使ってアカウントのコストを減らすこと。それが最優先のミッションだったのです。
もちろん、kintoneの導入によって事務の方の各種計算や発行事務の負担を減らすことも求められていました。

kintoneとWordPressと帳票Onlineを提案

  Topへ↑

ライライ様から弊社にご連絡をいただいたのは2021/1/28。すぐにZoomで打ち合わせを行い、さらに2/3には訪問して状況を伺いました。
その際、Salesforce社に年間契約の延長か停止かの連絡期限が3/12に迫っていることを伺いました。そこでSalesforceを解約すると連絡した場合、4/12には契約が終わってSalesforceが使えなくなります。
Salesforceからデータを移行させつつ、kintoneの特性を生かしたアプリを設計する。さらにスタッフが報告できるためのプラットフォームを作る。そしてSVF Cloudで出力していた帳票とほぼ同じレイアウトの帳票を出す。それらをSalesforceの契約が切れるまでの間に作り上げる必要がありました。

そこで弊社は、2月の上旬にはスタッフの報告手段をkinconeにした提案書(42P)を提示し、すぐに着手にかかりました。
その後さらに打ち合わせを進めた結果、スタッフとの連絡手段はkinconeでは難しいことが分かりました。そこでスタッフとの連絡手段をWordPressに切り替えた提案書(44P)を提示したのは2月の中旬でした。その際、帳票発行の仕組みはアイ・コン社の帳票Onlineで提案しました。

弊社にとっては、メンバーを増やしてから初の案件

  Topへ↑

ライライ様からご連絡をいただく約4週間前。年明けから弊社は二人のメンバーを迎えました。
ライライ様の案件は二人のメンバーに活躍してもらう良いチャンスです。
まず、前の現場でWordPressを扱ったことがあったメンバーに一連のウェブサイトの構築をお任せしました。さらに帳票Onlineの設計はもう一人のメンバーに携わってもらうことにしました。
また、Salesforceからのデータ移行プログラムは代表が作りました。

今回、スタッフのアカウントはすべてWordPressにまとめました。ライライ様の場合、Salesforceに約100名分のスタッフアカウントを割り当てていたことによる月額コストが経営を圧迫していました。そのため、kintoneにもスタッフのアカウントを持たせず、別のやり方を検討したいというのがライライ様のご要望でした。
当初はkinconeで可能かと思いましたが、連携する情報の多さからWordPressに切り替えました。
WordPress内にスタッフのみが見られるページを設け、そこに作業開始時間、終了時間、交通費や作業内容といったこまごました項目をすべて打刻してもらうようにしました。
スタッフが打刻した瞬間、入力した内容はkintoneの作業報告アプリに取り込まれるよう、phpで開発を加えました。

kintoneの設計にあたり、Salesforceからの移行を考える必要がありました。そのため、案件管理や顧客管理、スタッフ管理などについてはSalesforceのフィールドを連携できるように設計しました。
さらに、作業報告アプリはWordPressからの連携に加え、スタッフの支払書や映像プロダクションへの請求書に出力できるような考慮が必要でした。

帳票発行の一連の仕組みについて、ライライ様がMacをお使いだったことから思わぬ遠回りをしてしまいました。そのいきさつについては
この記事に記載しています。
結論として、何とか帳票も出せるようになりました。

もう一つ苦労したのは、さまざまな計算です。内部の計算ロジックはSalesforceの内部でカスタマイズされていたものを流用しました。
ただ、Salesforceの場合、内部のカスタマイズ言語はAPEXというJavaベースの言語です。私もAPEXはあまり詳しくなく、新たに入ったメンバーも同じ。
彼には帳票を設計しながら、この計算ロジックを読み解き、なおかつ計算ロジックをkintoneのJavaScriptに適用してもらう作業に従事してもらいました。

導入してから

  Topへ↑

正直にいうと、Salesforceの契約が終わってすぐの月は、帳票出力の運用がまだ不安定なままでした。その際、ライライ様にはご迷惑をおかけしました。
今では上記のリンクに書いたような帳票発行の運用方法を変え、帳票は出せています。また、スタッフの打刻も順調に動いています。

現在は2ndフェーズの開発の真っ最中です。
他の種類の仕事を担っているスタッフさんの打刻ページや、NaviTimeの実装、Rakumo/Google Calendarとのスケジュール連動を行っています。

三島様より

導入からの日々について三島様はこう語ってくださいました。

「経理作業・スタッフ管理等PC作業の自動化は、弊社の長年の課題でした。
特に、請求・報酬金額のまとめ作業は、チェック項目が細かく時間がかかる上に、手作業だとミスも多くなるので、少しでも負担を減らしたいと考えておりました。
Kintone導入後は、スタッフの打刻から帳票作成までの時間が大幅にカットされました。
弊社の規定はかなり細かいため、まだシステムの確認・改修作業は続きますが、それらが終われば、他業務に人員を割けるようになるので、会社全体としての成長につながるのではないかと考えています。
これからもアクアビット様と打ち合わせを重ねて、より良い形にしていきたいと思っております。」

まとめ

弊社にとってライライ様の案件は弊社メンバーが加わって初めての取り組みだったこともあってとても印象に残っています。

私が帳票発行の設計で迷走しかけた後も、変わらずお付き合いくださっていることに感謝いたします。
三島さんはやり取りのレスポンスが速く、同じテンポを感じています。
まずは2ndフェーズを早く完了させてしまいます。

ライライ様のご紹介

商号 株式会社ライライ
本社 〒105-0021 東京都港区東新橋2-7-3 BIZMARKS 新橋汐留 2F
TEL 03-6874-4642
代表者 代表取締役 中田 平
従業員数 従業員3名 / 請負登録スタッフ70名
設立 2017年7月24日
資本金 100万円
ウェブサイト http://www.rightright.co.jp/

事例:某弁護士法人様


事務所の立ち上げにあたって、多忙な先生とスタッフの連携に備える

  Topへ↓

利益相反(コンフリクト)の点で具体的な名前を出せないのですが、某弁護士法人様は、高度な専門知識を駆使した法律事務所としてご活躍しておられます。
弊社が初めてお話をいただいた時、事務所開設に向けた準備を行っている最中でした。
代表社員弁護士の先生は、事務所の立ち上げ前から弁護士として幅広く活動されており、そのスケジュールは多忙の一言に尽きました。
スタッフを雇用し、事務所として立ち上げる中、スタッフと先生のコミュニケーションをいかに円滑に回していくかは、喫緊の課題でもありました。
弊社がkintoneを提案した結果、最初の立ち上げ時からスタッフと先生のコミュニケーションロスを抑えながらの運営ができました。

いかにして先生の予定や業務を共有するかのヒアリング

  Topへ↑

弁護士とは多忙な職業という印象を持っていましたが、代表の先生がこなすスケジュールの多忙さは私の想像を超えていました。
まさに分刻みという言葉がふさわしい先生のご予定をスタッフとどのように共有するか。予定の共有をせずに事務所の運用は回りません。
先生がご相談したのが、鎌倉に事務所を構えておられるヒトノコト(https://hitonokoto.com/)の渡辺みさきさんでした。
渡辺みさきさんが、なぜ事務所のサポートをしようと思ったかは、代表の先生やオフィスメンバーが働き易い職場を作りたいと思い、そのためには情報共有が欠かせないと判断されたからだそうです。
そこで渡辺みさきさんは、弊社代表の私と知己であったことから、システム構築のご相談を弊社に持ち掛けていただきました。

弊社代表がお話を伺ったところ、代表の先生の多忙なスケジュール管理を行うには工夫しなければ難しいと感じました。
当初、ヒトノコトの渡辺さんはCybozu Officeをご提案しようとされていました。ですが、お話を伺ってみたところ、他システムとの連動を行わずにスケジュール共有を行うのは難しいと判断しました。そこでkintoneをご提案しました。

kintoneについては、弊社は諸アプリの作成には携わっていません。こちらはヒトノコトの渡辺さんから別の方にご依頼していただきました。
その方が事務所の運営に必要な各種アプリを構築し、事務所の方が使えるように作業を行っていただきました。
弊社は標準機能では難しい他システムとの連動に注力し、並列で開発する体制を組んでいただきました。

kintoneとTwillioとGoogle Calendarとカレンダーの連動を提案

  Topへ↑

先生はiPhoneを駆使して連絡をとっておられます。スケジュール管理もiPhoneの中に入っているカレンダーが中心でした。
ところが、kintoneはカレンダーとの連動ができません。なぜならiPhoneのカレンダーは外部との連動をそもそも許可していないからです。ただ、唯一連携ができたのがGoogle Calendarです。そのiPhone内の連携オプションを利用し、Google Celanderとkintoneの連動を開発することによって、kintoneとカレンダーの連動を実現しました。
これによって、先生がiPhoneのカレンダーに入れた予定をすぐにスタッフはkintoneでGoogle Calendarからの予定を取得する事で共有でき、スタッフが入れた予定も先生が取得できるようになりました。
なお、事務所が立ち上ってすぐ、もう一人弁護士の先生が入所されたのですが、その先生にも同じような仕組みで予定の共有を可能にしました。

もう一つ、考慮しなければならなかったのが、事務所から先生に連絡を行う場合です。例えば事務所に先生宛の電話があった場合、その要件をすぐに先生に伝える必要があります。
先生からは、kintoneの通知ではなくiPhoneのSMSで連絡をもらったほうがありがたい、というご希望がありました。
そこで、kintoneのアプリ上にボタンを設置しました。そのボタンをスタッフが押すことで、アプリに格納した情報を先生のiPhoneにSMSとして飛ばすように設定しました。その連携にあたってはJavaScriptでTwillioにAPIリクエストを投げることで実現させました。

カレンダーの表示を見やすくするための工夫

  Topへ↑

苦労したのは、多忙な先生と予定を合わせることです。というのも、先生の端末をお借りしての操作が必要となったからです。カレンダーとGoogle Celandarの連動設定、Google Calendarの設定、さらに内部のGoogle Cloud Platform上での認証設定などを行う必要があったからです。ガソリンスタンドの休憩スペースで落ち合って作業したのは良い思い出です。
先生の激務のさなか、分で刻まれるスケジュールの合間を縫っての作業でしたが、それ以外にお手を煩わせることがなかったのは幸いでした。
もう一人の先生の端末も後日事務所にお伺いして設定することができました。

もう一つ苦労した点は、カレンダーの見え方です。スタッフの方が日・週・月で先生の予定を把握するためのデザインや色の設定などを工夫しました。
特に二人の先生が抱えたそれぞれの予定に加え、数名のスタッフが入れた予定など、多くの予定が混在する情報をどのように整理するか、色分けの部分は何度か打ち合わせを行わせていただきました。

それと、Google Calendarへのアクセスの際にGoogleから認証を求められますが、このやり方については、動画でマニュアルを作成し、スタッフの皆さんにご理解をいただけるように努めました。
当初はスタッフからの連携方法や先生の端末操作などの操作に慣れていただく必要があり、その間は先生のお手間を煩わせたこともあったかと思います。が、無事に弊社の手を離れて今に至ります。

導入してから

  Topへ↑

弊社には時折Twillioからの通知が来ますが、今のところ弊社の手を離れ、自立して動いてくれているようです。
多忙な先生のスケジュール管理にもkintoneが活躍できる場を見いだせたことは、弊社にとっても貴重な知見となりました。

渡辺様より

今の状況について渡辺様はこう語ってくださいました。

「新入社員としてジョインしたメンバーも、最初は使うのをためらっていたけど、使って見たら便利だという事がわかったので使っている、との話も聞いています。
自分で使い勝手を考えて、ある機能を使っているようなので、いいサイクルになってきているのではないかと想像しています。」

まとめ

弊社にとって某弁護士法人様は、iPhoneのカレンダーをどうkintoneにつなげるのか、という点で工夫したことで印象に残っています。

また、多忙な皆さんのスケジュールの合間に伺ったタイミングで的確に作業を終わらせなければならず、とてもメリハリの利いた開発になったことでも思い出に残ります。
今も順調に動いているということで、安心しています。

某弁護士法人様のご紹介

情報については、非公開です。

事例:株式会社テル・コーポレーション様


既存基幹システムで対応できない周辺のシステム管理が課題に

  Topへ↓

テル・コーポレーション様は、分譲マンションの開発・販売業務、分譲戸建て住宅の開発・販売業務、居住用・事業用物件の賃貸管理業務、土地・建物の売買仲介業務、不動産の有効利用コンサルタント業務など、幅広い不動産事業を展開されています。1988年の創業以来、着実に業績を積み上げてこられました。
契約や販売など、業務の基幹となる部分は賃貸管理システムで長年運用されていましたが、賃貸管理システムで補えない周辺の管理コストが煩雑になってきました。
もともと、テル・コーポレーション様は社内の連絡手段についてはCybozu Officeのオンプレミス版をお使いでした。周辺の情報共有手段を同じサイボウズ社のkintoneにすることで、近しいインターフェースを持ったシステムで回すことを検討されておりました。
その結果、周辺の管理をkintone中心とした仕組みに切り替えることで、業務の改善を果たすことができました。

煩雑な社内フローをkintoneに置き換えるためのヒアリング

  Topへ↑

不動産事業を行う中で、管理が必要な業務は契約や支払だけではありません。
例えば入居されている方からのクレームや要望事項も発生します。また、解約時の諸手続きや、オーナーや仲介業者との金銭の授受、鍵や駐車/駐輪場の管理、保険業者や内装業者、行政とのやりとりも必要になってきます。
テル・コーポレーション様がもともと使われていた賃貸管理システムは、そうした周辺の管理まで対応していませんでした。そのため、Excelを使って管理しており、煩雑な運用をもたらしていました。例えば紙に出力したExcelを基にしたクレーム報告書を社内で回覧し、押印欄に閲覧者が印鑑を押印するワークフローの存在など。
例えばクレームが発生した場合、その状況は物件や入居者の状況、事象によって千差万別です。それらを内部で情報として共有し、きちんとした指示を出す必要があります。

今回、弊社にいただいたご依頼は、Excelで管理していた周辺の業務を全てkintoneに集約すること。それとCybozu Officeをオンプレミス版からクラウド版に移管することでした。

今回はシステムのご担当者様と頻繁に連絡を取り合いながら作業しました。そのため、要件定義の細かい部分にまで弊社で踏み込む必要がありませんでした。

kintoneとRepotoneU Excelを提案

  Topへ↑

今回のご依頼で特筆すべきは、既存のExcelで運営していたクレーム報告書をどのようにkintoneで実現するかでした。
クレーム報告書の体裁を保ちながら、内部の仕組みをkintoneに置き換える。そのような方法を採った理由は、テル・コーポレーション様の社内にITに不慣れな方がいらっしゃるため、と伺いました。
そのため、kintoneからクレーム報告書を同じような体裁で出せるようにしました。押印欄を設け、実際の疑似印鑑も出力できるように。

そこでRepotoneU Excelを提案しました。RepotoneU Excelは帳票のテンプレートを登録することで、出力項目とのマッピングが可能です。
その際、テンプレートとなるExcelには拡張子が.xlsm、つまりマクロが可能なワークブックを使用しました。それによって、kintone内で生成されたExcelにマクロが埋め込まれるようにしたのが工夫点です。そのExcelをkintoneからダウンロードし、御担当者様が開いた時点でExcelマクロを動作させることによって、RepotoneU Excelの機能だけでは実現できなかったさまざまな表現を可能にしました。
例えば、あるクレーム報告書の場合、約20カ所の押印欄がありました。これも、kintoneの日時フィールドとユーザー選択項目を組み合わせた結果を疑似印鑑として表示させることで実現しました。
なお、マクロの実行にあたっては、テル・コーポレーション様のセキュリティ・ポリシーに合わせた形で実行できるようにカスタマイズしたことも付け加えておきます。

コロナがまん延する中での開発

  Topへ↑

テル・コーポレーション様に初めてお伺いしたのは2020/3/9のことでした。すでにコロナウィルスが世間に深い影響を与え始めていた時期です。
ただ、開発にあたってコロナはあまり影響を与えませんでした。それは、打ち合わせのほとんどをオンラインで完結できたためです。

テル・コーポレーション様はコロナ前からリモートワークへの切り替えをお考えでした。それがコロナによって拍車がかかり、オンラインでの打ち合わせの状況が整いつつあったことが功を奏しました。

さらに、やりとりの記載にあたってはご担当者様と何度か認識を合わせておいたため、複雑なやりとりもkintoneのスペースだけで完結できました。
社内の状況に精通したご担当者様とのやりとりによって、そこまで苦労せずに開発を進めることができたのは良かったです。結果、Zoomなどのオンライン・ミーティングすら二、三回で済みました。
私がテル・コーポレーション様を訪れたのは、初回の打ち合わせを除けば一回のみ(2020/9/28)です。それも、Cybozu Officeのオンプレミス版からクラウド版にデータを移行する作業が主でした。この時はすでに本来の開発は大体終わり、運用に移っていました。

開発で苦労した点があるとすれば、kintoneのプロセス管理を駆使していたため、エラーが発生した場合の再現が難しかったことです。グループやロールや組織、役職も多く作成しましたし、プロセス管理のステータスの数もたくさん作成しました。
特に、プロセスが進んだタイミングや保存時でアプリ間のデータ処理やスペースをまたいだデータ連動を複雑に組んでいたため、不具合があった際の調査に時間がかかり、苦労しました。

導入してから

  Topへ↑

プロセス管理のフロー修正や、賃貸管理システムとの連動にあたっての修正など、最初の目的を達成した後もさまざまな修正が発生しました。
が、今年の秋になって賃貸管理システムの入れ替えも終わったことで、いったん当初の目的は終わりました。

今後も新しくなった賃貸管理システムと協力して、kintoneの運用を行っていただく予定です。
今は、ご御担当者によってkintoneのアプリを次々と作成していただいている状況です。

代表取締役 浅井輝彦様より

代表取締役の浅井輝彦社長はこのように語ってくださいました。

「kintoneの導入によって、紙の書類が少なくなり、時間を効率よく使えるようになりました。それによって、テレワークもスムーズに導入出来ました。ありがとうございました。

株式会社テル・コーポレーション 
代表取締役 浅井 輝彦」

まとめ

弊社にとってコロナ禍においてもリモートワークを駆使して作り上げたことで、テル・コーポレーション様の作業は印象に残っています。
特に、リアルで運用されていた帳票をそっくり再現しながら、kintoneでプロセス管理を使いこなせたことでも、弊社にとって貴重な事例となりました。
あらためて、テル・コーポレーション様の皆さま、ありがとうございました。

テル・コーポレーション様のご紹介

商号 株式会社テル・コーポレーション
本社 〒151-0053 渋谷区代々木四丁目42番19号 テルコーポレーションビル
TEL 03-5302-5311
FAX 03-5302-5312
代表者 代表取締役 浅井 輝彦
設立 昭和63年
ウェブサイト https://teru-co.co.jp/

kintone Café 神奈川 Vol.10を開催しました


十二月二十一日にkintone Café 神奈川 Vol.10を開催しました。

qloba上の公式サイトでの開催報告。
https://kintonecafe-kanagawa.qloba.com/activities/11229

今年の春先に行ったVol.7の中で、これからはkintone Café 神奈川は3カ月おきに開催する、と申し上げました。
今回の開催でなんとかその約束を守れました。まず、ご参加者の皆様やスタッフの皆様に感謝いたします。

今回のVol.10は、運営側はほぼリアルで、そしてほとんどの参加者の方にはオンラインで参加してもらいました。

今回のkintone Caféは、kintoneのショートカットキーの解説から、kintoneインポートチャレンジへ。
さらに災害支援チームや支援協定の活動のご説明から、開発フレームワークのGAMENIへの想いへ。

このように多彩な内容だったので、テーマを「LOVE YOUR 多様性(仮)」としました。
テーマが絞りきれない内容だったからです。
言うまでもなく、「LOVE YOUR 〜」というのは、今年のCybozu Days 2021のテーマ「LOVE YOUR CHAOS」を踏襲しています。
まあ、代表の私にとっては、違和感のないタイトルでした。

今回の司会は前回と前々回に続いて山田さん。
そして、お約束のkintone Caféの理念を述べる前口上は代表の長井が担当しました。

さて、トップバッターに立っていただいたのは、ほぼこのために高知から来てくださった「じゅんちゃん」こと片岡さんです。
今回のCaféで会場としてお借りした福祉パルたま。なんと20数年前、新婚当時のじゅんちゃんが愛の巣を築いた住まいのすぐ近くだったのです。
なんとしてもこの数奇なご縁を語りたかったじゅんちゃん。震えますね!

さて、そんなじゅんちゃんが語ってくださった内容は「kintoneでもショートカットキー」。kintoneのショートカットキーがテーマです。
これ、実はなかなか簡単なようで奥が深いのです。Ctrl+Sは保存。レコード詳細画面でCtrl+Eを押すと編集モードにできることは皆さんもご存じですよね。ですが、皆さん、一覧画面でもショートカットキーが使えることを知っていたでしょうか。
私はあまり使っていませんでした。せいぜいCtrl+Cで新規追加するくらい。
レコード詳細画面でCtrl+KやJを押せば、レコードを移動できるのは知ってましたが、レコード一覧画面でも使えるとは!

他にもGoogle ChromeやWindowsでのショートカットキーなど、とてもダメになりました。私も結構知らないショートカットキーがありました。特にグラフィックボードの再起動などは役に立ちそう。

続いては「kintone インポートチャレンジ」です。
11月のkintone Café JAPAN 2021で好評を博したこの企画は、代表の私もチャレンジャーとして挑みました。
その鬼のような罠に満ちたExcelには手を焼かされたものです。
その時Excelの出題や進行をしてくださったのがけいんさん。今回はその時と攻守を逆転させ、私が出題者。けいんさんがチャレンジャー。
さらに、今回は複数の方にチャレンジしてもらったら面白いかな、と思い、事前に手を挙げてくださった原田さんにもチャレンジャーをお願いしました。
いや、面白かった。
私もアプリに権限をつけ忘れるチョンボをしましたが、それにもめげず完走したけいんさんに拍手です。初めてのチャレンジだった原田さんにも難しさを実感していただけたようで。

さて、続いては「GAMENIの秘密」と題して、福岡から久米さんにオンラインで入ってもらいました。
毎年恒例のkintone Advent Calendar。そこで久米さんが今回のCaféの前日にアップしてくれていたのがGAMENIについてです。
GAMENIとは、わが国のシステム開発会社にこそ、もっとkintoneを扱ってほしいという願いから生まれたkintoneの開発フレームワークです。久米さんの想いに、代表の私も熱く賛同していました。今回のCaféが行われるのが記事をアップした翌日というご縁もあり、久米さんに語ってもらいました。
カスタマイズ言語が多く登場したので、kintoneの非技術者の方には難しかったはずです。が、これも多様性ということでご容赦ください。

最後は「サイボウズ災害支援チームとの取り組み」を原田さんから。
原田さんが所属している横浜市社会福祉協議会とサイボウズ災害支援チームの間で災害支援協定が締結されたそうです。そこで原田さんからは社会福祉協議会の仕組みや災害支援協定の重要性などを語っていただきました。今回はオンラインでサイボウズ社の柴田さんにも参加してくださいました。柴田さんからも災害支援チームの取り組みをご紹介くださいました。
こうした取り組みは地震や噴火などを控えたわが国にとって大切です。
各地の社会福祉協議会ではkintoneを使った取り組みを広げており、そこでアプリの改修やスタッフへの説明を行ってくれる方を求めているそうです。われこそはという方、ぜひとも。代表の私も可能な限りお手伝いしたいと思いました。

いやぁ、ご参加の皆様、スタッフの皆様、ありがとうございました。会場を手配し、司会進行を務めてくださった山田さん、会場にお越しいただいたけいんさん、原田さん、藤村さん。そして高知からお越しくださったじゅんちゃん。会場に来てくださった大竹さん。オンラインの場で参加してくださった松尾さん、加藤さん。オンラインで登壇してくださった久米さん、柴田さん。そのほかの皆様もありがとうございます。
来年も今年と同じペースで開催したいと思います。また3カ月後にお会いできればと思います!

懇親会はスタッフ四人とじゅんちゃんとで美味しく楽しく過ごしました!


私、Mac方面については素人なのですが、、、


kintone Advent Calendar 2021の17日目の記事です。

  Topへ↓

今年も弊社はkintoneの案件を多く請け負わせてもらいました。ありがたい限りです。
今の状況に甘んじず、引き続き精進を重ねなければ。
というのも、まだまだ精進が足りん!と界隈からどやされそうな案件があったので。

kintoneに没頭するのはいいけれど、窓とリンゴの違いは考えておかないとね。
というわけで、本記事ではMac環境に詳しくなかった私が設計に失敗しかけた話と、その後のリカバリ方法をご紹介したいと思います。
なお、この失敗は私の未熟さが全てなので、責任は全て私にあります。私以外の誰れ〜も悪くないのです。

のようなクラウドシステム。その利点はいろいろ挙げられると思います。中でも真っ先に挙げられるのが、端末の心配をせずに済むことではないでしょうか。
モダンブラウザさえインストールされていれば大抵の機能は動きます。一昔前のシステムでは必須だった、やれライブラリが古いとか、やれ依存関係がどうとか、やれドライバがどうとか。そんなもの気にしなくても導入できる。それがクラウドシステムの魅力です。
リンゴが大好きだろうが、窓から見る世界が全てだろうが、クラウドシステムは無関係に動いてくれます。
端末の差異を気にせずに済むようになったことで、システム開発のコストは下がりました。
スマホやタブレットがあれば外出先でも自由自在にシステムにアクセスできる。そんなクラウドシステムの恩恵を多くの人が受けられるようになりました。

私、すっかりこの前提に甘えてしまっていたようです。
私が大学を卒業した1996年。ちょうど、Windows 95が爆発的に世間に普及した年です。同時に、インターネットが新たなツールとして世の中にデビューした頃でもあります。
実は私、それ以来パソコンに関しては一貫してWindowsしか使っていません。
技術者として独立した2006年から、ずっとMacとは無縁でした。Macの操作を知らなくてもシステム・エンジニアのフリができたのです。なぜなら仕事の上ではWindowsだけで事足りてきたから。キャリアの現場でMacに遭遇したのはせいぜい三台ぐらい。

私のMac音痴はkintoneを扱い始めた2011年秋からも変わらずでした。お客様にMac使いがいらっしゃらないので、Macに疎い私の無知がバレる恐れはありません。
ところがついに今年、私はMacがらみでプチ失敗してしまいました。


2.複雑な帳票を帳票Onlineで設計

  Topへ↑

お客様からSalesForceをkintoneに移管したいとのお話があり、早速とりかかった弊社。
そのお客様は、SalesForceとSVF Cloudをつないで帳票を発行していました。そして、その帳票は複雑でした。明細行には、複数のサブテーブルの情報をつないで出す必要がありました。セルの結合もあちこちに潜んでいます。開発には相当の困難が予想されました。
下図は帳票のうちの一つです。


そこで弊社は、アイ・コンさんの帳票Online for kintoneをお客様に提案しました。帳票Onlineであれば、セル結合や複数のサブテーブルの明細行への表示もできるようです。自在な改ページや印鑑埋め込みなども含めて機能を満たしていると判断しました。

帳票設計にあたっては、帳票Onlineの帳票を設計するための風神レポートの開発キット(プロフェッショナル版)を弊社で購入しました。
弊社メンバーが頑張った結果、帳票についてはおおかたの設計ができました。

3.開発はしたけれど

  Topへ↑

ところが、ここから開発が迷走してしまったのです。
なぜ迷ってしまったのか。以下に理由を書きます。

下図は迷走の途中で作ったフロー図です。上からずっとフローが流れてきて、請求管理のアプリまでやってきています。
この請求管理アプリですが、複数のサブテーブルを持っています。上流のアプリから作業明細や交通費などのデータが流れてくるため、複数のサブテーブルで管理する必要がありました。
このサブテーブルの情報を明細テーブル内に複数表示させるのが今回の帳票です。先にアップした通りですね。


ここでまず、帳票Onlineの仕様が私の前に立ちふさがりました。帳票Onlineは帳票を出力するにあたって、アプリで登録されているデータを加工して出力できない仕様なのです。
ところが、今回の帳票はなかなかに複雑な制御を行っているため、kintoneアプリにはない項目をCSVに含める必要がありました。

つまり、帳票Onlineの標準機能では帳票が出せないのです……。

4.帳票ルックアップの導入とMacの制約

  Topへ↑

そこで私が考えたのは、風神レポートに別売りで用意されている「ルックアップ機能」を利用することです。
「ルックアップ機能」をインストールすると、そのパソコン上で任意のフォルダを監視できます。そのフォルダにCSVが格納されれば、帳票Online用の帳票設計ファイルを通して帳票を出力できます。

つまり、やるべきなのは請求管理アプリから整形したCSVを出力すること。
ただし、請求管理アプリが複雑なので、標準機能で帳票Online用のCSVは出せません。そのため、JavaScriptのライブラリを使い、CSVを出力しました。

ここで問題になったのは、「ルックアップ機能」がインストールできるのはWindows PCに限られていたことです。
ところが、お客様はMacでビジネスを回しておられました。そして、お客様のもとにあるWindows端末は一台のみでした。
かなりリスクがありましたが、私はこの時点で帳票Online+風神レポート+「ルックアップ機能」の構成を提案しました。これがプチ失敗の元。

そもそもMacに関してはもう一つの制約がありました。今回、風神レポートで帳票を設計してくれたメンバーはMac使いでした。ところが、風神レポートの開発キットはWindowsでしか動きません。
幸い、弊社で余っていた端末がサテライトオフィスに置いてありましたが、それによってメンバーは帳票設計の作業のためだけに通勤を余儀なくされました。
この時点で、すでにMacを甘く見ていた私の思惑があちこちで崩れかかっていました。それに気づかずプチ失敗へと突き進む私。

また、お客様がGoogle Driveをお使いだったので、「ルックアップ機能」の監視フォルダをGoogle Driveのフォルダに設定しました。ところがこれがうまく動きません。そのかわりにお客様にOneDriveのアカウントを作ってもらい、OneDriveのフォルダを監視フォルダにしました。すると、OneDriveのフォルダにCSVファイルを格納すると、自動的に帳票が出力できるようになりました。
さらに、生成したPDFファイルを格納するフォルダを任意のOneDriveのフォルダとして設定しました。その設定が功を奏し、Mac端末とWindows端末がOneDriveフォルダを介してつながりました。

この時、お客様からは風神レポートが出力した帳票をファイルとしてお客様に送付したいとのご要望もいただいていました。
そこでCube PDFを導入し、出力した帳票を自動的にPDFファイルとして生成する機能を考えました。Cube PDFでは出力時にどうしても確認ダイアログが出てしまいます。それを回避するため、Cube VPという仮想プリンタの機能を導入しました。Cube PDF LiteとCube VPを組み合わせると、確認のダイアログを省いてPDFが生成できます。この時の仕組みは以下の通りです。

ここまでで、いったんお客様がMacのOneDriveのフォルダにCSVをアップすれば、お客様の望む帳票が出せるようになりました。しかもMac端末のOneDriveを見れば、出力した帳票がPDFファイルとして見られるようにも。

この時点で以下のような仕組みが組みあがりました。

これで、お客様の最低限のご要望は満たせたのです。間にWindowsマシンが挟まっているとはいえ、Mac端末でCSVをインプットし、Mac端末でアウトプットされたPDFを見られるようになりました。

5.出力はできたけれど

  Topへ↑

ところが、この方式で数日テストしてみたところ、お客様にとって、このやり方は意に沿うものではありませんでした。普段Macを使っているのに、その時だけWindows端末を使うのは非効率だと。
たとえWindows PCの操作のために移動する必要がないとしても、Windows PCの電源のON/OFFのためにオフィスに行く必要が生じる。これによって、リモートワークもできない、という強いご要望をいただきました。
この「リモートワークができない」というご指摘は私に重くのしかかりました。クラウドシステムを提供する会社にとって、リモートワークができないというのは、あってはならない事態です。

Mac端末に「ルックアップ機能」がインストールできれば丸く収まったはず。ですが、仕様である以上どうもできません。これはMacリスクを甘く見ていた私の失策です。なんとかしなければ。
ここで私はとても悩みました。お客様の言い分ももっとも。ここを解決しなければシステム・エンジニアの名が廃る。

お客様がもともと使っていたSVF Cloudのライセンスがまだ有効なはずなので、それを使えないか、というご意見もいただきました。
そこで、SVF Cloudの開発元であるウイングアーク1st社にも連絡を入れました。
ここでSVF Cloudを導入していれば、あるいはうまく行ったのかもしれません。ですが、私はその判断を簡単に下せない事情を抱えていました。
まず、SVF Cloud for kintoneが諸般の事情で販売終了していたことです。これによってプラグインを使って開発工数を減らす道は閉ざされました。ということは、SVF CloudのAPIを一から学び、さらに帳票に当て込む作業が発生するのです。その工数や予算はどこから捻出すればよいのでしょう。しかもSVF Cloud for kintoneが販売終了した経緯が不透明で、今後の販売再開の見込みがない以上、kintoneを主に扱う弊社がSVFの知見を蓄えるメリットがあるのか、とも悩みました。ウイングアーク1st社がkintoneへ再び熱意を持ってもらえばよいのですが(再び持っていただきたいです!)。
さらに、SVF Cloudを導入すると、本案件を機会に帳票Onlineの設計スキルを弊社メンバーに学んでもらおうとした目論見が崩れてしまいます。さらに開発キットを購入した投資額も本案件で回収できなくなる見込みが高い。

さて、ここが知恵の絞りどころ。ここで妙案を出さねば。
悩んでいた私に、ひらめきが降りてきました。このひらめきで全てがうまくまとまりました。

6.構成をもう一度検討し直す

  Topへ↑

私の解決法は請求管理アプリではなく、もう一つ別に帳票発行専用のアプリを作ることでした。
問題の発端は、請求管理アプリの構成が複雑で帳票Onlineでは出せなかったことにありました。
ならば。もう一つアプリを作って、そのアプリを帳票Onlineで適切に扱えるようなデータ構成にすればよい。
こう書いてみると簡単ですが、思考が袋小路に迷い込むと単純な発想が出てこないものです。

ここで以下のように変更しました。

ここで新たに作った帳票発行用アプリのレコードの構成は、帳票Onlineの仕様に完全に沿っています。明細行まで含め、レコード単位で帳票Onlineが解釈できるデータに分解しています。
そのレコードは、請求管理アプリのデータを加工し、生成するプログラムを作ってあげればよい。それはJavaScriptで実装できます。
また、帳票発行用アプリは発行専用です。そのため、データを貯める必要がありません。毎回、請求管理アプリでボタンが押される度に、帳票発行用アプリのレコードを全て削除し、その後でレコードを新規に追加する仕様にしました。
その際、JavaScriptの中ではいくつかのPromise処理が必要になりました。ですが、それは普段からプログラミングしている処理なのでさほど悩まずにできました。

その結果、お客様はMac端末のブラウザ上で帳票が出せるようになりました。間に挟んでいたWindowsは不要になったのです。もちろん、移動も不要で、リモートワークも可能です。
その代償として、購入した「ルックアップ機能」は不要になってしまいましたが、風神レポート設計の工数やスキルが無駄になるよりはよっぽどよかったと思います。何よりもお客様の求める運用が実現できましたし。

7.まとめ

Topへ↑

それにしても、kintoneがMacでも動くから、とMacを甘く見ていました。
よくよく考えると、kintoneにはしばしば周辺の仕組みが絡んできます。特にハードウエアを含めた構成の場合は。ドライバ、ライブラリなど、Macが絡むとうまく行かないことはよくありますよね。
Excel VBAマクロもそうです。Windowsでは動いていたマクロがMacでは動かないこともよくあります。そもそもファイルシステムが違うので仕方がないのですが。
今回は私がMac端末のことを真摯に考えていなかったことに原因があります。あわやプチ失敗しかけました。

まあ、結果として無事に動いたのでよかったです。
今ではアイ・コンさんのツールはブラウザ上で問題なく動いてくれています。複雑な帳票が設計・導入できたのも帳票Online+風神レポートのおかげ。
帳票Onlineは今年の弊社が関わった別案件でもドットインパクトプリンタで日々の帳票を出力してくれています。

帳票にはいろいろあります。中には複雑なものも。
今後もまだまだ業界によっては帳票出力が必要になることでしょう。そして、さまざまなパターンでの出力が求められるでしょう。
今回の件を通して、弊社は帳票設計と出力のスキルを豊かに蓄えられました。今後もさまざまなパターンでの対応ができるよう切磋琢磨したいと思います。
もしkintoneと帳票出力でお困りの方がいらっしゃいましたら、ご遠慮なくご連絡をくださいませ。帳票Online for kintoneで自在に設計してお目にかけます。


kintone Café JAPAN 2021でミッションに挑みました


11/13に催されたkintone Café JAPAN 2021は、全国のkintoneユーザーや技術者有志が集まるイベントです。有志によって運営されています。
毎回、さまざまな趣向をこらしたイベントが行われ、kintoneを愛する人々の知見と刺激と交流を生んでいます。

今回のJAPANでも複数のセッションが企画されていました。私は冒頭のセッション
Excelインポートミッション!君はこのトラップに気付けるか!?
のミッションに挑戦者として指名されました。技術者代表として。

このミッションの具体的な進行を私が運営者に教えてもらったのは、JAPANイベントが始まる30分前。
指令されたのは、Excelとkintoneを画面共有で皆さんに見せながら、その場でExcelに仕込まれた不正データを見抜き、データを整えた上でkintoneにインポートするミッション。

私にとって幸いだったことは、初っ端が私ではなかったことです。
最初の挑戦者であるキンスキ松井さんに課された10分間のミッション。これはまさにスリルに満ちていました。
頻発するエラーに四苦八苦される松井さんの姿を見ながら、私はミッションの雰囲気を把握することができました。


さて、私の出番です。私に割り当てられた時間は15分。技術者枠なのでさらに難易度はアップしています。
スタートの合図とともに、割り振られたスペース上のアプリとインポート対象のExcelを開きます。
すると、松井さんのミッションにはなかったルックアップやチェックボックスフィールドが加わっていました。さらには、Excel上での住所連結、氏名分割までも。
結局15分ではミッションをクリアできず、二回の延長をお願いして約20分を要してしまいました。
ただ、皆さんにはとても盛り上がってもらえたようです。Twitter上でたくさんの応援や感動したとのお褒めもいただきました。ありがとうございました。


このセッション、出た本人がいうのもなんですが、神企画だったと思います。
観覧されている皆さんにとっては、手に汗を握るスリルがあり、データをインポートする方法の知見がたまります。ミッションで使われるExcelのデータも一見それほど複雑ではないため、kintoneに触れて間もない方でも理解できる配慮がなされています。
さらに、ミッションを課された私にとっても、奔放なExcelデータをkintoneに取り込む経験がたまります。

実際、システム開発を営んでいると、今回のミッションで提供されたようなExcelに遭遇することはしばしばあります。
都道府県の列に見知らぬ県が混ざっていたり、誤字やスペースが混ざっていたりのデータはザラにあります。選択肢にない値や異体字、さらには違う文字コードのデータが混ざっていて文字化けする場合もあります。厄介なことに目には見えない改行コードが混ざっていることもあります。

普通、そうしたデータのインポートには時間をかけて対応します。入念に移行のデータを検証し、準備する時間を確保するのがセオリーです。
そうした移行に関する手続きは、昨年のkintone Advent Calendarで以下の記事としてアップしたのでご参考にしていただければ。
kintoneにシステム移したいんや

ただしこの記事に書いたような、移行の作業にじっくりと専念ができるかどうかは何ともいえません。そうはお客様が許してくれない場合があるからです。
例えばお客様先で利用を始める段になって、システムにバグが出ることもあります。それがプログラムのミスならまだいいのです。kintoneは修正が比較的容易にできるのですから。
問題はデータに不備があったり、アプリの設計と食い違っていたりした場合です。しかも、こちらの移行設計のミスならまだしも、お客様が直前で項目を修正したり、今までに発生していなかったデータがCSVに紛れ込んでいたりするからタチが悪い。
訪問したお客様先のその場で設計変更が必要になり、その場でデータを旧システムからもらい、その場でデータを加工して取り込む状況に追い込まれることだってありえます。

さすがに、お客様先で今回のミッションのように15分の制限時間を課されることはないでしょう。
ですが、技術者としては現場での応急対応が求められることは想定しておかないと。
アウェイの場での孤独な作業。お客様からの無言の期待と圧力を感じつつ、その場でExcelのデータとkintoneアプリの構成を比較して正しいデータに直す。それには臨機応変な対応が必要ですし、さまざまなエラーのパターンを同時に考えながら手を動かすことも必要です。こうした場数を経験しておくと後で技術者のキャリアの上で役に立ちます。
私も何回か、現場で加工したデータを取り込みなおしたことがあります。

こうしたやり方は従来のウォーターフォール型の開発では許されません。アジャイル開発やスクラム開発でもあまり推奨されないはずです。ですが、kintoneは症状の度合いによってこうしたLive感に満ちた開発・修正が可能です。むしろ、そこに真価を発揮します。
今回のミッションは、その経験を思い起こさせてくれました。また、出た当初のkintoneに惹かれた気持ちも思い出させてくれました。
このミッションにチャレンジすることは、kintone技術者としてのスキルを鍛えてくれるはずです。

Twitter上でもこのミッションを自社の研修に使ってみたいというつぶやきを見かけました。弊社でも同様にミッションを課してみようと思います。

司会の「けいん」さん
@soulxoxo

サポートの「よしみ」さん
@yoshiminxkay

一人目の挑戦者の「松井」さん
@kinsukicom

ガヤりの「とうげ」さん
@touge_moved

の皆様、ありがとうございました。あと、観覧者の皆様、声援ともどもありがとうございました。

時間が取れるかどうかはわかりませんが、今回のミッションの中で行った処理については、ゆくゆくは記事にしたいと思います。
なの、ケインさんがnoteでミッションに必要なアプリやExcel一式をダウンロードして使えるようにしてくださっています。

続いてのセッション『それkintoneで作って下さい!駄菓子屋さんの棚卸システムを1時間で仕上げちゃおう!
は、まさにkintoneのファストシステムの良い例です。
ファストシステム。最近ではこの言葉は使われていませんが、kintoneが出た当時はファストシステムと銘打たれていました。迅速に構築のできるシステムであることを訴えて。
今回のセッションでは、要件定義をもとに基本設計とアプリ構築を同時に行いながら、棚卸しシステムのプロトタイプを一時間で作り上げてしまいました。
このセッションは弊社のメンバーにぜひ見てもらいたいと思いました。従来のシステム開発なら、持ち帰って検討して要件定義した後に実装するため、早くても三週間はかかっていたでしょう。それが一時間でできてしまうkintoneの性能と機能をフルに活用した良い例です。

続いてのセッション『教えて!みんながkintoneから学んだこと』も良かったです。
先日のcybozu daysでは、kintone SIGNPOSTが正式にお披露目されました。現場の課題をどのようにシステム要件にし、それをシステムとして組み上げるか。その際はシステム開発に留まらず、コンセプトや社内のビジネスフローの再構築にまで話を広げる必要があります。その中では体制やコンセプトの整理も求められるでしょう。
現場の声としてあがった本セッションの内容は、kintone SIGNPOSTの生きた事例として参考になりました。

続いてのセッション『チャレンジ!きんとん関数ドリル』は、
ここ二年間でkintoneに追加された機能として特筆される関数を取り上げていました。このセッションではkintoneの関数の奥深さを味わうことができました。
私は出題された10問のうち6問しか合わず、関数についての理解の浅さを露見させてしまいました。
なんでもJavaScriptで解決してしまおうとする考えから切り替えていかなければ。
それにしても、松田さんによる関数の分析はお見事としか言いようがありません。ここまで理解してこそkintoneエバンジェリスト。私も精進しなければ。

この後もkintone SIGNPOSTの紹介や懇親会などがありました。が、実家にいた私は両親と食事に出かけたため、この後の懇親会には参加していません。さぞや盛り上がったことでしょう。

また来年も開催されると思うので、楽しみにしたいと思います。

重ねて皆様、ありがとうございました。

当日のTwitterまとめはこちらです。


kintone Café 神奈川 Vol.9を開催しました


九月二十八日にkintone Café 神奈川 Vol.9を開催しました。

qloba上の公式サイト。
https://kintonecafe-kanagawa.qloba.com/activities/11229

前々回のVol.7の中で、これからはkintone Café 神奈川は3カ月おきに開催する、と申し上げました。
なんとかその約束を守れました。まず、ご参加者の皆様やスタッフの皆様に感謝いたします。

今回は、まだリアルとオンラインのハイブリッド開催には時期尚早ということで、完全オンラインで開催しました。

今回のテーマは「使って/買ってよかったプラグイン」とさせていただきました。
kintoneの良さは、プラグインを活用することでより輝きを増す。そのことに異論のあるかたはいらっしゃらないでしょう。
kintoneが単体で弱い部分をプラグインで補う。例えばJavaScriptによる開発は、プログラマーやシステム・エンジニアなら可能です。でも、そうではない方がkintoneをよりよく使うには、開発ベンダーに開発を依頼するか、プラグインを導入するかのどちらかです。


清水さんのセッション「顧客管理アプリと使ってよかったプラグイン」は、その生きた実例でした。導入プラグインはgusuku CustomineとCalendar Plusの二つのみ。ですが、その二つをとことん使い込み、活用しつくすことで業務を回しておられます。
Customineの設定の実画面や、デモを利用したkintoneのカスタマイズをノンコーディングで行う様子は、まさにkintoneの可能性を見せてくれました。たとえプログラミングができなくても、プラグインを使えば何でもできてしまう。その可能性に満ちたセッションでした。
実は清水さんがkintoneを使っていこうと決意して、初めて参加したコミュニティこそ、私が主宰したkintone Café だったのですね。そのご縁に感慨もありました。清水さん、ありがとうございました。


続いて鈴木さんのセッション「私のイチ推しプラグイン」です。656アプリを誰でも業務カイゼン、みんなで業務カイゼンの名のもとに、自由に使ってもらう。それだけでも見事ですが、読み込み済みのプラグインは83。
それほどの数のプラグインを使いこなしているだけあり、検索プラグインの各社ごとの比較はとても参考になるものでした。そして、計算式プラグインの詳細な紹介。これもまさに見事。開発ベンダーの目からみても、価格と機能を考えると、自社で開発して提供するより、はじめからプラグインで提案した方が良いと思わせるものでした。見事でした。鈴木さん、ありがとうございました。


続いて、LTです。まずは藤村さんよりプラグインの選び方について。藤村さんは昨年のkintone Hackの本選に出場されています。プラグインは数多くありますが、なんでも取り入れるのではなく、「やりたいこと」を意識する。そしてプラグインの内容をきちんと吟味した上で選ぶ。その大切さを教えてくださいました。
このことはkintoneを使う上で学ぶべきことです。藤村さん、ありがとうございました。


続いては金春さん。御存じアールスリーインスティテュートでgusuku Customineの製品を統括されています。金春さんからはgusuku Customineをなぜ作ったのか。今までの発展と、これからの可能性について教わりました。清水さんのセッションでもCustomineの威力は分かりました。実は弊社でもお客様にgusuku Customineをお勧めし、短納期で複雑な案件を納品にこぎつけた経験もあり、開発ベンダーであっても可能性を知っています。なぜCustomineを作ったかというのは私も初めて伺いましたし、サポートや頻繁な機能追加にもかかわらず値上げをしていないなど、金春さんの本気度とgusuku Customineの可能性を感じました。金春さん、ありがとうございました。


続いては吉田さん。kintoneエバンジェリストとしてkintone Café 浜松を主宰されています。浜松は全国のkintone Caféでも断トツの開催回数を誇っています。
吉田さんが話してくださったのはfreee for kintoneについて。会計クラウドであるfreeeとkintoneをつなぐプラグインですが、freeeの充実したAPIリファレンスの紹介や、freee for kintoneを使うことでかえってカスタマイズが必要になることもあるなど、開発者の実体験に即した内容でした。弊社もfreeeは良く扱っているだけに、とても分かりました。吉田さん、ありがとうございました。


最後に弊社代表の長井です。コロナ陽性からの回復途上にある中、リハビリテーションもかねての参加。LTの内容は数日前に遭難した山の中で考えました。そもそも開発ベンダーとして、JavaScriptやプラグイン開発も行うのは当然ですが、場合によっては既存のプラグインを提案することもありではないか。
その観点から、弊社としての判断基準を語ってみました。もっとも忘れてはならないのは、あくまでもお客様のご希望を優先することです。開発ベンダーとしてはなるべく自社で開発したい気持ちは良く分かりますが、場合によっては既存のプラグインを使うこともありではないか、ということを話しました。

その後の質疑応答の時間でも皆様から積極的な質問を頂きました。プラグインをテーマにしたことに手応えを感じた時間でした。

21時からは、ご希望する方で懇親会。ここでもプラグインの活用や今後のkintone Café、10月のkintoneアップデートなど、多彩な話題で盛り上がりました。22時半まで。

いやぁ、ご参加の皆様、スタッフの皆様、ありがとうございました。また次は3カ月後の開催を目指して手応えを感じました。またお会いしましょう!


チーム応援カフェ Vol.2に登壇しました



前日のサイボウズユーザーフェスティバルに続いて、チーム応援カフェVol.2にも登壇しました。

非営利団体のIT導入の課題を解決するための交流会です。
https://npo.cybozu.co.jp/blog/post/149/

Vol.1の開催前日に今回の登壇依頼をいただきました。

2018/5/16にチーム応援ライセンス開始記念セミナーで弊社代表が登壇しました。
サイボウズ社の記事
弊社の記事

今回はその時に話した自治会のIT化をベースに、現状とその後の課題を含めてお話しました。

当時登壇してから三年。今の世界はコロナウィルスによるリモートワークが普通になっています。
それもあって、非営利団体の運営においても対面ではなくリモートワークによる運営が一般的になりつつある、わけではなさそうです。
自治会は年齢層など、コロナだからと言って簡単にリモートワークに踏み切れない要因があります。

今回はそのあたりも含めてお話させていただきました。
また、kintoneを自治会で活用することについても、前回より踏み込んで書いてみました。

スライドはこちらです。

今回は40名弱の方にご参加いただいていましたが、年齢層が高い方へのIT導入について活発なご質問をさまざまな方からいただきました。
そのほかにもさまざまなご質問が多様な角度から飛び交い、皆様の関心度の高さを感じました。ありがとうございます。

これについては各自治体も課題として挙げておられるようです。代表の方にもそうしたご相談がちょくちょく来はじめています。
そこで今回は提案を含めてみました。

各自治体がセミナーを自治会向けに開催し、その中で弊社がセミナーを開催させていただくのはいかがでしょうか、と。

今の世の中の在り方はコロナによって流動的になっています。ビジネスも業種によっては大幅なダメージを被っています。
自治会についてもあり方や運営について、より変化が求められることは間違いないでしょう。
弊社も引き続きこの方向で何が出来るのかを考えていきたいと思います。

ご参加の皆様、サイボウズ社の皆様、ありがとうございました。


サイボウズユーザフェスティバルに登壇してきました


先日、7/20にサイボウズユーザーフェスティバルが開催されました。
https://page.cybozu.co.jp/-/userfes

弊社代表が、その中のセッション「kintoneエバンジェリストが厳選 教えて!今知っておくべき活用術ランキング」に登壇したので、そのレポートをお送りしたいと思います。

今、kintoneエバンジェリストは全国で19名が活動しています。
このセッションでは、その19名のエバンジェリスト全員がアイデアを持ち寄り、kintoneを使う上でこれだけは知っておいた方がよいと考える活用術のうち投票で上位に選ばれた五つを紹介しました。

紹介するのは、弊社代表も含めた四名のkintoneエバンジェリスト。サイボウズ東京オフィスと福岡オフィスの二拠点に二名ずつに分かれて連携しながら、オンラインで配信する。
そんな試みにあたって、弊社代表は東京オフィス側で登壇しました。

コロナ以降、オンライン配信は普通になりつつあります。代表もZoomなどで配信は何度も行っています。個人で簡単に配信することができるようになってきたのです。

ですが、今回のサイボウズユーザーフェスティバルは、きちんと配信用のコンソール卓が用意された本格的な配信です。東京と福岡で交互に連携をとりながら、タイミングを合わせて配信するにはそれなりの装備が必要です。
こうしたきちんとした配信は、代表は昨年の12月にCybozu Days 2020 Osakaで経験済みです。とはいえ、やはり緊張しますね。今回、最初は少しだけ硬かったように思います。

でも、大丈夫。東京にはニ名の、福岡では一名のサイボウズ社の方がフォローしてくださったことで順調に進みました。ありがとうございます。

さて、今回のセッションで選ばれた五つの活用術は、投票で上位に選ばれただけのことはあります。皆様にとってためになったのではないでしょうか。

「意外と知らない?!グラフの便利術!」
グラフで凡例をクリックすることで表示を切り替えられる。実はこれ、代表も知らなかった機能でした。
kintoneの標準機能にもまだまだ知らない便利な隠し技があるのかも。そう思わせてくれるすてきな活用術でした。

「迷子にならないためのkintone活用術」
こちらは代表が挙げた活用術です。ポータルのカスタマイズは奥が深く、弊社もまだまだこれからの部分です。今後、皆さんから多彩な技が報告され、ノウハウがたまっていくだろうと思っています。
私の前に用意されたモニターの文字がよく見えず、一緒に登壇した松田さんからの振りに見当はずれの返しをしてしまった気がしますが、そこはうまく松田さんがフォローしてくださいました。ありがとうございます。

「エバだからこそ伝えたい!kintone前提で考えないこと」
これも重要な活用術です。あえてkintoneを使わないのに活用術!?
私たちも構築する際、ついkintoneで完結させようと頑張ってしまいます。実際、ユーザー様からもなるべくkintoneで操作をまとめたいとのご要望をいただくからです。
ですが、無理やりkintone上でカスタマイズしてしまうことが正しいとは限らない。そうなのです。そこに完璧な正解はありません。
代表自身、あらためて深く考えさせられました。

「kintoneの活用情報に出会うコツ」
サイボウズユーザーフェスティバルの前日に、kintoneコミュニティ案内版が正式にリリースされました。弊社代表の記事が最初にアップされた五本の記事に選んでいただいています。
kintoneのコミュニティは活発です。並み居るPaaS/SaaSの中でも屈指だと言えます。ですが、活発であるが故に、増えてきたコミュニティをどのように乗りこなしていくかは迷います。
初めての方にとってまずTwitterでハッシュタグをつけて発信することの大切さも含め、とっかかりとなる情報がお届けできたのではないかと思います。

「標準機能で「計算」する際に知っておくべきポイント」
kintoneの関数を使いこなし、関数だけでデータを加工してしまうお見事な皆さん。いわゆる関数芸の使い手の方々です。
最近のアップデートで拡充されたkintoneの関数は、関数を究める楽しみを与えてくれました。

ですが、関数もコツを抑えておかねば、困ったことになってしまいます。Excelのように。
Excelを個人が囲い込んで育てるとアンタッチャブルな闇ブックが多数生産される。まさにブラックボックスのように。
代表もかつて、某銀行の中で無数のExcelツールを整理し、汎用化する仕事に携わっていました。Excelは簡単にダークサイドに堕ちるのです。
kintoneも同じ。この活用術は、kintoneを闇堕ちさせないための貴重な情報が込められていました。

「kintoneの禁断カスタマイズに気をつけて!!」
これもまたkintoneを使う上で陥りがちなワナです。
HTMLとJavaScriptとCSSで表示するシステムであるが故に、やろうと思えばどんなことだってできてしまいます。
ですが、無思慮にDOMを変えてしまうと、kintoneのバージョンアップに伴ってそれらのカスタマイズがバグを生む可能性は十分にあります。
これは、技術者のサガとして突っ走ってしまいがち。その懸念をきちんとした形でエバンジェリストから発信できたことはよかったと思います。

「ルックアップフィールドの落とし穴に気をつけて!!」
この活用術は、私が動画の作成も含めて担当しました。自分で録画したとはいえ、動画にナレーションを充てるタイミングが不安でしたが、何とかやり遂げられたように思います。
ルックアップフィールドこそは、kintoneを初めて扱うシステムエンジニアがまず戸惑う部分です。kintoneはルックアップを理解できれば大丈夫。
その際に陥りがちなワナを説明できたのではないかと思います。

さて、配信も無事に終わりました。まずは安心。
こちらは当日のスライドです。

この日は上に書いた通り、サイボウズ社の本社からの発信でした。
そのため、代表と一緒にうちの社のメンバーにサイボウズ社を案内できるよい機会でした。今年から参画してもらってからというもの、一度もつれてきていなかったので。

サイボウズ社のオフィスに広がる遊び心にあふれた設えの数々。そこから、サイボウズ社の社風や考え方の一端を感じてもらえるのではないかと思いました。
kintoneを単なるツールとして扱ってほしくない。機能とその背景となる考え方についても理解し、愛着を持ってほしい。

いわゆるよくあるオフィスとはかけ離れた様子に、興味津々のうちのメンバーたち。今回は二人のパートナー企業の方にも来ていただきました。
サイボウズ社の社風や、kintoneの可能性について理解してもらえたのであればよいのですが。

ただ、フェスティバルの日は弊社の毎週行っている対面開発の日に充てさせてもらいました。それもあって、登壇の直前まで内部で打ち合わせを行っていましたし、終わった後もそれぞれの作業のフォローに勤しんでいました。
それもあって、代表もメンバーもサイボウズユーザーフェスティバルのセッションはあまり聞けていません。

ですが、代表が登壇している間はセッションに集中してくれていたと聞いています。
うちのメンバーがサイボウズ社やkintoneに愛着を持ってくれたと確信しています。そしてもちろん、サイボウズユーザーフェスティバルをご覧いただいた皆様も!
皆様!ありがとうございました!

そうした見学の機会も含め、サイボウズ社のうっし-さん、かんちゃん、関根さん、配信ご担当の方、ありがとうございました!


kintone Café 浜松 Vol.31に参加してきました



先日、7/9にkintone Café 浜松 Vol.31に参加してきました。

代表の長井は先日のkintone Café 神奈川 Vol.8で語った「kintoneを活用するためのデータの持ち方」をLTバージョンに短縮して。

そしてうちの青木さんからはkintone機能改善の要望を。まだkintoneに触れはじめてそれほどたっていない立場からの思いが伝わりました。
kintoneの標準の検索機能についてはなんとかならないか、というのは私の思いでもあります。

他にもIntegromatとkintoneの連携について、中西さんと松尾さんがLTを続けてくださいまして。

https://note.com/matsuo_atsushi/n/ncfd0bcfcf31e

mizusawaさんのLTも連携事例がとても参考になりました。

私にとって今回のkintone Café 浜松 Vol.31は、うちの青木さんから「kintoneをやっていて初めて楽しいと思った」という言葉が出たことが全てです。
うれしいですね。

この日はうちのメンバーが揃っての対面開発の日。私と青木さんが同じ場からオンラインで参加したのですが、まさに青木さんの喜びを眼前にできました。

また今度のkintone CaféでもLTをしてもらおうと思っています。


kintone Café 神奈川 Vol.8を開催しました


六月二十二日にkintone Café神奈川を開催しました。

qloba上の公式サイト。
https://kintonecafe-kanagawa.qloba.com/activities/10622

前回のVol.7の中で、これからはkintone Café 神奈川は3カ月おきに開催する、と申し上げました。
なんとかその約束を守れました。まず、ご参加者の皆様やスタッフの皆様に感謝いたします。

今回は、上のサイトにも書いた通り、リアルとオンラインのハイブリッド開催を目指しました。
コロナが世を騒がし始めてからというもの、リアルで人と会う機会は極めて限られてきました。そのため、そろそろリアルでも開催したい。そう思っていました。
もちろん、コロナのワクチンが行き渡った後も、人々がリモートを手放すことはないはずです。ということは、リアルとリモートの両方を兼ねたイベントが主流になるに違いない。
今回ハイブリッドでやりたいというスタッフの山田さんの提案に私も乗らせていただきました。

今回のテーマは「kintoneとSalesforceを比較して、データの持ち方を考える」とさせていただきました。
kintoneの良さは、同じ分野で競う他のシステムと比べてみることでより一層際立つことでしょう。
むしろ、お互いの得意分野や長所を生かしつつ、適材適所で利用していけばよいのですから。

その意味でも、Salesforceを活用してのSIer活動をされていらっしゃる植本さんの発表は興味深いものがありました。
特に、Salesforceはその名前からしてもSalesに強いことは明らかです。SFA(Sales Force Automation)とは、まさにSalesforceの代名詞。
それらの強みを発表いただいたことで、なるほど、という反応がありました。
やはり、成り立ちや強みを生かして使えるところは使っていけばよいのです。
植本さん、ありがとうございました。


続いて、弊社代表長井より、「kintoneを活用するためのデータの持ち方」の発表でした。
kintoneもSalesforceもを導入するためには、データの持ち方の知識が欠かせません。
そこでkintoneのアプリがどのようなデータ構造から成り立っているかを話させていただきました。

https://slides.com/yoshikazunagai/kintone-cafe-kanagawa-vol-8-2

技術者であればデータベースを扱う機会は多いはずです。中でもSQLを使っての構築は多くの現場でいまだに現役だと思います。
ですが、kintoneを扱っていると、kintoneを意識することなくデータが扱えてしまいます。ですが、最適なデータの構造でアプリを構築するには、SQLの構造を理解していることが望ましいです。

その観点から発表させていただきました。ありがたいことに、皆様からの反応を頂けたのは良かったです。ちょっとマスクとマイクがこすれて異音を生じていたのは私の不覚です。もうしわけございませんでした。

さて、今日は緊急事態宣言が明けたとはいえ、神奈川県ではまん延防止法が適用されていました。そのため、会場に入るなり、20時までしか会場が使えないことが発覚しました。時間内に終わらせるため、私のセッションはかなり速足で語りました。
さらに続けてLTは二名の方に語ってもらいました。
一人目は弊社の武塙さんです。今年の春先にSalesforceからkintoneへの移管案件を手掛けた弊社。武塙さんはその時の経験からフィールド名の移管ルールについて実務経験者としての苦労を語ってくださいました。こうやって発表し、登壇する経験は今後もやっていってほしいですね。確実に自信につながりますから。
二人目はkintoneエバンジェリストでもあるkintone Café 浜松を主催されている吉田さんからです。シェルスクリプトも交えながらのSalesforceからkintoneの移管事例を語ってくださいました。特に添付ファイルの扱いについては、皆さん苦労されているようです。(弊社も一昨年に手掛けたSalesforceからkintoneの移管案件ではboxを組み合わせてURLでkintoneに移管しました)
お二人のご参加によって、今回のテーマがより定まったと思います。

20時で一旦会場を締めた後は、リアルの場からオンライン上の懇親会につなげるための場所探しを。ですが、武蔵小杉近辺の店はほとんどしまっており、残念ながらつなげられそうな場所は見つかりませんでした。そこで、主催の長井のみ現場に残り、某ビルの中からつながせて参加しました。
懇親会でもkintoneの深イィ話で盛り上がり、kintone Café の醍醐味である懇親会を存分に楽しみました。

いやぁ、ご参加の皆様、スタッフの皆様、ありがとうございました。会場を手配し、司会進行を務めてくださった山田さん、会場にお越しいただいた松尾さん、原田さん。オンラインの場で参加してくださった加藤さん、渋屋さん(植本さんのご紹介やテーマのご提案ありがとうございます)、鈴木さん(スタッフへようこそ)。また3カ月後にお会いできればと思います!


kintone Café 神奈川 Vol.7を開催しました



3/26にkintone Café 神奈川 Vol.7を開催しました。

開催の内容については、翌日に早くも渋屋さんがブログとしてアップしてくださいました。
https://100athlon.com/kintone-cafe-kanagawa-7/
松尾さんもアップしてくださいました。
https://note.com/matsuo_atsushi/n/nce32e0c0786b

私も渋屋さんと同じ感想ですね。松尾さんのセッションでFileMakerがkintoneの競合どころか、お互いの足りない部分を補い合える製品であることを知ったのは大収穫でした。23年前、私が初めて持ち帰りの仕事を受けたのはFileMakerを使った仕事だったというのに、全く状況を追えていなかった不明を恥じました。データ量や帳票などが整備されているのはさすが歴史のあるソフトウエアですね。
渋屋さんのセッションもテーマを深めるための冒頭の問題提議としてピッタリでした。最初にテーマに沿ったセッションを話してくださったことで、皆さんがkintone Caféの雰囲気になじめたと思っています。今回はzoomのチャットがとても盛り上がり、コメントも次々と書き連ねられたのですが、渋屋さんのセッションのおかげだと思っています。これは有効ですね。

LTは瀧村さん、松村さん、加藤さんと3人の方に登壇していただきました。
瀧村さんは、自己紹介をkintoneの基本機能と拡張機能を駆使した、まさに豪華絢爛kintone絵巻のような内容でした。わずかな間にkintoneの魅力を詰め込むところなど素晴らしい。エバンジェリストとして参考になりました。
松村さんは上海からご参加。kintoneを製造業に提案することの難しさと課題について素晴らしい問題提起をしてくださいました。中国のkintone事情にも触れたセッションに興味はつきませんでした。私も製造業へのkintone導入の提案については何度も跳ね返されています。このテーマで今後、セッションをお願いしたいくらいです。
加藤さんはkintone Café神奈川を立ち上げた方ですが、当日の朝にLTをお願いしたところ、快諾してくださいました。プラグインをあらためて紹介してくださったことで、あらためて浮き彫りになったのは、kintoneの標準機能の弱さです。まさに今回のテーマにふさわしく、kintoneでできること、できないことがプラグインからみえてきたように思います。
登壇してくださった皆様、ありがとうございました。

今回は、開催にあたっていくつか運用を変えました。最も大きい変更は、私自身が受け持つセッションをやめたことです。
今回、私は司会・進行に徹しました。セッションもLTにも登壇せず、冒頭の『kintone Caféとは?』を話したくらいで。
『kintone Caféとは?』では、あらためて過去のkintone Caféの開催状況を調べ直し、地図にして皆さんにお見せしました。地図を作りながら感じたのは、神奈川の開催回数の少なさです。

今まで私が携わったkintone Café 神奈川 Vol.2からVol.6までは、私が運営にも携わり、司会と進行を行うとともに、セッションも受け持っていました。
その体制のままだと、私が忙しくなると開催できず、開催間隔も延びます。
以前から神奈川の開催回数は少ないと感じていたのですが、今回、地図を作ることでそれを実感しました。それも私の忙しさのせいです。

そこで、前回のVol.6では、スタッフ体制を組みました。そのスタッフ体制を維持したまま、今回のVol.7を企画しました。企画にあたっても、最初から私は登壇もLTもしないと決めていました。
今回は、テーマも渋屋さんの発案です。

冒頭の『kintone Caféとは?』では、今後のkintone Café 神奈川は三カ月おきに開催する、と宣言しました。それもスタッフの皆さんのご協力があってこそ行えます。
次回以降、私は司会・進行すらしないかもしれません。

今回は懇親会の中でもスタッフを募りました。その結果、お二人の方が手を挙げてくださり、お一方はすでにやりとりもさせていただいています。また、当初、神奈川を立ち上げてくださった加藤さんにもあらためて入ってもらいました。
これでスタッフは私を含めて六人以上です。むやみに増やすのも考えものなので、これ以上募るかどうかは分かりません。ですが、次回以降は私がいなくても開催はできるのではないかと思います。

私の中で印象に残ったのは、懇親会で松田さんがおっしゃったひとことです。
今はオンラインなので地域別に分ける意味合いが薄れている。だから、主催者の色や個性が重要になるのではないか。とても良い意見で、参考になりました。ありがとうございます。
これからのkintone Café 神奈川も、これからは多様な色を出しつつも、どこかで私なりの特色を出しつつけてられるよう、考え続けていきたいと思います。

今回、ご参加してくださった皆様、誠にありがとうございました。


事例:北新海運様


kintoneを導入したことによる日常業務の効率化

  Topへ↓

北新海運様は、海運の国内運送を主に担っておられます。
海外の船がコンテナバースに到着し、荷揚げされたコンテナ。この荷物を国内のお客様に運ぶのが北新海運様の業務です。

従来はExcelで運用されていたお客様への請求業務や、ドライバーへの指示、ドライバーの稼働実績の取りまとめ。
それらをリリース間もないkintoneに切り替えることで、運用工数の削減を実現しました。

Excelによる単価管理やドライバーへの指示業務の煩雑化

  Topへ↑

お客様からのご発注を受け、それをドライバーへの運行指示書に印刷する。そして、その結果をお客様への請求書として発行する。ご発注から請求までの流れは単純に書くとこのような感じです。
ところが、お客様からの発送指示は千差万別。その発送場所によって単価が変わります。また、コンテナのフィートによっても単価が変わります。
配車指示を的確に行わねば、効率的な運用はできません。
また、案件ごとに単価が変わるので、その単価を的確に反映した請求書を発行し、同時にお客様によっては請求データを一覧表として発行しなければなりません。
そうした複雑な業務が伴う海運業務を行うには、Excelでは限界が生じていました。

また、ドライバーが従事した業務によって手当を計算する作業も負担になっていました。
複数の場所で荷を下ろす場合や、積み場所の変化。さらには、構内業務に従事する場合には別の計算方法が必要です。そして、それらが組み合わさった場合の作業もきちんと集計せねばなりません。そうした複雑な作業実績の集計は業務の負担となっていました。

リリースしたばかりのkintoneを提案し、採用。

  Topへ↑

Excelから離れ、新たなシステムを構築しなければ。
北新海運様で事務を統括する立場にあった紀村様は、旧知のデザイナー様に相談しました。
相談を受けた株式会社アトリエmの室井様は、そのご相談を受け、弊社にご相談くださいました。

その当時、まさにリリースされたのがクラウドサービス「cybozu.com」とそのサービスの一つであるkintoneでした。私はこのkintoneのβテスターであり、kintoneがリリースされたタイミングで導入できる機会を待っていました。そこにいただいたのが北新海運様のお話。
2012年の正月明けに北新海運様にお伺いし、紀村様にご要望を伺いました。
そしてご要望がkintoneで実現できると判断し、kintoneをご提案しました。

社長様は初めて会った私と、出来たばかりのサービスであるkintoneを信頼してくださいました。そして、ご発注にいたりました。
それが2012年1月26日のことです。

APIのリファレンスがなかった時期ゆえの苦労

  Topへ↑

私の手元には、この当時にサイボウズさんから頂いたMicrosoft Wordの「kintone API マニュアル」があります。表紙にはV0.1と書かれています。
この当時、リリースされたばかりのkintoneにはすでにAPIが実装されていました。とはいえ、レコードの追加・取得・更新・削除ぐらいしかできませんでした。今のリクエスト方法やレスポンス結果とそう仕組みは変わらないとはいえ、今のようなリファレンスは整っておらず、ウェブ上にブログなどの情報もほとんどありませんでした。
加えて、当時の私はRest APIを使った実装の経験がなく、ノウハウも持っていませんでした。

他にも問題はありました。それは、帳票をどうやって出すか、でした。
当時はまだプラグインの仕組みがありません。つまり、今のようなサードパーティーさんによる帳票発行プラグインもありません。
kintoneを使ってどうすれば帳票を出せるのか。まずその調査から始めました。

当時、すでに私は某案件でWeb上のphpライブラリ(TCPDF+FPDI)を使って帳票発行を実装した経験がありました。
そもそも、北新海運様からお話を伺った当初は、Accessによる実装という選択肢も有力でした。kintoneとAccessのどちらを採用するか決めかねていました。
Accessのレポートで帳票を出すのか、それともウェブ上でphpを使って帳票を出すのか。
私はそのどちらでもなく、Excelを使うことにしました。

VBA(Excelマクロ)からRest APIのリクエストを出し、その結果を受け取れれば、Excelで帳票が出せるのではないか。
私はそう判断し、ウェブ上であれこれと調べ、何とか実装にこぎつけられました。

結果、2012年の4月から運用を開始しました。ですが、当初は何度も調整が発生しました。
私自身、まだkintoneを完全に理解出来ておらず、ルックアップフィールドをはじめとしたフィールドの載せ替えなども何度も行いました。
夏前まではさまざまな調整が発生しましたし、帳票の発行についてもレイアウトや表示書式などなんども調整しました。おそらく全て落ち着くまでは1年はかかったように思います。

導入して9年

  Topへ↑

その後、当初の実装フェーズには含めていなかったドライバーの実績集計についても実装を終え、そちらも運用を開始しました。
さらに、北新海運様の業務拡張による別会社設立の際も、同じ仕組みの上に若干のカスタマイズを加えて実装し、運用を開始しました。

以来九年、Excelによる帳票発行の仕組みも含め、北新海運ともう一社の仕組みは動いています。

紀村様より

導入からの9年について、紀村様はこう語ってくださいました。

「アクアビット長井さんの原稿を拝見し、9年前の導入当時を思い出します。

弊社 有限会社北新海運は今年で創業17年目の会社になります。
9年前、私は入社3年目で事務全般を担当しておりました。その作業内容は受注・売上・請求だけではなく運賃管理・ドライバーの売上管理、それに伴う給料計算に至るまで殆ど全てでした。さらに車両の増車に伴う業務負担もあり現行をやり過ごすことが出来たとしても近い将来、必ず困った事態に陥る事は目に見えていたのです。

とはいえ当時リーマンショックからやっと立ち直ったばかりの小さな会社、そして海上コンテナ業界は輸出・輸入という特殊な世界のため専門ソフトがない中、システム導入を専門会社に依頼すれば何百万単位の金額が出てくる事は以前に在籍していた他社で見聞きし、十分に分かっていることでした。
コロナ禍における在宅勤務による環境の大きな変化でシステムが予算的にも身近になった昨今と違い、当時はシステムゼロからの依頼は予算の乏しい会社にとっては大きなハードルだったのです。

そこで広告・宣伝・HP作成等々の会社を経営なさっている友人にその問題点を相談をしたところ、アクアビットの長井さんをご紹介いただきました。
長井さんには何度も打ち合わせには来社、この業界の業務の流れをいちから丁寧に聞いてくださり、夜遅くなることもしばしばありました。

当時は長井さんが個人事業主ということもあり少し不安ではありましたが、kintoneを使ってのシステム構築でコストを非常に下げられるご提案を頂いたことで、初期投資として仮にリスクがあっても最小限にとどめられる事も想定し社長が決断して下さいました。
導入事例の中では1年程かかったとの文面がありましたが、kintoneの業務作業を並行・チェックをしながら手直しをし、追加リクエストもあったので、実は2年位はかかったと思います。その後、長井さんとのやり取りも年々少なくなってきましたが、それは業務システムが問題なく動いている証拠だと思います…いや、実はリクエストはまだまだありますが、kintoneバージョンアップがそこまでいっていないというのも本音です(笑)。

大手企業が作るシステムも大事ですが、実は中小企業の“小”の会社こそがこの様なシステムをすぐにでも必要としていると思います。初期投資が大きいために二の足を踏むオーナーさんも沢山いらっしゃると思います。そのなかには直ぐにでも使えるシステムが欲しい中高齢のアナログ世代の方々が相当いらっしゃいます。少なくともコンテナ輸送業界はそうです。
その様な会社を直ぐにフォロー出来るのがkintoneだと私は思います。
そして、この業界を少しでも知る長井さんの様なアドバイザー的な方がもっと増えることも今は大事かと考えます。

長井さんにはずっと以前よりkintoneの講習会参加を勧められておりましたが、今だ実現に至っておりません。コロナ禍収束の折には講習参加を真剣に考えたいと思っている今日この頃です。
有限会社北新海運 紀村多栄」

溝木様より

また、北新海運の溝木社長からはこのようなありがたいお言葉をいただきました。抜粋して掲載させていただきます。

「弊社も今年で創業16年になります。
長井様には色々なご相談に乗って頂き大変助かっております。
最初のころは、私はExcel、Wordも分からず、パソコンには色々苦労しました。

そこでお知り合いになったのが長井様で御座います。
弊社にとって何か良い業務方法ないか、何回も同じことを打つのではなく一回で作業を終わらす方法、当時、長井様は色々な方法を考えて下さいました、弊社の要望を聞きながら猛勉強をされたと思います。弊社の職業柄大変だったと思います。とても使いやすく助かっております。

専門的なことは今でも分かりませんが、長井様のおかげで業務が短縮になったのは確かです、継続は力なりとありますが、今では弊社にとって最高のパートナーです。
私がこれをやりたいとお話すると、私の考えが分かっているかのようにパソコンExcel、kintoneを組んでくれます。

昔の人は、「人は必要だから出会うと言います」必要でないのなら一生出会う
ことはないでしょう。
弊社もこれから色々なことに挑戦していきます、その度に長井様にお願いする
ことが多いと思います。
これからも末長く宜しくお願い致します。

有限会社北新海運 
代表取締役 溝木昭夫」

まとめ

涙が出そうになるほど、感動しました。
お二方より頂いた文章は、段落を整えた以外はなにも直していません。私と弊社にとってとても心強く、嬉しいお言葉です。

私も今までにいくつもの失敗をしてきました。特に、kintoneに出会う前、ホームページ制作を手掛けていた時期は。何度も。
でもこうしたお言葉をいただけると頑張ってきてよかったと思えますし、これからも頑張ろうと思えます。また、kintoneが私のスタイルに合っていたのだと強く思います。
北新海運の皆様、本当にありがとうございます。また、ご紹介を頂いたアトリエmの室井様、本当にありがとうございます。

北新海運様のご紹介

商号 有限会社 北新海運
本社 〒272-0522 千葉県市川市宮久保5-9-7
   
本社営業所 〒143-0001 東京都大田区東海5-4-1 大井海貨5号上屋北側1階
TEL 03-5755-7813
FAX 03-5755-7814
代表者 取締役 溝木 昭夫
従業員数 25名
設立 2005年(平成17年)9月28日
資本金 500万円
ウェブサイト http://www.hokushinkaiun.com/

kintoneが今年、拡がるために


はじめに

あけましておめでとうございます。
今年もよろしくお願いします。

弊社の年頭の抱負はこちらにアップした通りです。
その中で、kintoneを軸にするという項で、今年も弊社はkintoneに注力する旨を書きました。

そんな中、年始の2日に家族とワインを飲みながら団らんしていました。
テレビには家族が観たい「逃げるは恥だが役に立つ ガンバレ人類!新春スペシャル!! 」が映っていました。
そこに登場したテーマがコロナであり、選択式夫婦別姓であり、リモートワークであり、働き方でした。

私はドラマを観ながら、これってサイボウズさんの打ち出しとるテーマやんか、と目をみはりました。

昨年、弊社にとって顕著にkintone案件が増えました。また、旧システムからkintoneにシステムを移行したいとの案件のご依頼も増えました(ブログ)。
おそらく、その流れは今年も続いていくことでしょう。
それは、サイボウズさんの掲げる理念が世の中に広まったこととkintoneの魅力が世の中に行き渡りつつある証しだと思っています。
もともと、そうした働き方を変えたいとの機運は世に行き渡りつつありましたが、昨年のコロナはそれを促したのだと思っています。

ただ、kintoneはまだ世の中で誰もが知っている存在になっていません。
弊社のレベルでは顕著に案件が増えたとはいえ、それはもともと弊社が受けていた案件数が少なかっただけの話。
弊社の尺度ではなく、世の中全体でのkintoneのシェアを考えると、kintoneにはもっと広まる余地も拡がる伸びしろもあるはずです。
今年はその流れがより速まり、より拡がるはずです。より多様な業種や規模の企業にkintoneが採用されることでしょう。

ただ、それを口で予想するだけで済ませてはなりません。
自らが率先してその流れをより速め、広げていくことがkintoneエバンジェリストの役目であり、サイボウズ・オフィシャルパートナーとしての存在意義だと思っています。

そこで、kintoneに何が必要か。それを年頭に考えてみました。

kintoneの弱点

まず、kintoneに足りないのは、規模でしょうか。
今のところ、大規模案件や中小以上の規模の基幹システム案件に対して、kintoneを勧められる状態にはありません。
というのも、
https://jp.cybozu.help/k/ja/admin/limitation/limit.html
にも書かれているとおり、100万件以上のレコード件数に対しての品質保証が明記されていないからです。

過去データを保存する期間は、法令によると受発注や仕訳だと七年が定められているようです。
月間15000件の伝票が発生するお客様の場合、一年で180,000件。七年で1,260,000件のデータが発生します。
つまり法令上の保存レコード件数をkintoneが満たせないと見なされる可能性があります。

US版のKintoneは完全にAWSが基盤となったそうですから、オートスケールには対応しているはずです。

日本版のkintoneについても、今、サイボウズさんではNecoプロジェクトとManekiプロジェクトが進行中だそうです。


その成果を待ちたいと思います。

kintoneはもう一つ、アカウント管理回りにも改善の余地がありそうです。
例えば、大企業の複雑かつ大きな組織が一斉に組織改編を行う場合を考えてみましょう。周知のとおり、Cybozu.comのアカウント設定では組織の事前設定ができます。とはいえ、なかなか思った通りにいきません。ま、弊社はその部分の作業をお客様に委ねてしまっているのですが。
あと、ゲストスペース内アプリの権限設定の際に組織やグループが使えないのも不便だと思っています。

あと、スペースやレコード上のコメント機能も、ChatWorkやSlack並みの使いやすさをお客様から求められることがままあります。
kintoneの良さは、コミュニケーションとデータの融合にあると思うので、コミュニケーション機能のより一層の拡充は期待したいですね。

技術者としてすべきこと

さて、新年からクレクレマンのような要望を書いてしまいました。
とはいえ、昨年のkintoneに行われたバージョンアップの頻度は私たちの期待を満たしてくれています。
おそらく上に述べたようなことは私が言うまでもなく、サイボウズさんでも考えてくださっているはずです。
となると、こちらとしてはただ要望をいうだけではダメですよね。それだとクレクレマンに堕ちてしまう。
ユーザーや開発者の立場から広めるための働きかけを行わなければ。

例えば、kintoneのキャッチフレーズを考えるというのはどうでしょう。
kintoneを使えば何が良いのか。何が変わるのか。言葉を尽くしてそれを語るのはたやすいと思います。
ですが、一言でkintoneの良さを語るのは難しい。シンプルにズバリと本質をつく言葉を今年は考えたいですね。

また、ユーザーがシステムを作る手段としてkintoneの認知度は相当高まってきました。
また、年末にテレビCMが始まったことで、さらに認知度は上がっていくことでしょう。
とはいえ、技術者に対しての認知度はイマイチです。
さまざまなシステムを作る技術者の皆さんにこそ、kintoneの認知度を上げ、採用してもらわねば。

昨年、kintoneエバンジェリストとしてのインタビューでもその想いは語りました。
そこでも語った通り、わが国のシステム開発の生産性はまだまだ伸ばせる余地があると思います。統制のための統制、仕様のための仕様、ドキュメントのためのドキュメントではなく、設計から実装までの各フェーズが共通のフォーマットで流れるような仕組み。
海外のサービスの開発速度が速いのは、それができているからではないでしょうか。
わが国の場合、ミスが許されない文化性の違いもあるのでしょう。ですが、これからはバグや仕様を恐れない開発手法があってもよいと思います。
kintoneは画面や設計がプラットホームとして共通なので、共通言語で語れる部分も多く、スクラッチ開発よりもやりやすいはずです。

ただ、各アプリの連携やシステム全体の設計についてはkintoneは不得手ですよね。それを自動的に作れるようなツールが作りたいと常々考えています。各アプリを横断したER図や機能連携図を簡単に作れるようなツール。
これができれば、お客様との仕様確認も楽になるし、開発者側でもkintoneを導入する機運はさらに高まるはずです。それがわが国のシステム開発の生産性を上げられればいうことはありません。

弊社も昨年は、土壇場での仕様変更に何度も苦しみました。
ですが、その都度、kintoneの良さを生かしてすぐにリカバリできました。
今年はそのリカバリ手段をより研ぎ澄まし、要件定義に時間をかけずに、なおかつ、バグや仕様変更にもすぐに対応できるような体制を作りたいです。
それには、自社であらゆるパターンに対応できるJavaScriptやプラグインのストックをより多く作ることでしょうね。
その中で汎用的に出せそうなソースコードはブログなどで公開することで、エコシステムに貢献できればと考えています。

あと、今後は大手企業様の事例も増えるでしょう。
サブスクリプションの課金にも抵抗がないお客様には、積極的にサードパーティー製のプラグインを提案していこうと思います。
そのあたりは柔軟に取り組みたいですね。

あとは、ブログやYouTube、SNSなどの手段以外に、どうやって認知度を広めるかですよね。
kintoneにもともと興味を持ってくださっている方は、上記のようなメディアに来てくださいます。
ですが、世の中にはkintoneの存在すら知らない人がまだまだいらっしゃいます。そうした方にどうやって広めていくか。
おそらくkintoneのテレビCMはそうした意図で作成されたのだと思います。

あとは、私たちがどうテレビCMを補完するような発信ができるかですね。
おそらく私の場合は技術者向けのイベントや、SIerさんへの内部発信など、今まで取り組んできたことを深めていくのが良さそうです。
それと、弊社の場合、「自治会 IT」で検索すると一番上に登場しています(サイボウズさんの記事ですが)。

そのアドバンテージを生かし、今年は自治会やNPOにkintoneを告知するような手立てを考えていきたいと思います。
自治会やNPOといえば、比較的年配の方が活躍されています。年配の方は、ブログやYouTube、SNSに触れることも少ないように思います。そうした方へのアピールですね。
例えば市役所と組んだり、広報誌で告知したりといった手段で、実際に赴いてkintoneをアピールするのはどうか、と考えています。
おそらくそうした皆さんにkintoneを説明するには、システム用語を極限まで減らすなどの配慮が必要でしょう。

コロナで果たしてそうした機会がいただけるかどうかは不明です。が、チャレンジしてみたいと考えています。

kintoneが今年、拡がるためにはほかにも思いついた手段があれば試してみようと思います。


kintoneにシステム移したいんや


kintone Advent Calendar 2020の22日目の記事です。

  Topへ↓

おかげさまで今年はkintoneの案件が大幅に増え、ありがたい限りです。引き続き、頑張っていきまっせ^+++^

さて、案件が増えたのはめっちゃうれしいんやけど、今年は今までと比べ、案件の傾向に少し変化がありましてん。その傾向っちゅうのは旧システムからkintoneへ移行する案件の増加ですねん。
もちろん、昨年までも移行案件は請けてました。でも、今年はC/S(Cliend/Server)型の旧システムからkintoneへの移行案件をぎょうさんご依頼いただきまして。その数はめっちゃ増えましたわ。

おそらく今後もこうした移行案件は増えていくと思てますねん。そやさかい今年のkintone Advent Calendarは7回目の参加にして、初めて連携開発ではなく、移行について書いてみようと思とります。
これからkintoneへのシステム移行を手掛ける方の参考になればうれしいねん。

システム移行の建前と本音

  Topへ↑

システムを移行する目的はお客様によって千差万別です。
でも、システムを移行すると決断するのは経営層、少なくとも部署の責任者でっしゃろ?

この時、経営層と現場でシステムを扱う方の見る視点は違います。
経営層は人件費の削減や処理効率の改善に重きを置きます。一方で現場の視点は日々の業務の負担を軽減することと、業務を止めないことに向きがちです。

その時、建前上では業務改善を同時に行いながらシステム導入も行う、という意見が出ます。そりゃせやんなぁ。わてら提案側にとっても業務改善を錦の御旗に立てたほうが提案は通りやすいっちゅうもんで。

そやけど、往々にして現場の本音とは従来の業務フローを変えずに、なおかつ業務負担が軽くなることにあると思とります。業務改善によってオペレーションが大きく変わるのはいややなあ。新たなやり方になれるまでが大変やわ。てなわけで抵抗を覚えがちです。

わてがこの時に心がけとるんは、営業の相手である経営層や上層部とのお話がまとまったら、なるべく早いうちに現場の業務担当に挨拶し、現場の方とのコミュニケーションを増やし、現場の本音を伺いながら開発することですねん。
この時の建前と本音と取り違えると、あとあとまでボタンの掛け違いがえらいこっちゃになります。
また、営業目線でお客様の上層部とだけ話をしていると、現場のニーズが後から後から噴出してがっちゃがちゃになります。わては何度もこれでえらい目に遭っとります。

構築の順番

  Topへ↑

現場の方にとっては、慣れ親しんだ旧システムからkintoneという未知のシステムに触れるわけです。不安になって当然やんなぁ。
そやからわてはkintoneの良さ、つまり現場の方々が簡単にシステムが触れまっせ、簡単に設定ができまっせ、ということを早めにご説明します。

このあたりは旧来のシステム開発のセオリーとは違いますわな。要件定義、内部/外部設計、コーディング、単体テスト、結合テストが終わったあたりでようやくマニュアルが用意され、ユーザー受け入れテストで現場の方が触る。それが旧来のシステム開発。

わてはkintoneの場合はより早いうちに現場の方に触ってもらうことを重視します。フィールドコードは触らんといて、プラグインやJavaScriptはいじらんといて、という点だけお願いし、あとは積極的に使ってもらいます
その結果、kintoneってうちらでも触れるんや、現場でもシステム開発に参加してええんや、という実感を持ってもらえればもうしめたもんですわ。
この場合の現場というのは現場の統括者ではなく、文字通り日次の業務で手を動かしている方全員のことやからね。

これで現場の方からkintoneへの警戒感や拒否感が取り除けて、システム開発へ参加しているという実感を持ってもろたら、kintoneのファンにだってなってもらえます。そうなればシステム導入の成功は約束されたも同然ですねん。

その時、最後になるまでシステムを見せへん、という手法は逆効果。
まず移行が順調にできていることを示すためにも、一番やりやすいマスタ系からアプリを作っていくとよろしおま。
マスタは業務の基本であり、なおかつマスタアプリ自体には複雑なロジックはそれほど必要ないよって、導入側にとっても取り掛かりやすいはずですわ。
あと、早めにお客様にシステムに関わってもらうことによって、kintoneが苦手な部分をわかってもらうのも重要!なんでかいうたら、システム導入間近になっての仕様変更で断れるからやねん。

また、フィールドの追加や編集も自在にできるkintoneの特性がお客様に喜ばれるのもこの時。もちろん、ビジネスロジックに関わりの少ないフィールドを除いてやで。
例えば分析用に得意先種別を増やしたいねん、というご要望にもさくっと対応できるkintone。このかっこええ姿をアピールするだけで、好感度アップは間違いなしや。

また、ここで現場の方に新旧両方のシステムにマスタの入力を行ってもらえれば、次に述べるデータ移行の手間が大幅に減ります。ほんまやで。

データ移行の基本

  Topへ↑

kintoneへのシステム移行でいっちゃん肝心なんは、おそらくこの部分だと思とります。
kintoneはご存じの通り、簡単にアプリが構築できますやろ。そやから、元のシステムのデータの項目を再現するのはそれほど難しくない。そないに思うかたもおるんとちゃいますか?
ところが、ここを甘く見とったら後で苦労しますねん。

とくに、もともとのシステムの仕様で、マスタ上で管理する項目が制限されとったら要注意です。
入れたい情報を入れるべき項目がない。その場合、おうおうにしてお客様は備考欄にあれこれ詰め込みますねん。苦肉の策で本来ならメールアドレスやURLを入れるべき欄にまで雑多な情報を入れてしまいます。
kintoneでは簡単にフィールドを追加できまっしゃろ?でも、おうおうにして旧システムでは項目を追加するのに別途費用がかかります。だから、そないな状態になってしまうんですわ。
こうした雑多な情報がどこで管理されとるんか。その情報をkinotneのどの項目に移すんか。きちんと体系化されたデータとして活用したいんやったら、お客様ときちんと押さえとかなあきません。

次に、マスタをルックアップで呼び出す際の仕様は早めに定めとかなあきまへんで。御存じの通り、ルックアップでは関連付けるアプリを設定しますよって。
そしたら、コピー元のフィールドも設定せんならん。ルックアップフィールドではフィールドに文字を入力することで、候補を事前に絞り込むことができます。ただしコピー元のフィールドに設定した値に限りますけどな。

例えば得意先マスタの得意先コードを指定しておくと、マスタの得意先コードで検索が可能です。ですが、一度ルックアップフィールドをこさえた後にお客様から得意先名でも検索したい、と言われたらもうバンザイせなあきません。なんでかちゅうたら、コピー元のフィールドは一度設定すると変更でけへんよって。
もしどうしても変更の必要が生じたら、新たにルックアップフィールドを追加せんならんのです。もちろん古いルックアップのデータから新しいルックアップにデータを移さなあかん。そんなんいけずやんかぁ。

また、検索したい対象は得意先名だけに限りません。よくいわれるのは着信時の電話番号の末尾四桁ですわ。それ以外にもフリガナやらなんやら。つまり複数の項目で検索したいというご要望が出てきますねん。
この時は、わては検索キーっちゅう項目を設け、複数の項目の値を連結させとります。
この時はスペースなしでがっちゃんこしてまうとうまく検索がでけへんようになるから、半角スペースなどを間に挟んで連結するとよろしい。

さらに、その時は文字数にも気ぃ付けましょう。コピー元のフィールドに指定できるのは文字列(1行)です。
こちらのヘルプにも書かれとるけど、文字列(1行)の文字数に制限はあらへん。
ところが、今のページにはこうも書かれとったよね。
値の重複の禁止を設定すると、入力できる文字数が全角または半角で64文字までに制限されます、てな感じ。なんでやねん。

では、値の重複の禁止を設定せんかったらええんちゃうん?そう思いたなるやん?え?ならへん? いや、なってぇや。
なぜなら、ヘルプには以下のように書かとるからやねん。
既存のレコードを更新する場合、CSVファイルを読み込んで一括更新する方法が便利やと思うですわ。
けど、ヘルプにはこうも書かれとるねん。

こないな制限があったら、もうあかん。更新がでけへんのですわ。
APIで更新する場合も同じですわ。
ここのリファレンスにも。
システムの移行には、データの更新が欠かせませんわな。CSVで更新する場合も、APIで更新する場合も。
ルックアップ項目を更新するためには、値の重複の禁止せなあきません。ちゅうことは、連結した文字列の文字数が64文字を越えんようにせんならんのです。つまり、移行元のシステムの項目の文字数を考慮にいれなあかんちゅうわけですわ。難儀やなぁ。

もう一つ、移行にあたって注意しておかなあかんことがあります。
それは住所データの扱いです。日本の住所の場合、以下の4つの項目からなっとります。

  • 都道府県
  • 郡市町村
  • 住所(町・字・地番)
  • 建物・マンション名

これが旧システムでも四つに分かれとったら問題ないんよ。
そやけど、住所1、住所2という感じで二つだけのフィールドでしか管理されていない場合、えらいこっちゃになります。

なんでかゆうたら、それを分割する作業が発生するからですわ。分割?そんなんせんでええわ。てゆわれたかて、後々の分析のこと考えたらそうもゆわれへん。正味、お客様に後々の分析のことを考えてと提案してみたら、kintoneでは分割して管理するお客様が多いんですわ。
例えば旧システムの住所1に「東京都中央区日本橋2−7−1」。住所2に「東京日本橋タワー」の値が入っていたとしますやろ。そしたら、住所1から「東京都」「中央区」「日本橋2-7-1」を分割せんならんことになります。さて、ぼんやったらどないする?

わてはそんなとき、VBA(Excelマクロ)を活用しますねん。
その中でこちらのサイトを参考に正規表現から分割しますねん。
この正規表現をVBAの中に仕込んだら、都道府県と郡市町村と住所(町・字・地番)を分割できるんよ。
以下に簡単やけどコードを掲示してみたから、よかったらみてみて。必ず本番では使う前にテストしたってぇやぁ。もちろん当方では一切の責任は負われへんから。

Sub ConvertSplitAddressData()
    Dim regExp              As Object           '正規表現オブジェクト
    Dim strPattern          As String           '正規表現パターン
    Dim lngRowCounter       As Long             '行カウンター
    Dim intRegMatchCount    As Object           '結果
    Const clngMaxRowCount   As Long = 65535     '行の末尾
    Const cintTargetColumn  As Integer = 18     '結合された住所列番号
    Const cintPrefColumn    As Integer = 14     '結果の都道府県を格納する列番号
    Const cintCityColumn    As Integer = 15     '結果の郡市町村を格納する列番号
    Const cintAddressColumn As Integer = 16     '結果の住所を格納する列番号
    Const cintAnotherColumn As Integer = 17     '結果の建物を格納する列番号

    Set regExp = CreateObject("VBScript.RegExp")
    strPattern = "(...??[都道府県])((?:旭川|伊達|石狩|盛岡|奥州|田村|南相馬|那須塩原|東村山|武蔵村山|羽村|十日町|上越|富山|野々市|大町|蒲郡|四日市|姫路|大和郡山|廿日市|下松|岩国|田川|大村)市|.+?郡(?:玉村|大町|.+?)[町村]|.+?市.+?区|.+?[市区町村])(.+)"
    With regExp
        .Pattern = strPattern
        .IgnoreCase = True
        .Global = True
        For lngRowCounter = 2 To clngMaxRowCount
            If ActiveSheet.Cells(lngRowCounter, cintAddressColumn).Value = "" Then
                Set intRegMatchCount = .Execute(ActiveSheet.Cells(lngRowCounter, cintTargetColumn))
                If intRegMatchCount.Count > 0 Then
                    ActiveSheet.Cells(lngRowCounter, cintPrefColumn).Value = Trim(intRegMatchCount(0).SubMatches(0))
                    ActiveSheet.Cells(lngRowCounter, cintCityColumn).Value = Trim(intRegMatchCount(0).SubMatches(1))
                    If InStr(intRegMatchCount(0).SubMatches(2), " ") > 0 Then                '建物以降が全角空白で分割されている場合
                        ActiveSheet.Cells(lngRowCounter, cintAddressColumn).Value = Trim(Mid(intRegMatchCount(0).SubMatches(2), 1, InStr(intRegMatchCount(0).SubMatches(2), " ")))
                        ActiveSheet.Cells(lngRowCounter, cintAnotherColumn).Value = Trim(Mid(intRegMatchCount(0).SubMatches(2), InStr(intRegMatchCount(0).SubMatches(2), " ") + 1, 100))
                    ElseIf InStr(intRegMatchCount(0).SubMatches(2), " ") > 0 Then             '建物以降が半角空白で分割されている場合
                        ActiveSheet.Cells(lngRowCounter, cintAddressColumn).Value = Trim(Mid(intRegMatchCount(0).SubMatches(2), 1, InStr(intRegMatchCount(0).SubMatches(2), " ")))
                        ActiveSheet.Cells(lngRowCounter, cintAnotherColumn).Value = Trim(Mid(intRegMatchCount(0).SubMatches(2), InStr(intRegMatchCount(0).SubMatches(2), " ") + 1, 100))
                    Else                                                                      '建物がないか続けて入力されている場合
                        ActiveSheet.Cells(lngRowCounter, cintAddressColumn).Value = Trim(intRegMatchCount(0).SubMatches(2))
                    End If
                End If
            End If
        Next lngRowCounter
    End With
    Set intRegMatchCount = Nothing
    Set regExp = Nothing
End Sub

データ移行の方法

  Topへ↑

kintoneにデータを取り込む方法はいくつかあります。そやけど、だいたいはCSVによる一括登録・更新か、APIでの登録/更新かcli-kintoneの三択ちゃうやろか。
わてはCSV経由で取り込むことがほとんどですわ。
なんでかいうたら、APIやとHTTP Client Tool for kintoneを使う場合でも、何かのプログラムで書く場合でも、コードのマッピングの記述が面倒になるからやねん。
あと、一リクエストでも100件しか登録や更新ができないAPIの仕様制限があるやんか。そやから、100万件をこえるデータを移行する場合、一日のAPIリクエスト回数制限にも引っかかってしまうんや。
cli-kintoneは便利やねんけど、上と同じくマッピングの部分が手間なのであまり使用しとりません。ただ、余談すると、Bashとcli-kintoneを使った効率化は追及せなあかんと思とります。そやから弊社としてはcli-kintoneを使ったツールの作成ははよ進めよ思てます。
ただ、それでも画面上でマッピングを確認できるcsv取込の方が安全ちゃうかと思います。ここはよぉ考えてみてください。その時、旧システムが出すcsvの見出し項目名とkintoneのフィールドラベルは合わせといたほうが移行マッピングが圧倒的に楽になるで。

先に挙げた住所や備考以外にも、データの加工はあちこちのフィールドで発生しますやろ。それらはめっちゃ面倒やと思うねん。それらをチェックとか加工とかせなあかんから。例えば下のような感じやね。

  • 項目の値の中に半角カンマは入っていないか。
  • 項目の値の中にダブルクォーテーションなどは入っていないか。
  • 項目の値の前後に空白は入っていないか。
  • 旧システムから出力されたファイルの文字コードは統一されているか。(複数のシステムからそれぞれ出力して取り込む場合、Shift-JISとUTF-8が混在しているとkintone側で文字化けの恐れあり)
  • ルックアップの値はkintoneの関連付けるアプリの参照アプリのコピー元のフィールドに等しいか。
  • 電話番号や郵便番号、メールアドレスやURLの書式は正しいか。
  • 日付書式は正しいか。(元データがyyyymmdd形式の場合、空白セルがあると空白に変換してくれずエラーになる等)
  • データの重複はないか。
  • kintoneのラジオボタン/チェックボックス/複数選択/ドロップダウンの選択肢に等しい値のみが含まれているか。

もしでけるんやったら、VBAマクロやcli-kintoneなんかでツールを作ったほうがええと思うで。
あと、ツールの作成と簡単に書いとるけど、旧システムによって項目がまちまちなんは、わかりますやろ?旧システムごとに工数と時間を使うから、わては移行ツールの作成には消極的で、あまりやってへんかったわ。

そやけど、毎度Excelの関数を駆使して移行データを作るんはもうしんどい。わても実は今年手掛けた数々の移行の中で、一つだけめっちゃ苦労した移行がありましてん。それをしおに、めんどいかもしれんけど、移行ツールを作ったほうがええなぁと痛感しましたわ。

ただし、早めにマスタの項目を固め、マスタアプリを作り、初回のデータ移行がでけたところで、それ以降は本番までお客様にマスタデータの入力をしてくれまへんやろか?とお願いしたほうがよろし。もしそれがでけたらマスタの移行ツールはいらんからね。
ま、それでもトランザクションデータの移行に関しては何かしら作らんといかんけどね。

なんでかいうたら、マスタのデータは生き物やねん。お客様によってガーっと追加され、あちこちでバァーっと更新されますやろ。
しかも住所の更新が起こるし、しかも項目が連結されている住所データやったら、さっき書いたみたいに分割の作業が毎度いるんでっせ?
それに、本番移行直前でせーので一回でガバっと取り込めば済むほどシステム移行は甘いわけやあらへん。

もちろん、どっかの時点で初回分を取り込み、定期的に差分データを取り込み、最後に移行日までの残り差分がきれいに取り込めた場合は楽ですわ。そやけど、そうした移行の運用ができるのは、こっち側が旧システムにアクセスできる場合だけやねん。

遠方のお客様で、しかもVPNでつながれへんような旧システムの場合、データの取り出しはお客様にご依頼するほかありませんやろ。
お客様のやり方によっては項目に抜け漏れがあるやろし、項目の順番が違っていたりします。ましてや差分データの時間の基準もあいまいになってしまいますねん。そやから、きれいなデータを毎度もらえないと考えなあきません。
そやから、移行ツールを作らんでええ場合は、旧システムにこちらから簡単にアクセスできる場合に限ったほうがええね。もしそないにアクセス出来るんやったら、毎回Excelのフィルターや並び替えや置換などを駆使しても円滑に移行できると思うけどね。
ただ、実際はそうでない場合が多いから、そないなリスクを考えたら、最初に工数と時間をかけてでもお客様専用の移行ツールを作り、それを運用したほうが格段に楽やと思うんやけどどない?

データ移行のTIPS

  Topへ↑

なんぼかTIPSを列挙しておきますわ。

  • データの本番移行までは、取り込み時には変更履歴はオフにしといたほうがええで。
    設定は、アプリの設定→高度な設定→変更履歴のチェックを外す。
    そうしないとサイボウズさんに注意されまっさかい。また、変更履歴だけで契約のディスク使用量を軽く超過してしまいますねん。(一度、うっかりしていて100万件のデータを何度も取り込みなおし、サイボウズさんに注意されてもうた。※EvaCamp 2020で言いそびれた失敗談の一つ)
  • 可能であれば、本番移行後は旧システムのトランザクションデータ(売上や仕入などの伝票データ)は、kintoneでも別アプリにした方がええで。
    しかも、旧システムのトランザクションデータのフィールドはルックアップをなくし、文字列(1行)と数値のみにしといたほうが楽やで。なんでかいうたら、過去分のデータはマスタデータの変更などで古い値として入っとるからやねん。過去のルックアップはその時のマスタデータの値を再現して保存しといて、てな具合にご要望もろたら、移行作業はめっちゃごっつい苦行になってまう。さっきも書いたけど、ルックアップのコピー元のフィールドはマスタにある値やなかったらエラーになるからね。そやから、ここは初めのころに決めておいた方がええかも。
    旧システムの部分については別アプリに分け、ルックアップを外してしまえば、旧システムの生データをそのまま取り込むだけ済むさかい、ごっつい楽ですわ。
    そやけど、一つだけ注意しとかな。アプリを分けた場合、新旧両方のアプリをまたいだ分析に対応できませんやろ。その場合は、自分でカスタマイズビューを作成するか、トヨクモさんのDataCollectのようなプラグインを活用するとよろし。便利でっせー。
  • 添付ファイルの移行が必要な場合は先にも挙げたcli-kintoneを使うとええで。また、要件定義の段階でDropboxやboxなどのオンラインストレージの移行を提案しとったら、kintoneではそちらのストレージとの連携を行えばええから、あんじょういきまっせ。
    オンラインストレージへのデータ移行と整理作業は、お客様にお願いしといたほうがええやろし。
    2019年のわてのAdvent Calendarもご参考にしたってやー。
  • C/S側の旧システムは、たいがいレイアウトが小さくまとまっとるやろ。それに比べるとkintoneのフラットデザインは、項目の間の余白もがっつりとられとるし、そこは一目で情報が見られる旧システムに劣ると思われるかもしれへん。
    無理やりJavaScriptでレイアウトを調整したったりもしたけど、それはあんまり本筋のやり方ちゃうしなぁ。
    これも早い段階で現場の担当者と話を詰めといたほうがええで。
    あ、もう一個。デザインについてはkintoneのアプリの設定→デザインテーマの設定でブラックを選ぶとお客様の印象が変わるかもしれんで。一度試すとよろしおま。
  • Excel上でデータの加工を行う時、何使てます?フィルタ? もしそやったら、スライサーの機能とか試すと幸せになれるで。
    スライサーはこの記事が参考になるんちゃうかな。
  • kintoneの難儀な仕様ってあるやんか。例えば英単語の一部分の文字だけで検索でけへんとか。
    ヘルプにもこない書かれとるし。
    もしそれやったら、Excelのフィルタ使たらええねん。まあJavaScriptで
    一文字検索の機能を作ってもええし、プラグインでもええのんあるけどね。
  • C/S側の旧システムのユニークの項目は早めにお客様と共通認識をもっといたほうがええ。さっきも書いたけど、お客様からデータをもらう際は、旧システムのデータ出力方法を把握して、その設定や出力操作は完全に共通認識をもっといたほうがええ。あと、これも上で書いたけど、旧システムのデータを先に修正できるのならお客様に頼んで修正しといたほうがええ。

まとめ

Topへ↑

ちゅうわけで、本記事は皆様のkintoneへの移行のお役に、そしてご参考になればよろし思ぅて書きました。もちろん、これは弊社にとっても参考にすべき自社のノウハウですわ。
弊社も今年は一件、移行で苦労した案件がありましてん。だからこそ、一度ノウハウを言語化すべきやなぁと思ったんよ。それがきっかけです。
また、弊社の新規の案件の際にもお客様にも読んでもらお思ぅて、ここで知見を共有したいと思います。
なので、今後も折をみてアップデートを重ねていこうと思います。よろしゅうお願いいたします
また、こんなTipsや失敗談などありましたら、ガァーっとご意見をお寄せください。また本稿の内容に不備があった場合も遠慮せんとご指摘ください。

本稿が旧システムからkintoneへの移行をお考えの皆様にとってちょっとでも手助けになったら幸せやわ。


Cybozu OfficeのスケジュールをCalendar Plusで(だいぶ)再現!


カレンダーPlus Advent Calendar 2020の5日目の記事です。

  Topへ↓

先日のCybozu Days 2020 Osakaの後、Calendar PlusのAdvent Calendarに空きがあると聞き、やってみましょうか?と言ってしまいまして。
言った以上はエントリーせねば。というわけで翌日、神戸で商談する前に中華街で飯を食べながら記事にエントリー宣言。

さて、エントリーしたのはいいが、何を書けばええんやろ?しかもエントリーしたタイミングは前日やし(^^;)。これはひょっとして勇み足をやらかしてしまったのではなかろうか。

迷いを振り切った私が商談に臨むと、なんとお客様がCybozu Officeのスケジュールを愛用しており、それをkintoneに載せ替えたいとのこと。しかもkintone標準の標準のカレンダー機能は表現に乏しく、Calendar Plusを検討してみたけど、プラグイン設定の色設定の種類が少なくてなぁ。と悩みを吐露されまして。商談からネタが転がってきた瞬間です。
これはCybozu Officeのスケジュールアプリの画面です。

私は今までも何回かCalendar Plusは提案してきました。けれど、本格的なユーザーではないし、弊社のkintone納入実績からするとCalendar Plusの納品実績は一割もありません。熟練のユーザーではないのです。

が、Calendar Plus JavaScript APIを使ったカスタマイズの経験はあります。API使えば、ある程度ならCybozu Officeの体裁にCalendar Plusを合わせられるんちゃうの?という見切り発車でした。

Calendar Plusのプラグイン設定画面

  Topへ↑

うーむ、確かにCalendar Plusの色設定は12種類か。

そして、お客様のCybozu Officeのスケジュールの色設定で設けた種別は25種類。つまり倍。

確かにお客様がkintoneへの移行をためらわれるのもわかるなあ。

アプリを作る

  Topへ↑

じゃあ、ちょっと試しにアプリを作ってみよう。こんな感じで。

あらよっと、Cybozu Officeと同じようにレコードを登録してみました。さて、Calendar Plusで見るとどうなる・・・?

あかん・・・Calendar Plus側の色設定をしていないのですべて同じ緑地になってる。
しかも予定の状況がカレンダー上に表示されておらず、直行なのか直帰なのかが一目で区別できない。
やはり見にくいなあ・・・・これは、Calendar Plus JavaScript APIの出番かな。

コーダーモード発動

  Topへ↑

ということで、ガリガリとコーディングすること2時間。うん、こんな感じになりました。


というわけで最低限、記事にできるところまでこぎつけたのでいったん寝ます。アップ当日になってしまいましたが、AM2時前なのにもう眠い。年や。

プログラム開示

  Topへ↑
さて、アップ当日の朝、旅に出かける前に少しだけ記事を書きまして。
ここにコードを開示しておきます。すみません。洗練されたコードとは程遠くて・・・・。

(function () {
  "use strict"

  // 関数本体
  const calenderformat = function (event) {
    // Calendar Plusのイベントリスナー定義
    const calendareventslist = ["cp.event.show"];
    // kintoneのイベントの書き方と似ててわかりみ
    calendarplus.events.on(calendareventslist, function (calendarevent) {
      // kintoneのイベントのjson(上記イベントで対象データループしてくれます)
      const record = calendarevent.record;
      // kintoneのイベントの要素
      const element = calendarevent.element;
      // テーブルだけkintoneのイベントの要素
      const tdelement = document.getElementsByClassName("fc-event-container");
      // Cybozu Officeの時刻表示に合わせるため(ださいかも)
      const starttime =
        ("00" + new Date(record.開始時刻.value).getHours()).slice(-2) +
        ":" +
        ("00" + new Date(record.開始時刻.value).getMinutes()).slice(-2);
      const endtime =
        ("00" + new Date(record.終了時刻.value).getHours()).slice(-2) +
        ":" +
        ("00" + new Date(record.終了時刻.value).getMinutes()).slice(-2);
      // 左端の行高がCalendar Plusでは縮まるため、Cybozu Officeの行高っぽくする
      tdelement[0].style.minHeight = "90px";
      tdelement[1].style.minHeight = "90px";
      tdelement[2].style.minHeight = "90px";
      tdelement[3].style.minHeight = "90px";
      tdelement[4].style.minHeight = "90px";
      // リンクするためのurl
      const baseurl =
        kintone.api.url("/k/").replace(".json", "") +
        kintone.app.getId() +
        "/show#record=" +
        record.$id.value;
      // 予定の状況にあわせてSwitch(ださい)
      switch (record.予定の状況.value) {
        case "ーーー":
          // 枠の背景色
          element[0].style.backgroundColor = "#FFFFFF";
          // 文字色(本当はhoverとかの定義も必要。そもそもcssにまとめたほうがよい)
          element[0].style.color = "#006bac";
          // 折り返してくれなかったので折り返し(そもそもcssにまとめたほうがよい)
          element[0].style.whiteSpace = "break-spaces";

          // 終日フラグかどうか
          if (record.終日.value.length > 0) {
            // 頭に・をつける
            element[0].innerText = "・" + element[0].innerText;
          } else {
            // 頭に時刻をつけて改行
            element[0].innerHTML =
              starttime +
              "-" +
              endtime +
              "
 " +
              '<a href="' +
              baseurl +
              '">' +
              record.予定.value +
              "</a>";
          }
          break;
        case "直行":
          // 枠の背景色
          element[0].style.backgroundColor = "#ebf7ef";
          // 枠の線色
          element[0].style.borderColor = "#d8f2e0";
          // 文字色(本当はhoverとかの定義も必要。そもそもcssにまとめたほうがよい)
          element[0].style.color = "#006bac";
          // 折り返してくれなかったので折り返し(そもそもcssにまとめたほうがよい)
          element[0].style.whiteSpace = "break-spaces";
          // 終日フラグかどうか
          if (record.終日.value.length > 0) {
            // 頭に・をつけ、予定の状況を枠で囲む
            element[0].innerHTML =
              "・<span style="background-color:#32a759;color:#fff;" class="scheduleMarkEventMenu">" +
              record.予定の状況.value +
              "</span>" +
              record.予定.value;
          } else {
            // 頭に時刻をつけ、予定の状況を枠で囲む(以下コメントは省略)
            element[0].innerHTML =
              starttime +
              "-" +
              endtime +
              "
 " +
              '<a href="' +
              baseurl +
              '">' +
              '<span style="background-color:#32a759;color:#fff;" class="scheduleMarkEventMenu">' +
              record.予定の状況.value +
              "</span>" +
              record.予定.value +
              "</a>";
          }
          break;
        case "直帰":
        case "直行/直帰":
          element[0].style.backgroundColor = "#e8f2fc";
          element[0].style.borderColor = "#dae8f7";
          element[0].style.color = "#006bac";
          element[0].style.whiteSpace = "break-spaces";
          element[0].innerHTML =
            "・<span style="background-color:#3182dc;color:#fff;" class="scheduleMarkEventMenu">" +
            record.予定の状況.value +
            "</span>" +
            record.予定.value;
          break;
        case "転送":
        case "納品":
        case "設定":
        case "設置":
        case "移設":
          element[0].style.backgroundColor = "#f4fce8";
          element[0].style.borderColor = "#e5f2d3";
          element[0].style.color = "#006bac";
          element[0].style.whiteSpace = "break-spaces";
          element[0].innerHTML =
            "・<span style="background-color:#83cb26;color:#fff;" class="scheduleMarkEventMenu">" +
            record.予定の状況.value +
            "</span>" +
            record.予定.value;
          break;
        case "点検":
          element[0].style.backgroundColor = "#fff4e3";
          element[0].style.borderColor = "#fae8cd";
          element[0].style.color = "#006bac";
          element[0].style.whiteSpace = "break-spaces";
          element[0].innerHTML =
            "・<span style="background-color:#ef9201;color:#fff;" class="scheduleMarkEventMenu">" +
            record.予定の状況.value +
            "</span>" +
            record.予定.value;
          break;
        case "デモ":
        case "営業":
        case "商談":
        case "打合せ":
        case "来客":
          element[0].style.backgroundColor = "#faf6f2";
          element[0].style.borderColor = "#f2e9df";
          element[0].style.color = "#006bac";
          element[0].style.whiteSpace = "break-spaces";
          element[0].innerHTML =
            "・<span style="background-color:#c3a88b;color:#fff;" class="scheduleMarkEventMenu">" +
            record.予定の状況.value +
            "</span>" +
            record.予定.value;
          break;
        case "当番":
          element[0].style.backgroundColor = "#fcfae8";
          element[0].style.borderColor = "#f2efd3";
          element[0].style.color = "#006bac";
          element[0].style.whiteSpace = "break-spaces";
          element[0].innerHTML =
            "・<span style="background-color:#dfc506;color:#fff;" class="scheduleMarkEventMenu">" +
            record.予定の状況.value +
            "</span>" +
            record.予定.value;
          break;
        case "休み":
        case "有休":
        case "リフ":
        case "代休":
          element[0].style.backgroundColor = "#ffebeb";
          element[0].style.borderColor = "#fcdede";
          element[0].style.color = "#006bac";
          element[0].style.whiteSpace = "break-spaces";
          element[0].innerHTML =
            "・<span style="background-color:#f44848;color:#fff;" class="scheduleMarkEventMenu">" +
            record.予定の状況.value +
            "</span>" +
            record.予定.value;
          break;
        case "午前半休":
        case "午後半休":
          element[0].style.backgroundColor = "#fff2f5";
          element[0].style.borderColor = "#f7e9d2";
          element[0].style.color = "#006bac";
          element[0].style.whiteSpace = "break-spaces";
          element[0].innerHTML =
            "・<span style="background-color:#f3a4b4;color:#fff;" class="scheduleMarkEventMenu">" +
            record.予定の状況.value +
            "</span>" +
            record.予定.value;
          break;
        case "土曜当番出勤":
        case "出張":
        case "会議":
          element[0].style.backgroundColor = "#f5edfc";
          element[0].style.borderColor = "#ebe1f5";
          element[0].style.color = "#006bac";
          element[0].style.whiteSpace = "break-spaces";
          element[0].innerHTML =
            "・<span style="background-color:#b592d8;color:#fff;" class="scheduleMarkEventMenu">" +
            record.予定の状況.value +
            "</span>" +
            record.予定.value;
          break;
        case "土曜振休":
          element[0].style.backgroundColor = "#ffebeb";
          element[0].style.borderColor = "#fcdede";
          element[0].style.color = "#006bac";
          element[0].style.whiteSpace = "break-spaces";
          element[0].innerHTML =
            "・<span style="background-color:#f44848;color:#fff;" class="scheduleMarkEventMenu">" +
            record.予定の状況.value +
            "</span>" +
            record.予定.value;
          break;
      }
      return calendarevent;
    });
  };
  // kintone自体のイベント
  const eventslist = ["app.record.index.show"];
  kintone.events.on(eventslist, (event) => {
    // ビューが一致したら本体の関数呼び出し
    if (event.viewId === 5543487) {
      calenderformat(event);
    }
    return event;
  });
})(jQuery);

あと、cssも全体のフォントに関する設定と予定の状況の枠に対して設定しています。

div#calendarPlus {
    font-family:"ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", ヒラギノ角ゴシック, "Hiragino Sans", メイリオ, Meiryo, "MS Pゴシック", "MS PGothic", sans-serif;
    font-size:14.4px;
    font-weight:400;
}
    
div#calendarPlus span.scheduleMarkEventMenu{
    display: inline-block;
    padding: 1px 2px;
    color: #fff;
    margin: 0 1px 2px 1px;
    line-height: 1.2em;
    border-radius: 2px;
    font-size: 12px;
    vertical-align: middle;
}
    

まとめ

  Topへ↑

てなわけで、日中は記事のことは一切忘れて徳島のあちこちをめぐっておりました。で、21時前に実家に帰ってきました。
では、早速記事の続きを。うん、あらためて確認しても表示はこんな感じで大丈夫かと。

本当は実装すべきなのは週だけでなく、他の日や月でも同じように表示できるか試さねばならないですね。また、Cybozu Officeのスケジュールアプリの日時と曜日の行見出しの部分はCalendar Plusでは再現していません。
まあこんな感じですが、記事の主旨は満たせたと判断し、今宵はここまでにしてアップしたいと思います。

あとは、金曜日に商談したお客様がこの実装でご満足いただけるかどうかでしょうか。なにしろ、お客様に商談の御礼のメールを送るより先に、こちらの記事をアップしてしまったので(^^;)。おいおい。

本稿がCybozu Officeからkintoneへの移行をお考えの皆様にとって少しでも手助けになれば幸せです。

もしお困りの際は弊社までご連絡くださいませ。

当エントリーの参考にさせていただいたブログ

  Topへ↑

最後になりましたが、このエントリー作成にあたり、以下のサイトからの情報を参考にさせていただきました。
ラジカルブリッジの斎藤さんにはいつも感謝です。内容にやばい内容が含まれていたら直しますね。
ありがとうございました。

 Calendar Plus JavaScript APIのリファレンス


RPA界の技術者の皆様にお話しをしました



今月、唯一のお話の機会をいただきました。
お招きくださったのはPeaceful Morning株式会社様です。

Peaceful Morning株式会社様は、RPAの界隈のメディアを運営し発信しておられると同時に、RPAに知見のある大勢の技術者を擁し、RPAのツールやサービスを提供されています。
Peaceful Morningという社名にも見られる通り、従来の働き方に一石を投じる理念は、私が推すkintoneやサイボウズ社にも通ずるところがあります。
https://peaceful-morning.com/

今回は、一時間程度のお時間をいただきました。
一時間のすべてを座学形式ではなく、技術者の皆様から事前に質問を募り、それに答える構成でした。

事前にいただいた皆さんの質問内容を拝見すると、kintoneとは何かを知りたいというのは当然として、機能の詳細よりもむしろkintoneの概要や競合ツール、さらにコロナ禍におけるkintoneの需要や今後の展望など、kintoneを扱うことの可能性にご興味がおありの様子でした。
また、kintoneを扱うことによる働き方の変化や、エバンジェリストである私自身がkintoneを推す理由など、技術者としてのキャリアの可能性の一つとしてkintoneを検討したいとの意識を感じました。

事前の質問だけでも十二問に達し、質問に答えるだけで一時間が過ぎることは確実でした。
そのため、kintoneエバンジェリストとして登壇する私は、kintoneそのものの機能よりも、私の個人的な思いや、kintoneのどこに可能性があるのかといった本質的な部分を語ろうと決めました。

折悪しく本番直前になって私のPCの処理が終わらず、kintoneの画面イメージが映せなかったため、kintoneの紹介すらも口頭のみで済ませてしまいましたが(終わりの方で処理が終わったので画面共有で3,4分ほどお見せできました)。

私からの回答の中では、kintoneはREST APIが使えればほかのシステムとも連動が可能とお伝えしました。RPAでいうとUiPathはREST APIが扱えるので、kintoneとは相性が良いですよ、ということも。
おそらくRPA界の皆様には、データベースのバック/フロント構築が簡単にできるツールですよ、という視点で深く掘り下げたほうがより響いたのかもしれません。

参加者の皆様からのアンケートも開示していただきました。
kintoneの画面の動きやRPAとの連動の実例をもっと見たかったというご意見もありました。当然ですね。私の不手際があり、失礼いたしました。
また、私のkintone愛を感じた、といったご意見も数点ほどいただきました。それはまさに狙い通りのご感想だったのでうれしかったです。これを機会にkintoneに興味を持ってもらえればなおさらうれしいです。
RPAとkintoneの連携事例はまだ世に出ていないと思っているので、皆さんと一緒に事例を増やしていきたいです。

こうやって分野の違う技術者の方を前に語るといつも感じることがあります。
それは、kintoneのすそ野がユーザー部門には広がっているとはいえ、まだまだ技術者への浸透には至っていないということです。
技術者の中にはスクラッチ開発に価値を感じる方もいらっしゃれば、基盤から構築してすべてを統制することに意義を認めていらっしゃる方もいます。
もちろん、それは人それぞれなので自由です。ですが、No-Code/Law Codeといった従来のシステム開発の概念と違うツールへの使わず嫌いがあるとすればもったいないと思うのです。

ここ一年、私の中でエバンジェリストとしての活動の主眼の一つを技術者さんへの伝道に置こうと決めました。
それは、私がkintoneに賭けようと思った時期を見つめなおしたことで気づいたことです。
その時期、私には常駐現場を渡り歩く中で感じた既存のシステム開発への疑問が渦巻いていました。それは、人月換算や多層契約によるSES業務の課題、膨大なドキュメントの山、そして作った設計書や仕様書やプログラムが現場のオペレーターさんに直接届かないもどかしさなどほんの一部でしかなく、とても悶々としていました。
その時期の私がkintoneに感じた可能性とそれに賭けようとしたことで、今の私はあります。
それを考えると、技術者の方々が今の開発環境やツールから別のステップに進みたいと感じたときに、kintoneを開発ツールの一つとして選択肢に含めてもらえれば、私がkintoneに身を投じたモチベーションも共有できると考えたのです。

RPA界の技術者の皆様には、また機会があればkintoneを中心としたPaaS/SaaSの可能性について語ってみたいですね。今度はきちんと画面の動きもお見せしながら。今回の処理の遅れを機会にノートPCを新調したことですし。

まずは、今回のご参加者の皆様、ありがとうございました。
また、セミナーを運営してくださったPeaceful Morning株式会社の皆様、ありがとうございました。


freee & kintone BizTech Hackの第一期を終えて


9/17に、freee & kintone BizTech Hackの第四回目が行われました。
(freeeさんからのレポート)。
私は久々にオンラインハンズオン講師を務めました。第一回目以来です。

4/24に行われた第一回で感じた感想は、以下の記事に書きました。
https://www.akvabit.jp/freee-kintone-biztech-hackでオンラインハンズオンの講師を務めました

第二回と第三回では、ハンズオンのメンターとしてサポート役を務めさせていただきました。また、ビジネスセッションの登壇者として、SaaSの隆盛について、基幹システムの最後の砦である会計にもクラウドが使われるようになってきた現状を語りました。

こうしたオンラインハンズオンでの登壇経験や、メンターとしての参加は、私の経験値をかなり高めてくれました。おそらくは知名度も。
そうした活動をSNSに載せる中で、何人かのお客様には「kintone以外にもfreeeにも詳しいんだよね?」という嬉しいお言葉まで。

何よりも私が持っていた経理業務への苦手意識が、この四回の登壇を通して払拭できたように思います。

おそらくはfreeeの設計思想が、貸方借方に象徴される伝統的な簿記ではなく、トランザクションデータとしての受発注伝票に似た形式で組み立てられていたことが大きいと思います。

なんや、普通のデータのように扱えるんや、という安心。
これが学べたのは私にとっても大きいですね。

また、APIキーではなく、きっちりとしたOAuthの仕組みに則った認証が求められることによって、私の知見を高めてくれました。ハンズオンをやる以上、理解していなければ。
これはかけがえのない財産になってくれそうです。

今も、とあるkintoneとfreeeの連携案件で、kintoneから投げたwebhookを、freee側でリフレッシュトークンを使い、都度の認証なしに連動する仕組みがを作っています。その時ももOAuthの知見が生かされました。

四回目のハンズオンでは、参加者の方から、今後のハンズオンはこういうのを期待している、と言った前向きな意見をいただきました。
四回目にして初めてこうしたご意見が頂けたのは嬉しいです。講師冥利に尽きます。
今回で第一期は終わりますが、次回に繋げたいですよね。
他にもお褒めのお言葉をいろいろといただけたことですし。

実は今回の登壇は、別案件をいくつも並行ですすめている中の登壇でした。かなり疲労が溜まった中での登壇でした。でも、オンラインの恩恵を受け、無事にやり遂げられました。疲れてても喋りではなんとかやり遂げられる自信がついたのも大きいです。

おそらくはまだ、これからも来年も、オンラインの上のイベントが主流になると思います。
オンラインハンズオンという挑戦が無事に終わったことで、私の自信になりましたし、私も次なるチャレンジに挑んでみたくなりました。
例えば、先日作った私のアバターを出してみたり。

最後になりましたが、ご参加者の皆さん、メンターやハンズオンを行っていただいた皆さん、ありがとうございました。


弊社はCYBOZU DAYS 2020に出展いたします。


9月が始まった今日、
弊社にとって三つのニュースを発表できる機会が到来しました。

一つ目は、
CYBOZU DAYS 2020への出展です。
2020年11月に千葉の幕張メッセで開催されるCYBOZU DAYS 2020のシルバースポンサーとしてブースを出展いたします。
弊社とPolaris Infotech株式会社(https://www.polarit.co/)との共同出展の形をとらせて頂きます。

URL:
https://cybozuconf.com/
日時:
2020/11/11-2020/11/13
場所:
幕張メッセ 国際展示場1-3ホール
(弊社の出展ブースの場所はすでに決まっていますが、詳細は当日お越しになられた際に配布される地図をご覧くださいませ)

来場方法:
JR京葉線 – 海浜幕張駅 (東京駅から約30分、蘇我駅から約12分)から徒歩約5分
JR総武線・京成線 – 幕張本郷駅(秋葉原駅から約40分)から「幕張メッセ中央」行きバスで、約17分
出展内容:
お楽しみに

Cybozu Daysは、毎年大勢のお客様がお越しになります。今年はコロナ禍のため、感染対策の中で開催されます。
若干の制約事項もあるでしょうが、来場された方は必ず楽しめますし、持ち帰って糧としていただけるだけの内容になっています。これは毎年参加している代表が心から実感していることです。
是非、来場のお申込みをお待ちしております。

二つ目は、
弊社の代表がインタビューを受けた記事がkintone エバンジェリストのサイトで公開されました。
https://www.kintone-eva.com/
代表は今までも何度かインタビューされた経験や、記事に登場したことがあります。
ですが、今回のインタビューは、kintoneを通した代表自身の生き方にまで踏み込みましたので、とても思い入れがあります。

こちらもお読みいただければと思います。

最後は、
弊社のロゴの刷新です。
akbを組み合わせた従来のロゴの色合いをkintoneに近づけたものです。
このデザインは弊社代表の妻と長女によるものです。

長女も現在、デザイン専門学校生ですが、弊社の社名のakbの文字を組み合わせつつ、同時に弊社の代表の頭文字「N」を表したデザインは、デザインやプレゼンテーションのプロの方からもおほめ頂きました。

よりkintoneにデザインを近づけたことで、kintoneに賭けようとする弊社の意気込みを感じて頂ければと思います。

まだ発表していませんが、この夏には
・社是
・企業理念
・経営理念
・9つ(ナイン)のない
・アクアビットに合わない方
という五つの指針も作成しています。

また機会があればご紹介したいと思います。

今後ともよろしくお願いいたします。


freee & kintone BizTech Hackでオンラインハンズオンの講師を務めました


4/24(金)に行われた「freee & kintone BizTech hack」で、セミナーとハンズオンを弊社代表が担当させていただきました。
今回、初めての開催でありながら、全てがzoom上で行われました。100%ピュアのオンラインです。

ハンズオンとは講師が壇上に立ち、スクリーンに映した作業の一部始終を参加者に見てもらいながら、参加者にも同じ操作を再現してもらうセミナーの形態です。

ハンズオンは、どこか一つでも参加者が手順を誤るとうまく動きません。ですから通常は数名のメンターやサポートスタッフが会場を巡回し、参加者が課題を完遂できる様に導きます。
それでも多くの方が途中で脱落してしまいます。
私も参加したハンズオンのうち、完遂できなかったことがあります。

今回はそのハンズオンをオンライン上で行いました。つまり、難しさはさらに上がります。

弊社代表は、参加者を会場に集めてのハンズオン講師の経験は持っていましたが、オンラインハンズオンの講師は初めてです。
初めてだったのは弊社代表だけではありません。運営側の全員がほぼ未経験でした。
そのため、リハーサルは三回行いました。

皆さんにどうやったらわかりやすく内容を伝えられるか。どうやれば皆さんにハンズオンの課題を完遂してもらえるか。
手順を省くことは許されません。参加者がどこまで理解しているかも予断できません。

矛盾のない内容になっているか。話す速度は大丈夫か。提供するプログラムは破綻していないか。
リハーサルではそうした確認を行い、運営者の皆さんから指摘してもらいました。KPT法にのっとり、keep、problem、tryを繰り返しつつ。

結果として、15名の参加者の皆さんに最後まで完遂してもらうことができました。これも運営の皆さんと参加者の皆さんのご協力のたまものです。ありがとうございました。
公式開催報告:(https://fk-biztech.qloba.com/activities/7256

私にとって、今回の経験はとても得難いものでした。
ハンズオンの講師は、内容を完全に理解していなければ務まりません。
今回、ハンズオンでOAuthの仕組みを扱うにあたり、今まで何となく扱っていたOAuthについてさらに理解を深めました。
学びを通して自分の中にOAuthの仕組みをきちんと落とし込めたことは、今後の業務にとって助けとなるはずです。

ハンズオンの前のセミナーでお話しした通り、これからはSaaS同士の連携が欠かせません。
セミナー資料:(https://slides.com/yoshikazunagai/freee-kintone-biztech-hack-seminar
既存の構成から、新たな仕組みへと。
技術者に求められる役割はこれからも多岐にわたることでしょう。私たち技術者が学ぶべきことは多く、しかも新たな技術を取り入れねばなりません。

今後もオンラインでハンズオン講師を務める機会はあるでしょう。
私もできる限り、力を尽くしたいと思います。
より多くの人にエコシステムを使ってもらうために。より多くの技術者にオープンプラットホームの世界で活躍してもらうために。

すでに今回、ご好評をいただいたことで、次回の開催が決まっています。
freee & kintone BizTech Hackの二回目が5/22に行われます。
申込サイト:(https://fk-biztech.qloba.com/
次回は私は登壇しませんが、スタッフとして皆さんをサポートさせてもらえればと思います。
よろしくお願いします。


kintone Café 神奈川 Vol.6を開催して得た気づき


4/2にkintone Café 神奈川 Vol.6を開催しました。

公式の開催報告はしかるべき場所に書かせていただきました。
こちら

関連するツイートのまとめサイトも作成させていただきました。
Twitterはこちら
zoomグループチャットはこちら

代表である私が登壇の際に語った
kintoneの導入はお客様にファンになってもらいながら!
サイボウズ社のチーム応援ライセンスについて
については、上に挙げた開催報告の中で補足させていただいております。

ここでは、完全オンラインで開催することで気づいたことを書きたいと思います。

まず、開催にあたって大変お世話になったkintone大好きYouTuberこと、サイボウズ社の松井さんにはお礼を申し上げなければ。
松井さんからは、zoomでの運用のノウハウや、YouTube Live配信のノウハウを教えていただきました。当日も開催の間、さまざまなフォローを行ってくださいました。
最終的に、リアル開催からオンライン開催に切り替える決断をしたのも松井さんの一言がダメ押しとなりました。色々とありがとうございました。

あと、当日はYouTube Liveで同時配信を行いました。
配信された結果の動画は、松田さんが編集を買って出て下さいました。助かりました。ありがとうございます。
その動画リストはこちらに載せてくださっているようです。

さて、今回は私にとってはじめてのオンライン・イベントの主催でした。
リアルのイベントでは何度か主催を経験してきましたが、オンライン・イベントは初めての経験。同じ技術イベントとはいえ、やるべき作業は違います。

一言でいうと、事前と最中の忙しさの違い、でしょうか。
リアルのイベントでは事前の準備が大変ですが、開催の間はそれほどやることはありません。
一方、オンラインのイベントは事前の準備より、開催中のほうが大変です。
その部分をお知らせできれば。

オンライン・イベントの場合、事前にやるべき事は大きく分けて三つあります。
一つ目はzoomのミーティングの準備です。今回のzoomのミーティングはウェビナーではなく、ミーティングを選びました。ウェビナーだと観覧者の皆さまがギャラリービューに出ないからです。
ミーティングは「新しいミーティングをスケジュールする」で日時指定で予約すれば大丈夫です。
二つ目は、YouTube Liveの配信の許可です。その方法をご理解いただくには、キンスキ松井さんのブログをご覧いただくのが早いです。
なお、YouTubeアカウントに対してLive配信をを行う場合、24時間ほどの準備が必要だそうです。その許可を行うため、アカウントへLive配信の許可を申請する作業は前もって行っておきましょう。
その後の配信枠の予約などの処理は、キンスキ松井さんのブログに書かれているので、そちらをご覧ください。
三つめは、イベントの告知と招待です。それはリアルのイベントでも同じです。なので、qloba、connpass、peatix、doorkeeperなどとSNSを組み合わせて利用されるとよいでしょう。

続いて、本番中に行う作業です。これがオンライン・イベントでは大変なのです。私は今回、その事に気づきました。
まず、zoom内で司会と進行を行わねばなりません。恰好よく言うとファシリテーションです。
ただ、それはまだいいのです。たとえ今回、私が登壇のセッションを二つ受け持っていたとしても。

本当に大変なのは、皆さんがオンライン上でみるzoomの画面を制御する作業です。それは大きく分けるとギャラリービューにするか、スピーカービューにするか、という二つです。
zoomは喋っている人を自動的に判別し、その人にフォーカスを当ててくれます。
ギャラリービューは喋っている人にフォーカスを当てても、パネルの大きさは他の人と一緒です。例えば16名が参加している場合も4×4のままです。
ところがスピーカービューは話している人の枠が大きくとられ、その他の人は上部に4枠ほど出るだけです。

ここを適切に切り替えておかないと、話している人の表情が見えにくいのです。とくに、話者が画面共有をすると、その間は切り替えることができないので要注意。YouTube Liveは、ホストが設定するビューによって見え方が大きく変わってしまいます。
それにはzoomのスポットライトビデオの機能を使い、話者をロックオンしておく必要があります。この機能はキンスキの松井さんのブログをご参考になさってください。

また、こうしたイベント中の細かい制御は、zoomのホストか共同ホストでないとできないため、事前に複数の運営スタッフ間で権限を委譲しておくことをお勧めします。
ちなみに、zoomからYouTube Liveの配信制御は共同ホストではできません。ホストしかできないので注意しましょう。
もう一つ、本番中にやるべきこと。それは、画面と音声の制御です。参加者の誰かがミュートし忘れ、そのせいでセッション中に大きな物音が響いた場合、スピーカーの話が邪魔されてしまいます。その時にもホストか共同ホストが該当の方のミュートをOnにすることでつつがなく進められます。これも複数人でやり方を共有しておくべきですね。
なお、zoomでは、参加者によるミュート制御の可/不可を設定できます。ただ、不可にしてしまうと話者以外の方が喋りたい時に喋れなません。そのため、可にしておいた方がよさそうです。

やるべきことはまだあります。イベント中のTweetの盛り上げです。リアルのイベントでは、実況も含めたTweetが欠かせません。だからハッシュタグを冒頭に掲示するのです。
ですが、zoomにはミーティング内チャットという機能があります。
参加者にどちらで呟いてもらうか。これは難しいところです。
ミーティング内チャットの場合、同じユーザーインターフェースにチャットボタンがあり、そこから呟けます。そしてその内容はミーティングの参加者に限定されます。だから参加者の皆さんにとってはつぶやくためのハードルは低いです。
ただ、主催者の立場に立ってみると、ミーティング内チャットは、zoomの内に閉じてしまいます。
イベントの発信力を考えるとTwitterのほうが外へのアピールとなりやすく、Twitterで発信して欲しいという気になります。
実際、今回のkintone Café 神奈川 Vol.6ではzoomのミーティング内チャットは451件も呟かれ、43人の最大同時参加者があったのに、38人の方に呟いてもらえました。一方のTwitterは250件と、約1.8倍の差が出ました。
もちろん、zoomでもミーティング内チャットを無効にすることができます。ただ、それを禁止すると、肝心のイベントの盛り上がりに逆効果となりかねません。本末転倒もいいところです。
zoom APIを使い、ミーティング内チャットをTwitterに流せないか、調べてみましたが、どうも難しいように思えます。そもそもzoom内のチャットを外に公開してもよいか、事前に参加者の許可を取っておくべきだともいえます。
ここは、事前にTwitterやミーティング内チャットの盛り上げ役を何人かにお願いしておいたほうが良いと思います。また、ミーティング内チャットは手動で外部に保存できますので、それを定期的にTweetしてもらうのも一つの方法でしょう。
あと、今回はYouTube Liveも同時で配信しました。ですが、YouTube Liveのは双方向の関係が薄くなるため、開始直前まで配信URLを告知しませんでした。これも、本番が始まると忘れてしまいますので、拡散して下さる方を事前に決めておいた方がよいです。今回はキンスキの松井さんにフォローしてもらえました。

主催者がやるべきことはまだあります。それは、間が空いた時の埋め方です。
kintone Café 神奈川 Vol.6でも30分ほど最後にフリートークの時間ができました。
この時に質疑を行うよう促したのですが、まだまだオンライン・イベントには皆さん慣れていないのか、そこで質問を投げて下さる方は少ないようです。
他のオンライン・イベントにも何度か参加したのですが、リアルのイベントに比べると、主催者からの懇願の視線にさらされないためか、積極的に発言する方がなかなか現れないようです。
今回は冒頭でzoomの挙手機能や、はい/いいえでアンケートを取る機能を試してみたのですが、運営側スタッフでその集計や挙手へ反応する運営を打ち合わせ損ねていました。ここはぜひ、事前にコンセンサスを取っておくべきです。

結局、今回は5/9のイベントやkintone Caféの開催場所などのネタで間は持たせました。
決して皆様、話さないわけでは、ないのです。お酒が入った懇親会では、比較的に話が盛り上がりました。そのため、先にアルコールを許可しておくのも方法の一つかもしれません。
事前に質問を受け付けておき、それをネタにするというのも一つでしょう。
この部分は、これからノウハウを貯めてゆくしかないと思われます。
また、何人かに質問を投げて下さるように頼んでおくのも一つの手です。いわゆるサクラのように。

イベントの終了後にやるべきこともあります。
まず、YouTube Liveの配信停止です。今回もキンスキの松井さんにフォローしてもらわなければ、懇親会までLive配信を続けてしまったかもしれません。
そしてもう一つは、開催レポートの執筆です。
YouTubeを見直せば、内容については文章に起こすことはさほど難しくありません。
ですが、その記事に出す写真。これは案外見落としがちになると思います。
イベントの全体を表す画像をどう撮るのか。私は、ギャラリービューをスクリーンショットを撮る以外の写真が思いつきませんでした。

そんな形で、イベントの開催中は、かなり集中する仕事が多いのです。
さらにいうと、ディスプレイという狭い視野の中で作業が複数発生するため、マルチタスクに慣れていないと厳しいです。代表の私の場合、ノートパソコン一台と、Facebook messengerやイベントに関係ないお客様とのやり取りをiPad miniでこなしていました。おそらくイベント用には複数のディスプレイを併用して使いこなすしかないのでしょう。
オンラインのイベント主催とは、このようになれないうちは難しいかもしれません。

ですが、新型コロナ・ウィルスの猛威が衰えを知らない以上、オンラインのイベントはこれからも催されるはずです。ファシリテーションのスキルも求められるに違いありません。そのためには、運営上の工夫の余地はまだあるはず。
弊社も私も、引き続きノウハウの獲得に努力していきたいと思います。

最後に今回、zoomで参加して下さった皆様、YouTubeで参加して下さった皆様、事前と最中と事後にご協力くださった皆さま、本当にありがとうございました。
次回は5/9にkintone Café Online Vol.1が開催されます。
告知サイト
そこでまたお会いできればと思います。

代表の私はfreee株式会社とサイボウズ株式会社の共催イベント
freee & kintone BizTech hackでオンラインのハンズオン講師というさらに難易度の高いイベントに挑戦します。(※すでに満席なのです)
そうした挑戦を通して得たノウハウは、皆様にも還元していきたいと考えております。
今後ともよろしくお願いいたします。


ワーキングツリーにはkintoneとboxをお飾り!


kintone Advent Calendar 2019の24日目の記事です。

  Topへ↓

ん?この著者、この間もAdvent Calendarでみたで? はい。二度目の登場です。

kintoneは優れたツールですが完全ではない?
なーんてディスられても動じず、欠点を正直に認めるのもkintoneの憎めないところ。そう思ってやまない著者です。

kintoneの欠点のいくつかはすぐに挙げられます。
例えばブラウザーベースで動いているので、ファイルアップロードの作業が面倒、とか。
添付ファイルフィールドに画像データを放り込みまくると、一ユーザーあたり5GBの容量の制限が足かせになってくる、とか。

そんな限界を解消するためのささやかなクリスマスプレゼントを皆様にお届けしたいと思います。
なに、ちょっとした贈り物です。クリスマスツリーによくぶら下がっている箱のような。
箱・・・つまりboxです。
今回の記事では私の2019年の失敗事例も公開しているので、ひょっとしたら皆さまのご参考になるかもしれません。

box for kintoneのご紹介

  Topへ↑

世の中にオンラインストレージ製品はたくさんありますよね。その中でもboxが存在感を出しているのはご存じでしょうか。

kintoneとboxの連携はbox for kintoneというプラグインとして公開されています。
それを使えばブラウザー上でアップロードなどせず、ドラッグ&ドロップでブラウザー上から操作できちゃうのです。

クライアントツールのbox Driveをインストールすれば、Windowsのエクスプローラと同じ操作でbox上にファイルをアップロードできてしまう。なんて優れもの。

boxを使うと無尽蔵(契約プランによる)を誇る容量にファイルを置きまくり。
それをkintoneの画面上からに自由に呼び出せる。素晴らしい!
上に書いたkintoneの弱点を周囲のツールが補ってくれるいい例です。
本稿もそうしたkintoneを補ってくれる一つの例としてお役に立てれば幸いです。お日柄もよいので。

box for kintoneの使い方は、Cybozu developer networkにも出ています。
https://developer.cybozu.io/hc/ja/articles/205070124-Box-for-kintone その記事に従えば、簡単にbox for kintoneを導入できるはずです。

ところが、この記事で書かれているのは、一つのレコードに一つのフォルダーを対応させるところまで。
kintoneでちょっとしたシステムを作ろうとすれば複数アプリにまたがった構成が必要です。それに応じてboxのフォルダー構成も複数の階層にまたがってしまいます。

合同会社アクアビットダム設計なる会社

  Topへ↑

たとえば、大阪と東京に支店がある合同会社アクアビットダム設計があったとします。
この会社はダムを独自の技術で製造し、お客様にお納めしている設定です。

受注システムをkintoneで構築するにあたり、
大阪支店[組織]の
長井何某[個人]が担当する
担当案件[案件]の
施行状況[施工]と
湛水状況[湛水]を管理すると仮にしましょう(工程はしょりすぎ。ちなみに最後の工程は水を貯める工程です)。

他に顧客マスタがあるでしょうがここは割愛。また、[組織]と[個人]はアプリではなく、kintoneのアカウントを使用する想定です。
この場合3アプリですね。

ここでご注文からの流れをkintoneで管理したとしましょう。
各アプリの連動はkintoneのアクション機能を使ったとします。

ダム完成までにはさまざまな状況を報告していかねばなりません。するとダムの進捗に合わせて写真が大量に溜まっていきます。
kintoneの添付ファイルフィールドにファイルをアップしていると、すぐに容量が危うくなりかねません。
ここでboxの出番です。

ここでboxで写真を管理しようとした場合、box内のフォルダー構成はこのようになると思います。

さて、先ほどご紹介したbox for kintoneを思い出してみましょう。
プラグイン設定画面にルートフォルダーのIDを設定していましたね。

つまり、アプリ自体にルートフォルダーのみを作る仕様。
それって、どのレコードであろうと共通で1つのフォルダーだけ、、、
いやいや多層boxと多層アプリでは対応できないのはちょっと、、、
結論! box for kintoneだとちょっとキツイかも。

合同会社アクアビットダム設計にboxを

  Topへ↑

ということで、本稿では多段階にわたるboxの連動例をお伝えしたいと思います。また、その時にしでかしてしまった失敗と、そのリカバリ例もお伝えしたいと思います。

まず、話を簡単にするため、合同会社アクアビットダム設計としてのルートフォルダーを設定しておきましょう。

さらに、支店ごとにフォルダーを設定し、支店の配下に担当ごとのフォルダーも生成しておくと話が早いですね。

実際のboxのフォルダー構成はこんな感じ。

ここでルートフォルダーのフォルダーIDを取得しておきます。boxの画面から取れます。

その状態で、案件アプリに新規レコードを登録します。
案件アプリの項目には案件の主管支店と、案件の主担当を指定するフィールドも忘れずに。もちろん必須項目として。

なぜ必須項目にするのでしょう。
その理由は、レコードが保存成功後、案件フォルダーを作る際にどこのフォルダーの配下に作成するか決めなければならないためです。

boxのフォルダー生成APIについて

  Topへ↑

ここでboxの仕様を押さえておきましょうか。
サービスの仕様を確認するには、APIから逆引きしたほうが理解しやすい。いわゆる技術者あるあるです。
boxのAPIはこちらのサイトをご覧になると良いでしょう。
https://ja.developer.box.com ・・developerサイトトップ
https://ja.developer.box.com/reference ・・APIレファレンス

boxのフォルダー作成の項を読むと、親であるフォルダーのIDがパラメーターとして必須のようです。
編集時には親フォルダーのIDは必須ではなくなりますが、もしフォルダーの場所を移動する際は親フォルダーのIDは指定しなければなりません。

案件フォルダーを作る際は、親となる担当者フォルダーのIDを把握しておかねばなりません。
そしてその上の支店フォルダーも。

つまり、案件レコードの保存のタイミングで行うべきことは、まず、そのレコードの支店フィールドの値に等しい支店フォルダーを検索することです。
その際、基準となるのはルートフォルダーです。

ルートフォルダーの下にある支店フォルダーを検索し、そのIDを特定します。
間髪入れずに支店フォルダーの配下にある担当者フォルダーを検索します。
これは同一担当者が複数支店にフォルダーを持っている場合など、運用も考慮していますが、支店フォルダーのIDを内部で保持できるのであれば、いきなり担当者フォルダーから検索してもよいです。
重要なのは案件フォルダーを作成するにはその親フォルダーのIDを事前に必ず保持しておくことです。

先ほど、kintoneの案件アプリの支店と担当者の両フィールドは必須でなければならないとしたのには、そういう理由があったのです。
これら二つのフィールドの値がないと、案件を保存する際に生成されるべき案件フォルダーの保存先が迷子になってしまうので。

JavaScriptで実装してみた

  Topへ↑

続いてはいよいよboxの操作を行います。

その前に本稿ではboxの権限周りには踏み込まないことを言っておきます。
OAuthについては、もともとbox  for  kintoneで用意されていたclient IDを使用します。本当はbox内でアプリを作成し、そのアプリ内で設定した権限を認証しなければならないのですが。
box for kintoneに甘えてしまいましょう。

ついでにpromise処理が考慮されたAPI実行部分もbox for kintoneの処理を流用させていただきましょう。

処理の大まかな順序としては以下の通りです。
ただ、のちに述べますが、このコードは動きません。なのでコードは画像として参考程度に載せます。

まず、イベントが動くタイミングはapp.record.create.submit.successです。新規作成処理成功後ですね。

処理の都合上、この中で別のアプリに更新を行い、その結果が成功した場合にboxフォルダー生成処理を呼び出しています。

boxフォルダー生成処理では、まずルートフォルダーから支店フォルダーを検索します。
続いて支店フォルダーから担当者フォルダーを検索します。

ここでboxの検索の仕様が立ちふさがってきます。
boxの検索仕様として、対象の種類、生成時刻、オーナーIDや親フォルダーIDなどは指定できるのですが、肝心の文字列を完全一致で検索できないのです。queryというパラメータがあるにもかかわらず、そこに指定した文字列は曖昧検索として処理されてしまうのです。
APIレファレンス

つまり、親フォルダーに属する検索対象が複数ありうる場合、検索文字列に工夫が必要です。例えば姓名の間にスペースが入る場合など。
「長井 権兵衛」と「長井 主水」が対象のフォルダー配下にあって「長井 権兵衛」を検索したい場合、queryに「長井 権兵衛」を設定してもマッチしません。
ではどうやればよいか。
スペースの前後の文字列で検索するのです。
この場合、「長井」または「権兵衛」で検索します。すると前者は二件がヒットし、後者は一件がヒットします。
その結果を再度ループして回し、一件ごとにname属性の値が検索文字列に一致するかを確認する。
そのような面倒な処理がboxの検索には必要です。

このコードも実際は使っていませんが、軽く提示します。

これで、担当者フォルダーIDまで求められました。

boxのフォルダー生成と検索にまつわる問題

  Topへ↑

続いてはフォルダーの生成に移りましょう!
APIレファレンス

生成にあたっては、名前と親フォルダーのIDを指定するだけです。

これで、案件レコードが保存されたら案件フォルダーを作成するところまでができました。

ここで当初想定していたboxの構成を見てみましょう。
案件フォルダーの配下に「提案状況」「施工状況」「湛水状況」の三フォルダーがあります。
このフォルダーの生成にも実は厄介な問題が潜んでいます。

例えば、案件のレコードが保存されました。そして案件フォルダーが生成されました。
そしたら、アクション機能によって施工状況アプリにレコードをコピーし、施工状況アプリでもレコードが保存された瞬間、案件レコードの時と同じように施工状況フォルダーを生成すればええんちゃうの?と思ったでしょう。

ところが、フォルダーを生成するには親のフォルダーの指定が必須です。
親フォルダー、つまり案件フォルダーをフォルダー生成処理の直前で検索してフォルダーIDを取得しなければなりません。
ところがこの親フォルダーの検索取得にはひとつハードルが控えています。そのハードルとは、コンテンツが生成されてから検索可能となるまでに時間がかかる、というものです。
boxはなんらかのコンテンツが作成されてから、それが検索可能となるまでにbox内部でindexを構築しており、それに時間が掛かるのです。
boxの APIレファレンスには以下のように書かれています。

つまり、案件フォルダーの生成からすぐ、施工状況アプリのレコードを保存した場合、親となるべきフォルダーが検索できないため、親フォルダーの指定ができないのです。

boxを多層構造でkintoneと連動させる場合、この仕様上の制限は現状では避けられません。

この制限を回避するため、発想を切り替えました。
つまり、案件フォルダーが生成された後、同時に配下のフォルダーも作ってしまうのです。

box APIでは、フォルダー生成が成功した時点で返り値として生成されたフォルダーのIDが得られます。このIDを使えば配下のフォルダーも即時に生成できます。

このコードも実際は使っていませんが、軽く提示します。

この下の処理ではさらに生成した案件フォルダーのURLを取得し、そのURLやフォルダーIDをkintoneの2アプリに更新して設定しています。

ここまででkintoneのapp.record.create.submit.successイベントを見てきました。その結果、実装ができそうです。
テストでもフォルダーが意図通りに生成されました。開発用のPCでも、お客様のご担当者様のPCでも。

バグ大魔王降臨!

  Topへ↑

ところが! やったと思った安心のかげに潜むのが落とし穴。バグが出てしまったのです。
テストではうまく動いていたのに、いざ本番になるとうまくいかない。なんということでしょう!

実は、その根本的な原因は今もなお究明できていません。
事象としてはboxにAPIリクエストを投げた後、何も戻ってこないのにプログラムが終了してしまいます。httpレスポンスすら帰ってこずに。
それも終了する場所がまちまちなのが始末が悪い。複雑なPromiseの構造に加え、referredを混在させたことにも問題があったのかもしれません。
この不具合がやっかいなのは、boxからのレスポンスを待つ間、app.record.create.submit.successの結果が完了できないことにあります。その間、ブラウザーは固まってしまい、kintoneを利用されている皆様にはただ困惑が。

そして、この不具合の原因がブラウザーにあるのか、box側にあるのか、kintone内部にあるのか、それともPCのスペックにあるのか。はたまたネットワーク環境によるものなのか。いまだに分っていません。
ただ、ブラウザー上でレスポンスを待つ運用はまずい、という悔いだけは骨身に沁みました。
私はその原因を追究するよりもお客様の運用を円滑に進めることを優先しました。
その決断として、ブラウザーに依存する実装を止めました。

AWSへ処理を移管

  Topへ↑

では、どうすればよいか。

幸いなことにkintoneにはWebhookという機能が備わっています。Webhookには、レコード保存時にWebhookのリクエストを受け付けてくれるWebhook URLを設定できます。

私がWebhook URLとして設定したのはAWSのAPI Gatewayで設定したURLでした。
API Gatewayについての説明は割愛しますが、kintoneから受け取ったWebhookのリクエストに含まれるJSONを読み取り、それを後続の処理に渡すことができます。
後続の処理にはAWS Lambdaを選びましたので、同じAWS上で処理が連携できます。

AWS LambdaではNode.jsを使い、ほぼkintoneのkintone.app.create.submit.successで実装したのに近いコーディングを行いました。
box Node SDKがAWS Lambdaから簡単に使用できるので、それを使えば似たような実装ができるのです。
ただし、boxのアプリは一から作る必要があります。設定もあれこれ行う必要が生じました。
最初、こちらのブログの力も借りました。ありがとうございました。
Lambda関数のコードを以下に掲示します。なお、このコードは動いているものを基にいろいろといじっているので参考になると思います。

/**
 * This sample demonstrates how to call Box APIs from a Lambda function using the Box Node SDK.
 *
 * For step-by-step instructions on how to create and authorize a Box application,
 * see https://github.com/box/samples/tree/master/box-node-lambda-sample.
 */
const BoxSDK = require('box-node-sdk');                                                // Node.jsのbox-node-sdkモジュールを呼び出す
const request = require('request');                                                    // Node.jsのrequestモジュールを呼び出す
const boxConfig = JSON.parse(process.env.BOX_CONFIG);                                  // AWS Lambdaの環境変数のBOX_CONFIGの値をJSONで扱えるように

boxConfig.boxAppSettings.appAuth.keyID = boxConfig.boxAppSettings.appAuth.publicKeyID; // 9行目で取り出したkeyIDにpublicKeyIDを代入

const sdk = new BoxSDK(boxConfig.boxAppSettings);                                      // 9行目で取り出したboxAppSettingsをsdkに代入

/**
 * Create a service account client that performs actions in the context of the specified
 * enterprise.  The app has a unique service account in each enterprise that authorizes the app.
 * The service account contains any app-specific content for that enterprise.
 * Depending on the scopes selected, it can also create and manage app users or managed users
 * in that enterprise.
 *
 * The client will automatically create and refresh the service account access token, as needed.
 */
const client = sdk.getAppAuthClient('enterprise', boxConfig.enterpriseID);             // boxアプリが適用できるアカウントのグローバル設定を管理

var DOMAIN = '*********.cybozu.com'; //kintone環境のドメイン                            // *****はご使用のkintoneのサブドメインを
var APP_ID_1287 = 1287;   //案件管理アプリのアプリID
var BASE_URL = "https://" + DOMAIN + '/k/v1/';
var APITOKEN_1287 =  "kintoonkaramottekitatookunwokokoniiretene";                      // kintoneの案件アプリのAPIトークン
var headers_1287 = {'X-Cybozu-API-Token': APITOKEN_1287};                              // リクエストで使用するヘッダ
var FolderId;
var updaterecordid_1287;

exports.handler = (event, context, callback) => {                                      // eventはkintoneのWebhookからAPI Gatewayを経由したレコード情報
                                                                                       // contextはLambda関数に関する情報
    const API_BASE_PATH = 'https://api.box.com/2.0';                                   // box Node SDKの文法に準拠

    // targetnameはコンテンツの文字列
    // typeはコンテンツの対象。本稿の場合はfolder
    // content_typesは検索対象とするプロパティ。本稿の場合はname
    // limitは検索結果として戻す件数。
    // idsは親フォルダーのフォルダーID
    // methodは本稿では全てGETなので使用していない
    // dataは本稿の場合検索対象(支店,担当者,案件No)のうち、担当者の場合["担当名"]で渡ってくる。
    function searchFolder(targetname, type, content_types, limit, ids, method, data, success, error) {  //157,159,161行目から呼び出されて検索処理を実施
        if (data !== undefined) {                                 // dataが指定されている場合
            if (data[0] === "担当名") {                            // dataの配列の最初の要素が"担当名"の場合
                targetname = targetname.split(' ')[0];           // 受け取るtargetnameは「長井 権兵衛」の様に全角スペースで区切られた姓名なので姓を取得
            }
        }

        return new Promise(function (resolve, reject) {           // Promiseを設定
            client.search.query(                                  // 24行目でclientとして承認されたbox Node SDKのsearchクラスのquery関数を呼び出し
                "\"" + targetname + "\"",                         // 最初のパラメーターは検索対象文字列。文字列なのでエスケープした""で囲む。でも曖昧検索
                {                                                 
                    fields: 'id,name,modified_at,extension,permissions,collections',  //検索結果として返すコンテンツのプロパティ
                    type: type,                                                       //folder
                    content_types: content_types,                                     //検索対象はnameプロパティ
                    limit: limit,                                                     //結果として返す件数
                    ancestor_folder_ids: ids,                                         //親フォルダーID 
                    offset: 0                                                         //オフセットしないので0
                })
                .then(function(results){                                              //結果が取得されたのでこのPromiseチェーンへ
                    if (data !== undefined) {                                         //dataが指定されている場合
                        if (data[0] === "担当名") {                                   //dataの配列の最初の要素が"担当名"の場合
                            for (var i = 0; i < results.entries.length; i++) {        //戻り値の件数分(limitで指定した件数分)
                                if (results.entries[i].name === data[1]) {            //戻り値のnameプロパティがdataの2番目の要素(担当名)か
                                    resolve(results.entries[i].id);                   //Promiseは完了したと戻り値のidプロパティ(フォルダーID)を返す
                                }
                            }
                        }
                    } else {
                        resolve(results.entries[0].id);                               //Promiseは完了したと戻り値のidプロパティ(フォルダーID)を返す
                    }
                })
                .catch(function(error){ // エラーの場合
                    reject(error);
                });
        });
    }

    // createParamは生成フォルダー名と親フォルダーIDが含まれたJSONオブジェクト
    function postFolder(createParam) {                     //176行目から呼び出されてフォルダー生成処理を実施
        return new Promise(function (resolve, reject) {    // Promiseを設定
            client.folders.create(createParam.parent.id, createParam.name)  //24行目でclientとして承認されたbox Node SDKのfolderクラスのcreate関数を呼出
                                                                            //1つ目は親フォルダーID、2つ目は生成するフォルダーの名称 
                .then(function(results){                                    //85行目の処理が成功したのでこのPromiseチェーンへ
                    var ankenid = results.id;                               //生成したフォルダーIDを以下のforeach内で使うためにankenidに代入 
                    var subfolders = [                                      //生成した案件フォルダーの配下に作成する三つのフォルダー名を配列にしています
                        "提案資料",
                        "施工状況",
                        "湛水状況"
                    ];

                    var promiseset = [];                                    //三つのフォルダーの生成が終わるまで待つPromiseを三つ作るので配列を設定
                    subfolders.forEach(function(val,index,ar){              //89行目で生成した配列の各要素をループします
                        promiseset[index] = new Promise( function( resolve, reject ) {  //95行目で生成した配列にPromiseを設定します。
                            client.folders.create(ankenid, val)             //24行目でclientとして承認されたbox Node SDKのfolderクラスのcreate関数を呼出 
                                                                            //1つ目は親フォルダーID(案件フォルダー)、2つ目は生成するサブフォルダーの名称
                                .then(function(results){                    //98行目の処理が成功したのでこのPromiseチェーンへ
                                    resolve(results.id);                    //97行目のPromiseは完了したと戻り値のidプロパティ(フォルダーID)を返す
                                }).catch(function(error){                   //98行目の処理が失敗したのでこのPromiseチェーンへ
                                    reject(error);                          //97行目のPromiseは失敗したとエラーオブジェクトを返す
                                });
                        });
                    });
                    Promise.all( promiseset )                               //97行目で設定した三つのPromiseが全て完了したらここに来る
                        .then( function ( message ) {
                        resolve(ankenid);                                   //84行目のPromiseは完了したと戻り値のidプロパティ(フォルダーID)を返す
                    })
                        .catch( function ( reason ) {                       //97行目で設定した三つのPromiseのどれかが失敗したらここに来る
                            console.log( reason ) ; // "失敗!!"
                        reject(false);                                      //84行目のPromiseは失敗したとエラーオブジェクトを返す
                    });
                })
                .catch(function(error){                                     //85行目の処理は失敗したらここに来る
                    reject(error);                                          //84行目のPromiseは失敗したとエラーオブジェクトを返す
                });
        });
    }

    // boxフォルダーIDは更新対象となるフォルダーID
    // createParamは更新フォルダー名と親フォルダーIDが含まれたJSONオブジェクト
    function putFolder(boxフォルダーID, updateParam) {             //165行目から呼び出されてフォルダー更新処理を実施
        return new Promise(function (resolve, reject) {         // Promiseを設定
            client.folders.update(boxフォルダーID, updateParam)    //24行目でclientとして承認されたbox Node SDKのfolderクラスのupdate関数を呼出
                                                                //1つ目は対象となるフォルダーID、2つ目は更新するフォルダー情報の含まれたJSONオブジェクト 
                .then(function(results){                        //126行目の処理が成功したのでこのPromiseチェーンへ
                    resolve(results.id);                        //125行目のPromiseは完了したと戻り値のidプロパティ(フォルダーID)を返す
                })
                .catch(function(error){                         //126行目の処理が失敗したのでこのPromiseチェーンへ
                    reject(error);                              //125行目のPromiseは失敗したとエラーオブジェクトを返す
                });
        });
    }

    function getFolderURL(createdid) {                          //178行目から呼び出されてフォルダーの共有処理を実施
        return new Promise(function (resolve, reject) {         // Promiseを設定
            client.folders.update(createdid, {shared_link: client.accessLevels.OPEN}) 
                                                                //24行目でclientとして承認されたbox Node SDKのfolderクラスのupdate関数を呼出
                                                                //1つ目は対象となるフォルダーID、2つ目は更新するフォルダーのプロパティ(共有設定)
                .then(function(results){                        //139行目の処理が成功したのでこのPromiseチェーンへ
                    resolve(results.shared_link.url);           //138行目のPromiseは完了したと戻り値の共有URLプロパティ(リンクURL)を返す
                })
                .catch(function(error){                         //139行目の処理が失敗したのでこのPromiseチェーンへ
                    reject(error);                              //138行目のPromiseは失敗したとエラーオブジェクトを返す
                });
        });
    }
    function createBoxFolder(支店, 担当者, 案件No, boxフォルダーID) {  //212行目から呼び出されてフォルダーの共有処理を実施
        return new Promise(function (resolve,reject) {             // Promiseを設定
            var rootfolder = "12345678910";                        //boxのフォルダー制御のルートとなるフォルダーのフォルダーIDを静的に代入
            var ownerbranchfolder;                                 //支店フォルダーのフォルダーID
            var personinchargefolder;                              //担当者フォルダーのフォルダーID
            var createParam;                                       //searchFolder関数へはダミーオブジェクト。putfolderとpostfolderへはJSONオブジェクト

            searchFolder(支店, "folder", "name", 10, rootfolder, 'GET', createParam).then(function (branchfolderid) {  //45行目へ
                ownerbranchfolder = branchfolderid;                           //searchFolderからの返り値を上位スコープのownerbranchfolderへ代入
                searchFolder(担当者, "folder", "name", 10, ownerbranchfolder, 'GET', ["担当名",担当者]).then(function (personfolderid) {  //45行目へ
                    personinchargefolder = personfolderid;                    //searchFolderからの返り値を上位スコープのpersoninchargefolderへ代入
                    searchFolder(案件No, "folder", "name", 10, personinchargefolder, 'GET', createParam).then(function (projectfolderid) {  //45行目へ
                        var name = "案件No" + " " + 案件No;                    //生成/更新する案件フォルダーの名称を設定する
                        createParam = {name: name, parent: {id: personinchargefolder}};  //案件フォルダーの設定情報をJSONオブジェクトに組み立てる
                        if (projectfolderid.length > 0) {                     //161行目で案件フォルダーが存在した場合(フォルダー情報更新)
                            putFolder(projectfolderid, createParam).then(function (updatedid) {  //124行目へ
                                FolderId = updatedid;                         //161行目の処理で得た更新したフォルダーIDをスコープ外の168行で使うため
                                getFolderURL(updatedid).then(function (updatedurl) {             //137行目へ
                                    resolve(FolderId+"****"+updatedurl);      //151行目のPromise完了をフォルダーIDと共有URLプロパティ(リンクURL)で返す
                                }).catch(function(error){                     //167行目の処理が失敗したのでこのPromiseチェーンへ
                                    reject(error);                            //151行目のPromiseは失敗したとエラーオブジェクトを返す
                                });
                            }).catch(function(error){                         //165行目の処理が失敗したのでこのPromiseチェーンへ
                                reject(error);                                //151行目のPromiseは失敗したとエラーオブジェクトを返す
                            });
                        } else {
                            postFolder(createParam).then(function (createdid) {       //83行目へ
                                FolderId = createdid;                                 //生成したフォルダーIDを以下の179行目で使うためにFolderIdに代入
                                getFolderURL(createdid).then(function (createdurl) {  //137行目へ
                                    resolve(FolderId+"****"+createdurl);      //151行目のPromise完了をフォルダーIDと共有URLプロパティ(リンクURL)で返す
                                }).catch(function(error){                             //178行目の処理が失敗したのでこのPromiseチェーンへ
                                    reject(error);                                    //151行目のPromiseは失敗したとエラーオブジェクトを返す
                                });
                            }, function(res) {                                        //176行目のフォルダー生成処理でrejectレスポンスが返った場合
                                if (res.status && res.status === 409) {               //176行目のフォルダー生成処理でrejectレスポンスが409返った場合
                                    if (res.context_info                              //176行目のフォルダー生成処理でrejectレスポンスが競合を示した場合
                                        && res.context_info.conflicts
                                        && res.context_info.conflicts.length > 0) {
                                        return;                                       //150行目のcreateBoxFolder関数を終える
                                    }
                                }
                            }).catch(function(error){                                 //176行目のフォルダー生成処理でエラーが帰った場合
                                reject(error);                                        //151行目のPromiseは失敗したとエラーオブジェクトを返す
                            });
                        }
                    }).catch(function (error) {                                       //161行目のフォルダー検索処理でエラーが帰った場合
                        // 非同期処理失敗。呼ばれない
                        console.log(error);
                    });
                }).catch(function (error) {                                           //159行目のフォルダー検索処理でエラーが帰った場合
                    // 非同期処理失敗。呼ばれない
                    console.log(error);
                });
            }).catch(function (error) {                                               //157行目のフォルダー検索処理でエラーが帰った場合
                // 非同期処理失敗。呼ばれない
                console.log(error);
            });
        });
    }

    var recordjson = JSON.parse(event.body);                                 //34行目で受け取ったkintoneのWebhookのレコード情報をJSON形式で扱えるように
    updaterecordid_1287 = recordjson.record.レコード番号.value;               //210行目のレコードデータの「レコード番号」フィールドの値を代入
    createBoxFolder(recordjson.record.支店.value[0].code,                    //150行目へ
                    recordjson.record.担当者.value, 
                    recordjson.record.案件No.value, 
                    recordjson.record.boxフォルダーID.value).then(function(idurl) {
        if (idurl) {                               //212行目のcreateBoxFolderの戻り値(168、179行目で値設定)
            var targetrecordids = [updaterecordid_1287+"**"+APP_ID_1287];   //211行目で設定したレコード番号と27行目で設定したアプリID
            var kintonepromiseset = [];                                     //kintoneのレコードアップデートが終わるまで待つPromiseの配列を設定
            targetrecordids.forEach(function(val,index,ar){                 //217行目で生成した配列の各要素(本稿では1つ)をループします
                kintonepromiseset[index] = new Promise( function( resolve, reject ) {  //218行目で生成した配列にPromiseを設定します。
                    var body_post = {                                                  //kintoneの既存案件アプリを更新するレコードを組み立てます。
                        app: val.split("**")[1],                                       //217行目で設定した配列の**で区切られた右側(アプリID)
                        id: val.split("**")[0],                                        //217行目で設定した配列の**で区切られた左側(レコード番号)
                        record: {
                            boxフォルダーID: {
                                value: idurl.split("****")[0]                       //212行目のcreateBoxFolderの戻り値の****で区切られた左のフォルダーID
                            },
                            表示: {
                                value: idurl.split("****")[1].replace("*******.box.com","app.box.com")
                                         //212行目のcreateBoxFolderの戻り値の****で区切られた右のURL(契約のboxのサブドメインをapp.box.comに置換の必要あり)
                            }
                        }
                    };
                    var options_getsalesamount = {                            //リクエストのbody部分を組み立てます。
                        url: BASE_URL + 'record.json',                        //28行目で設定したURLのルートと一行レコードの更新なのでrecord.jsonを連結
                        method: 'PUT',                                        //更新なのでPUT
                        headers: headers_1287,                                //30行目で設定したAPIトークン
                        'Content-Type': 'application/json',                   //リクエストのボディ部分のタイプ
                        json: body_post                                       //221行目で設定したボディ部分
                    }
                    //レコードを取得
                    request(options_getsalesamount, function (error, response, body) {    //Node.jsのrequestモジュールで234行のリクエストを送信
                        if (error) {                                                      //242行目の値がerrorだったら
                            console.log('Error: ' + error.message);
                            reject();                                                     //220行目のPromiseは失敗したとエラーオブジェクトを返す
                        }
                        console.log("kintone recordput:succcess"+val);
                        resolve();                                                        //220行目のPromise完了を返す
                    });
                });
            });
            Promise.all( kintonepromiseset )                                              //220行目で設定したPromiseが全て完了したらここに来る(本稿は1つ)
                .then( function ( message ) {                                             //252行目の処理が成功したのでこのPromiseチェーンへ
                    context.done(null, {text: "kintone POST and Box Folder Create success!"});  //Lambdaの処理結果をログとして残す
            })
                .catch( function ( reason ) {
                    context.done(null, {text: "Box Folder Create failed!"});              //Lambdaの処理結果としてエラーログ
                return;
            });
        } else {
            context.done(null, {text: "Box Folder Create failed!"});                      //Lambdaの処理結果としてエラーログ
        }
    }, function(res) {                                                                    //212行目の返り値がrejectで戻ってきた場合
        context.done(null, {text: "Box Folder Create failed!"});                          //Lambdaの処理結果としてエラーログ
        return false;                                                                     //212行目の結果としてfalseを返す
    });
};

 

なんとか実装

  Topへ↑

いずれにせよ、私が2019年に出した唯一の大きなバグがこれでした。
結局、バグが出てから実運用にこぎつけるまでにさらに二カ月ほどの時間をいただきました。お客様にも多大なご迷惑をおかけしてしまいました。

これが実装できたことで、案件アプリにレコードを登録した時点で、Webhookが発動し、AWS API GatewayからAWS Lambdaを介してboxへのフォルダー生成と、レコードに対応するboxのURLとフォルダー番号をkintoneの該当レコードに登録することができました。

kintoneの画面上にboxのフォルダーを出す部分はbox for kintoneの内部にも書かれている通りです。
実際それを使わせていただいています。ありがとうございます。
以下にコードを載せていますが、疲れてきたのでコード内のコメントは割愛します。ごめんなさい。

(function() {
    'use strict';

    var BOX_CLIENT_ID = 'wkgp4k64whsha8mwvg7k5k63cim82mmv';   //sample_plugin_default
    // localStorage
    var LOCAL_STORAGE_PREFIX = 'kintone.plugin.' + BOX_CLIENT_ID;
    var LOCAL_STORAGE_JUDGED_ALLOW_ACCESS = LOCAL_STORAGE_PREFIX + '.judgedAllowAccess';

    var config = [];

    var BOX_EMBED_WIDTH = 840;
    var BOX_EMBED_HEIGHT = 420;

    var getUrl = function(path) {
        var matchedGuestSpacePath = location.pathname.match(/^\/k\/(guest\/\d+\/)/);
        var guestSpacePath = '';
        if (matchedGuestSpacePath !== null && matchedGuestSpacePath.length === 2) {
            guestSpacePath = matchedGuestSpacePath[1]; // "guest//"
        }
        var apiPath = '/k/' + guestSpacePath + path;
        return apiPath;
    };

    var boxApi = {
        clientInfo: {'provider': 'box', 'client': BOX_CLIENT_ID},

        getAccessToken: function() {
            // add a hash parameter for distinguishing OAuth redirect
            var delimiter = (location.hash.indexOf('#') === 0) ? '&' : '#';
            location.hash += delimiter + BOX_CLIENT_ID + '.oauth_redirect=true';
            kintone.oauth.redirectToAuthenticate(this.clientInfo, location.href);
        },
        hasAccessToken: function() {
            return kintone.oauth.hasAccessToken(boxApi.clientInfo);
        }
    };

    var validateConfig = function(record) {
        config['folderId'] = '0';//Box親フォルダーID
        config['keyFld'] = '顧客名';//kintoneキーフィールド
        config['boxUrl'] = '表示';//Box共有リンクの格納先
        config['boxFolderId'] = "boxフォルダーID";
        config['access'] = 'Open';//Box共有リンクのアクセス権[Collaborator/Company/Open]
        config['prohibitToDownload'] = 'false';//コラボレータにのみダウンロードを許可する

        if (!config) {return false; }
        return true;
    };

    var decorateBoxLinkField = function(boxUrl) {

        var boxLinkPattern = /^https:\/\/([a-zA-Z0-9]+).box.(com|net)(\/s\/[a-z0-9]+)$/;
        var match = boxUrl.match(boxLinkPattern);
        if (!match) {
            return;
        }
        var iframeSrc =
            'https://app.box.com/embed_widget/000000000000' +
            match[3] +
            '?theme=gray' +
            '&show_parent_path=no' +
            '&show_item_feed_actions=no' +
            '&partner_id=233';

        var elEmbed = kintone.app.record.getFieldElement(config.boxUrl);
        if (elEmbed === null) {return; }
        $(elEmbed).empty();

        var width = BOX_EMBED_WIDTH;
        var height = BOX_EMBED_HEIGHT;

        $(elEmbed).parent().css({
            'width': (width + 100) + 'px',
            'height': 'auto',
            'background-color': 'rgba( 255, 255, 255, 0 )'
        });
        var embedIframe = $('', {
            src: iframeSrc,
            width: width,
            height: height,
            frameborder: '0',
            allowfullscreen: 'true',
            allowscriptaccess: 'always'
        });
        $(elEmbed).append(embedIframe);
    };

    var judgedAllowAccessFlag = {
        isSet: function() {
            return (localStorage.getItem(LOCAL_STORAGE_JUDGED_ALLOW_ACCESS) !== null);
        },

        set: function() {
            localStorage.setItem(LOCAL_STORAGE_JUDGED_ALLOW_ACCESS, 'true');
        },

        remove: function() {
            localStorage.removeItem(LOCAL_STORAGE_JUDGED_ALLOW_ACCESS);
        }
    };

    kintone.events.on('app.record.detail.show', function(e) {
        if (validateConfig(e.record)) {
            var boxUrl = e.record[config.boxUrl].value;
            if (!e.record[config.boxUrl].value) {

                var elEmbed = kintone.app.record.getFieldElement(config.boxUrl);
                if (elEmbed === null) {return null; }
                $(elEmbed).empty();

            } else {
                decorateBoxLinkField(boxUrl);
            }
        }

        return e;
    });

    var checkAccessToken = function() {
        var oauth_redirect_param = BOX_CLIENT_ID + '.oauth_redirect=true';
        if (location.hash.indexOf(oauth_redirect_param) !== -1) {
            judgedAllowAccessFlag.set();

            // remove a hash parameter
            location.hash = location.hash.replace(oauth_redirect_param, '');

            var t = setInterval(function() {
                if (location.hash.indexOf(oauth_redirect_param) !== -1) {
                    // cancel button was clicked
                    clearInterval(t);
                    location.href = getUrl(kintone.app.getId() + '/');
                }
            }, 500);
        } else if (!judgedAllowAccessFlag.isSet() || !boxApi.hasAccessToken()) {
            kintone.oauth.clearAccessToken(boxApi.clientInfo, function(body, status, headers) {
                boxApi.getAccessToken();
                return null;
            });
        }
    };

    kintone.events.on('app.record.create.show', function(e) {
        if (validateConfig(e.record)) {
            checkAccessToken();
            e.record[config.boxUrl]['disabled'] = true;
            e.record[config.boxFolderId]['disabled'] = true;
        }

        return e;
    });

    kintone.events.on('app.record.edit.show', function(e) {
        if (validateConfig(e.record)) {
            if (!e.record[config.boxUrl].value) {
                checkAccessToken();
            } else {
//                e.record[config.keyFld]['disabled'] = true;
                e.record[config.boxFolderId]['disabled'] = true;
            }
            e.record[config.boxUrl]['disabled'] = true;
        }
        return e;
    });

    kintone.events.on('app.record.index.edit.show', function(e) {
        if (validateConfig(e.record)) {
            e.record[config.boxUrl]['disabled'] = true;
            e.record[config.keyFld]['disabled'] = true;
            e.record[config.boxFolderId]['disabled'] = true;
        }
        return e;
    });
})();

 

 

まとめ

  Topへ↑

実案件ではさらに凝った実装(フォルダー数も階層も本稿の例よりさらに多い)が施されています。
そして、古くboxが設定されていないレコードには手作業がたまに発生しているものの、実運用に乗っています。
この記事ではそれ以上の情報を出すことはお客様の業務に関わるのでここまでにしとうございます。

本稿がkintoneを運用している皆様にとって少しの手助けになれば幸せです。

kintone上で大量の添付ファイルに困っていらっしゃる方や、社内ファイルサーバーからの移行でお困りの方。他のPaaSからkintoneへ移行する作業があって、添付ファイルの扱いにお困りの方。
弊社では本稿のようなboxとkintoneの連動事例を何例も手掛けております。お困りの際はおっしゃってくださいませ。

最後に蛇足ですが、boxの案件で例に挙げた三つのダムは、私が実際に訪れてダムカードを入手した場所です。


当エントリーの参考にさせていただいたブログ

  Topへ↑

最後になりましたが、このエントリー作成にあたり、以下の2サイトからの情報を参考にさせていただきました。ありがとうございました。

 box APIレファレンス
 AWS Lambda上でBox Node SDKを利用する-九龍堂雑録


コーチングのグラフってkintoneで出せるんやって!


kintone2 Advent Calendar 2019の5日目の記事です。

  Topへ↓

突然ですが皆さん、コーチングって聞いたことがありますか?
あっ! そこのあなた、ページはそのままに!
これは間違いなくkintone Advent Calendarの記事ですから。
ほら!

きとみちゃん楽しいですよね!
https://kintone.cybozu.co.jp/jp/kitomi/

日々、お仕事に励むきとみちゃん。
きとみちゃんとお仕事をする仲間はとっても個性が豊か。

ちょっぴりあわてんぼうでドジっ子のきとみちゃんがkintoneに救われる姿は微笑ましいです。
ちなみに私は巻物で見積書を出してくださる麻呂な方が好きです。この方のお名前はなんでおじゃる?

さて、きとみちゃんがお仕事をする上で助けになる手法はkintoneの他にもさまざまなものがあります。

その中の一つが冒頭に書いたコーチングなのです。

コーチングを一言で言い表すなら、
・相手の学習や成長、変化を促し、相手の潜在能力を解放させ、最大限に力を発揮させる。
でしょうか。

詳しくはWikipediaの「コーチング」
をご覧くださいませ。

ビジネスにフォーカスを当てたコーチングの歴史はまだまだ浅いです。
ここでお伝えしておかなければならないのは、自己啓発セミナーとは違う、ということです。

と、偉そうにウンチクを述べる私ですが、コーチングを受けた経験は人生で1,2回だけ。
では、そんな私がkintone Advent Calendarで何を語るというのでしょうか。

結論を先に書いちゃうと、kintoneでこんなグラフを作ってみましょう!
ということなんですね。

グラフとデータのご説明

  Topへ↑

上に登場したのは四つの傾向を円グラフにしたものです。
それぞれの傾向の文字列にマウスを合わせると、事前に登録しておいたキーワードが出てくる。
これ、実は以前、お客様に依頼されて作ったkintoneにChart.jsを組み込んだグラフ生成の仕掛けです。

私はコーチングには無知です。
ですから、kintoneに入力画面を作り、その結果を集計することで、設問に応じた四つの傾向が算出できる、ということを知ったときは新鮮でした。

お客様によれば、
相手をほめる場合の、個人に響くキーワードは4つの傾向に分けられる
だそうです。

それに合わせて、こんな入力画面を作ってみました。

仮に20問の設問としています。それぞれの4つの傾向ごとに5問を設問しました。
それぞれの問いごとに
・よく当てはまる
・当てはまる
・当てはまらない
・まったく当てはまらない
の4種類の答えをラジオボタンで設定しています。

もちろん、さらに設問数を増やすことも可能ですし、設問数を自在に増減させたい、というご要望もあるでしょうね。
その場合はサブテーブルを使えばよさそうです。
この記事ではサブテーブルではなく、20問に固定したバージョンでお届けしてみます!

実際の内容

  Topへ↑

はい。ではアプリの設定画面です。フォームはこんな感じ。

一番左の文字列フィールドは設問の文字列を入力します。
フィールドコードは上から順にquestion_1からquestion_20としています。

真ん中のドロップダウンフィールドは4つの傾向を選びます。
フィールドコードは上から順にtrend_1からtrend_20としています。

右のラジオボタンフィールドはそれぞれの答えを入力する欄です。
フィールドコードは上から順にanswer_1からanswer_20としています。

で、続いてはグラフを表示するカスタマイズビューを設定してみましょう。

こんな感じですね。

続いてはロジックです。
実は、このグラフを作るには以下の二つのJavaScriptファイルを設定するだけ。

上に設定したのは、Chart.jsです。
Cybozu Developer Network
からCDNのページに移動してもらえれば。

そこのChart.jsに書かれているURLをコピーし、上の画面の
から

に貼って保存するだけ! きとみちゃんでもできますよね?
htttps://がダブらないようにだけ気を付けて!

続いてグラフ表示のロジックです

  Topへ↑

では続いてきとみちゃんとグラフ.jsの内容を。
ここからはVisual Studio Codeの画面にコメントを入れています。




ちょっと見にくいので、直に貼ったコードも提供します。右にスクロールしてくださいね。

(function () {
  "use strict";

  // 一覧ページ
  kintone.events.on('app.record.index.show', function(event) {                       //一覧画面表示時の定型文です
    var record = event.records[0];
    var itemcount = 20;
    var 1_Score = 0;
    var 2_Score = 0;
    var 3_Score = 0;
    var 4_Score = 0;
    var selectedScore = 0;
    var dataLabelPlugin = {                                                          //ここは以下の162行目で呼び出されるチャートのプラグインコンフィグで呼び出される部分です。
      afterDatasetsDraw: function (Chart, easing) {                                  //afterDatasetsDrawとはプラグインコアAPIとして呼び出されるChart.js内部のフックです。要は描画後です。
        var ctx = Chart.ctx;                                                         //チャートが描画されている対象のDOM要素です。157行目で定義され、159行目でChartオブジェクトに渡されます。
        Chart.data.datasets.forEach(function (dataset, i) {                          //対象チャートをループしています。データは77行目で一種類で指定していますのでループは一回のみです。               
          var meta = Chart.getDatasetMeta(i);                                        //チャートのメタデータを取得しています。データやラベルも含まれています。
          if (!meta.hidden) {                                                        //チャートのhiddenプロパティがTrueの場合そもそもチャートが描画されません。
            meta.data.forEach(function (element, index) {                            //メタ要素のデータをループします。今回は4種類ですね。
              ctx.fillStyle = 'rgb(0, 0, 0)';                                        //円グラフの中の文字の色です。rgb(0, 0, 0)は黒を表しています。
              var fontSize = 16;                                                    //36-37行目で文字の場所を設定するためのフォントサイズを16pxで設定しています。表示フォントのサイズとは別に。
              ctx.font = "24px \"Helvetica Neue\", Helvetica, Arial, sans-serif";    //これが実際に描画される文字のフォント情報です

              var sum  = function(arr) {                                             //ここでは対象となるデータの合計値を返します。4種類のデータの合計です。
                  return arr.reduce(function(prev, current, i, arr) {
                      return prev+current;
                  });
              };
              var percentString = ((dataset.data[index] / sum(dataset.data))*100).toFixed(1) + "%";  //それぞれのデータの値を全体の合計で割り、パーセントの文字列を構築します。
              var dataString = Chart.data.labels[index];                                             //それぞれのデータのラベルです。79行目で定義した4つの傾向のラベルですね。 
              ctx.textAlign = 'center';
              ctx.textBaseline = 'middle';

              var padding = 5;
              var position = element.tooltipPosition();
              ctx.fillText(dataString, position.x, position.y - (fontSize / 2) - padding);           //30行目で設定したラベルの値を計算した位置に表示します。
              ctx.fillText(percentString, position.x, position.y - (fontSize / 2) - padding + 35);   //29行目で設定した値のパーセントの文字列を計算した位置に表示します。
            });
          }
        });
      }
    };
    for (var i=1 ; i<=itemcount ; i++){                                                              //ここから76行目までは大人の事情でいろいろとあいまいですがお許しを
      switch( record['answer_' + i]['value'] ) {                                                     //要するに20レコードの設問の答えを基に四つの傾向に加算しているのです
        case 'よく当てはまる':
          selectedScore = 係数は内緒よ♪;
          break;
        case '当てはまる':
          selectedScore = 係数は内緒よ♪;
          break;
        case '当てはまらない':
          selectedScore = 係数は内緒よ♪;
          break;
        case 'まったく当てはまらない':
          selectedScore = 係数は内緒よ♪;
          break;
      }
      switch( record['trend_' + i]['value'] ) {
        case '一つ目の傾向':
          1_Score = 1_Score + selectedScore + 山藤ゆりさんに教えてもらった魔法の値を加えるの♪;           //要するに20レコードの設問の答えを基に四つの傾向に重みづけしているのです
          break;
        case '二つ目の傾向':
          2_Score = 2_Score + selectedScore + 山藤ゆりさんに教えてもらった魔法の値を加えるの♪;
          break;
        case '三つ目の傾向':
          3_Score = 3_Score + selectedScore + 山藤ゆりさんに教えてもらった魔法の値を加えるの♪;
          break;
        case '四つ目の傾向':
          4_Score = 4_Score + selectedScore + 山藤ゆりさんに教えてもらった魔法の値を加えるの♪;
          break;
      }
    }
    1_Score = ロジック関数は内緒よ♪(1_Score);
    2_Score = ロジック関数は内緒よ♪(2_Score);
    3_Score = ロジック関数は内緒よ♪(3_Score);
    4_Score = ロジック関数は内緒よ♪(4_Score);                                          //さらに四つの傾向に値を秘密ロジックで精緻化しています。この辺も大人の事情が絡んでいます。
    var pieChartData = {                                                             //161行目でChartオブジェクトに渡されるデータとラベルと背景色のホバー色や枠の組み合わせです。四要素です。   
      labels : ["リーダー合理系","アイディア活動系","ヘルプ支援系","クール分析系"],       //ラベルですね。四つの要素に分かれています。
      datasets : [                                                                   //四つの要素のそれぞれの色の指定です。
        {
          backgroundColor: [
            '#ff6384',
            '#36a2eb',
            '#cc65fe',
            '#ffce56'
          ],
          hoverBackgroundColor: [
              "#FF2384",
              "#3662EB",
              "#cc25fe",
              "#FF8E56"
          ],
          hoverBorderColor: [
              "#000000",
              "#000000",
              "#000000",
              "#000000"
          ],
          hoverBorderWidth: [
              2,
              2,
              2,
              2
          ],
          data : [1_Score,2_Score,3_Score,4_Score]                                   //四つの要素の値です。大人の事情で実際の回答から複雑に計算された結果が格納されます。
        }
      ]
    }
    var tooltipkeyword = {                                                           //ここは四つの傾向ごとに176行目で乱数を設定し、任意のキーワードを表示するようにしています。
      type : [
        {
          word : [
            '同業者もあの人を噂している',
            '他の部署でも話題になっている',
            '○○さんしかできない',
            '自分で判断し、動ける人',
            '部署のメンバーに信頼されている',
            'あのひとには任せられる'
          ],
          title : "任せる、難題、未知の分野、他に頼めない、誰にもできない"
        },
        {
          word : [
            '発想がおもしろい!!',
            '一緒にいるだけで楽しい!!',
            'さすがアイデアマン!!',
            'すばらしいサービス精神!!',
            'うちの部署のムードメーカー!!',
            'その自由な発想がうらやましい!!'
          ],
          title : "自由にして、思いっきり、楽しく、面白く、みんなでいっしょ"
        },
        {
          word : [
            'みんなが働きに感謝している',
            '縁の下の力持ち',
            '一緒にいて落ち着く',
            '丁寧で親切で信頼できる',
            '細かいところによく気が付く',
            '相手の気持ちを分かってくれる'
          ],
          title : "感謝、ありがとう、仲良く、話し合い、相手の気持ち"
        },
        {
          word : [
            '詳しく業務を理解している',
            '商品のことをよく知っている',
            'わが社のことになんでも詳しい',
            'うちの課の歩く辞書',
            'あの人に聞けば間違いない',
            'このデータ量は大したもの'
          ],
          title : "情報、正確、正しく分析、予定通り、計画通り"
        }
      ]
    }
    var canvas = document.getElementById('canvas').getContext("2d");                 //Chartが描画されるDOM要素を指定するChart.jsの定型文です。id="canvas"はカスタマイズビューで指定しました。
    canvas.canvas.height = 256;                                                      //描画される領域の高さを指定しています。
    var test_chart = new Chart(canvas, {                                             //ここでChartオブジェクトをインスタンスとして実体化させています。
      type: 'pie',                                                                   //type: 'pie'はグラフの種類ですね。円グラフです。
      data: pieChartData,                                                            //77行目で定義したデータの実態です。
      plugins: [dataLabelPlugin],                                                    //プラグインコンフィグで関数を呼び出すことができます。その関数は13行目をご参照ください。
      options: {                                                                     //ここからはオプション情報です。
        animation: {
          animateRotate: true,
          animateScale: true
        },
        tooltips: {
          titleFontSize: 48,
          bodyFontSize: 36,
          callbacks: {
            label: function (tooltipItem, data){                                     //ここは描画後にマウスカーソルが乗った時の事前に内部でtooltipItemに定義された情報を基に値を返します。
                return pieChartData["datasets"][0]['data'][tooltipItem['index']] + "ポイント"       //77行目で定義されたデータから該当するデータを表示し
                  + "  キーワード → " + tooltipkeyword["type"][tooltipItem['index']]["title"];      //さらにキーワードとして109行目で定義された四つの傾向のタイトルを表示します。
            },
            afterLabel: function (tooltipItem, data){                                //172行目のラベルの後に別の情報を表示させるにはafterLabelツールチップコールバックが呼び出せます。
                  return "「" + tooltipkeyword["type"][tooltipItem['index']]["word"][Math.floor(Math.random()*(6-0)+0)] + "」";
            }                                                                        //さらにテキストとして109行目で定義された四つの傾向の文言のオブジェクトから乱数で選ばれた文言を表示します。
          }
        },
      }
    });
  });
})();

あとはこのJavaScriptファイルを

にのようにアップロードしていただければ。

どうでしょう。kintoneのデータにChart.jsを組み合わせるだけで、
kintoneのデータを分析することができてしまうのです。

Chart.jsにはさまざまなグラフが用意されているので、
kintoneの標準グラフでは表現できないことも可能です。

コーチング用の分析ツールとしても使えてしまうkintoneの奥深さを楽しんでいただけたらきとみちゃんも喜ぶはずです!
よかったら以下にChart.jsの公式サイトのリンクも貼っているのでご参考になさってくださいね。

当エントリの参考にさせていただいたブログ

  Topへ↑

最後になりましたが、このエントリ作成にあたり、以下の2サイトおよび、コーチングについて教えて頂いたお客様からの情報を参考にさせていただきました。ありがとうございました。

 Chart.jsドキュメント翻訳
 Chart.js公式サイト


kintone Café 東京 Vol.9を開催しました


11/15にkintone Café 東京 Vol.9を開催しました。

公式の開催報告はしかるべき場所に書かせていただきました。
こちら

関連するツイートのまとめサイトも作成させていただきました。
こちら

なので、ここでは代表である私が登壇の際に語った
kintone Caféとは?スライド
kintoneを簡単にご紹介スライド
Cybozu Days 2019のkintone周りをフィードバックスライド
をさらに補足するように、開催であらためて感じた思いを書かせていただきます。

3月末のkintone Café 広島に登壇した時、今までkintone Caféで話したことのなかった自治会を取り上げました。
今までは技術に即した内容を話すことが多かったのですが、技術に触れないkintone Caféの登壇が私に新鮮でした。

8月末に開催したkintone Café 東京 Vol.8 @多摩では、プロジェクト・アスノートの松田さんと共催しました。
それを機に私の話す内容を思い切って初期化し、kintoneを一から語ってみました。当然技術ネタは封印。

技術ネタだと、kintone Caféに来てくださった方がついて来れない可能性があります。当然、反応も薄くなります。
そもそもkintoneエバンジェリストとは、技術うんぬんではなく、kintoneの良さを広めることにあるのではないか。
私の中でkintone Café神奈川を何度か行う中で迷いが生じていましたが、直近の二回のkintone Caféで修正することができました。

今回のkintone Café 東京 Vol.9は開催要項にユーザー向けをうたっていました。
その一方で、今回の参加者の中には私の知る限り、かなりのスキルを持つ技術者も6,7名はいました。

そうした方々に対し、kintoneの初歩を語ることに意味はあるのか。
私はあると判断しました。
むしろ、技術者であるほど、kintoneが新鮮に映るはず。そうした意味でもユーザー向けの内容でよかったと思います。

今回、会場を提供してくださったのはクロス・ヘッド株式会社様。System Integrateの豊富な経験をお持ちです。
クロス・ヘッド様の会場をお借りしながら、技術に触れず、ユーザー向けの内容にすることに若干のためらいもありました。
ですが、kintone Caféを通しての皆様の反応は上々で、七割以上の方が懇親会に参加してくださいました。その事からも、ユーザー寄りで行く、との方向性は続けようと思いました。

私の登壇では、そもそもなぜkintoneをユーザーに勧めるのか、という観点で一生懸命語ってみたつもりです。
さらに、Cybozu Days 2019 in 東京で発表された内容を報告しました。

今回、一緒に登壇したkintone大好きキンスキ YouTuberの松井さんは、私のPCトラブルによる順番交代にも動じず、見事な登壇を務めてくださいました。そればかりかサイボウズさんならではの事例を提供してくださいました。

私に続いて登壇してくださった情報親方の東野さんは、Cybozu Days 2019で発表され、来場された方々に感心されたkintone導入ガイドブックの制作について、マニュアル制作のノウハウも惜しげなく披露してくださいました。

トリを務めてくださったTeruさんは、登壇を公開できないリスクを押してkintoneが最大に活きる業務改善の生の事例を語ってくださいました。kintoneの紹介から導入、そして業務改善効果に至るまで、今回のCaféを締めるにふさわしい内容でした。

あらためて、こうした地道な活動が、今後につながると確信できた1日でした。
12/7にはkintone Café JAPAN(サイト)が予定されています。そこでもきっと実のある内容が得られる事でしょう。
今回来てくださった35+αの皆様、登壇してくださった3名の仲間。会場を提供してくださったクロス・ヘッド株式会社様。皆さま本当にありがとうございました。


Cybozu Days 2019 in 東京に行きました


2019/11/7、11/8の幕張はある気配に包まれていました。
そこではCybozu Days 2019 in 東京が催されていたのです。
ただし、幕張に満ちていた気配とは、熱気ではなく禍々しい気でした。

今年のテーマは「モンスターへの挑戦状」
そのテーマ通り、モンスターたちに占拠されたパビリオン。会場全体が禍々しく彩られています。
その中にはちらほらと勇者のイラストも見受けられます。ですが、空間の大部分はモンスターに占められたまま。

そんな会場にも、参加者が増えていくにつれモンスターに立ち向かう機運が満ちていきます。
勇者とはすべての参加者のこと。皆でモンスターに立ち向かうのが今年のCybozu Daysのミッションなのです。

では、私たちが立ち向かうモンスターとは何でしょうか。
そのヒントは既にサイトにも動画で流されていました。そして、二日目のメインセッションでも青野社長から語られました。
モンスターとは目に見えません。そもそも存在すらしません。
モンスターとは私たち自身が作り上げてしまった存在なのです。

戦後の高度経済成長の結果、成功体験として日本中に刷り込まれてしまった観念。その代表が年功序列や終身雇用です。
そうした観念から派生したモンスターたち。
毎日決まった場所に通勤し、背広とネクタイの着用が正しいとする「通念」が蔓延り、その背後には一度きりの人生を「カイシャ」に捧げさせようと蠢くモンスターの闇が見え隠れします。

そうしたもろもろのモンスターたちと一緒に戦う私たちのために、七カ所に分かれたセッション会場のあちこちで、二日間にわたっていろいろなセッションが行われました。

初日のProduct Keynoteでは、GAROON、kintoneを軸に、これまでのアップデートと今後のアップデート予定が披露されました。
チーム応援ライセンスは対象アカウントが三倍に増え、危うく私の口から歓声が飛び出そうに。
LGWAN対応やアメリカでのkintone状況など、今後に期待が持てそうな発表が続きます。

keynoteの前には「俺キン」のセッションがありました。
俺はこんな風にモンスターと戦ってきた、と発表する勇者たちの姿は尊いです。私も場外から戦いの軌跡に聞き惚れました。
モンスターとの戦い方は勇者によってまちまち。あえてKINTONEに乗って登場する掟破りの登場もまたよし。

Keynoteの次は、kintone hiveです。
毎年聞いていますが、全国で知らぬうちに育ってしまったモンスターたちと戦う姿には、共感と感動があります。
例えるなら上出来のRPGのプレイ動画を大勢の勇者とともに観戦する臨場感のような。

私はhiveの前、各社のブースをダッシュで巡りました。
中でもfreee社のブースに長居していました。freee社で今度kintoneとfreeeのAPI連携についてお話しするためです。
その情報を入手し、freee社のみなさんと会話をして勉強。今後にもつなげていくためにも。

hiveの後は、kintone Café in Cybozu Daysにも参加しました。
Cybozu Daysが終わってすぐ、お膝元でのkintone Café 東京 Vol.9を主宰する私としては、全国各地にある勇者の集うギルドのあり方から学べるもの多かったこと。
kintone Café開催の意義や目的を考えるきっかけにもなりました。

このセッションと同じ時間には開発者向けのセッションがありました。
私はとても行きたかったけれど、kintone Caféのセッションを選びました。
まだまだ私もか弱い勇者なので、分身の術が会得できておらず悔しい。いずれ公開される動画を待ってみます。
なお、このセッションから冒険仲間に情報親方が加わってくれました。以後は行動をともに。

続いてはkintone hack Nightです。このセッションも見逃せません。
勇者として最前線に出てモンスターと戦うには、スキルを磨かねば。それを披露する場こそhack Night。
勇者の出で立ちに身を包んだ六名の勇者がおのおのの磨き上げたスキルを披露します。そして採点。
採点の間、魔の司会者ウッシーが召喚したモンスターが登場し、勇者にさらなる試練を与えます。あるモンスターは18世紀二ポーンの「コウメダユウ」に姿をかえ、華麗なる滑り芸を駆使して勇者に襲いかかります。あるいは21世紀の「ワタナベケン」がレスラーの出で立ちで絶叫して勇者の行く手を遮るのです。
勇者、危うし!
奮闘もむなしく、魔法に魅入られ笑わされた勇者には激烈なゴムパッチンが顔面に炸裂。容赦なくHPを削っていきます。

毎年、勇者の激闘から学ぶところは多いです。
私的には、AR世界の振る舞いをkintoneに結びつけた勇者「ウィル」さんのセッションがインパクト大でした。
が、優勝はヲタ芸とkintoneの組み合わせで満場の笑いをさらった勇者「つっきー」さんの逆転勝利。いや、楽しかった!

一日目『最軽量のマネジメント』を出版されたばかりのサイボウズ社副社長の山田さんがサイボウズ商店の店頭に立たれていたので、著書を購入し一緒に写真を撮っていただきました。
そして、情報親方と飯を食って締め。
ルーラを唱え、二時間以上かけて町田の宿屋に戻りまして。

さて、二日目。
いきなりの「SEKAI NO OWARI」の曲にバイオリンをフィーチャーしたバンドが登場し、素晴らしい二日目を予感させます。

二日目は、働き方をメインに据えたセッションが主です。
メインセッションでは青野社長の書籍「会社というモンスターが、僕たちを不幸にしているのかもしれない。」を編集したphp研究所の方と青野社長の対談から始まりました。
今回のCybozu Days 2019のテーマ「モンスターへの挑戦状」のもとになったというこの書を、私はまだ読めていません。ですが、この対談を聞くと、早く読まねば、という気にさせられます。
私が常々感じていた日本を覆う思い込みの数々。

タカマツナナさんとの対談も参考になりました。
お笑い芸人として活動する中、活動を若年層への政治参加を促すものに変えるなど、自在に活動を行うタカマツさんの意気込みが面白かったです。
タカマツさんもまた、芸人の立場から世の中のモンスターと戦っているのでしょう。

そのタカマツナナさんの後に登場したのが麹町中学校の工藤校長との対談です。
工藤校長は、宿題や委員会など学校生活につき物のさまざまな制度に抜本的な改革を加えたことでよく知られています。
一人一人の生徒のことを考えた結果、そうした制度や行事で必要のないものは廃止も辞さない。そうした伝統的に伝わる制度の多くは、実は前例主義に基づいた思い込みのモンスターの生み出した幻想にすぎない。そう力強く言い切る工藤校長こそ、教育界にさっそうと現れた勇者の中の勇者なのかもしれません。

この日の私は、作業もしなければならず、昨日以上にブース巡りができませんでした。用意してくださった電源席で、作業に没頭。

続いてのセッションはサイボウズ社に中途入社した社員が語る、サイボウズ社内の情報共有のあり方です。
私もお客様とともにモンスター退治の旅に出る時、早い時期にこのモンスターと戦います。
そもそも、情報共有に妙なブロックがあると、kintoneという武器もうまく機能しません。
どこまでの情報をkintoneにアップしてもらえるのかによって導入の成否も分かれるのではないか。そう思います。

その視点でみたこのセッションはまさに驚きです。
社内経営会議の生の声まで含めて全社員に公開するというのですからすごい。
ですが、私も妙な秘密主義は面倒なので、この点はとても勇気づけられます。
また、経営者の方にもサイボウズさんはここまでやってますよ、という根拠を得られたことも大きかった。

続いてのセッションは医療介護業界の四天王がパネリストとなって、kintone導入のあれこれを語ってくださるセッションです。
四天王の内、三人はCybozu Days 2019の前日にkintone エバンジェリストに就任した方で、まさに豪華な陣容です。
実際、医療業界へのクラウド導入は、クラウドの認知のバロメーターです。
妻が歯科診療所を経営している私にとっても、とても興味深いセッションでした。

その次のセッションも、クラウドの認知のバロメーターの一つです。
自治体への導入にあたっては、LGWANとの連携がセットでないと情報の流通が滞ります。
神戸市と市川市の事例ですが、かつて神戸市役所と芦屋市役所で入力オペレーターをした経験がある私にとって、神戸市の事例には興奮しました。神戸市が主宰するワークショップには芦屋市の方も参加されているとか。
私の来し方を考えると感慨が湧きます。この分野でも今後は協力をしていければうれしいと思いました。
「来なくてもいい市役所」の実現に向けて。

そしてすでに最終セッションへ。
その前に、アーセスさんのブースに立ち寄りました。
お客様がチーム応援ライセンスに申請していて、申請が通ればアーセスさんのプラグインを使う提案もお客様にしていました。なので、KOUTEIやKOYOMIについてあらためてお話を聞きに伺ったのです。

最終セッションは『五体不満足』で知られる乙武氏の講演。そして青野社長との対談です。
乙武氏もまた、世に跋扈するモンスターと戦い続けてきた勇者です。とにかく目の力が強く、意思のみなぎった面構え。表情は豊かに、雄弁に語ってくださいます。不満足な五体で表現できない分を言葉と顔と喉だけで。
私も話者の端くれとしてとても刺激を受けました。スピーカーたるものこうありたいものです。
美しいものは、と問われた乙武氏が「覚悟」と答えた姿が、まさに美しい。モンスターと戦い続けるには覚悟がいります。その覚悟こそ、勇者のまとうべき究極の鎧なのかもしれません。
著書『四肢奮迅』を出されたばかりだというので、私も手に取ってみようと思いました。

冒険の旅に終わりはありません。
とはいえ、四人の勇者と幕張で飲みかわし、いったん私にとってのCybozu Days 2019 in 東京は幕を閉じました。
三日続けて幕張と町田を往復したのでHPとMPはすっからかん。でも、その替わりKP(気力)は満タンに充填されました。

初日の禍々しい気配からは一変、幕張の夜にはさわやかな風が吹いていました。ここ、幕張の地からモンスターは退けられたのです。

ただし、RPGの世界ではラスボスを倒してもゲームは永遠に続いていきます。私たちの人生もそうであるように。
まだまだモンスターは世に棲んでいるのです。

そうしたモンスターを退治する冒険の旅路では、仲間との交流が欠かせません。
今回、こうした英雄たちの交流の場を作っていただいたサイボウズさんには感謝です。
スタッフの皆様、登壇者の皆様、参加者の皆様、ありがとうございました。
これからもモンスターと戦い続けていきましょう!