用 Notion 做一份课程表
summary
用看板视图,将课程表与课程数据库相关联,还可实现单双周。快来收下用 Notion 做一份课程表的模板和指南。
tags
Notion
Example
Tip
date
Sep 11, 2021
Chinese version
English version
如何用 Notion 做一份课程表?你可以用表格视图,每一列分别是星期一、星期二、星期三……但如果涉及单双周或者需要关联,就比较麻烦了。这里介绍一种看板视图的实现方法,将课程表与课程数据库相关联,还可实现单双周。涉及了不少有趣的小技巧,相信看完一定会有收获~
效果展示
课程 + 课程表 两个数据库关联,设定简单,可实现单双周。更多图片:
想使用这个课程表,请 duplicate 以下页面到自己的工作区,然后参照页内使用说明操作。
Notion 课程表模板 by Niin想了解更多原理,请对照模板继续阅读。
结构说明
- 由 课程 + 课程表 两个数据库相互关联组成。在课程表中添加每个时间段有哪些课程,以及单双周情况,在课程数据库中也可以显示每门课程分别在单双周哪几个时间段上课。
- 为什么不用每一列分别是星期一、星期二、星期三……的表格视图已在开头说明,不易关联课程数据库和实现单双周效果。相比而言,使用看板视图时,每天的每个时间段都对应一个条目,可以进行全局的设定。
数据库属性说明
以下无特殊说明均为课程表数据库中属性:
星期
:星期几如何按“一、二、三、四……”不按字典顺序排序?一般的文本属性排序时,会按字母表进行字典排序,但根据单选属性排序时,顺序由单选属性的选择面板决定,可以自己上下拖动。
节数
:这里用了数字属性。为什么不把节数放在标题列,用 formula 获取数字呢?因为数据库制作过程涉及 duplicate,标题的属性会变成 "Copy of ...",遂直接标题留空。如果觉得留空不舒服,也可以 formula 得到星期几第几节,复制到标题,但其实没有必要。
上课时间
:根据事先填入的 时间文本
和 节数
得到这节课对应的时间段值。用到正则,先在最前面加一个 ","
代表首项为空,然后去除前 n 项 "^(.*?,){" + format(prop("节数")) + "}"
,再去除首项后内容 ",.*$"
,这样超过范围时会为空。另外增加去除空格,增强鲁棒性。
replaceAll(replace(replace("," + prop("时间文本"), "^(.*?,){" + format(prop("节数")) + "}", ""), ",.*$", ""), " ", "")
显示
:checkbox 指示条目是否需要,一方面根据时间段个数,另一方面可更改函数选择是否需要星期六和星期日。时间段个数通过 ,
个数 +1 获得,即 length(replaceAll(prop("时间文本"), "[^,]", "")) + 1
,为增加鲁棒性,考虑最后也加了逗号的情况,将 +1 修改为 + ((slice(prop("时间文本"), length(prop("时间文本")) - 1) == ",") ? 0 : 1)
。
prop("节数") <= length(replaceAll(prop("时间文本"), "[^,]", "")) + ((slice(prop("时间文本"), length(prop("时间文本")) - 1) == ",") ? 0 : 1) and prop("星期") != "星期六" and prop("星期") != "星期日"
单周的课
&双周的课
:对于一个特定时间段,单双周的情况可分为:每周相同课,只在单周或双周有课,单双周不同课。这两个 formula 区别只在于一个单
和双
,还有一个$1
和$2
。- 每周相同课:不做特殊处理;
- 只在单周或双周有课:在另一情况下不显示该课程;
- 单双周不同课:最难处理的情况。判断方法为关联了两个课程,即
课程
属性含有,
。但如果课程名称中含有英文逗号,结果就可能出错。因此我在课程数据库中增加了课程加符号
属性,先给每个课程加上了<>
,再正则匹配"^<(.+?)>,<(.+?)>$"
,就不容易出问题了(注意 rollup 的结果中,逗号后无空格)。此时单双周的课程分别为$1
和$2
。 - PS:为什么没课时显示一个空格而不是留空?如果留空,当为每格增加显示其他属性(如上课时间)时,每格的高度会不同,导致错位。如果没有这个需求,且希望看板视图中,每一列右上角显示当天课程数,可以在 formula 中改为留空,将右上角属性设定为
Count not empty
。
相关 formula
"<" + prop("课程") + ">"
prop("星期") ? ((prop("只单/双周") == "双周") ? " " : (prop("课程") ? (test(prop("课程加符号"), "^<(.+?)>,<(.+?)>$") ? replace(prop("课程加符号"), "^<(.+?)>,<(.+?)>$", "$1") : prop("课程")) : " ")) : prop("上课时间")
prop("星期") ? ((prop("只单/双周") == "单周") ? " " : (prop("课程") ? (test(prop("课程加符号"), "^<(.+?)>,<(.+?)>$") ? replace(prop("课程加符号"), "^<(.+?)>,<(.+?)>$", "$2") : prop("课程")) : " ")) : prop("上课时间")
本周的课
: formatDate(now(), "w")
获取现在是今年第几周,再间隔显示单双周课表。因此需要初始设定除以 2 的余数为 0
或 1
。
(1 == toNumber(formatDate(now(), "w")) % 2) ? prop("单周的课") : prop("双周的课")
星期加节数
:是为了在课程数据库中显示该课在单/双/每周星期几第几节上课。还是上述的三种情况,前两种都简单,第三种由于单双周课程不同,不能简单的返回单周或双周,因此返回 "<$1>单周<$2>双周"
,再在课程数据库的 上课日期节数
中,分别替换所有 "<" + prop("课程") + ">单周<.+?>双周"
为 "单周"
, "<.+?>单周<" + prop("课程") + ">双周"
为 "双周"
。
(test(prop("课程加符号"), "^<(.+?)>,<(.+?)>$") ? replace(prop("课程加符号"), "^<(.+?)>,<(.+?)>$", "<$1>单周<$2>双周") : (prop("只单/双周") ? prop("只单/双周") : "每周")) + prop("星期") + "第" + format(prop("节数")) + "节"
replaceAll(replaceAll(replaceAll(prop("上课日期节数获取"), "<" + prop("课程") + ">单周<.+?>双周", "单周"), "<.+?>单周<" + prop("课程") + ">双周", "双周"), ",", ", ")
节数中文
:可以把阿拉伯数字 1~99 转为汉字。在模板中其实没有用到,但如果你想让节数显示为中文,可以把 星期加节数
中的 prop("节数")
改成 prop("节数中文")
,可以更规整。原理: slice("一二三四五六七八九", prop("节数") - 1, prop("节数"))
,20 及以上的取十位 + 10及以上的含 "十"
+ 所有数字都有个位。
((prop("节数") >= 20) ? slice("x二三四五六七八九", floor(prop("节数")) / 10 - 1, floor(prop("节数")) / 10) : "") + ((prop("节数") >= 10) ? "十" : "") + slice("一二三四五六七八九", (prop("节数") - 1) % 10, prop("节数") % 10)
空文件
:为了隐藏看板视图下的标题。因为如果想关闭看板视图下的标题属性,需要开启 Card preview,由于不想每个卡片高度太大,因此把 Card preview 的内容设定为一个空的文件属性,就可以不显示 preview 了。
用到的正则表达式
^
:匹配开头(在方括号表达式中表示不匹配表达式内字符集合,如[^,]
表示不匹配,
)
$
:匹配结尾
.
:匹配任意字符(除换行)
+
:匹配一次或多次前述表达式
*
:匹配零次或多次前述表达式
?
:匹配零次或一次前述表达式(接在+
或*
后面表示非贪婪即最小匹配)
{n}
:匹配 n 次前述表达式
(...)
:捕获匹配的分组,可在结果中用$1
,$2
…… 表示第一、二……组来使用
除以上这些外,
, < >
等都是字符正常的含义。