今までスプレッドシートで管理していたあらゆるお仕事グッズをNotionで再現できないか、という時間泥棒な遊びに没頭している私(@saosaoyamayama)です。
記事チェックツールに引き続き、契約時間に対する稼働時間を管理するツールを作りました。その中身はちょっと長いのでまた別途。
ツールを作っている最中に気付いたことがあります。
Notionの関数で「テキスト」を切り刻んで遊ぶときは、テキストプロパティと数値プロパティの存在を知っておいたほうがいい。
本日出てくる関数
toNumber・slice・format・floor・mod・if・concat・join・formatDate
わかること
Notionで文字を切り出して数字にして計算させて文字に戻すなどの回りくどい方法で「自分が望む表示形式」にコミット。
Contents
テキストプロパティと数値プロパティ
Notionで関数を適用する時に「テキストじゃありません・数値じゃありません」というエラーを吐かれることがしばしばあります。
このエラーを事前に回避する、あるいはすぐ対処するためには、テキストプロパティと数値プロパティの違いを知っておくとよいかなと思います。
簡単にいうと、テキストは四則演算のような「計算」ができません。数値は文字を連結したり切り刻んだりできません。
Notionデータベースでいろいろなプロパティを作ってみる
特に意味のないテーブルです。
例①の[テキスト]プロパティと[数値]プロパティには「5,000」をカンマ区切り付きで入力しました。
ですが[数値]プロパティではカンマが外れてしまいました。
例②では同じく2つのプロパティに「09:20」と入力しました。この場合も[数値]プロパティではコロンが消え、さらに先行ゼロも消えました。
例③では[日付]プロパティに日付と時間を入力しました。[日付]プロパティはカレンダーから日付を選択し、時間は手入力です。
[日付]プロパティから関数を使って時間だけを抜き出したのが[時間だけ]プロパティです。「formatDate」という関数を使っています。
これらのなかで[数値]だけが仲間はずれなんですね〜。コイツはプロパティ選択画面で「数値」を選んでいます(「♯」アイコンが付いているのは数値プロパティ)。
数値縛りのマス目にカンマや先行ゼロ・各種記号などを入力すると、それらはすべて取り除かれて純粋に数字(number)だけが格納されるようです。だから09:20と入力しても「920」になっちゃう。意味が違ってきます。
スプレッドシートだと、本質的には数値だけど表示形式をそれっぽく変更(カンマ区切りとか¥付けとか)できます。Notionで同じことをやるには関数が必要なようです。
値の表示位置で区別できる
[テキスト]プロパティ・[日付]プロパティ・[時間だけ]プロパティは、文字が列の左側に寄っています。
対して[数値]プロパティは右寄りです。
つまり、関数を使って「計算」できるのは文字が右に寄っているプロパティ、それ以外は「計算」できないってこと。
ただし左に寄っているテキストも、形式を変換すれば計算できるようになります。変換は関数で行います。
まずは……テキストと数値を見分けるポイントはわかってきましたな。
プロパティを選択する時はアイコンをチェック
数値なのかテキストなのか気にする必要があるのは、関数をいじっている最中です。
実はNotionの関数入力画面では、左側にデータベース上の全プロパティがリストアップされていて、アイコンを見ればテキスト or ナンバーがわかるんですよね。
- テキストは計算できない・数値は切り刻めない・数値は連結できない
- テキストは左寄り・数値は右寄り
テキストを切り刻んで計算させてテキストに戻す実例
データベースの[開始時刻]・[終了時刻]に時刻を入力しました。いずれも左に寄っているのでテキスト扱いですね。
- 09:20に仕事を始めて12:30に終了した場合、何時間何分稼働したことになるか計算
- 時間・分が1桁の場合は頭にゼロを付けて必ず2桁で表示
- 完成形は「○時間○分」
こんなことをやってみたいと思います。ゴールは先行ゼロ付きで「○時間○分」です!
- 時間だけ・分だけテキストを取り出す
- テキストを数値に変換して引き算
- 稼働時間の単位を「分」に揃える
- 稼働時間を○時間と○分に分ける
- ゼロの要不要を判断する
- ゼロと数字と「時」と「分」を連結する
こんな流れです。
開始・終了時間と開始・終了分に切り刻む
[開始時刻][終了時刻]の前2文字と後2文字だけを切り取って、[開始H][開始m][終了H][終了m]プロパティに格納してみましょう。
ここで使うのは「slice」関数です。
slice(テキスト,何文字目から,何文字目まで)
ex)09:20
slice(prop("開始時刻"),0,2) = 09
slice(prop("開始時刻"),3,5) = 20
うまく切り刻めましたね!
関数を使ってテキストを切り刻んだとしても、得られる値はテキスト扱い(左寄り)です。
稼働時間を計算する
稼働時間は「終了時間ー開始時間」で算出できるはずですね。単純に考えると以下でいけそうなんですが……。
NG:prop("終了時刻")-prop("開始時刻")
NG:12:30 - 09:20
これだと計算できません。コロン付きの時刻はテキストであり、テキストプロパティは「計算」できないので当然引き算もできないんです。
じゃあ無理矢理数値にすれば……と思いますが、数値化するとコロンが消えてただの3〜4桁の数値になっちゃいます。
ということで、先ほど切り刻んだ2桁のテキストを使って計算しますよ。「テキスト」だけど大丈夫。
テキストプロパティを数値化する関数「toNumber」を使います。
toNumber(prop("開始H"))
toNumber(prop("開始m"))
[開始H]はテキストなので左寄りの「09」です。
これにtoNumberを適用すると数値化されて「0」が消えて「9」になり、右寄り表示に変わります。[数値化開始H]ですね。他3つの値も同様です。
続いて、「時間」と「分」それぞれ引き算します。すべて数値化してあるので引き算できますね〜!
prop("数値化終了H") - prop("数値化開始H")
prop("数値化終了m") - prop("数値化開始m")
これで例1の時間が「3」、分が「10」になりました。つまり稼働時間は3時間10分です。
ただ、例2を見ると稼働時間が5時間-51分になっちゃいますね。
やべーですね、マイナス出てくるだけでわけわからん。
ということで、稼働時間の単位を「分」に揃えようと思います。恐ろしく単純な計算です。[経過H]に60を掛けて、[経過m]を足すだけ。
prop("経過H") * 60 + prop("経過m")
これで例1は190分、例2は249分稼働したことがわかりました。
マイナスは消えたので、ここからもう一度「時間」「分」に分けてまいりましょう。
まず「分→時間」に換算するなら、「分」を60で割りますよね。うむ、割る割る。やってみましょう。
例1) 190分
190/60=3 あまり10
3時間10分
例2) 249分
時間換算:249/60=4 あまり9
4時間9分
稼働分を時間に換算したときの商とあまり、これが○時間○分なので、これをうまく拾いたい……。そんなに都合よく数字を拾ってくれる関数なんてあるの?
あるよ、Notionには。
- floor:入力している値以下の整数を返す
- mod:割り算のあまりだけを返す
190/60=3.1666666667
→3.16…以下の整数は「3」
floor(190/60)=3時間
190/60=3 あまり10
→あまりは「10」
mod(190,60)=10分
神かよ……。
例1は「3と10」、例2は「4と9」がうまく算出できました。
この関数、やばない? ヤバいな?
先行ゼロ判定
floor/modの計算結果は数値属性なので、9以下の数値は1桁で表示されます。しかし今回の指令は「1桁の数値は頭に0を付けて持ってこい」なので、ここをどうにかしましょう。
もしも1桁ならゼロを付ける、つまりif関数の出番ですね!
ifによってゼロを付けるか付けないかを判定するプロパティ[0判断H/m]を新たに作りました。
- [floor]が9より大きかったら何も表示しない(「””」)
- [floor]が9以下だったら「0」を表示
これをif関数に当てはめてみましょう。NG例とOK例があります。
NG:if(prop("floor") > 9, "", 0)
OK:if(prop("floor") > 9, toNumber(""), 0)
「何もしない・値を入れない」を表す「””」ですが、Notionではテキスト属性なんザマス!
ですからif関数という数値ベースの計算の中に組み込むと「テキストは受け付けませんよ」と弾かれてしまいます。
「””」をtoNumberで数値化したうえでif関数に組み込むのが正解です。
その結果「3」には「0」が必要で「10」には不要、という正確な判断をしてくれましたね。[mod]も同じように判定しました。
○時間○分に整形
ここまでで以下が算出できています。
- #稼働した時間[floor]
- #稼働した時間にゼロを付けるかどうか[0判断H]
- #稼働した分[mod]
- #稼働した分にゼロを付けるかどうか[0判断m]
すべて数値属性です。この4つをつなぎ合わせて、間に「時間」「分」を挟めばOKですね!
Notionで文字列を連結する場合、大きく2通りの方法があります。
- 「+」でつなぐ
- 関数でつなぐ(concat, join)
なおスプレッドシートでも同じく2通りです。
- 「&」でつなぐ(E62&E63, “3”&”時間” など)
- 関数でつなぐ(concatenate, textjoin など)
※関数による連結についてはコチラ
Notionではテキスト連結に「&」が使えません。代わりに「+」を使います。
「+」は加算記号なので、数字を見つけると足し算したくなるタチです。そのため、数字はテキストに変換したうえで連結する必要があるんですね〜。
テキストに変換する関数「format」を使います。
format(prop("floor"))
format(prop("mod"))
format(prop("0判断H"))
format(prop("0判断m"))
formatを適用すると数字はすべて左寄り、つまりテキスト化されました!
あとはつなぎ合わせていきます。
ここでちょいとトラブりました。4つの数値をテキスト化したプロパティを「+」でつなげばいいはずなのですが、なぜかうまくいかない。
本来は[正しい]の表記「03時間10分」になるはずですが「00時間00分」になってしまいました。
検証したところ、「0」をテキスト化している[0判断○テキスト化]が悪さしている模様。「0」って特殊な数字なので、まあこういうこともあるんですかね……。
知らんけど。
こちらが[正しい]の数式です。[0判断○テキスト化]を入れ子にしただけで、数式の意図は先ほどととまったく同じなんですけどね。
[うまくいかない]
:prop("テキスト化0判断H") + prop("floorテキスト化") + "時間" + prop("テキスト化0判断m") + prop("modテキスト化") + "分"
[正しい]
:format(prop("0判断H")) + prop("floorテキスト化") + "時間" + format(prop("0判断m")) + prop("modテキスト化") + "分"
結果オーライってことで!
ミッションコンプリート
今回のミッションは以下でした。
- 【完】09:20に仕事を始めて12:30に終了した場合、何時間何分稼働したことになるか計算
- 【完】時間・分が1桁の場合は頭にゼロを付けて必ず2桁で表示
- 【完】完成形は「○時間○分」
完了でよろしいですね!
なお上のキャプチャには、手入力した[開始時刻][終了時刻]と関数入りの[正しい]しか表示していません。この3つがあれば今回の一連の作業は完結するんですね〜。
今までやってきた切り刻み・プロパティ変換などすべてを[正しい]の中にぶち込むことができます。入れ子です。
まず[正しい]のコードがコチラ↓
format(if(floor(((toNumber(slice(prop("終了時刻"), 0, 2)) - toNumber(slice(prop("開始時刻"), 0, 2))) * 60 + toNumber(slice(prop("終了時刻"), 3, 5)) - toNumber(slice(prop("開始時刻"), 3, 5))) / 60) > 9, toNumber(""), 0)) + format(floor(((toNumber(slice(prop("終了時刻"), 0, 2)) - toNumber(slice(prop("開始時刻"), 0, 2))) * 60 + toNumber(slice(prop("終了時刻"), 3, 5)) - toNumber(slice(prop("開始時刻"), 3, 5))) / 60)) + "時間" + format(if(mod((toNumber(slice(prop("終了時刻"), 0, 2)) - toNumber(slice(prop("開始時刻"), 0, 2))) * 60 + toNumber(slice(prop("終了時刻"), 3, 5)) - toNumber(slice(prop("開始時刻"), 3, 5)), 60) > 9, toNumber(""), 0)) + format(mod((toNumber(slice(prop("終了時刻"), 0, 2)) - toNumber(slice(prop("開始時刻"), 0, 2))) * 60 + toNumber(slice(prop("終了時刻"), 3, 5)) - toNumber(slice(prop("開始時刻"), 3, 5)), 60)) + "分"
もう、何のこっちゃですね。だけど、確かに2つのプロパティしか使っていないことはおわかりいただけるかと思います。
太字にした部分だけを抜き出して、何をやっているのか書いてみました。
まあ、ややこしいこと。
入れ子にすれば余計なプロパティを作らずに済みますが、エラーが出たときに修復が大変かなと思っています。
なので今回のように1つずつプロパティを作って、うまくいっていることを確認しながら進めたほうがよろしいかと。
- プロパティをガンガン作って計算進める
- 正しい値が出た!
- 正しい数式内のprop()を各propの数式に置き換える
頭の中で数式がパパパーっと連なって出てくる人以外は、一段ずつ積み上げて、一段ずつ崩していくのをオススメしますよ。
なお、propを数式に置換するときは「加算・除算入りならカッコで括って置換」です。
以下で「テスト代入」プロパティに①や②の数式を代入する場合、①はそのまま、②は引き算しているのでカッコを付けます。
prop("テスト") + prop("テスト代入")
①slice(prop("AAAA"), 0, 2)を代入
→prop("テスト") + slice(prop("AAAA"), 0, 2)
②prop("AAAA") - prop("BBBB")を代入
→prop("テスト") + (prop("AAAA") - prop("BBBB"))
- slice:テキストの位置を文字数で指定して文字を抜き出す
- toNumber:テキスト形式の値を数値形式に変換する
- format:数値形式の値をテキスト形式に変換する
- floor:値以下の整数を返す
- mod:割り算のあまりだけを返す
- concat:文字列を連結する
- join:指定の文字列で他の文字列を連結する
- formatDate:日付データから任意の数値を抜き出す(日でも時間でも分でも年でも)
ヨシ!
【参考】Notionのテキスト連結関数
Notionにはスプレッドシートと同じように、テキストを連結する関数があります。
- スプレッドシートのconcatenate=Notionのconcat
- スプレッドシートのtexjoin=Notionのjoin
以下はスプレッドシートのキャプチャです。
concatenateは、指定範囲内あるいは指定したセルのテキストを連結します。Notionでは「concat」※です。
textjoinは「何かを使ってつなぐ」関数です。たとえばハイフンで連結するとかね。キャプチャでは「何も使わずにつなぐ」をやっています。Notionでは「join」です。
それぞれNotionでどう使うのか書いておきまーす。
concat("ほ" , "げ" , "ほ" , "げ") == ほげほげ
join("-" , "ほ" , "げ" , "ほ" , "げ") == ほ-げ-ほ-げ
※スプレッドシートにも「concat」という関数があるんですが、引数を2つしか指定できない驚きのポンコツです。
伝え方を大間違いしている記事が誰かの役に立つ日が来るといいな
結構どのサイト様も、1〜2つの関数に絞って説明している感じですね……。ここまでドカンと盛り込むと何が何だか、だと思います。
一応これでも「一連の作業のうちの一部分」だけ抜き出しているんですよ。
実はNotionで稼働管理ツールを作成して使っています。その中で先行0付き○時間○分表示っていうのがめちゃくちゃ面倒くさくて面白かったって感じです。
これからはAIがチャチャチャーっと数式を書いてくれるようになるんでしょうけれど、あれ、うまくいかないぞ? と思ったときにサクッと手直しできるぐらいには、理解を深めておきたいわけです。
つーわけで、次は稼働管理ツールのお話ですかね〜。これ長くなりそうですけどね〜。
※記事の左上に「2分で読める」みたいなのが出ていますが、絶対嘘だ。