DataView 和 ChartsView
DataView是个可以将整个文件库当作数据库进行读取分析的插件,它提供了笔记中属性和任务信息的标记方法,以及用于查询展示数据的接口。 可以用它将你感兴趣的带有特定标签属性路径信息的笔记查询出来,并且可以做简单的表格可视化。笔记中的任务,包括创建时间截至时间完成状态等信息,也可以通过类似的方法分析和展示。
ChartsView是一个图表可视化的插件,可以跟DataView结合起来,将DataView得到的结果,在更丰富的图表上展示。
DataView
CodeBlock中的代码可以有两种语言形式,但是同时只能使用一种。 一种是Query查询语言,类似SQL。
```dataview
TABLE rating AS "Rating", summary AS "Summary" FROM #games SORT rating DESC
```
一种是Js语言,当作Js代码执行,所以代码需要符合Js语法,通过DataView提供的对象即可完成相关操作。
```dataviewjs
dv.pages("#thing")
```
以下简单介绍标记语法和Js接口就。详细请见文档
标记语法
在笔记中标记属性
BasicField:: Basic
**BoldField**:: Bold
my mode is [mod:: nice]
以上属性可以通过page.BasicField
和page.BasicField
以及page.mod
访问。
另外page还有以下属性
file.name
: The file title (a string).file.folder
: The path of the folder this file belongs to.file.path
: The full file path (a string).file.link
: A link to the file (a link).file.size
: The size (in bytes) of the file (a number).file.ctime
: The date that the file was created (a date + time).file.cday
: The date that the file was created (just a date).file.mtime
: The date that the file was last modified (a date + time).file.mday
: The date that the file was last modified (just a date).file.tags
: An array of all unique tags in the note. Subtags are broken down by each level, so#Tag/1/A
will be stored in the array as[#Tag, #Tag/1, #Tag/1/A]
.file.etags
: An array of all explicit tags in the note; unlikefile.tags
, does not include subtags.file.inlinks
: An array of all incoming links to this file.file.outlinks
: An array of all outgoing links from this file.file.aliases
: An array of all aliases for the note.file.tasks
: An array of all tasks (I.e.,- [ ] blah blah blah
) in this file.
If the file has a date inside its title (of form yyyy-mm-dd
or yyyymmdd
), or has a Date
field/inline field, it also has the following attributes:
file.day
: An explicit date associated with the file.
任务中也可标记属性。
- Hello, this is some [due::2022-08-15] [mod::fine].
- Get up
- Code [due::2022-08-15] [mod::fine].
- 任务截至时间是当天 [due::2022-03-05] [mod::fine].
- 任务截至时间是昨天 [due::2022-03-04] [mod::fine].
- 任务截至时间是去年 [due::2021-03-04] [mod::fine].
- 任务截至时间是明天 [due::2022-03-06] [mod::fine].
- I finished this on [completion::2022-03-05]. [mod::nice].
可以通过以下方式访问
page.file.tasks.due
page.file.tasks[1].completion
page.file.tasks[0].mod
page.file.tasks[1].mod
As with pages, Dataview adds a number of implicit fields to each task:
- Tasks inherit all fields from their parent page - so if you have a
rating
field in your page, you can also access it on your task. completed
: Whether or not this specific task has been completed; this does not consider the completion/non-completion of any child tasks.fullyCompleted
: Whether or not this task and all of its subtasks are completed.text
: The text of this task.line
: The line this task shows up on.path
: The full path of the file this task is in.section
: A link to the section this task is contained in.link
: A link to the closest linkable block near this task; useful for making links which go to the task.subtasks
: Any subtasks of this task.real
: If true, this is a real task; otherwise, it is a list element above/below a task.completion
: The date a task was completed. If not annotated, will default to file modified time.due
: The date a task is due, if it has one.created
: The date a task was created. If not annotated, defaults to file creation time.annotated
: True if the task has any custom annotations, and false otherwise.
文件寻址
根据标签路径等信息筛选文件
let page = dv.current(); // 当前文件
let pages = dv.pages() // Vault 中所有的文件在
pages = dv.pages("#books") // 所有带标签的文件
pages = dv.pages('"folder"') // 在文件夹中所有的文件,注意引号
pages = dv.pages("#yes or -#no") // 组合筛选
let page_path = dv.pagePaths(); //获取满足筛选要求的所有文件的路径
dv.page("Index") // 单个文件寻址,自动补全后缀
dv.page("books/The Raisin.md") // 单个文件寻址 /books/The Raisin.md
页面渲染
在页面上创建可见的元素
let page_path = dv.pagePaths('"Daily"'); //获取满足筛选要求的所有文件的路径
let pages = dv.pages('"Daily"') ;
let page = dv.current();
dv.el("b", "This is some bold text");
dv.header(1, "Big!");
dv.header(6, "Tiny");
dv.paragraph("This is some text, paragraph");
dv.span("This is some text,span");
dv.paragraph("可以用来调试,简单的显示js变量");
dv.paragraph(page_path);
dv.header(4,"测试标记");
dv.header(4,page.mod);
dv.header(4,page.BasicField);
dv.header(4,page.BoldField);
dv.header(4,page.file.tasks.due);
dv.header(4,page.file.tasks[1].completion);
dv.header(4,page.file.tasks[0].mod);
dv.header(4,page.file.tasks[1].mod);
日期
dv.header(4, "测试日期");
let date1 = dv.date("today");
let date2 = dv.date("2022-03-01");
let dur = (date1 - date2) ;
let dur_day = dur / (1000 * 60 * 60 * 24);
dv.header(3, date1);
dv.header(3, date2);
dv.header(3, "dur_day = " + dur_day );
let date3 = Date("2022/03/02"); // js Date
简单可视化
可以简单的显示list列表,taskList任务,table表格
let page_path = dv.pagePaths('"Daily"'); //获取满足筛选要求的所有文件的路径
let pages = dv.pages('"Daily"') ;
let page = dv.current();
dv.list([1, 2, 3])
dv.list(page_path);
dv.list(pages.file.name);
dv.header(4,"所有文件");
dv.list(pages.file.link);
dv.header(4,"where 筛选 今天之前的文件");
dv.list(pages.file.where(p => ( (p.day - dv.date("today")) /(1000 * 60 * 60 * 24) <0) ).link);
dv.header(4,"where 筛选 今天之前的文件的任务");
dv.taskList(pages.file.where(p => ( (p.day - dv.date("today")) /(1000 * 60 * 60 * 24) <0 ) ).tasks);
dv.header(4,"where 筛选 今天之前的文件的未完成任务");
dv.taskList(pages.file.where(p => ( (p.day - dv.date("today")) /(1000 * 60 * 60 * 24) <0 ) ).tasks.where(t => !t.completed));
dv.header(4,"任务计数");
let task_num = page.file.tasks.length;
dv.header(4, "task_num = " + task_num);
let unfinished_tak_num = page.file.tasks.where(t=> !t.completed).length
dv.header(4, "unfinished_tak_num = " + unfinished_tak_num);
let unfinished_task_with_due_num =page.file.tasks.where(t=> !t.completed && t.due ).length
dv.header(4, "unfinished_task_with_due_num = " + unfinished_task_with_due_num);
let fail_task_num = page.file.tasks.where(t=> !t.completed && t.due && t.due < dv.date("today")).length;
dv.header(4, "fail_task_num = " + fail_task_num);
dv.taskList(page.file.tasks.where(t=> !t.completed && t.due && t.due < dv.date("today")));
dv.taskList(page.file.tasks.where(t=> !t.completed && t.due && ((t.due - dv.date("today") )/(1000 * 60 * 60 * 24)===0 ) ));
dv.taskList(page.file.tasks.where(t=> !t.completed && t.due && ((t.due - dv.date("today") )/(1000 * 60 * 60 * 24)>0 ) ));
复杂例子统计任务完成情况
let page = dv.pages('"Daily"');
let task = page.file.tasks;
let all_unfinished_task_num = task.where(t => !t.completed).length;
let all_unfinished_due_task = task.where(t => !t.completed && t.due
&& t.due < dv.date("today"));
let all_unfinished_due_task_num = all_unfinished_due_task.length;
let all_unfinished_todue_task = task.where(t => !t.completed && t.due
&& t.due >= dv.date("today")).sort(t => t.due);
let all_unfinished_todue_task_num = all_unfinished_todue_task.length;
let task_in_5_day = all_unfinished_todue_task.where(t=> !t.completed && t.due && (((t.due - dv.date("today") )/(1000 * 60 * 60 * 24))<5 ) ).sort(t => t.due)
;
let task_in_30_day = all_unfinished_todue_task.where(t=> !t.completed && t.due && (((t.due - dv.date("today") )/(1000 * 60 * 60 * 24))<30 ) ).sort(t => t.due)
;
let task_beyond_30_day = all_unfinished_todue_task.where(t=> !t.completed && t.due && (((t.due - dv.date("today") )/(1000 * 60 * 60 * 24))>30 ) )
;
dv.table(["历史未完成任务","超期任务","待办任务"],[[all_unfinished_task_num,all_unfinished_due_task_num,all_unfinished_todue_task_num]]);
dv.header(1,"超期任务");
dv.taskList(
all_unfinished_due_task
);
dv.header(1,"5天内待办任务");
dv.taskList(
task_in_5_day
);
dv.header(1,"30天内待办任务");
dv.taskList(
task_in_30_day
);
dv.header(1,"超过30天内待办任务");
dv.taskList(
task_beyond_30_day
);
ChartsView
饼状图
可以简单的给定一个字典组成的数组,字典的key需要与options中的field对应。
```chartsview
#-----------------#
#- chart type -#
#-----------------#
type: Pie
#-----------------#
#- chart data -#
#-----------------#
data:
- type: "Wage income per capita (¥)"
value: 17917
- type: "Operating net income per capita (¥)"
value: 5307
- type: "Property Per Capita Net Income (¥)"
value: 2791
- type: "Transfer of net income per capita (¥)"
value: 6173
#-----------------#
#- chart options -#
#-----------------#
options:
angleField: "value"
colorField: "type"
radius: 0.5
label:
type: "spider"
content: "{percentage}\n{name}"
legend:
layout: "horizontal"
position: "bottom"
```
也可以与DataView结合使用。
#-----------------#
#- chart type -#
#-----------------#
type: Pie
#-----------------#
#- chart data -#
#-----------------#
data: |
dataviewjs:
let table = [{type : "good",value:12},{type : "bad",value:4}];
return table;
#-----------------#
#- chart options -#
#-----------------#
options:
angleField: "value"
colorField: "type"
radius: 0.5
label:
type: "spider"
content: "{percentage}\n{name}"
legend:
layout: "horizontal"
position: "bottom"
条行图
与DataView生成文件数量统计的条行图。
#-----------------#
#- chart type -#
#-----------------#
type: Column
#-----------------#
#- chart data -#
#-----------------#
data: |
dataviewjs:
return dv.pages()
.groupBy(p => p.file.folder)
.map(p => ({folder: p.key || "ROOT", count: p.rows.length}))
.array();
#-----------------#
#- chart options -#
#-----------------#
options:
xField: "folder"
yField: "count"
padding: auto
label:
position: "middle"
style:
opacity: 0.6
fontSize: 12
columnStyle:
fillOpacity: 0.5
lineWidth: 1
strokeOpacity: 0.7
shadowColor: "grey"
shadowBlur: 10
shadowOffsetX: 5
shadowOffsetY: 5
xAxis:
label:
autoHide: false
autoRotate: true
meta:
count:
alias: "Count"