• Reading time:17 mins read

学生時代「プログラミングを勉強する」っていう選択肢が皆無だったことを今になって悔やんでいる私(@saosaoyamayama)です。プログラミングはできないけれど、難しい採血なら割とできます。

今回もまた、どこに需要があるかわからないショートカットを作りました。作ったのは昨年なんですが、実際に使って「便利だな」と感じてから記事化しようと思い、様子を見ていたわけです。

カレンダーアプリの入力のしにくさに辟易している方、もしもテキストから予定が追加できたら便利じゃぁないですか?

ということで、コピーしたテキストからカレンダーに予定を追加するショートカットを作りました。

カレンダーアプリにちまちま入力するのが面倒な方のお力になれたらうれしいです。

やりたいこと|テキスト内容をカレンダーに登録

テキストからカレンダー登録

たとえば、こんなメール・チャットが届いたとしましょう。

キックオフミーティングの件、2024年12月23日(月)の19:00からでお願いします!場所は○屋です。

これをカレンダーに登録したい。カレンダーアプリを開いて、タイトル・日付・時間・日付・時間・カレンダー名をちまちま記入するのって、地味に面倒くさいんですよ。

メール文のように規則性がないテキストから、日付・時間・場所といった指定項目を取得できるのが生成AIです。AIエージェント「satto」で、メールキャプチャからGoogleカレンダーに予定を登録するスキル(機能)を見た時は指をくわえました(汚い)。

当然ながらMacのショートカットアプリではできない芸当です。「曖昧な文章から曖昧を排除」というつよつよスキルがないから。だけど多少のしばり=記述ルールを設けることで、似たようなモノは作れるのではないか……と考えました。

テキストで予定をバーッと書いて読み取ってもらえたら、結構ラクなんじゃないかな、と。

以下は試作した3つのショートカットです。

  • ①予定追加に必要な項目をズラッと書き並べてコピー
  • ②①のうち、予定タイトルだけ任意の記号で囲んで全体をコピー
  • ③キャプチャからOCRでテキストを取得して① or ②

結果として③は中断しました。

①②は実用化

①2024/12/11 08:00-12/11 10:30 仕事、○○さんと12/23の仕事の件についてミーティング
②2024/12/11 08:00-12/11 10:30 仕事、★○○さんと12/23の仕事の件についてミーティング★

①と②の違いは、予定タイトルを記号で囲むか否かです。②のほうが記述ルールが少なく済むので、最近は②を使うことが多いですね。

今回は②をメインに説明し、その応用として①にも少し触れようと思います。

③は中断

ショートカットには「画像からテキスト抽出」というアクションがあるので、sattoと同じようにキャプチャから予定が登録できるのではないかと考えました。

試してみたところ、最初はOCRがポンコツで、特に半角スペースの認識がうまくいかなかったんですが……。M4 Mac miniに変えたからなのか、OCRで正確にテキストが取得できるようになりました。

とはいえ、今のところ活用ケースが思い浮かばないので、一旦ペンディングとしました。

テキストからカレンダーに予定を追加するショートカットの基本ルール

テキスト表記のルール

今回は前項の②のショートカットを作ります。エラーなく動かすために、自分が日付や予定を書く時のクセをベースに以下6つのルールを設定しました。

  • 開始日時→終了日時の順に並べる(間に他のテキストを挟むのはOK)
  • 予定タイトルを「★」で囲み、「★」は予定タイトル・カレンダー名の中で使わない
  • カレンダー名を必ず指定する
  • 年をまたぐ場合は必ず西暦を記載する
  • 翌年の予定には必ず西暦を記載する
  • 日付はスラッシュ区切り、時刻はコロン区切り

この6つを満たしていれば、西暦の有無や先行ゼロの有無、★以外の記号、スペースや改行は自由です。どれも自分のクセをベースにしているので、難しいことを考えずに使えています。

その他、今回のショートカットの注意点を3つまとめました。

予め指定する項目=変更が生じにくいモノに

以下の項目はアクション内に直接書き込みます。

  • カレンダー名
  • 予定タイトルを囲む記号(今回は★)

変更する時は書き直しが必要なので、できるだけ変更が生じにくいものを指定しましょう。

西暦適用ルール

テキスト内の西暦の有無については、以下の3パターンを想定・対応しています。

  • 西暦なし:現在の西暦を適用
    例)12/11 8:00〜12/11 10:30→登録時の西暦
  • 西暦が1つ:記載の西暦を適用
    例)2024/12/11 8:00-12/11 10:30→2024を適用
  • 開始・終了に西暦あり:記載どおりの西暦を適用
    例)2024/12/31 23:30〜2025/1/1 10:30

年内の予定なら西暦を書かなくていいってのは結構ラクですね〜!

終日の予定を追加する場合

いつの間にか終日設定もできるようになっていました。

時間ナシの日付と予定タイトル・カレンダー名を読み込ませればOKです。

1/5 ★ミーティング★ 仕事、みたいに。

テキストからカレンダーに予定を追加するショートカットを作る

西暦による条件分岐

それでは早速ショートカットを作っていきましょう。条件分岐があるので手順が多く見えますが、ほとんどが正規表現の一致と置換(削除)です。

  1. クリップボードにテキスト格納
  2. 現在の西暦を変数化
  3. 予定タイトルを取得
  4. カレンダー名を取得
  5. 日付だけのテキストを作成
  6. 西暦が1つの場合の処理
  7. 西暦なしの場合の処理
  8. 西暦が2つの場合の処理
  9. 予定開始日時取得
  10. 予定終了日時取得
  11. 予定作成
●こちらをクリックすると、ショートカットの全構成が一気に確認できます。

今回は、西暦表記が異なる3種類のテキストを用意し、正確に予定が登録できるか確認しました。

  • 西暦記載あり
    2024/12/11 08:002024/12/11 10:30仕事★○○さんと12/23の仕事の件についてミーティング★
  • 西暦1つ記載あり
    2024/12/11 8:0012/11 10:30 ★○○さんと12/23の仕事の件についてミーティング★ 仕事
  • 西暦記載なし
    仕事 12/11 8:00から12/11 10:30 ★○○さんと12/23の仕事の件についてミーティング★

西暦以外にも細かな表記がバラバラですが、どんな表記でもショートカット内で形式を統一してからカレンダーに登録する、という流れです。

全行程を細かく説明するとタイムレコーダーの二の舞なので、ポイントだけ掻い摘まんで説明します。

現在の西暦を変数化

西暦パーツ

ショートカット内でよく使う「現在の西暦」を変数化しています。この作業は必須ではありません。

私は「今年の1月1日」を取得→西暦を取り出していますが、「現在の日付」から西暦を取り出すのもアリですね。西暦は必ず後ろにスラッシュを付けて使うので、変数化と同時に「yyyy/」でフォーマットしました。

これを変数[今の西暦]と名付けています。動的な日付を元に変数化しておけば、年が変わると自動で年数が進むので、修正は不要です。

※IF分岐フローで[今の西暦]を使うとエラーが出るようになったので、「現在の日付から開始の年を取得」を使っています。

補足

「変数に設定」アクションでは変数に任意の名前を付与でき、変数のセットミスが激減します。

クリップボードをフラット化

クリップボードにはコピーで取得したテキストが格納されています。

万が一改行や改行コードが含まれていた時にエラーが起きないよう、クリップボードのテキストから改行「\n」を削除しました。

置き換えアクションで改行削除

このテキストは[改行削除テキスト]と名付けて変数とし、使い回します。

予定タイトル・カレンダー名を取得

予定タイトルの取得

正規表現「(?<=\★).*(?=★)」を使い、[改行削除テキスト]の中から★に囲まれたテキストを取得し、[予定タイトル]という変数名を付けました。

2024/12/11 08:00-2024/12/11 10:30、仕事、○○さんと12/23の仕事の件についてミーティング
→[予定タイトル]○○さんと12/23の仕事の件についてミーティング

続いて予定タイトルを正規表現「★.*★」で★ごと検出し、[改行削除テキスト]から削除します。

2024/12/11 08:00-2024/12/11 10:30、仕事、★○○さんと12/23の仕事の件についてミーティング★

こうしておけば、予定タイトル内の「仕事」というテキストがカレンダー名に間違われることがありませんし、この後の西暦・日付処理におけるエラーも回避できます。

補足

★で囲まないタイプのショートカット(②)を作る場合「カレンダー名を予定タイトル内に入れない」というルールが必須です。

次はカレンダー名です。

カレンダー名を取得

正規表現としてカレンダー名を記入し、一致アクションを使ってカレンダー名を取得します。こちらは[カレンダー名]という変数にしました。

仕事|リマインド|AAAA|BBBB|CC|dddd@gmail.com

カレンダー名は「|」で区切って並べればOKです。Googleカレンダーのアカウントも検出できます。

続いて、予定タイトルと同じく[改行削除テキスト]から削除しましょう。

2024/12/11 08:00-2024/12/11 10:30、仕事★○○さんと12/23の仕事の件についてミーティング★

残ったのは日時と区切り文字(〜、-など)のみ。これを[日時のみテキスト]と名付けて変数化しました。

西暦を数えて条件分岐

「西暦適用ルール」に書いたとおり、西暦の数によってその後の処理を変更するので、[日時のみテキスト]に含まれる西暦の個数を数えます。

西暦の個数を数える

西暦の正規表現「\d{4}/」に一致するテキストを検出し、「数える」アクションでカウントします。

ここからは西暦の数が「1 or 0 or 2」で条件分岐しますが、どの条件を通過しても最終的には以下の形式で出力させます。

yyyy/MM/dd HH:mm〜yyyy/MM/dd HH:mm
例)2024/12/11 8:00〜2024/12/11 10:30

西暦が1つの場合の処理

西暦が1つの場合、[日時のみテキスト]は以下のようになっています。

yyyy/MM/dd HH:mm – MM/dd HH:mm
例)2024/12/11 8:00 – 12/11 10:30

西暦がない日付に西暦を付与する、というのが大まかな流れです。ただし変数化した[今の西暦]ではなく、[日時のみテキスト]内の西暦を付与する必要があります。

開始日時

ということで、まずは西暦あり日時を正規表現で取得。[ ]の中は半角スペースと全角スペースです。

\d{4}/\d{1,2}/\d{1,2}[  ](0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9]

これを[西暦あり開始日時]とします。さらに「\d{4}/」で西暦を取得し[開始西暦]に設定。

終了日時は「MM/dd HH:mm」ですが、これを正規表現で取得すると開始日時もヒットしてしまいます。そのため[日時のみテキスト]から[西暦あり開始日時]を削除しました。

こうすれば「MM/dd HH:mm」は終了日時のもの1つだけになります。

終了日時と出力設定

終了日時は以下の正規表現でピックアップします。

\d{1,2}/\d{1,2}[  ](0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9]

これを[終了日時]という変数にしました。ここまでで、西暦ありの開始日時とその西暦、終了日時が出揃いました。あとはテキストアクション上で「〜」で繋いで出力形式を整えるだけです。

[西暦あり開始日時]〜[開始西暦][終了日時]
[yyyy/MM/dd HH:mm]〜[yyyy/][MM/dd HH:mm]

西暦が0の場合の処理

西暦を使って連結

「その他の場合」の下にif文を追加して、西暦0の処理を書いていきましょう。開始・終了日時とも西暦が付いていないので、以下の正規表現で2つ一気に取得します。

\d{1,2}/\d{1,2}[  ](0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9]

2つの日時に西暦を付けながら出力形式に寄せていきましょう。本来は以下の形にしたかったんですが……。

[今の西暦]開始日時〜[今の西暦]終了日時

[今の西暦]がフォーマットの不一致でエラーを吐くので、「開始の年を取得」で取った西暦を使って結合しています。

開始日時〜yyyy/終了日時

この西暦はフォーマットしていないものなので、結合するタイミングで「〜yyyy/」にフォーマットが必要です。

先頭にも同じように西暦を「yyyy/」でくっ付ければ、出力形式完成!

yyyy/開始日時〜yyyy/終了日時

西暦が2つの場合の処理

日付を繋ぐだけ

西暦ありの日時を正規表現で取得し、間に「〜」を挟むだけ。カンタンですね。

日時のピックアップには以下の正規表現を使っています。

\d{4}/\d{1,2}/\d{1,2}[  ](0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9]

カレンダー登録用の日時を取得

開始日時・終了日時

IF文を通過した開始・終了日時は以下の形式で出力されます。

yyyy/MM/dd HH:mm〜yyyy/MM/dd HH:mm
例)2024/12/11 8:00〜2024/12/11 10:30

ここから「〜で終わる日時」を取得して[登録用開始日時]としました。

\d{4}/\d{1,2}/\d{1,2}[  ](0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9](?=〜)

同じように「〜で始まる日時」も取得して[登録用終了日時]とします。

(?<=\〜)\d{4}/\d{1,2}/\d{1,2}[  ](0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9]

カレンダーに登録

予定として登録

最後にカレンダーへの予定追加です。日時と予定タイトルをセットしたら、「表示を増やす」からオプションを開き、[カレンダー名]も追加します。

今回は「作成シートを表示」にチェックを入れました。こうすると、予定確定前に登録内容が確認できます。

ミスが怖いっていうのもあるんですが、このショートカットを作成した当初、どうやっても「終日」に設定できなかったんですよね……。

終日にしたい場合は時間を適当に入力して、作成シート上で終日設定に切り替えていました。

右上の「追加」を押せばカレンダーに予定が追加できます。

正規表現でターゲットの文字列を拾うのがポイント

このショートカットでは、テキストの中から特定のテキストを拾うために正規表現をたくさん使いました。

「西暦だけ」「日付だけ」「★の中身だけ」など、欲しいテキストをピンポイントで拾えればいいんですが、それがなかなか難しい。

今回はまず生成AIに正規表現を書いてもらい、それを正規表現チェッカーに入力し、実際に使うテキストに対して正確にマッチするか確認しました。

こちらは正規表現チェッカーのキャプチャです。マッチするテキストを赤で表示してくれます。

ご自身のテキストに対して正規表現がうまくマッチするか確認しながら、ショートカットを作ってみてください。

実際に使ってみて感じる「面倒くさい撲滅」の効果

sattoもそうなんですが、自動化を考えるキッカケって大抵「面倒くさい」なんですよね、私の場合は。

多くの人が「面倒だ」と感じる作業は、既に誰かが自動化しています。私だけが「面倒だ」と感じる作業は、だれも自動化してくれません。たった5秒のロスだとしても、私は永遠にロスし続けるんです。

だから「面倒くさい」を見つけ次第、何かしらの方法でソイツを取り除けないか考えるようにしています。

今回作ったショートカットは、私の「めんどくせ」を確実に減らしてくれています。

予定を追加したい時は、MacのメモやSpotlightの窓にタタタタタと打ち込んでコピーしてショートカットを実行。カレンダーに直接登録するのと比較して、所要時間に大差はないかもしれません。

それでも「面倒だな」という小さなストレスが減らせるからショートカットを使います。面倒なことを後回しにするクズにとって、面倒と「感じる」こと自体リスクですしね。

今回のショートカットは、自分が何気なく打ち込む日付・時間の書き方をベースにしている、いわばオーダーメイドのショートカットなので、他の誰かの「面倒くさい」は解決できないかもしれません。

ぜひ個々のクセを反映したオーダーメイドのショートカットを作って遊んでみてください。

S.Nakayama

一帖半執筆工房代表。 デジタルマーケ企業のフリーランスPMとして計9サイトのコンテンツ制作を並行指揮した経験を持つ。 現在は企業の人材育成コンサルやメディア進行管理をしながら、グラフィックデザイン・文章校閲・校正者・ライターとしても活動中。 DigitalCameraWorld認定フォトグラファー、臨床検査技師。