【Obsidian】dataviewプラグインでデータ集計して合計をテーブル表示する基本の手法

Obsidianのプラグインは2,000以上あり、お目当てのプラグインが見つかることもあります。もっとも、有名なプラグインで用が済んでしまうことが多い。
中でもdataviewは、他のプラグインと連携もできることもありよく使います。しかし最初はこれが難しい。慣れもありますけど、覚えないといけないことが多くて投げ出したくなりますね。
ということで、比較的に簡単なデータ集計に使える用法を順番に解説していきます。
私はJavaScriptはとんと分かりませんから、dataviewjsではなく、いつもdataviewだけで済む手段しか使いません。それほど複雑なことはしていないから充分です。
データの記述
デイリーノートに必要な時だけデータを記述しています。
例えば、レシート。
いつ、何に、いくら使ったか、という支払管理です。
これを月毎や項目毎に集計するのにdataviewプラグインを使っています。
他に、習慣の記録にも使えますね。
体調のバイオグラフィ、筋トレやウォーキングといった数字で管理できるものです。
お天気なんかも数字化すれば付けられますね。
他にもその時だけのデータ集計に使います。
旅行に行ったときの支払金額だったり、部品・部材をまとめて買った金額だったり、毎月決まって買うが不定期購入の集計などです。
日付けで一覧に目するだけでも違います。
月別の集計を得たい
テストとして最終的には次のように集計させてみます。
ここでは簡単に1月といった値を持たせていますが、実際はデイリーノートから抜き出すため、日付形式で絞り込んでから月別にまとめます。
合計された数字と、桁区切りカンマ、そして円表示もさせました。
この集計でも10行のコードで済みます。
あとは少し条件を変えたり、そのままコピーして他の集計に使っています。
テストデータの用意
取りかかる前に、どこでもいいのでObsidianの新規ノートを作成してください。
タイトルは適当です。
ここでは「Obsidian Dataview テスト」としました。
最初にフロントマターにタグだけを付けておきます。
tags: "test-data"
あくまでもこのmdファイルのみでデータを表示しますが、タグがあればタグを指定して複数のmdファイルでもデータを集計できるからです。
もちろん他のフロントマター要素も引っ張れるので、dataviewプラグインを理解してきたら使ってみてください。今回はタグだけです。
次のようなデータを用意してみます。
データは[key:: value]
で入力する形です。
[]
が無くても構わないみたいですけど、よく分かりません。タグをvalueにすることもできて家計簿に使っています。ここでは基本?通りの型で適当に用意しました。
同じページの上部に置きました。
[month:: 1月]
[money:: 1000]
[shop:: 本屋]
[month:: 2月]
[money:: 2000]
[shop:: 本屋]
[month:: 3月]
[money:: 500]
[shop:: 本屋]
単純に、月と金額、お店といった買い物で必要な項目です。
雑に繋げて並べてもOKです。
改行しても同じです。
リストで表示
私はリスト表示を上手に扱えません。フロントマターの作成日や修正日などの条件で引っ張り、ソートして使うのが実用的でしょうか。
ここでは基本通りのリストとfromだけです。
```dataview
list month
from #test-data
```
fromはデータソースを示すます。作成したmdファイルのフロントマターにタグを用いたので、それを指定しています。
もしもこのmdファイル限定ということであれば、次が基本でしょうか。
this.file
がこのmdファイルです。
```dataview
list month
WHERE file = this.file
```
これはmonthのkeyで取り出しています。
ここをshopに変更すれば、shopに入れた値の「本屋」が表示されます。
keyを指定して、それに対する値(value)が表示されるというわけです。
デイリーノートのような大量のmdファイルからでも楽にデータを引っ張ってこられるというわけです。
テーブルで表示もできるが・・・
次はよく使うテーブルで表示してみます。
fromでタグ、WHERE file = this.file
も同時に書きましたがどちらかでも同じ結果です。
```dataview
table WITHOUT ID month, shop, money
from #test-data
WHERE file = this.file
```
WITHOUT ID
を入れてあるので、3列4行になっています。
もしも外すと、一番左列に「ファイル」(デフォルトだとfile)と表示されます。
このmdファイルを指定しているので、中身は「Obsidian Dataview テスト」とタイトルが出てリンクされています。
必要が無いので、IDになっている部分を除くWITHOUT ID
を入れています。
実はデータの書き方として、それぞれ別々にkeyを用意したため、これ以上だとコードが複雑になっていきます。
というか、私にはできません。
なので、データを少し変更して作り、あとで集計しやすいようにした方が手っ取り早いです。
別の形式でデータを用意
私がいつも使っている形式に、1行でなるべくデータセットとして持たせるやり方です。
先人の教えに従ってタグ形式で用意しています。
今回はシンプルにカンマ区切りのデータセットにして試してみます。
keyや変数で用意している例は適当でご容赦ください。プログラマーではないためセンスはありません。
[mmm:: 1月,book,1000]
[mmm:: 2月,book,2000]
[mmm:: 2月,book,3000]
mmmというkeyに、1月、book、1000と先程同様の意味で入力しています。
1月に買った本は1,000円みたいな感じです。
値側に3つ入っているので、そのままmmmを呼び出してもそのまま表示されます。
それでは都合が悪いので、それぞれ配列変数として抜き出します。
```dataview
table mmm, s, k, z
WHERE file = this.file
FLATTEN mmm as i
FLATTEN list(split(i, ",")) as j
FLATTEN j[0] as s
FLATTEN j[1] as k
FLATTEN number(j[2]) as z
```
1行目のtableに指定したのは、テーブルで言えば列名になります。
表を見てください。やはりmmmには3つ全て入っている値です。
FLATTEN mmm as i
3行目にあるFLATTENは平滑化?平坦化?というらしいですね。
ともかく、一度変数iにmmm(=1月,book,1000〜)を入れます。
FLATTEN list(split(i, ",")) as j
次のFLATTEN〜は、list形式から",“でsplit(分ける)してjに入れるという意味です。
そのjは配列でj[0]``j[1]``j[2]
と3つの値が入っているハズです。
つまり、1月、book、1000ですね。
それぞれ、s、k、zに代入しました。
sには左から1番目の1月、kには左から2番目のbook、そしてzには3番目の1000です。
ちなみに、スペースで分けるなら\s
、スペース付きハイフンで分けるなら\s*-\s*
としてあげればOKです。
普段は2つのデータセットにして取り出しています。あまり数が多いのは入力するのに分からなくなってしまいますし、別の方法があるハズです。
ここでは3つで分けました。2つくらいなら入力も手間ではありません。
最後の行は、j[2]
をnumberで括っています。これは数字形式にしているからです。
何もないとテキストを含むすべてになるため、あとで計算することを前提にしているため数値形式にしました。
データの形式はint型とかbool型とか、まぁ、プログラム的にありますよね。
なぜ?分けるのか
なんでデータを1行で書いてから分けるかというと、それぞれで絞り込みたいこともありますが、、数字であれば合計したいじゃないですか。
そのためにも単独で分ける必要があります。
ただ、最初のようにkeyを別にしてしまうと、関係性が保てないので、同じkeyで引っ張ることができて集計もしやすいという条件が、1つのkeyに対して複数の値というわけです。
集計してみる
先程のdetaviewのコードに3行付け加えてみます。
実際のコードは次の通りです。
```dataview
table mmm, s, k, z, sum, csum
WHERE file = this.file
FLATTEN mmm as i
FLATTEN list(split(i, ",")) as j
FLATTEN j[0] as s
FLATTEN j[1] as k
FLATTEN number(j[2]) as z
GROUP BY s
FLATTEN sum(rows.z)+"円" as sum
FLATTEN regexreplace(sum, "\B(?=(\d{3})+(?!\d))", ",") as csum
```
GROUP BY 〜
絞り込む、まとめるためにGROUP BY
があります。
今回は月別に表示しながら集計したいので、月を表しているs
を指定します。
2月は2件あって、2,000円と3,000円です。合計の5,000円になっていますね!
円表示と桁区切りカンマの付与
最後の2行で円表示させ、3桁カンマの追加をしています。
それぞれsum、csumとして代入しました。
FLATTEN sum(rows.z)+"円" as sum
zは金額の数字でした。
これに円を付けただけです。
テーブル表のsumの列は円だけが付いている値が入っています。
FLATTEN regexreplace(sum, "\B(?=(\d{3})+(?!\d))", ",") as csum
最後の桁区切りカンマは、海外のフォーラムで散々探しました。国によってもカンマの切り方が違いますからね。
正規表現でカンマをリプレイスしてcsumに代入しています。
これは覚えるよりカンマ区切りしたい時にコピペでいいと思います。難しい。
同じく、テーブル表のcsumには、先程の円表示+桁区切りカンマも付与されている状態と分かります。
最終的な仕上げ
最初の行にあるtableに各列をそのまま表示させましたが、要らないのもあります。
mmm、k、zです。最初の列のIDも要りません。
これらを消すと、1行目は次のようになります。
table WITHOUT ID s, csum
更に、変数名のままでは分かりにくいので、日本語にします。
table WITHOUT ID s as 月別, csum as 合計
as(〜として)に続けて月別、合計としました。
これで最初にご覧に入れた画像になったというわけです。
奥が深い
Obsidianのdataviewプラグインは色々なことができます。
もう本体に組み込んだ方がいいんじゃないかというくらいです。
自分ではJavaScriptは書けませんので、活用はできていないながら、dataviewjsを使うとかなりのことができます。
私もコードはコピペばかりですけど、少々イジれば自分用の集計や表現が可能なくらい分かりやすいのは難有いですね。
デイリーノートに記載しなくても、データの集計は便利です。
記事の例ではソートは扱っていません。
SORT file.ctime
といったファイルの作成日や、フロントマターの要素を取り出すこともできるので、最初にどういったデータを持たせるか頭を悩まします。
日付で絞り込むなら、Tableの後の行にでも追加してください。
WHERE file.ctime >= date("2025-03-01")
AND file.ctime <= date("2025-03-31")
もしくは
WHERE file.day >= date("2025-03-01")
AND file.day <= date("2025-03-31")
更新順ならmtimeなど、使えるプロパティはたくさんあるので、Obsidian公式ページのヘルプなどで調べてください。