Dataviewjs的奇技淫巧

感谢大佬详尽教学,想请问大佬这「呈现」上有没有可能用 JS 实现? :sweat_smile:

●情境:
人员 A 和 B 针对不同的案子有不同的负责内容,
在有多个案子的状况下,希望有一区块能一次呈现人员负责的工作内容分别是哪些案子。

●YAML的纪录方式:
案子 : 旺旺牛奶
人员A : 撰写文章、制作推图
人员B : 文章排版

●呈现:希望案子是像下面这样集合在一个栏内,而不是每个案子都必须一列一列地显示,并且每个案子之间能自动用 " 、" 分开。

人员 A

工作内容 案子
撰写文章 旺旺牛奶、晶晶果冻
撰写推文 花花洗发水
制作推图 旺旺牛奶、花花洗发水

人员 B

工作内容 案子
文章排版 旺旺牛奶

这样应该可以

```dataviewjs
let files = dv.pages().filter(p=>p.案子)
for(let i=0;i<26;i++) {
	let field = '人员'+String.fromCharCode(65+i)
	let d={}
	files.forEach(file=>file[field]?.split('、').forEach(p=>d[p]?d[p].push(file.案子):d[p]=[file.案子]))
	if(Object.keys(d)==0) continue
	dv.header(2,field)
	dv.table(
		['工作内容','案子'],
		Object.entries(d).map(p=>[p[0],p[1].join('、')])
	)
}
```
1 个赞

感谢大佬, 有成功实现!但不好意思前面没有讲清楚
我本来想试着自己改改看,但JS实在太难了…TT

●想调整最终呈现效果是这样:
(人员的名字不是规律性,抱歉我范例没有做好)

【文章 A 的 yaml】
案子 : 旺旺牛奶
陈小明 : 撰写文章、制作推图
王阿娇 : 文章排版

【文章 B 的 Dataviewjs 呈现】

陈小明

工作内容 案子
撰写文章 旺旺牛奶、晶晶果冻
撰写推文 花花洗发水
制作推图 旺旺牛奶、花花洗发水

(这里中间还需要安插其他东西,所以不同人员希望是分两块 dataviewjs 代码块)

王阿娇

工作内容 案子
文章排版 旺旺牛奶



【并想加问可能增加这 1 个功能吗】
呈现表格上的「案子」内容(即旺旺牛奶等),可能自动带入文章连结吗?在 dataview 上可以使用 link(file.link, 案子),但 JS 不知道怎么转换?

好吧, 看来是我搞错了,按你新发的帖子重写了一下

```dataviewjs
let files = dv.pages().filter(p=>p.菜名)
console.log(files)
let d=[]
for(let p of files) {
	p.file.link.display=p.菜名
	d.push({link:p.file.link,name:p.菜名,非常喜欢:p?.非常喜欢,不喜欢:p?.不喜欢})
}
let target = '陈大'
dv.header(2,target+'饮食喜好表')
dv.table(
	['程度','菜名'],
	[['非常喜欢',d.map(p=>{if(p.非常喜欢?.split('、').includes(target)) return p.link}).filter(p=>p).join('、')],
	 ['不喜欢',d.map(p=>{if(p.不喜欢?.split('、').includes(target)) return p.link}).filter(p=>p).join('、')]]
)
```
1 个赞

感谢大佬一次解决我两个需求! :joy: :joy: :joy:
将两组代码对照调整了一下,上面「案子类」需求也解决了!

只是带入连结的那段琢磨不懂,另外找了一种写法

```dataviewjs
let files = dv.pages().filter(p=>p.案子)
for(let i=0;i<1;i++) {
	let field = '陈小明'
	let d={}
	files.forEach(file=>file[field]?.split('、').forEach(p=>d[p]?d[p].push("[[" + file.file.path + "|" + file.案子 + "]]"):d[p]=["[[" + file.file.path + "|" + file.案子 + "]]"]))
	if(Object.keys(d)==0) continue
	dv.header(2,field)
	dv.table(
		['工作内容','案子'],
		Object.entries(d).map(p=>[p[0],p[1].join('、')])
	)
}

请教题主,能否使用dataview实现块状内容的聚合并且将这些内容进行排列,类似于gallery视图那样,具体的效果图就是这样

请教下,笔记的yaml写成如下,能正常返回数据

file:菜名: 麻辣猪蹄
非常喜欢: 小明
不喜欢: 二狗

但“非常喜欢”似乎不能有多个值,例如写成 非常喜欢: 小明,小华 ,就不会返回数据。

请问有解决办法吗?

你是想用上面的代码吗,那个代码是用 分割的

请问表格的样式是怎么设置的?我的表格样式还是默认的

大佬,请问一下 dataviewjs 能不能查询出当前笔记中所有高亮的内容呢?

```dataviewjs
//定义一个函数,接受一个markdown字符串作为参数
function extractHighlight(markdown) {
  //定义一个空数组,用来存放高亮部分
  let highlights = [];
  //定义一个正则表达式,匹配被==包裹的部分
  let regex = /==(.+?)==/g;
  //定义一个变量,用来存放正则表达式的匹配结果
  let match;
  //使用循环,遍历所有的匹配结果
  while (match = regex.exec(markdown)) {
    //把匹配结果中的第一个捕获组(也就是高亮部分)添加到数组中
    highlights.push(match[1]);
  }
  //返回数组
  return highlights.filter(p=>p!='(.+?)');
}

dv.list(extractHighlight(await app.vault.readRaw(dv.current().file.path)))
```

提一嘴,你敢相信上面那个函数是 newbing 生成的吗 :joy:,太离谱了

谢谢!确实可以诶!
new bing有点强,相比之下chatGPT就显得跟智障一样,这是它给我的回答 :joy:

那确实没办法,chatgpt 的资料好像到 2021 还是 2022 年就停止了,还不能联网,newbing 还是基于 chatgpt 呢。
以下是 newbing 的回答,真的是强的离谱

Obsidian是一个笔记软件,Dataview是Obsidian的一个社区插件,可以用来查询和展示笔记中的元数据。Dataview有两种查询语法:Dataview Query Language (DQL) 和 DataviewJS。DQL是一种简单的语言,可以用来筛选和排序笔记。DataviewJS是一种基于JavaScript的语言,可以用来编写更复杂的查询和自定义视图。

DQL的基本格式是:

TABLE|LIST|TASK [columns]
FROM [files]
WHERE [filter]
SORT BY [field] ASC|DESC

其中:

  • TABLELISTTASK 是三种不同的视图类型,分别显示表格、列表和任务。
  • [columns] 是要显示的字段或表达式,用逗号分隔。
  • [files] 是要查询的文件范围,可以是文件夹、标签或其他条件。
  • [filter] 是要应用的过滤条件,可以使用逻辑运算符(如 ANDORNOT)和比较运算符(如 =<>)组合字段或表达式。
  • [field] 是要排序的字段或表达式,可以有多个,用逗号分隔。
  • ASC|DESC 是升序或降序的标志。

例如,如果你想查询所有标签为 #book 的笔记,并按照评分降序显示标题和作者,你可以写:

TABLE file.name as Title, author as Author
FROM #book
SORT BY rating DESC

如果你想查询所有包含未完成任务的笔记,并按照创建日期升序显示标题和任务内容,你可以写:

TASK file.name as Title, task as Task
WHERE contains(tasks, t -> !t.completed)
SORT BY file.ctime ASC

更多关于DQL的信息,请参考¹ 和²。

DataviewJS的基本格式是:

// JavaScript code to query and display data

其中:

  • 你可以使用 dv.pages() 函数来获取所有或部分笔记的元数据对象。
  • 你可以使用 JavaScript 的数组方法(如 filter()map()sort())来处理数据。
  • 你可以使用 dv.table()dv.list()dv.taskList() 函数来显示不同类型的视图。
  • 你可以使用 Luxon 库中的 DateTime 对象和函数来处理日期时间数据。

例如,如果你想查询所有标签为 #movie 的笔记,并按照评分降序显示标题和导演,并且对于评分高于 8 的电影,在标题后面加上一个爱心符号:heart: ,你可以写:

let movies = dv.pages("#movie");
movies.sort((a, b) => b.rating - a.rating);
let rows = movies.map(m => [
  m.rating > 8 ? `${m.file.name} ❤️ ` : m.file.name,
  m.director
]);
dv.table(["Title", "Director"], rows);

更多关于DataviewJS的信息,请参考¹ 和³。

源: 与必应的对话, 2023/2/25(1) How to get started with Obsidian Dataview and DataviewJS. How to get started with Obsidian Dataview and DataviewJS | by Jacqui Read | OS TechBlog | Medium 访问时间 2023/2/25.
(2) DataView Query for tasks with certain tag - Resolved help - Obsidian Forum. DataView Query for tasks with certain tag - Resolved help - Obsidian Forum 访问时间 2023/2/25.
(3) Dataview Date Formatting - Resolved help - Obsidian Forum. Dataview Date Formatting - Resolved help - Obsidian Forum 访问时间 2023/2/25.

明白了,谢谢。不过我现在想实现下述需求,例如:小明(名字以外的描述性文字)、小华(名字以外的描述性文字)
请问应该怎样修改代码呢?

大佬,这个JS代码渲染的内容导出时总是一片空白,能出手帮忙解决下不?我水平有限,实在无能为力

```dataviewjs
const files = app.vault.getMarkdownFiles()
.filter(p=>p.parent.path.includes(""))		//目标路径,例如A/B
.filter(p=>p.name.includes(""))		//目标文件名
.sort(function(x,y){return y.stat.mtime-x.stat.mtime})		//按修改时间降序排列,升序请改成:.sort(function(x,y){return x.stat.mtime-y.stat.mtime}),即:直接直接对调xy的位置
const prompt = "关键词A"
const prompt2 = "关键词B"

const fileObject = files.map(async (file) => {
const fileLink = "[["+file.name.split(".")[0]+"]]"
const content = await app.vault.cachedRead(file)
return {fileLink, content}
})

Promise.all(fileObject).then(files => {

let values = new Set(files.reduce((acc, file) => {
const lines = file.content.split("\n").filter(line => line.match(new RegExp(prompt, "i")) || line.match(new RegExp(prompt2, "i")))
if (lines[0] && !file.fileLink.includes("啊啊啊") && !file.fileLink.includes("模板-") && !file.fileLink.includes("啊啊啊2") && !file.fileLink. includes("测试") && !file.fileLink.includes("测试2")) {
if (acc[0]) {
return [...acc, [file.fileLink, lines.join("\n")]]
} else {
return [[file.fileLink, lines.join("\n")]]
}
}
return acc
}, []))

dv.header(2, prompt)
dv.table(["file", "所在行"], Array.from(values))
})
```

额,我有点没看懂这是做什么的

按关键词提取 关键词所在行内容 并汇总成表格

```dataviewjs
let files = dv.pages('#目录')
extractKeywords(['复数'],files)

async function extractKeywords(keywordArr,files) {
	let values = []
	for(let file of files) {
		let content = (await app.vault.readRaw(file.file.path)).split('\n')
		keywordArr.forEach((k)=>{
			content.filter(p=>p.includes(k))
				   ?.forEach(p=>values.push([file.file.link,p.trim()]))
		})
	}
	dv.table(["file", "所在行"], values)
}
```

问题是什么啊:heart_eyes::heart_eyes: