CONTACT

楽天商品ページの”バナー予約機能”で店舗運営を効率化 | イージークリエイティブ

楽天市場で店舗運営をされている皆さん、こんな経験はありませんか?

「セールの度にバナーを設定するのがめんどくさい…」
「毎月5と0のつく日のバナーの設定を忘れてしまう…」

特に大型セールや期間限定セールでは、開始時刻に合わせてバナーを変更する必要があり、深夜作業を余儀なくされることも少なくありません。また、複数のセール期間がある場合、それぞれのバナーを都度手動で管理するのは大変です。

そんな悩みを解決するのが、『イージークリエイティブ for 楽天市場』が提供するバナー予約機能です。

▶︎新規会員登録はこちら!(7日間の無料トライアル期間実施中)

『イージークリエイティブ for 楽天市場』公式

バナー予約機能とは

バナー予約機能は、楽天市場の店舗トップページに表示される「スマートフォン用大バナー」を、“複数の”期間・日時を指定して、”一度の設定”で自動変更できる機能です。

事前にバナー画像と表示期間を設定しておくだけで、指定した時刻になると自動でバナーが切り替わります。分単位での予約設定が可能なため、セール開始時刻にピッタリ合わせたバナー変更が実現できます。
しかも、バナー登録数の上限はありませんので、必要な分だけ予約設定できます。

主な特徴

  • 分単位での予約設定:開始日時・終了日時を分単位で指定可能
  • 自動適用機能:予約した開始日時になると自動でバナーを変更。毎分チェックして確実に適用されます
  • 柔軟な画像設定:既存の画像URLを指定する方法、画像をアップロードする方法、どちらでも対応可能
  • 複数バナーの一括管理:1~10の表示順で管理でき、複数のバナーを同時に予約設定可能

こんな場面で活躍します

定期セール準備の自動化

毎月「5と0のつく日」のキャンペーンで、その月の5日、10日、15日、20日、25日、30日にバナーの予約登録をすると、その1回の登録で、あとその日になったら自動でバナーが表示されます

複数期間のバナー管理

期間限定セールが複数あり、それぞれ異なるバナーを表示したい場合でも、複数のバナー予約を事前に設定しておけば、期間ごとに自動で切り替わります。手動での切り替え作業が不要になり、確実に実行されます。

バナー予約機能のメリット

  • 更新忘れを防止:予約日時に自動で適用反映されるため、確実にバナーが切り替わります
  • セール準備の時間削減:手動での作業が減り、他の業務に時間を使えます
  • 複数バナーの一括管理:予約一覧で一括管理でき、フィルター機能やコピー機能で効率的に運用できます

まとめ

楽天の標準機能でもバナー予約は可能ですが、「イージークリエイティブ for 楽天市場」のバナー予約機能なら、複数の期間を一度に予約設定できることが最大の強みです。0と5の付く日の定期セールのように、月に何度もバナーを切り替える必要がある場合でも、1回の設定で完了します。

深夜作業から解放され、切り替え忘れの心配もありません。事前に一括設定しておくだけで、指定時刻に自動でバナーが切り替わるので、安心してセール準備に取り組めます。

「使ってみたい」と思われた方は、ぜひEasy Creative(イージークリエイティブ)のバナー予約機能をお試しください。

『イージークリエイティブ for 楽天市場』公式

楽天運営を効率化で運用コストを下げつつCTR平均+45%改善!『イージークリエイティブ for 楽天市場』正式リリース

株式会社ユーファスは、楽天市場出店者向けに商品情報の一括編集と商品名/サムネイル画像ABテストの自動運用を実現するクラウドツール『イージークリエイティブ for 楽天市場』を2025年11月1日に正式リリースしました。最短2日で効果を判定し、平均で【CTR45%改善】、【運用コスト最大60%削減】を支援することで、サービス利用者のEC運営において”少ない投資で大きな結果を出せる運用”に貢献します。

楽天市場状況

楽天市場の出店店舗は増加を続け、サムネイル最適化や商品情報更新の重要性が高まる一方、運用担当者は更新作業の手間・ABテストの設計と分析・継続的な改善サイクルの維持に課題を抱えています。限られた人員で効率よく成果を出すための「自動化」と「簡易運用」が求められています。

楽天店舗運営における課題

実際に、開発前のヒアリングの中で下記のようなお悩みのお声を頂戴しました。

  • 既存のツールでは、利用するための環境の準備が難しくて、新規スタッフが業務にあたるまでに時間がかかる…
  • 商品情報の編集を楽天にアップロードするタイミングでエラーが出た場合に、今までの作業が水の泡…
  • 商品情報の更新日時の予約ができないので、セール前はいつも深夜作業が発生する…
  • サムネイルAとBを切り替えるのに時間がかかりすぎて、ABテストまで手が回らない…
  • 楽天公式でABテストツールを提供していないので、商品名やサムネイル画像を「勘」と「経験」に頼るしかない…
  • データの集計作業や勝者サムネイルの反映が手作業で面倒…

サービス概要と特徴

◼︎商品情報一括編集

  • 商品情報をExcelで一括編集
    直感的なUIで複数商品の情報をまとめて更新。更新漏れや手戻りを抑え、日次の運用負荷を軽減します。
  • 商品情報編集内容の予約設定が可能
    セール開始タイミングに合わせるなど、希望する日時に編集内容を反映できます。
  • バナー表示の予約設定が可能
    商品詳細ページに表示する1年分のバナーの予め予約可能で、切り替え漏れを軽減します。
  • 運用コストを最大60%削減
    専門的な環境構築不要。手作業と属人プロセスを削減し、改善サイクルを継続可能にします。

◼︎商品名/サムネイル画像一括編集機能

  • テストパターンの自動切替、勝者パターン自動反映
    AパターンとBパターンの切り替え〜勝者パターンの反映まで全て完全自動なため、テスト内容を設定したあとは結果を待つだけです。
  • 商品名/サムネイル画像のABテストを自動で実施・分析
    テスト設計から配信、計測、勝ちパターンの反映まで自動化。弊社の独自解析技術によって、他社サービスでは取得できなかったデータを利用でき、正確な根拠の元“意味のある”テスト結果を得られます。
  • 既に導入いただいた店舗では、CTR(クリック率)が平均で45%改善

※ 効果は店舗規模・商品構成・期間等により異なる場合があります。

利用方法・料金プラン

ご利用方法:Webブラウザで即日利用開始。公式サイトからアカウント登録後、ガイドに従って店舗連携・初期設定を行うだけです。

料金:初期費用無料/月額5,000円

導入支援:初期オンボーディング資料・サポート窓口を提供

キャンペーン

無料トライアル期間を提供中!
登録から7日間は全機能を無料でお試し可能です。
期間中に解約いただいても費用は発生しません(自動課金なし)。お申し込みは公式サイトから新規登録ボタンからご登録いただけます。
その際、クーポンコードが入力されていることをご確認ください。

今後の展開・展望

魅力的な画像をAIで生成し、更新作業をさらに短縮する機能など
引き続き、運用現場の時間創出と継続改善を実現する機能を順次提供してまいります。

会社概要

  • 会社名:株式会社ユーファス
  • 所在地:〒103-0014 東京都中央区日本橋蛎殻町1-12-7 WACROSS NINGYOCHO 7F
  • 代表者:代表取締役 天満 弘将
  • 設立:2023年11月
  • 事業内容:コンサルティング事業・コンサルタントマッチング事業、システム開発
  • 企業URL:https://ufas.co.jp/

本件に関するお問合せ先

株式会社ユーファス 開発責任者:墨屋

メールアドレス:developer+easycreative@ufas.co.jp

【AI×自動化】SES業界の課題を解決する「SES自動マッチングシステム」を自社開発しました

SES業界が抱える「人材マッチング」の課題

SES(システムエンジニアリングサービス)業界では、
案件と人材のマッチング業務が極めて時間と手間のかかる作業です。

営業担当者は日々大量のメールを確認しながら、
「このエンジニアのスキルはどの案件に合うのか?」を判断する必要があります。

しかしこの作業には、次のような課題がありました。

  • 手作業による照合作業の非効率さ
  • 見落としリスクの高さ
  • 担当者の経験や勘に依存した属人的判断
  • メール処理に費やされる膨大な時間コスト

こうした課題は、SES事業のスピードと精度の両立を難しくしていました。
この非効率な仕組みを変えるために、当社はAIを活用した自動マッチングシステムの開発に着手しました。

開発の背景 – なぜAIによる自動化が必要だったのか

SES業界では、案件情報やスキル情報がメールベースで日々やり取りされます。
そのため、情報の構造化や一元管理が難しく、属人的な判断に依存する傾向がありました。

当社は、「このプロセスこそ自動化できるのではないか」と考え、
Google Apps ScriptとGPT-4を活用した完全自動マッチングシステムの開発を進めました。

目的は明確

  • 営業担当者の日常業務を自動化し、生産性を向上させる
  • AIによる客観的判断で、マッチング精度を安定化させる
  • 業務標準化によって属人化を解消する

このシステムは「AIを業務の一部として自然に組み込む」ことを目指して設計されています。

「SES自動マッチングシステム」とは

自動で人材と案件をマッチングする仕組み

本システムは、Gmailに届くメールを自動で分析・分類し、人材情報と案件情報を抽出、スキルマッチングを行う仕組みです。

AIがそれぞれのメールを判定し
「候補者メール」と「案件メール」を自動分類。
抽出したスキルや条件をもとに
AIが類似度スコアを算出して最適なマッチング結果を出力します。

結果はGoogleスプレッドシートに自動保存され
営業担当者は毎朝、最新のマッチング結果をすぐに確認できます。

Google Apps Script × GPT-4による低コスト運用

本システムはGoogleのクラウド環境上で動作し
専用サーバー不要・無料枠で運用可能です。

AI部分にはOpenAIのGPT-4 APIを活用し
自然言語処理とスキル抽出を高精度に実現。

この構成により、高精度かつ低コストな自動化システムを実現しています。

導入効果 – 営業業務の90%を自動化

導入後の効果は非常に大きく、
これまで営業担当者が1日2〜3時間費やしていたメール確認とマッチング作業が、
ほぼゼロに削減されました。

工数削減と標準化による生産性向上

  • メール処理・照合・スプレッドシート更新を完全自動化
  • 業務を標準化することで、担当者によるばらつきを排除
  • 処理件数が増えても、工数は一定のまま

営業担当者が戦略業務に集中できる環境へ

日常的なルーティン作業が削減されたことで、
営業担当者はより戦略的な案件開拓や顧客対応に時間を使えるようになりました。

また、AIによるマッチング結果の「スコア化」により、
判断の透明性と再現性も確保されています。

技術面での特長とこだわり

経営層の方にも安心して導入をご検討いただけるよう、
技術面でも運用性と信頼性を重視しています。

AIによるスキル類似度計算で高精度マッチング

GPT-4のEmbedding技術を活用し、
スキル情報を数値化して類似度を計算。
感覚や経験に依存しない客観的なマッチング基準を実現しています。

安定稼働・自動復旧による運用効率

メール取得エラーやAPI応答遅延が発生しても、
自動リトライ・ログ管理機能により安定稼働を維持
日々の運用において、担当者がシステムの存在を意識する必要はありません。

今後の展望 – 学習機能・CRM連携でさらに進化

当社では今後、以下のような機能拡張を予定しています。

  • 学習機能:過去のマッチング結果をもとにAIが精度を向上
  • 通知機能:最適なマッチング結果をSlackなどに自動通知
  • CRM連携:顧客データベースと自動で連携し、契約管理まで一元化

このように、AIによる業務支援の幅を広げることで、
SES業務全体のDX(デジタルトランスフォーメーション)を加速していきます。

SES業務の未来を変える – AI活用の可能性

このシステムの開発を通じて、私たちは改めて実感しました。
「AIは一部の高度な開発ではなく、現場業務のパートナーとして機能する」と。

SES業界に限らず、多くの業種で同様の仕組みを応用できます。
当社では、今後もAI・自動化技術を活用した業務改善ソリューションの開発を積極的に進めていきます。

よくある質問(FAQ)

Q1. このシステムはどのくらいのコストで運用できますか?
A2. 基本構成の導入であれば約1〜2週間程度です。カスタマイズ内容により変動します。

Q2. 導入にはどのくらいの期間がかかりますか?
A2. 基本構成の導入であれば約1〜2週間程度です。カスタマイズ内容により変動します。

Q3. セキュリティ面は安全ですか?
A3. Googleクラウド上で動作し、外部データベースを使用しないため、情報漏洩リスクは極めて低いです。

Q4. 他業種でも活用できますか?
A4. はい。メールベースの情報抽出・分類が必要な業務なら、同様の仕組みを応用可能です。

Q5. どのAIモデルを使用していますか?
A5. OpenAIのGPT-4モデルを利用し、スキル抽出とマッチング判定を行っています。

Q6. 今後のアップデート予定はありますか?
A6. はい。CRM連携や学習機能など、さらに高機能なバージョンを開発中です。

まとめ – AIと自動化でSES業務を次のステージへ

「SES自動マッチングシステム」は、
AI技術による業務効率化と標準化を実現する第一歩です。

私たちは今後も、AI・自動化技術を通じて
お客様の業務課題を解決し、より付加価値の高いサービスを提供してまいります。

✅ この記事のポイント

  • 営業業務を90%自動化
  • GPT-4を活用した高精度マッチング
  • Google環境で低コスト運用
  • 今後は学習機能・CRM連携を予定

このシステムは、「AIを業務に組み込む時代」の到来を実感させるプロジェクトとなりました。
当社はこれからも、AI技術を活用したソリューション開発を通じて、
お客様のビジネス変革を支援してまいります。

【楽天市場売上UP!】サムネイル画像のABテストを完全自動でパターン切替〜勝者反映ができるサービスご紹介

以前、「Excelだけで指定時間に商品情報の編集を自動反映できるサービス」をご紹介し、楽天店舗運営者様の業務効率化に一層貢献すべく、サービスの改善を続けてまいりました。

https://ufas.co.jp/post/-ENJITCt

そして今回、「商品サムネイルABテスト」が新機能として追加されました!
これにより、売上向上×業務効率化を同時に図れるサービスとなりましたので、是非とも最後まで記事に目を通していただけますと幸いです。

こんなお悩み、ありませんか?

楽天市場で店舗運営をされている皆さん、

・「どのサムネイル画像が売れるのか分からない」
・「ABテストをやりたいけど、手動で画像を切り替えるのが面倒」
・「データを見ながら最適な商品画像を選びたいが、時間がない」
・「複数商品のサムネイルを同時にテストしたい」

そんなお悩みを抱えていませんか?

これらの課題はイージークリエイティブ for 楽天市場の新機能を活用することで解決することができます。

本記事では、新しく追加された「サムネイルABテスト機能」について、機能説明から具体的な利用シーンまで詳しく解説いたします。

サービスについて

まずは簡単に、サービスの概要をご紹介します。

「イージークリエイティブ」は、楽天市場に出店している店舗オーナー様向けに商品管理を一つのプラットフォーム上で完結できる「統合型商品管理ツール」です。

主要機能として「商品一括編集」と「ABテスト」を提供しており、店舗運営における作業効率化売上向上に貢献します。

既存の主要機能

|商品情報の予約編集機能

 楽天RMSに出品している商品の画像差し替え、商品説明文、キャッチコピー、ポイント変倍の開始・終了日時などの編集が指定した時間に自動で反映されます(即時反映も可能)。

詳しくは以下の記事をご覧ください。

https://ufas.co.jp/post/-ENJITCt

新機能:サムネイルABテスト自動化

そして今回、データドリブンな商品最適化を実現する新機能を追加しました!

|サムネイルABテスト機能とは?

商品のサムネイル画像2パターン(AパターンとBパターン)を自動で切り替えながら、どちらがより効果的かを自動で検証・最適化する機能です。

この機能でできること

 1. 自動サムネイル切り替え
 
・夜間に自動でA画像とB画像を切り替え
 ・複数商品を同時並行でテスト可能

 2. 自動で目標達成を判定
 
・設定した目標値に達したら、自動でテストを終了することができます。

 3. 進捗レポートメール受け取り
 
・毎朝9時に、前日までの進捗状況がメールで届く
 ・A/B それぞれの実績データを自動集計
 ・現在の達成率が一目で分かる

 4. テスト終了後の自動アクション設定
 
テスト終了時のアクションとして、以下から選択することができます
 ・勝者を自動適用:効果の高かった画像を楽天に自動反映
 ・Aパターンを維持:Aの画像を継続使用
 ・Bパターンを維持:Bの画像を継続使用

具体的な利用シーン

ケース1:季節商品のサムネイル最適化

「夏物商品で、商品単体の画像と着用イメージの画像、どちらが売れるか検証したい」
2パターンでABテストを実施し、売上金額を目標に設定。勝者を自動適用。

ケース2:セール前の最適画像選定

「楽天スーパーSALE前に、最も効果的なサムネイルを見つけたい」
 セール開始2週間前からテストを開始。クリック率を目標に、セール開始前に最適画像を自動適用。

ケース3:複数商品の一括最適化

「売れ筋商品10点のサムネイルをまとめて最適化したい」
10商品すべてでABテストを同時スタート。各商品ごとに最適な画像が自動で選ばれる。

まとめ

最後までご覧いただきありがとうございました!
「イージークリエイティブ for 楽天市場」は、商品編集の自動化だけでなく、データに基づく商品最適化まで実現するツールへと進化しました。

このサービスで目指せること

  • 深夜作業の削減による働き方改善
  • データドリブンなサムネイル最適化
  • クリック率・売上の改善可能性
  • 作業時間の大幅削減

▶️イージークリエイティブ公式(1週間無料トライアル実施中!)

https://x.gd/cuDoZ

また、ご意見・ご不明点等ございましたら、いつでもお気軽にご連絡ください。
皆さまからのフィードバックを心よりお待ちしております。
引き続き、ご愛顧のほどよろしくお願いいたします。


イージクリエイティブ for Rakuten 開発担当
連絡先:developer+easycreative@ufas.co.jp

【保存版】楽天RMSのCSV編集・一括更新を効率化する方法まとめ(自動化・予約対応)

楽天市場の店舗運営者の皆さん、「商品情報の編集作業に追われて深夜残業になっていませんか?」
「CSVでの一括編集が複雑すぎて難しい」「セール開始に合わせて更新予約できれば楽なのに…」と感じたことはありませんか?

本記事では、楽天RMSが提供するCSV一括編集機能の仕組みと課題を整理し、大量の商品情報を効率よく編集・更新するコツや、セール時の更新作業を自動化・予約する方法をご紹介します。
煩雑なCSV編集に悩む担当者の方はぜひ参考にしてください!

楽天RMSのCSV編集機能の仕組みと課題

楽天市場では、商品情報をまとめて登録・変更できる「CSV商品一括編集」機能が有料オプションとして提供されています。

月額11,000円(税込)を支払ってRMS上で申し込むと利用可能になり、商品データ(販売価格や在庫数など)をCSVファイル経由で一括管理・更新できる仕組みです。

大量の商品を個別に編集していては膨大な時間がかかるため、多数の商品を扱う店舗には欠かせない機能と言えるでしょう。

CSV一括編集の基本的な流れは次の通りです

まず、RMSから既存の商品データをダウンロードする条件を設定します。
すると、そのCSVファイルが店舗専用のFTPサーバーにアップロードされるので、それをWinSCPなどFTPクライアントを利用して、パソコンにダウンロードします。
そのCSVファイルをACCESSやエクセル(クセがあります・・・・)を使い編集します。
編集後のCSVをまたFTPクライアントを利用し、指定のフォルダにアップロードすると、楽天のシステムがそれを感知した段階でシステムが一括で商品情報を更新してくれます。
このように複数商品の情報をまとめて編集できるため、商品点数が多い場合でも効率よく更新できるのがメリットです。

しかし一方で、楽天のCSV一括編集機能にはいくつかの課題・デメリットも存在します。

  • 利用ハードルが高い:CSV一括編集機能は有料オプション(月額11,000円)であり、事前申し込みが必要です。利用開始までの手続きや、CSV編集に使うソフトの準備(Excelなどの表計算ソフト、ファイル転送ソフト等)が必要になります。
  • データ形式が複雑:楽天市場は近年SKU単位での商品管理に移行したため、CSVのフォーマットも複雑になりました。一つの商品に対して「商品レベル情報」と「SKUレベル情報」の両方を入力する必要があり、項目を正しく分けて記入しないとエラーで更新できません。実際、「SKU版になってCSV編集に時間がかかるようになった」「エラーが増えてアップロードできない」といった声も多く聞かれます。従来はExcelの関数で商品名や価格を一括変換する等の手法も使えましたが、SKU対応後は商品ごと・SKUごとに行を分ける必要があるためハードルが上がっています。
  • 更新予約ができない:最大の課題が、CSV一括編集機能に「予約更新(スケジュール実行)」機能がないことです。例えば深夜0時スタートのセールに合わせて商品情報を切り替える場合、CSVをその時間に手動でアップロードするしか方法がなく、事前に予約セットして自動反映…といったことが標準機能ではできません。また、時間ぴったりにアップロードしたとしても楽天側のシステムがその時間に編集を反映してくれるかは運次第となってしまいます。楽天の販促イベントは深夜開始・終了になるケースが多いため、この制約は担当者にとって大きな負担となっています。

以上のように、「CSVで一括編集できる」とはいえ専門知識と手間がかかるのが楽天RMSのCSV編集機能の現状です。特にセール時の更新対応では、後述するように深夜や週末の作業が発生しやすく、運用上の悩みになりがちです。

CSV編集のやり方

RMSの「商品管理」ページを開き、「CSVダウンロード」をクリックします

編集したい商品の情報を指定し、編集したい項目のチェックボックスを選択し、最下部の「ダウンロード」ボタンを押します

WinSCPなどのFTPクライアントを開き、次のように接続情報を設定します
転送プロトコル:SFTP
ホスト名:upload.rakuten.ne.jp
ポート番号:22
ユーザー名:ご自身の店舗の店舗識別子(店舗TOPページのhttps://www.rakuten.co.jp/○○○の部分)
パスワード:空欄

上記の設定で「ログイン」を押すとパスワードの入力を求められるので、設定済みのパスワードを入力。

画像のようなフォルダの一覧が表示されるため次の順番でファイルを開く
ritem > download

対象のファイルをドラッグ・アンド・ドロップで適当なフォルダにダウンロードする

ダウンロードしたCSVファイルをエクセルで開く場合、次の手順で開くようにしてください。
まずファイルではなく「エクセル」を開き、「空白のブック」を作成する。

「データ」タブから「テキストまたはCSVから」を選択し、ダウンロードしてきたCSVを選択する

すると、以下のように表示されるため、「読み込み」をクリックする

すると、次のように正しい形式でCSVが開けるようになるので、エクセル上で編集を行い、「normal-item.csv」というファイル名で保存します
※商品削除用CSVファイルの場合は「item-delete.csv」となります

⚠️CSVには
・商品レベル行
・商品オプションレベル行
・SKUレベル行
という異なる情報が記載された行が存在します。
その情報を修正する際にも「商品レベル行」は必須ですので、編集しないからと言って削除しないようにしましょう。

編集が終わったらWinSCPなどを使用して商品編集後のCSVをサーバーにアップロードします。
場所はritem > batchです。

アップロードが完了し、楽天のシステムがそれを感知した段階で一括編集が実行されます!

セール時のCSV更新を効率化する方法

楽天市場では、「楽天スーパーSALE」「お買い物マラソン」「5と0のつく日キャンペーン」など毎月のようにセールイベントが開催されます。売上アップのチャンスである反面、セール準備に伴う商品情報の更新作業が毎回発生し、担当者の負担にもなりがちです。典型的なセール対応として、次のような更新業務が発生します:

  • 商品名でのセール訴求 – 商品名に「〇時間限定〇%OFF」「ポイント○倍」などセール用キーワードを追加して目立たせる。
  • セール用サムネイル画像への差し替え – 商品画像を期間限定のバナー付き画像や「SALE」アイコン入り画像に変更し、視覚的に訴求力を高める。
  • 二重価格表示や販売期間の設定 – セール価格と通常価格(参考価格)を併記したり、セールの開始・終了日時を設定して期間限定で価格が切り替わるようにする。
  • 商品説明文でのセール告知追加 – 商品説明の冒頭にセール開催告知やクーポン情報、セール会場へのリンクバナーなどを挿入する。

これらの作業を対象商品すべてに行うのは手間が膨大ですが、CSV一括編集を使えば比較的短時間で実施可能です。

例えば、対象商品の商品名に一括で「ポイント○倍」等の文字を加えることも、normal-item.csvを編集してアップロードすれば一度で完了します。
また、販売期間や表示価格の項目を活用しておけばセール価格への切替は自動化可能です。

事前にCSV上で「セール開始日時~終了日時」と特価を設定しておくことで、その時間帯のみ自動的に値下げ価格が表示され、時間が来れば元の通常価格に戻ります。
価格改定に関してはこのようにRMS標準機能でタイマー設定できますので、事前に設定できる項目(価格やポイント倍率等)は極力活用するのがポイントです。

問題は、商品名や説明文、画像など時間指定で自動切替できない要素です。

これらは通常、セール開始直前にCSVをアップロードし、セール終了後に再度CSVで元に戻す必要があります。

更新予約機能がないRMSでは、人手で深夜対応せざるを得ないケースも多く、担当者から「夜中の更新が大変」「週末返上で準備しなければならない」といった悩みが多く聞かれます。

自動化ツール「イージークリエイティブ for 楽天市場」の紹介

近年、楽天RMSのCSV編集作業をサポートする自動化ツールが続々と登場しています。

例えば「イージークリエイティブ for 楽天市場」は、Excelで商品情報を編集し、指定した日時にその変更を自動反映できるサービスです。
従来は「セール直前に深夜までかかって手動編集する」しかなかった作業が、このツールを使えば日中に準備して予約セットするだけで完了します。

イージークリエイティブの基本的な仕組みは以下の通りです。

  1. RMSと連携し、管理画面上から最新の商品データをExcel形式でダウンロードします(通常のnormal-item.csvに近いフォーマット)。
  2. ダウンロードしたExcelファイル上で、変更したい項目を編集します。操作はExcelベースなので、担当者は普段の表計算ソフトの要領で商品情報を修正できます。
  3. 編集が終わったら、そのファイルをサービス上にアップロードし、反映したい日時を予約設定します。即時反映も可能ですが、深夜や早朝の時刻を指定して予約しておけば、その時間にシステムが自動でRMSに更新を反映してくれます。

このように、Excelでの一括編集と自動反映を一気通貫で実現できるため、「CSV一括編集機能の課題だった予約不可を解決できる」のが大きな強みです。

実際、商品名・商品画像の差し替え、商品説明文やキャッチコピーの更新、ポイント倍率の開始・終了設定など、セール対応で必要になる様々な項目を指定時刻に自動更新できます。

例えば
「セール開始と同時に目玉商品の画像をSALEバナー付きに変更し、説明文先頭にクーポン案内を追加」
「セール終了後に画像と説明文を元に戻す」
といった高度な更新も、人手を介さず予約機能任せでOKです。

担当者が深夜にPCに張り付いて作業する必要はなくなり、夜間・休日の作業ゼロでセールを乗り切れるようになります。

※この他にも、楽天公式の認定ツールとして提供されている「item Robot」などの商品情報管理ソフトもあります。
それらは複数店舗や他モールも含めた商品一括管理に強みがありますが、更新予約機能に関しては対応していないケースも多いため、深夜の自動更新まで行いたい場合は上記のような新しい自動化サービスを検討すると良いでしょう。

ABテスト機能も!

EC運営では、ABテストが「作業のひと手間」ではなく「売上を伸ばすための当たり前の習慣」になりつつあります。同じ商品でも、サムネイルや紹介文を少し変えるだけで、クリックのされ方や購買率が大きく変わるからです。特に楽天市場のように検索結果からの流入が多いモールでは、ユーザーが最初に目にするサムネイルの印象が訪問者数に直結します。ほんの数秒の判断を味方につけるためにも、複数パターンを試し続けるABテストが重要だと、多くの店舗様が実感されています。

ところが、サムネイルのABテストを手作業で回すのは大変です。毎日パターンを切り替えるために深夜に作業したり、数値の集計に時間を取られたりすると、本来注力したい商品企画や販促のアイデア出しが後回しになってしまいます。担当者の方からは「ABテストで試したい案はあるのに、運用の手間がネックで続かない」という声をよく耳にします。

そこでイージークリエイティブでは、ABテストの流れそのものを丸ごと自動化しました。サムネイルは事前にA案・B案を登録するだけで、システムが毎日自動で切り替えてくれます。そのため、営業時間中に余裕をもって準備できます。さらに、RPPのCTR・IMP数・CVRなどの指標も自動で取り込み、日次レポートとして可視化。どの案が優秀だったか、何が原因で伸びたのかがひと目で分かります。

この仕組みによって、店舗担当者は「切り替える→集計する」という繰り返し作業から解放されます。その分、結果を見て新しいアイデアを考えたり、シーズンイベントに合わせて追加のテスト案を仕込んだりといった、本質的な仕事に時間を使えるようになります。ABテストが毎日のルーティンとして自然に回るため、経験の浅いスタッフでも迷わず運用を継続できる点も好評です。

実際の導入事例では、ある店舗がサムネイルのABテストを自動化した結果、クリック率が従来比で150%まで改善しました。Beforeは「商品が見やすい白背景画像」でしたが、テストを通じて「訴求ポイントを文字としてサムネイルに記載した画像」がユーザーに響くことが判明し、長期的にも安定した成果を出しています。数字に裏付けられた勝ちパターンを手に入れられることが、ABテストを続ける最大のメリットです。

忙しい現場でも、ABテストを「気合と根性」ではなく「仕組み」で回せるように。イージークリエイティブは、そんな店舗様の頼もしい相棒としてご活用いただいています。

まとめ

ご多忙の中、本記事をご覧いただきありがとうございます。
「イージークリエイティブ for 楽天市場」は、店舗運営の課題を根本から解決する革新的なツールです。ぜひご登録いただき、その利便性を実感いただき、皆様の店舗運営にお役立ていただければ幸いです。

▼イージークリエイティブ公式
https://x.gd/oYrvH

また、ご意見・ご不明点等ございましたら、いつでもお気軽にご連絡ください。
皆さまからのフィードバックを心よりお待ちしております。

イージクリエイティブ for Rakuten 開発担当
連絡先:developer+easycreative@ufas.co.jp

【2025年最新】楽天商品情報をExcelで一括編集して自動反映まで一気通貫でできる神サービスを開発した件

楽天市場で店舗運営をされている皆さん、こんなお悩みはありませんか?

  • セールが来るたびに深夜まで商品編集作業をしている
  • 人手が足りなくてセールに合わせた商品情報の更新ができていない
  • 手動での商品管理に限界を感じている

実は、これらの課題はイージークリエイティブ for 楽天市場というサービスを活用することで誰でも簡単に解決できます。
本記事では、サービスの利用方法から実際の導入効果まで詳しく解説いたします。

▶️サービス詳細はこちら
https://x.gd/ckgz3

このサービスについて

「イージークリエイティブ for 楽天市場」は、楽天市場に出店している店舗オーナー様向けに商品管理を一つのプラットフォーム上で完結できる「統合型商品管理ツール」です。

主要機能として「商品一括編集」と「ABテスト」を提供しており、店舗運営における作業効率化と売上向上に貢献します。

商品一括編集機能とは

“Excelで編集した商品情報を指定時間に自動反映できる”新しい自動化サービスです。

これまでのように「セール直前に深夜作業する」必要はありません。
ベータ版では、主にRMS商品情報を指定した時間に自動編集してくれる機能を提供しております。

編集用のExcelファイルをダウンロード→Excelを開いて編集→本サービスにアップロード→あとは指定時間に自動反映。

上記のように、全てを本サービス上で一気通貫で作業が完結します。

作業時間を”深夜2時間”から”日中5分”へ。
そんな働き方を実現します。

詳しくは以下記事をご覧ください!
https://note.com/ufas/n/nd96ee020b162

▶️会員登録はこちらから(一週間の無料トライアル実施中!)
https://x.gd/ckgz3

主要機能の詳細解説

1. Excelで商品情報を予約編集

楽天店舗運営者様のRMS情報を本サービスに連携いただくことで、商品情報を自動で取得し、本サービス上で編集用のExcelファイルをダウンロードしていただけます。
編集したExcelファイルを本サービス上にアップロード→RMS反映まで一気通貫で作業を完了できます。

楽天RMSに出品している商品の画像差し替えや、商品説明文、キャッチコピー、ポイント変倍の開始・終了日時などの編集が指定した時間に自動で反映されます(即時反映も指定可能)。

2. サムネイルのABテスト自動化

複数案のサムネイルをテストし、自動集計・自動反映までワンストップで実行できます。
データに基づきながらサムネイルを最適化してくれるため、売上向上を見込めます。

3. サムネイル画像の自動生成(開発中)

魅力的な画像をAIで生成し、更新作業をさらに短縮します。
これにより、クリック率やコンバージョン率も向上を期待できます。

▶️イージークリエイティブ公式
https://x.gd/ckgz3

まとめ

この度はご多忙の中、本記事をご覧いただきありがとうございます。
「イージークリエイティブ for 楽天市場」は、店舗運営の課題を根本から解決する革新的なツールです。ぜひご登録いただき、その利便性を実感いただき、皆様の店舗運営にお役立ていただければ幸いです。

また、ご意見・ご不明点等ございましたら、いつでもお気軽にご連絡ください。
皆さまからのフィードバックを心よりお待ちしております。

イージクリエイティブ for Rakuten 開発チーム
連絡先:developer+easycreative@ufas.co.jp

【PMO業務支援】Jira自動化ツール導入事例 〜チケット起票・更新の効率化〜

背景

弊社はコンサルティングファームとして、さまざまなクライアントのITプロジェクトをPMOの立場で支援しています。

PMO業務と聞くと「進捗を管理してレポートをまとめる」というイメージを持たれがちですが、私たちは単に管理を徹底するだけでなく、ツール開発を含めた実効性のある支援を重視しています。

その一環として、日常的に利用しているJiraをさらに便利にするため、自動化ツールの開発・導入を行いました。

課題感

実際の現場では、次のような“小さな不便”が積み重なり、メンバーの負荷になっていました。

  • サブタスクをExcelから一括登録したいが、標準機能では対応できない
  • 担当課題をまとめて一覧化したいが、毎回フィルタ条件を設定する必要がある
  • Excelで更新した内容をJiraに反映する際、1件ずつ手入力せざるを得ない

これらは一見些細ですが、プロジェクト全体では大きなロスに繋がります。

解決アプローチ

そこで私たちは、Python × Jira API を活用し、
「起票 → 一覧化 → 更新」という一連の流れを自動化するツールを開発しました。
構成はシンプルで、以下の3本のスクリプトを組み合わせています。

  1. サブタスク一括起票(upload.py)
  2. 担当チケットのダウンロード(export.py)
  3. 一括更新(update.py)

この仕組みにより、現場メンバーが感じていた細かな不便を解消し、タスク管理の効率化を実現しました。

実際のシナリオ

① サブタスクの一括起票

テスト工程では「設計」「実行」「レビュー」など複数のサブタスクを一気に登録する必要があります。

従来はJira画面から1件ずつ起票していましたが、CSVを用意してスクリプトを実行するだけで、数秒で作成できるようになりました。

サブタスクCSV例

要約,終了日,ステータス,担当者,親チケット
テストケース設計,2025-09-20,To Do,user01,ABC-101
テスト実行,2025-09-22,To Do,user02,ABC-101

upload.pyコードの一部

fields = {
    "project": {"key": project_key},
    "parent":  {"key": parent_key},
    "summary": summary,
    "issuetype": {"id": issuetype_id},
}
resp = jira.post("rest/api/2/issue", data={"fields": fields})
print(f"  -> {resp.get('key')}")

② 担当チケットのダウンロード

進捗確認や棚卸しでは、担当課題をExcelに出力できるようにしました。

出力Excel例

課題キー 要約 ステータス 期限
ABC-201 APIテスト実装 In Progress 2025-09-20
ABC-202 レビュー対応 To Do

export.pyコードの一部

jql = 'assignee = currentUser() ORDER BY updated DESC'
res = jira.get(
    "rest/api/2/search",
    params={"jql": jql, "fields": "summary,status,duedate"}
)

これにより、週次の進捗確認が効率化され、メンバーも状況を把握しやすくなりました。

③ Excelからの一括更新

②で出力したExcelに進捗や期限を更新した後、そのまま一括でJiraに反映できます。

更新後Excel例

課題キー 要約 ステータス 期限 コメント
ABC-201 APIテスト実装 Done 2025-09-20 完了しました
ABC-202 レビュー対応 In Progress 2025-09-18 対応中です

update.pyコードの一部

if fields:
    jira.issue_update(key, fields=fields)
if status_name:
    transition_to_status(jira, key, status_name)
if comment_text:
    jira.issue_add_comment(key, comment_text)

効果

導入後、次のような成果が得られました。

  • サブタスク起票にかかる時間を 90%以上削減
  • 担当チケットの棚卸しが 数クリックで可能
  • 一括更新で 更新漏れや操作ミスを防止

現場からも「単純作業に時間を奪われなくなり、本来のタスクに集中できるようになった」という声が多く上がっています。

PMOとしてのスタンス

弊社PMO支援が大切にしているのは、「管理だけではなく、実際に現場で役立つ工夫を提供すること」です。

プロジェクトを成功に導くには、進捗や課題の可視化だけでなく、「どうすればメンバーがストレスなく動けるか」を仕組みで支援することも不可欠です。

今回のようにツールを開発して提供するのも、弊社のPMO業務の一部。クライアントに寄り添い、プロジェクト全体の効率と成果を高める取り組みを続けています。

【ソースコードあり】ベンチャーなので名刺管理ツールをGASで作ってみた【作り方も載せます】

TL;DR:完成した名刺管理ツールの紹介

特定フォルダに社員ごとのフォルダを作成し、そこに名刺のjpg画像を格納することで自動的にスプレッドシートに名刺の情報が格納されるツールを作りました。

仕組みとしては「時間経過」をトリガーにGASのスクリプトが実行され、特定フォルダ以下の画像ファイルを「クローリング」し、未処理の画像があれば「OCR」→「ChatGPTで解析」をする、というものです。

はじめに

名刺管理ツールは市販のSaaSが数多く存在します。しかし、スタートアップやベンチャーの現場では「費用対効果が合わない」「機能が大きすぎる」「まずは最低限でいい」といった理由から、導入に踏み切れないことも少なくありません。

私たちのチームでも同じ課題を抱えていました。営業や社外折衝で毎日のように名刺が増えていく一方で、情報の整理は各自に任せきり。結果、

  • どの名刺がどこにあるのか分からない
  • Excelや手書きの管理で属人化してしまう
  • データ化が追いつかず、営業リストに活用できない

といった状態が起きていました。

そこで「市販ツールをいきなり導入する前に、自分たちで小さく作ってみよう」と考えました。幸いGoogle Workspaceを全社で利用していたため、Drive・スプレッドシート・Apps Scriptを組み合わせれば、最低限の名刺管理システムがすぐに作れそうです。さらに最近はChatGPTの活用で、OCRの結果をきれいに構造化することも可能になっています。

この記事では、「Driveのフォルダに名刺画像を置くだけで、自動でOCR → ChatGPTで整形 → スプレッドシートに反映する仕組み」を作ったプロセスを、ソースコード付きで解説します。小さく始めたいベンチャーやスタートアップにとって、役立つ参考になるはずです。

プロジェクトの全体像

以下がプロジェクトの全体像です。

  1. GASのスクリプトから、フォルダ内の画像ファイルを取得
  2. 未処理の画像ならGCP内の「Google Drive API」に含まれるOCR機能を活用して、名刺の画像を文字列化
  3. 帰ってきた文字列をChatGPTに構造化(JSON)させる
  4. JSONをパース(分解)し、スプレッドシートに記録

準備編:GCPとGASの設定

名刺管理ツールをGASで動かすためには、Google Cloud Platform(GCP)でAPIを有効化し、Google Apps Script(GAS)と連携させる必要があります。ここでは必要な準備をステップごとに解説します。

1. GCPプロジェクトの作成

まずはGCPで新しいプロジェクトを作成します。

  1. Google Cloud Console にアクセスし、右上のプロジェクト選択メニューから「新しいプロジェクト」をクリック
  2. プロジェクト名を入力(例:BusinessCardOCR)
  3. 作成を押す(「組織」と「場所」はデフォルトで大丈夫です)

2. Drive APIの有効化

次に、このプロジェクトで Google Drive API を有効化します。

  1. 画像赤枠部分で「Google Drive API」を検索
  2. 検索結果から「Google Drive API」を開く
  3. 「有効にする」をクリック

3. OAuth同意画面の設定

Google Drive APIを利用するためにOAuth同意画面の設定が必要です。

  1. 「APIとサービス」→「OAuth同意画面」を開く
  2. ユーザータイプを選択(社内利用であれば「内部」、外部公開なら「外部」)
  3. アプリ名、サポートメールアドレスを入力
  4. 以下の画像のボタンからスコープに「…/auth/drive」を追加
  5. 保存して完了

4. スプレッドシートとの紐付け(コンテナバインド型)

今回のプロジェクトは「スプレッドシートと連動する前提」なので、対象のスプレッドシートから直接GASを開きます。

  1. 名刺情報を保存するスプレッドシートを用意(シート名は data 推奨)
  2. スプレッドシートのメニューから「拡張機能」→「Apps Script」をクリック
  3. これでスプレッドシートと紐づいた(コンテナバインド型)GASが作成されます

5. 高度なGoogleサービスの有効化

最後に、GAS側でDrive APIを使えるように設定します。

  1. GASエディタを開き、メニューから「サービス」→「高度なGoogleサービス」へ
  2. Drive API v2 をONにする
  3. これで Drive.Files.copy(…) が使えるようになります

6. APIキーの設定

ChatGPTのAPIキーの取得方法などの記事はたくさんあるので、そちらを参考にしてください!

  • プロジェクトのプロパティを開く
    メニュー「プロジェクトの設定(歯車アイコン)」をクリック
    「スクリプトのプロパティ」欄を探します
  • スクリプトプロパティを追加
    「+追加」を押して新しいキーを追加
    名前: OPENAI_API_KEY
    値: OpenAIのAPIキー(例: sk-xxxx…

これで準備は完了です!
次章からは、実際にOCRとChatGPTを組み合わせて名刺を自動で構造化していく実装に入ります。

実装編:ソースコード

以下をGASのスクリプトエディタにコピペしてください。
PARENT_FOLDER_IDには名刺を格納するフォルダのURLの〇〇部分を入れてください
「https://drive.google.com/drive/u/1/folders/〇〇」

var PARENT_FOLDER_ID = "XXXXXXXXXXXXXXXXXX";  // 社員フォルダをまとめるフォルダID

function crawlAndProcess() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("data");
  var lastRow = sheet.getLastRow();

  var processedFiles = [];
  if (lastRow > 1) {
    var values = sheet.getRange(2, 1, lastRow - 1, 1).getValues();
    processedFiles = values.map(function(row) {
      return row[0];  // 1列目の値(ファイルID)
    });
  }

  var parent = DriveApp.getFolderById(PARENT_FOLDER_ID);
  var subFolders = parent.getFolders();

  while (subFolders.hasNext()) {
    var folder = subFolders.next();
    var employeeName = folder.getName();
    var files = folder.getFiles();
    

    while (files.hasNext()) {
      var file = files.next();
      if (processedFiles.indexOf(file.getId()) !== -1) {
        continue; // 既に処理済み
      }
      Logger.log(file);
      // --- OCR実行 (Advanced Drive Service 必要) ---
      var resource = {
        title: file.getName(),
        mimeType: MimeType.GOOGLE_DOCS
      };
      var ocrFile = Drive.Files.copy(resource, file.getId(), {ocr: true});
      var doc = DocumentApp.openById(ocrFile.id);
      var text = doc.getBody().getText();

      Logger.log("OCR完了");

      // ChatGPTで構造化
      var structured = callOpenAI(text);

      Logger.log(structured);
      // スプレッドシートに追記
      sheet.appendRow([
        file.getId(),
        employeeName,
        file.getName(),
        new Date(),
        structured.name || "",
        structured.company || "",
        structured.department || "",
        structured.position || "",
        structured.address || "",
        structured.phone || "",
        structured.email || "",
        structured.website || ""
      ]);

      // 中間ファイル(Google Doc)は削除
      DriveApp.getFileById(ocrFile.id).setTrashed(true);
    }
  }
}

function callOpenAI(text) {
  const API_KEY = PropertiesService.getScriptProperties().getProperty("OPENAI_API_KEY");
  const url = "https://api.openai.com/v1/chat/completions";
  const payload = {
    model: "gpt-4o-mini",
    messages: [
      {
        role: "system",
        content: "あなたはOCRされた名刺情報を必ず以下のキーでJSON化するアシスタントですJson以外のコンテンツは生成しないでください。: name, company, department, position, address, phone, email, website"
      },
      {
        role: "user",
        content: "以下のOCRテキストから名刺情報を抽出してください:" + text
      }
    ]
  };

  const response = UrlFetchApp.fetch(url, {
    method: "post",
    headers: {
      Authorization: "Bearer " + API_KEY,
      "Content-Type": "application/json"
    },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  });

  const json = JSON.parse(response.getContentText());
  try {
    return JSON.parse(json.choices[0].message.content);
  } catch (e) {
    return {};
  }
}

運用編:自動化

名刺管理を日常的に使うには、「新しい名刺画像がアップロードされたら自動で処理される」ことが大切です。Google Apps Script では、時間主導型トリガーを設定することで、関数を一定間隔で自動実行できます。

1. トリガー画面を開く

  1. Apps Script エディタを開く
  2. 左側の時計アイコン「トリガー」をクリック

2. 新しいトリガーを追加

  1. 右下の「トリガーを追加」をクリック
  2. 実行する関数を crawlAndProcess に設定
  3. 実行するデプロイ → Head
  4. 実行ユーザー → 自分(アカウント)

3. イベントの種類を選択

  1. イベントのソース:時間主導型
  2. 時間ベースのトリガーのタイプを選択
    分ベース → 5分ごと、10分ごとなど
    時間ベース → 1時間ごと、2時間ごと
    日ベース → 毎日決まった時刻

例えば「1時間ごと」にすれば、Driveに追加された名刺画像を自動的にOCR & 保存してくれます。

実際に使ってみた感想

実際に社内でこの仕組みを運用してみると、いくつかの気づきがありました。

まず、技術的な側面では ChatGPTが返すJSONのフォーマットが必ずしも正しいとは限らない という課題がありました。時折、余計なテキストが混ざったり、JSONの波括弧が欠けていたりするケースがあり、その場合はスプレッドシートに正しく反映されません。プロンプトを工夫することで精度は改善しますが、「AIからの出力を前提にシステムを組む場合はエラーハンドリングが必須」という学びがありました。

次に、仕組みそのものを作るのは思った以上に簡単で便利でしたが、「名刺画像をDriveにアップロードする」という運用ルールを根付かせる方がはるかに難しい という現実に直面しました。どれだけ便利な仕組みでも、社員全員が日常的に使う習慣を持たなければ、データは蓄積されません。技術の課題よりも文化を浸透させる難しさの方が大きいと感じています。

そして最後に、実際に使ってみると 人間がこれまで目で確認していた情報整理を、かなりの部分AIに任せられるようになってきた という実感がありました。OCRとAIの組み合わせは、単なる自動化を超えて、知的労働の一部を置き換え始めています。こうした仕組みを日常的に取り入れることで、今後は名刺管理に限らずさまざまな業務で、AIによる労働力の代替が加速していくと強く感じました。

まとめ

今回紹介した名刺管理ツールは、Google Drive API の OCRChatGPT による構造化、そして GAS + スプレッドシート を組み合わせることで、比較的簡単に実現できました。
システム自体は短時間で構築できますが、実際に使い続けるには「名刺画像をアップロードする文化を根付かせること」が大きな課題です。

一方で、AIを組み合わせることで、これまで人間が手作業で行っていた判断や整理の一部を自動化できることを強く実感しました。こうした仕組みを小さく作って運用してみることが、今後の業務効率化やAI活用の第一歩になると考えています。

【GAS】GoogleスプレッドシートとApps Scriptで予定管理ツールを自作!(複数招待者の空き状況自動取得編)

本記事の概要

Googleカレンダーに予定を手動で登録するのが面倒くさい…
そんな悩みを解決するために、GoogleスプレッドシートとApps Scriptを使った「予定管理ツール」を自作しました!
本記事では、複数招待者の空き状況を自動で取得してくる機能について解説します。

ターゲット

  • Google Workspaceを活用している企業の管理者・エンジニア
  • 社内予定調整・会議予約の工数を削減したい方
  • Google App Script(GAS)で業務効率化をしたい方

Googleカレンダー連携予定管理ツールとは?

この「予定管理ツール」は、GoogleスプレッドシートとApps Script(GAS)を組み合わせて作った業務自動化ツールです。

予定の入力はスプレッドシート、
登録・通知はGoogleカレンダー、
全てをワンクリックで完結できます。

シート構成と役割

シート名役割
予定管理登録予定の一覧(手入力 or 空き時間から自動反映)
登録一覧カレンダーに登録済みの予定履歴
招待者マスタ社員名とメールアドレスの対応表(自動取得)
会議室マスタ会議室名とGoogleカレンダーIDの一覧(自動取得)
空き状況招待者の空き時間を自動出力するためのワークシート

機能要件

①スプレッドシートUI機能

機能内容
カスタムメニュー追加シート起動時にメニューバーへ「空き状況確認」メニューを追加
空き状況取得招待者の予定を確認し、空いている時間を30分単位で可視化
予定反映空き時間の候補を選択して、予定管理シートへ自動入力

②Googleカレンダー連携機能

機能内容
カレンダー登録シート上の予定情報からGoogleカレンダーにイベント登録(Meetリンク付き)
招待者追加招待者マスタを参照してメールアドレスに変換し、ゲストとして自動追加
会議室予約会議室マスタのメールを使用してイベントに会議室を招待
イベントID保存作成されたイベントのIDを履歴としてスプレッドシートに記録
入力行削除カレンダー登録完了後、予定管理シートから該当行を削除

③履歴メンテナンス機能

機能内容
終了イベント削除終了日時が過去のイベントは履歴シートから自動削除
カレンダー削除検知カレンダー上から削除されたイベントも履歴から削除
毎日トリガー実行上記処理を毎日午前2時に実行するトリガーを自動作成

④マスタメンテナンス機能

機能内容
招待者マスタ更新Google Workspace のユーザー一覧を取得してシートに自動反映
会議室マスタ更新会議室リソースを一覧取得し、メールアドレスとともにシートに反映
自動トリガー作成毎日午前3時にマスタを更新するトリガーを自動生成

実装コード解説

①カスタムメニューの追加(onOpen())

function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('空き状況確認')
    .addItem('選択行の空き状況取得', 'showFreeBusyForRow')
    .addItem('選択スロットを予定管理に反映', 'applyFreeSlotsToInput')
    .addToUi();
}

解説

  • onOpen()はGASにおけるスプレッドシートの「カスタムメニュー追加」などに使う代表的なトリガー関数。ユーザーがスプレッドシートを開いたときに自動的に実行される
  • SpreadsheetApp.getUi()→スプレッドシートのUIにアクセス
  • createMenu→ユーザー定義のメニューに追加
  • GAS独自のカスタムメニュー機能により、クリックで関数実行が可能になる

実装後イメージ

②空きスロットの取得(Googleカレンダー連携)

function showFreeBusyForRow() {
  const ss    = SpreadsheetApp.getActiveSpreadsheet();
  const input = ss.getSheetByName(SHEET_INPUT);
  const ui    = SpreadsheetApp.getUi();
  const sel   = input.getActiveRange();
  if (!sel || sel.getSheet().getName() !== SHEET_INPUT) {
    ui.alert('予定管理シートでデータ行を選択してください');
  return;
  }
  const row = sel.getRow();
  if (row < 2) {
    ui.alert('データ行を選択してください');
    return;
  }

  // デフォルト設定
  const defaultStart = new Date(); defaultStart.setHours(0,0,0,0);
  const defaultDays  = 7;
  const defaultFromH = 9, defaultFromM = 0;
  const defaultToH   = 20, defaultToM   = 0;

  // 開始日時(I3) と 期間日数(J3)
  let rawStart = input.getRange('I3').getValue();
  let timeMin  = rawStart instanceof Date? new Date(rawStart): rawStart? new Date(rawStart): defaultStart;
  let rawDays  = input.getRange('J3').getValue();
  let days     = rawDays? Number(rawDays): defaultDays;
  let timeMax  = new Date(timeMin); timeMax.setDate(timeMin.getDate()+days);

  // 時間帯(K3,L3)
  const parseHM = (v,defH,defM)=>{
    if (v instanceof Date) return [v.getHours(),v.getMinutes()];
    if (typeof v==='string' && v.includes(':')) {
      const [h,m]=v.split(':').map(x=>parseInt(x,10)||0);
      return [h,m];
    }
    return [defH,defM];
  };
  let [fh,fm] = parseHM(input.getRange('K3').getValue(), defaultFromH, defaultFromM);
  let [th,tm] = parseHM(input.getRange('L3').getValue(), defaultToH,   defaultToM  );
  const fromTotalMin = fh * 60 + fm;
  const toTotalMin   = th * 60 + tm;

  // 招待者取得 (G列)
  const inviteeStr = input.getRange(row,7).getValue();
  if (!inviteeStr) { ui.alert('招待者セルが空です'); return; }
  const names      = inviteeStr.toString().split(',').map(s=>s.trim()).filter(s=>s);
  const inviteeMap = buildMap(ss, INVITEE_MASTER,1,2);
  const attendees  = names.map(n=>inviteeMap[n]).filter(e=>e);
  if (!attendees.length) { ui.alert('招待者マスタに該当がありません'); return; }

  // FreeBusy.query
  const fbReq  = { timeMin: timeMin.toISOString(), timeMax: timeMax.toISOString(), items: attendees.map(e=>({id:e})) };
  const fbResp = Calendar.Freebusy.query(fbReq);

  // busy→free slots
  const busy      = attendees.flatMap(e=>fbResp.calendars[e].busy||[]).map(p=>({start:new Date(p.start),end:new Date(p.end)}));
  const slotIntervalCell = input.getRange('M3').getValue();
  const slotMin = slotIntervalCell
    ? Number(slotIntervalCell)
    : 30;
  const freeSlots = calcFreeSlots(busy, timeMin, timeMax, slotMin)
  .filter(s=>{
  const m  = s.start.getHours()*60 + s.start.getMinutes();
  return m>=fromTotalMin && m+slotMin<=toTotalMin;
  });

  // 出力
  let out = ss.getSheetByName('空き状況');
  if (!out) out = ss.insertSheet('空き状況');
  // ヘッダー以外の値をまるっとクリア
  const maxRow = out.getMaxRows();
  if (maxRow > 1) {
    // A2:C<最終行> の内容を消す
    out.getRange(2, 1, maxRow - 1, 3).clearContent();
    // A2:A<最終行> のチェックボックス設定を消す
    out.getRange(2, 1, maxRow - 1, 1).clearDataValidations();
  }

  // フリー枠を書き込む
  if (freeSlots.length > 0) {
    const outputValues = freeSlots.map(s => [
      false,
      s.start,
      s.end
    ]);
    out.getRange(2, 1, outputValues.length, 3).setValues(outputValues);
    // ③ 書き込んだ行だけチェックボックスを再設定
    out.getRange(2, 1, outputValues.length, 1).insertCheckboxes();
  }
  ui.alert(`空きスロットを${freeSlots.length}件出力しました`);
}

解説1:基本定数の定義と選択行のチェック

const ss    = SpreadsheetApp.getActiveSpreadsheet();
const input = ss.getSheetByName(SHEET_INPUT);
const ui    = SpreadsheetApp.getUi();
const sel   = input.getActiveRange();
  • ss:現在アクティブなスプレッドシートを取得
  • input:予定管理用のシート(例:‘予定管理’)を取得
  • ui:UIダイアログ用のオブジェクト
  • sel:現在選択されているセルの範囲
if (!sel || sel.getSheet().getName() !== SHEET_INPUT) {
  ui.alert('予定管理シートでデータ行を選択してください');
  return;
}
const row = sel.getRow();
if (row < 2) {
  ui.alert('データ行を選択してください');
  return;
}
  • 選択セルが正しいシート・データ行であることをチェック。間違っていると警告を出して処理終了。

解説2:検索範囲の開始日時・終了日時の取得(I3,J3)

const defaultStart = new Date(); defaultStart.setHours(0,0,0,0);
const defaultDays  = 7;
  • デフォルトは「今日0:00」から7日間。
let rawStart = input.getRange('I3').getValue();
let timeMin  = rawStart instanceof Date ? new Date(rawStart) : defaultStart;

let rawDays  = input.getRange('J3').getValue();
let days     = rawDays ? Number(rawDays) : defaultDays;
let timeMax  = new Date(timeMin); timeMax.setDate(timeMin.getDate() + days);
  • I3 に開始日、J3 に日数が入力されていれば使用し、未入力ならデフォルト使用。

解説3:時間帯の取得(K3:開始時刻、L3:終了時刻)

const parseHM = (v,defH,defM)=>{
    if (v instanceof Date) return [v.getHours(),v.getMinutes()];
    if (typeof v==='string' && v.includes(':')) {
      const [h,m]=v.split(':').map(x=>parseInt(x,10)||0);
      return [h,m];
    }
    return [defH,defM];
  };

引数の意味

  • v… 時刻情報(Date型または”10:30″などの文字列、または未入力)
  • defH… デフォルトの「時」(vが無効だった時に使用)
  • defM… デフォルトの「分」(vが無効だった時に使用)

処理の流れ

1. v instanceof Date

  • 入力 v が Date オブジェクトなら、getHours() と getMinutes() で [時, 分] を返します。

例:
parseHM(new Date(“2025-08-05T14:45:00”), 9, 0)  // → [14, 45]

2. typeof v === ‘string’ && v.includes(“:”)

  • 入力 v が “14:30” のような文字列なら、それを : で分割して、parseInt で整数に変換します。
  • 不正な文字列でも parseInt(x, 10) || 0 によって0に変換されるため、安全です。

例:
parseHM(“10:45”, 9, 0) // → [10, 45]
parseHM(“abc:99″, 9, 0) // → [0, 99](”abc” は parseIntでNaN → 0 に)

3. それ以外はデフォルト値を返す

return [defH, defM];

  • 日時が未入力だったり、文字列が “abc” のように完全に無効だった場合など。

例:
parseHM(“”, 9, 0) // → [9, 0]

解説4:招待者(G列)を取得し、メールアドレスに変換

const inviteeStr = input.getRange(row, 7).getValue();
if (!inviteeStr) { ui.alert('招待者セルが空です'); return; }

const names = inviteeStr.toString().split(',').map(s => s.trim()).filter(s => s);
const inviteeMap = buildMap(ss, INVITEE_MASTER, 1, 2);
const attendees = names.map(n => inviteeMap[n]).filter(e => e);
if (!attendees.length) { ui.alert('招待者マスタに該当がありません'); return; }
  • G列には 山田太郎, 佐藤花子 のように招待者名が入っている想定。
  • buildMap() で「名前 → メールアドレス」マップを作り、各招待者のアドレスを抽出。
  • マスタに存在しない名前は無視。

解説5:GoogleカレンダーAPIでFreeBusy(予定あり)取得

const fbReq  = {
  timeMin: timeMin.toISOString(),
  timeMax: timeMax.toISOString(),
  items: attendees.map(e => ({ id: e }))
};
const fbResp = Calendar.Freebusy.query(fbReq);
  • 複数人のカレンダーの「予定あり時間(busy)」を取得。

解説6:空きスロットの計算

const busy = attendees.flatMap(e => fbResp.calendars[e].busy || [])
  .map(p => ({ start: new Date(p.start), end: new Date(p.end) }));

const slotIntervalCell = input.getRange('M3').getValue();
const slotMin = slotIntervalCell ? Number(slotIntervalCell) : 30;
  • 予定のある時間(busy)をまとめて、30分単位などで区切った空き時間(free)を計算。
const freeSlots = calcFreeSlots(busy, timeMin, timeMax, slotMin).filter(s => {
  const m = s.start.getHours() * 60 + s.start.getMinutes();
  return m >= fromTotalMin && m + slotMin <= toTotalMin;
});
  • 指定時間帯の中に収まるスロットだけ抽出。

解説7:結果を「空き状況」シートに出力

let out = ss.getSheetByName('空き状況');
if (!out) out = ss.insertSheet('空き状況');
  • 出力先の 空き状況 シートが存在しない場合は新規作成。
if (freeSlots.length > 0) {
  const outputValues = freeSlots.map(s => [false, s.start, s.end]);
  out.getRange(2, 1, outputValues.length, 3).setValues(outputValues);
  out.getRange(2, 1, outputValues.length, 1).insertCheckboxes();
}
// A2:C<最終行>の値とチェックボックスをクリア
const maxRow = out.getMaxRows();
if (maxRow > 1) {
  out.getRange(2, 1, maxRow - 1, 3).clearContent();
  out.getRange(2, 1, maxRow - 1, 1).clearDataValidations();
}
  • 空きスロットを A列:チェックボックス、B列:開始時刻、C列:終了時刻として出力。
  • チェックボックスは再度挿入されるので再利用可能。

解説8:完了ダイアログ

ui.alert(`空きスロットを${freeSlots.length}件出力しました`);