dataview 对markdown笔记进行解析,使得提取笔记信息变得非常方便,可以方便的结构化展示内容,对一些不会代码的人不友好,我就分享自己的应用场景和写下的代码,供大家参考
我受到一部分他人的启发,用数据库的方式显示内容
dataview 对markdown笔记进行解析,使得提取笔记信息变得非常方便,可以方便的结构化展示内容,对一些不会代码的人不友好,我就分享自己的应用场景和写下的代码,供大家参考
我受到一部分他人的启发,用数据库的方式显示内容
首先是最简单的统计功能 ,比如说 我看牙医花了多少钱,这是在当前页面里 列表统计
左边是预览效果,右边是源码模式
重点是在 在每个列表里面增加 [price:: ]
里面的名称可以变化,但是要 英文开头,不要有空格,最多用下划线连接(就是js的变量名称要求, 其实可以有空格,dataviewjs会转化)
```dataviewjs
let sum=0
dv.current().file.lists.map( t => sum+= t.price ?? 0)
dv.el("b", "总实际花费(扣除医保): "+sum +" 元")
```
这里是 利用了 tags 对文件汇总,提取 #健身
这个大标签, 把 task 中有 的 #健身/健身环
子标签提取出来,再获取 dur:: 25 min
的属性值,进行汇总
```dataviewjs
const pages = "#健身"
const re = /#(.+?)(?=\s)/g //去标签
let fitTime=dv.duration("0 s")
let fitCount =0
const list = []
dv.pages(pages) .sort(k => k.file.cday, 'desc').map(k =>
k.file.tasks.filter(t => t.text.includes(pages))
.map( t =>{
list.push( [k.file.link, t.tags , t.text.replace(re,"").replace(/\[.*\]/,"").trim(), t.duration ?? t.dur ?? "" ])
fitTime = fitTime.plus(t.duration ?? t.dur ?? dv.duration("0 s"))
fitCount +=1
}
))
dv.table(["日期", "项目","内容", "持续时间"], list)
dv.el("b", "总运动时间: "+fitTime.shiftTo('hours').hours.toFixed(2) +"h ,运动次数 "+ fitCount)
```
首先也是通过 tag 聚合,十分通用,把括号里 #GTD/03项目
改成你需要的标签即可
```dataviewjs
for (let group of dv.pages("#GTD/03项目").groupBy(p => p.file.folder)) {
dv.header(3, group.key);
dv.table(["Name", "Inlink", "修改时间"],
group.rows
.sort(k => k.file.mtime, 'desc')
.map(k => [k.file.link, k.file.inlinks, k.file.mtime]))
}
```
这些本来可以不用这么复杂,我为了更加醒目,做了一些修改
比如 k.file.folder
改成 k.file.folder.split("-")[2]
因为我的文件路径是 03-task/02-work
就化简为 work
k.file.inlinks
改成
dv.array( k.file.inlinks.map((k)=>{
const q = dv.page(k.path)
return "#"+q.file.folder.split("/")[0].split("-")[1] + " [["+ q.file.name +"]]"
})).filter( (k)=> !k.includes("#Task"))
因为 我还想知道 被引用的md文件属于我的哪个顶层文件夹,是 输入
还是 输出
还是 成果
,如果是 任务
就不显示,用 #
更加显眼,不是真的标签
```dataviewjs
const pages = "#GTD/01重要"
dv.table(["Name", "folder","Inlink", "修改时间"],
dv.pages(pages)
.sort(k => k.file.mtime, 'desc')
.map(k => [k.file.link, k.file.folder.split("-")[2] , dv.array( k.file.inlinks.map((k)=>{
const q = dv.page(k.path)
return "#"+q.file.folder.split("/")[0].split("-")[1] + " [["+ q.file.name +"]]"
})).filter( (k)=> !k.includes("#Task"))
, k.file.mtime])
)
```
这个不错,套用改下,用来统计阅读时长
因为JavaScript的教程繁多,眼花缭乱,所以向您提问请教:
要想达到像您这样使用dataviewjs的程度,您建议需要提前学习什么课程/看什么书?
谢谢!
*背景:
本人无编程语言基础
纯靠阅读blacksmithgu官方文档学习了dataview的基本用法
很吃力进行到Query Language Reference部分
再往后就读不下去了T_T
hh,本身会一点js的基础语法就好了,推荐 菜鸟教程的js 。我也看 blacksmithgu 的教程学的,多看多用,需要用到某个函数的时候再查询。看到别人好的实现,尝试理解一下,我写这个代码也花了我半天思考怎么实现,所以想分享出来,给大家一点思路。
我这部分代码,大部分都是操作数组,所以会有函数式编程,也就是 map,sort,filter
然后不断调试, console.log(dv.current())
看看解析后的数据结构里面有什么,
dataviewjs 是根据 js 的实现,所以 js 的方法在里面都可以用。我用下来,有两个不一样的点
dv.page()
获取到的不是js的普通数组,而是一个代理数组,在全程使用 dv的函数会自动解析,如果用js的方法的话,需要 数据.array()
再用 dv函数的时候需要 dv.array(数据)
Data Arrays - Dataview 里面写的清楚,一开始不知道的时候,用 数据.values
,另一种从代理获取值的方式很好的实用案例。
```dataviewjs
const pages = '#task'
const tags = '#task'
const list = []
dv.pages(pages).sort(k => k.file.mday, 'desc').file.tasks.map( t =>{
t.visual = t.text.replace(/\[.*?\]/g,"").trim()
const f = dv.page(t.path)
const date = moment().format("yyyy-MM-DD");
const dur = dv.date(date) - t.due
const sg = dur<0 ? 'in ' : 'out '
const taskList= dv.el('div',"")
dv.api.taskList([t],false,taskList ,dv.component)
list.push([ taskList ,sg + Math.round(Math.abs(dur)/24/3600/1000) +" days" ,f.priority ?? "" ,f.file.name ])
}
)
dv.table(["Name","Due", "Priority","Page"], list)
```
可以去掉 task.visual 表示显示的html,还可以用 html元素包裹,根据不同重要醒显示颜色,详细看下面链接
https://s-blu.github.io/obsidian_dataview_example_vault/20%20Dataview%20Queries/Colorcode%20tasks%20based%20on%20meta%20data/
t.visual = t.text.replace(/\[.*?\]/g,"").trim()
tags 只是为了获取要统计的文件
---
created: 2024-08-20T17:09
updated: 2024-08-20T17:38
priority:
- normal
tags:
- task
---
- [x] 测试 1 [due:: 2024-08-22] [scheduled:: 2024-08-21] [completion:: 2024-08-20T21:12]
- [x] 测试 2,这是一大段很长很长很长很长很长很长很长很长很长的文字 [due:: 2024-08-23] [scheduled:: 2024-08-21] [completion:: 2024-08-20T21:17]
- [ ] 测试 3 [due:: 2024-09-24] [scheduled:: 2024-08-21]
还有一个问题,就是这个里面通过JS统计出来的这个数值还可以在别的地方被引动么。比如这里是牙齿消费的汇总,另一个页面是娱乐消费汇总。再建一个页面作为总汇总,这个总汇总可以把娱乐消费汇总和牙齿消费汇总统计好的,再进行相加么。
抱歉,刚看到
这个点是 dataview 自动转化,如果是源数据是数组,就会变成列表格式。
不想要点,可以把数组变成字符串
不可以 ,dv.current 只是说当前页面,但是数据来源可以更换的,简单改一下就好
```dataviewjs
let sum=0
dv.page('"要统计文件的路径1"').file.lists.map( t => sum+= t.price ?? 0)
dv.page('"要统计文件的路径2"').file.lists.map( t => sum+= t.price ?? 0)
dv.page('"要统计文件的路径3"').file.lists.map( t => sum+= t.price ?? 0)
...
dv.el("b", "总实际花费(扣除医保): "+sum +" 元")
```
或者用标签统计,dv.pages('#生活 and #工作' )
还可以添加时间限制,比如一个月内,要看你怎么保存数据,用 where 语句 限制
只通过定义来把数组变成字符串么。
也可以用css样式 list-style: none;
不好意思,又来了,把数组变成字符串复杂么。css,我没有找到对应的代码,没成功。
感谢,晚一些我试试看。