【Dataview View】表格样式

简介

我将 Excel 中自带的表格样式(好像是 60 种)弄到 Obsidian 中了,用起来还不错。而且可以任意选择样式,甚至同一篇笔记中的多个表格分别使用不同的样式。

不算十分完美,但足够满足日常。

样式

TableStyle

安装

首先建立一个文件夹,名为 TableStyle,将如下代码保存为 view.js 文件放入刚才的文件夹中。

/**
 * 表格样式
 * @author: 稻米鼠
 * @description: 动态调用多种表格样式
 * @created: 2024-05-20
 * @updated: 2024-05-20
 * @version: 0.0.1
 */

/** 表格样式数据
 * @type {object} 
 * @description 内部数据依次为:
 * color, hdColor, bdColor, bgColor, hdBgColor, outBdWidth, hdBorderWidth, trBorderWidth, tdBorderWidth, altBgColor, hoverBgColor
 */
const TableStyle = {"Light-1-1":["#000","#000","#000","none","none",0,"3px",0,0,"#D9D9D9","rgba(255, 206, 100, 0.2)"],"Light-1-2":["#305496","#305496","#485DB1","none","none",0,"3px",0,0,"#D9E1F2","rgba(255, 206, 100, 0.2)"],"Light-1-3":["#C65911","#C65911","#ED7D31","none","none",0,"3px",0,0,"#FCE4D6","rgba(255, 206, 100, 0.2)"],"Light-1-4":["#7B7B7B","#7B7B7B","#A5A5A5","none","none",0,"3px",0,0,"#EDEDED","rgba(255, 206, 100, 0.2)"],"Light-1-5":["#BF8F00","#BF8F00","#FFC000","none","none",0,"3px",0,0,"#FFF2CC","rgba(255, 206, 100, 0.2)"],"Light-1-6":["#2F75B5","#2F75B5","#5B9BD5","none","none",0,"3px",0,0,"#DDEBF7","rgba(255, 206, 100, 0.2)"],"Light-1-7":["#548235","#548235","#70AD47","none","none",0,"3px",0,0,"#E2EFDA","rgba(255, 206, 100, 0.2)"],"Light-2-1":["#000","#FFF","#000","none","#000","3px",0,"2px",0,"none","rgba(255, 206, 100, 0.2)"],"Light-2-2":["#000","#FFF","#485DB1","none","#485DB1","3px",0,"2px",0,"none","rgba(255, 206, 100, 0.2)"],"Light-2-3":["#000","#FFF","#ED7D31","none","#ED7D31","3px",0,"2px",0,"none","rgba(255, 206, 100, 0.2)"],"Light-2-4":["#000","#FFF","#A5A5A5","none","#A5A5A5","3px",0,"2px",0,"none","rgba(255, 206, 100, 0.2)"],"Light-2-5":["#000","#FFF","#FFC000","none","#FFC000","3px",0,"2px",0,"none","rgba(255, 206, 100, 0.2)"],"Light-2-6":["#000","#FFF","#5B9BD5","none","#5B9BD5","3px",0,"2px",0,"none","rgba(255, 206, 100, 0.2)"],"Light-2-7":["#000","#FFF","#70AD47","none","#70AD47","3px",0,"2px",0,"none","rgba(255, 206, 100, 0.2)"],"Light-3-1":["#000","#000","#000","none","none","3px",0,0,"2px","#D9D9D9","rgba(255, 206, 100, 0.2)"],"Light-3-2":["#000","#000","#485DB1","none","none","3px",0,0,"2px","#D9E1F2","rgba(255, 206, 100, 0.2)"],"Light-3-3":["#000","#000","#ED7D31","none","none","3px",0,0,"2px","#FCE4D6","rgba(255, 206, 100, 0.2)"],"Light-3-4":["#000","#000","#A5A5A5","none","none","3px",0,0,"2px","#EDEDED","rgba(255, 206, 100, 0.2)"],"Light-3-5":["#000","#000","#FFC000","none","none","3px",0,0,"2px","#FFF2CC","rgba(255, 206, 100, 0.2)"],"Light-3-6":["#000","#000","#5B9BD5","none","none","3px",0,0,"2px","#DDEBF7","rgba(255, 206, 100, 0.2)"],"Light-3-7":["#000","#000","#70AD47","none","none","3px",0,0,"2px","#E2EFDA","rgba(255, 206, 100, 0.2)"],"Normal-1-1":["#000","#FFF","#000","none","#000","3px",0,"2px",0,"#D9D9D9","rgba(255, 206, 100, 0.2)"],"Normal-1-2":["#000","#FFF","#485DB1","none","#485DB1","3px",0,"2px",0,"#D9E1F2","rgba(255, 206, 100, 0.2)"],"Normal-1-3":["#000","#FFF","#ED7D31","none","#ED7D31","3px",0,"2px",0,"#FCE4D6","rgba(255, 206, 100, 0.2)"],"Normal-1-4":["#000","#FFF","#A5A5A5","none","#A5A5A5","3px",0,"2px",0,"#EDEDED","rgba(255, 206, 100, 0.2)"],"Normal-1-5":["#000","#FFF","#FFC000","none","#FFC000","3px",0,"2px",0,"#FFF2CC","rgba(255, 206, 100, 0.2)"],"Normal-1-6":["#000","#FFF","#5B9BD5","none","#5B9BD5","3px",0,"2px",0,"#DDEBF7","rgba(255, 206, 100, 0.2)"],"Normal-1-7":["#000","#FFF","#70AD47","none","#70AD47","3px",0,"2px",0,"#E2EFDA","rgba(255, 206, 100, 0.2)"],"Normal-2-1":["#000","#FFF","#FFF","#D9D9D9","#000","3px",0,0,"2px","#A6A6A6","rgba(255, 206, 100, 0.2)"],"Normal-2-2":["#000","#FFF","#FFF","#D9E1F2","#485DB1","3px",0,0,"2px","#B4C6E7","rgba(255, 206, 100, 0.2)"],"Normal-2-3":["#000","#FFF","#FFF","#FCE4D6","#ED7D31","3px",0,0,"2px","#F8CBAD","rgba(255, 206, 100, 0.2)"],"Normal-2-4":["#000","#FFF","#FFF","#EDEDED","#A5A5A5","3px",0,0,"2px","#DBDBDB","rgba(255, 206, 100, 0.2)"],"Normal-2-5":["#000","#FFF","#FFF","#FFF2CC","#FFC000","3px",0,0,"2px","#FFE699","rgba(255, 206, 100, 0.2)"],"Normal-2-6":["#000","#FFF","#FFF","#DDEBF7","#5B9BD5","3px",0,0,"2px","#BDD7EE","rgba(255, 206, 100, 0.2)"],"Normal-2-7":["#000","#FFF","#FFF","#E2EFDA","#70AD47","3px",0,0,"2px","#C6E0B4","rgba(255, 206, 100, 0.2)"],"Normal-3-1":["#000","#FFF","#000","none","#000","3px",0,0,"2px","#D9D9D9","rgba(255, 206, 100, 0.2)"],"Normal-3-2":["#000","#FFF","#000","none","#485DB1",0,"3px",0,0,"#D9E1F2","rgba(255, 206, 100, 0.2)"],"Normal-3-3":["#000","#FFF","#000","none","#ED7D31",0,"3px",0,0,"#FCE4D6","rgba(255, 206, 100, 0.2)"],"Normal-3-4":["#000","#FFF","#000","none","#A5A5A5",0,"3px",0,0,"#EDEDED","rgba(255, 206, 100, 0.2)"],"Normal-3-5":["#000","#FFF","#000","none","#FFC000",0,"3px",0,0,"#FFF2CC","rgba(255, 206, 100, 0.2)"],"Normal-3-6":["#000","#FFF","#000","none","#5B9BD5",0,"3px",0,0,"#DDEBF7","rgba(255, 206, 100, 0.2)"],"Normal-3-7":["#000","#FFF","#000","none","#70AD47",0,"3px",0,0,"#E2EFDA","rgba(255, 206, 100, 0.2)"],"Normal-4-1":["#000","#000","#000","#D9D9D9","#D9D9D9","3px",0,0,"2px","#A6A6A6","rgba(255, 206, 100, 0.2)"],"Normal-4-2":["#000","#000","#8EA9DB","#D9E1F2","#D9E1F2","3px",0,0,"2px","#B4C6E7","rgba(255, 206, 100, 0.2)"],"Normal-4-3":["#000","#000","#F4B084","#FCE4D6","#FCE4D6","3px",0,0,"2px","#F8CBAD","rgba(255, 206, 100, 0.2)"],"Normal-4-4":["#000","#000","#C9C9C9","#EDEDED","#EDEDED","3px",0,0,"2px","#DBDBDB","rgba(255, 206, 100, 0.2)"],"Normal-4-5":["#000","#000","#FFD966","#FFF2CC","#FFF2CC","3px",0,0,"2px","#FFE699","rgba(255, 206, 100, 0.2)"],"Normal-4-6":["#000","#000","#9BC2E6","#DDEBF7","#DDEBF7","3px",0,0,"2px","#BDD7EE","rgba(255, 206, 100, 0.2)"],"Normal-4-7":["#000","#000","#A9D08E","#E2EFDA","#E2EFDA","3px",0,0,"2px","#C6E0B4","rgba(255, 206, 100, 0.2)"],"Dark-1-1":["#FFF","#FFF","#FFF","#737373","#000",0,"3px",0,0,"#404040","rgba(255, 206, 100, 0.2)"],"Dark-1-2":["#FFF","#FFF","#FFF","#4472C4","#000",0,"3px",0,0,"#305496","rgba(255, 206, 100, 0.2)"],"Dark-1-3":["#FFF","#FFF","#FFF","#ED7D31","#000",0,"3px",0,0,"#C65911","rgba(255, 206, 100, 0.2)"],"Dark-1-4":["#FFF","#FFF","#FFF","#A5A5A5","#000",0,"3px",0,0,"#7B7B7B","rgba(255, 206, 100, 0.2)"],"Dark-1-5":["#FFF","#FFF","#FFF","#FFC000","#000",0,"3px",0,0,"#BF8F00","rgba(255, 206, 100, 0.2)"],"Dark-1-6":["#FFF","#FFF","#FFF","#5B9BD5","#000",0,"3px",0,0,"#2F75B5","rgba(255, 206, 100, 0.2)"],"Dark-1-7":["#FFF","#FFF","#FFF","#70AD47","#000",0,"3px",0,0,"#548235","rgba(255, 206, 100, 0.2)"],"Dark-2-1":["#000","#FFF","#000","#D9D9D9","#000",0,0,0,0,"#A6A6A6","rgba(255, 206, 100, 0.2)"],"Dark-2-2":["#000","#FFF","#000","#D9E1F2","#ED7D31",0,0,0,0,"#B4C6E7","rgba(255, 206, 100, 0.2)"],"Dark-2-3":["#000","#FFF","#000","#EDEDED","#FFC000",0,0,0,0,"#DBDBDB","rgba(255, 206, 100, 0.2)"],"Dark-2-4":["#000","#FFF","#000","#DDEBF7","#70AD47",0,0,0,0,"#BDD7EE","rgba(255, 206, 100, 0.2)"]}

/** Dataview 视图的配置
 * @type {object}
 * @property {string} style - 风格名称
 */
const config = Object.assign({
  style: 'Light-1-1',
  table: 'next'   // next | all
}, input)

/** 表格类名
 * @type {string}
 */
const tableClass = `DMS-Table-Style-${config.style}-${crypto.randomUUID().split('-')[0]}`

/** @type {array} 当前样式 */
const thisTableStyle = TableStyle[config.style]
// 样式前缀
const prefix = config.table == 'next' ? ` table.${tableClass}` : `.${tableClass} table` 

dv.container.innerHTML = `<style>
/* ======== ${config.style} ======== */
${prefix} {
  /* 便于修改的变量 */
  --table-text-color:              ${thisTableStyle[0] }; /* 表格文字颜色 */
  --table-header-color:            ${thisTableStyle[1] }; /* 表头文字颜色 */
  --set-table-border-color:        ${thisTableStyle[2] }; /* 表格边框颜色 */
  --table-background:              ${thisTableStyle[3] }; /* 表格的背景色 */
  --table-header-background:       ${thisTableStyle[4] }; /* 表头的背景色 */
  --set-table-out-border-width:    ${thisTableStyle[5] }; /* 表格外边框宽度 */
  --set-table-header-border-width: ${thisTableStyle[6] }; /* 表头和底部边框宽度 */
  --set-table-tr-border-width:     ${thisTableStyle[7] }; /* 行底部边框宽度 */
  --table-border-width:            ${thisTableStyle[8] }; /* 单元格边框宽度 */
  --table-row-alt-background:      ${thisTableStyle[9] }; /* 用来差别现实的奇偶行(列)的别景色 */
  --table-row-background-hover:    ${thisTableStyle[10]}; /* 鼠标悬停的行背景色 */
  --table-row-alt-background-hover:${thisTableStyle[10]}; /* 鼠标悬停的行背景色 */
  --table-header-background-hover: ${thisTableStyle[4] }; /* 鼠标悬停的表头背景色 */
  /* 系统主题自带设定 */
  --border-color: var(--set-table-border-color);                       /* 外边框颜色 */
  --line-height-tight: 1.2rem;                                         /* 表头的行高 */
  --size-2-2: .5em;                                                    /* 单元格上下内补 */
  --size-4-2: 1em;                                                     /* 单元格左右内补 */
  --table-border-color: var(--set-table-border-color);                 /* 内边框颜色 */
  --table-column-alt-background: none;                                 /* 偶数列的背景颜色 */
  --table-column-first-border-width: 0;                                /* 第一列左侧边框宽度 */
  --table-column-last-border-width: 0;                                 /* 最后一列右侧边框宽度 */
  --table-column-max-width: none;                                      /* 单元格最大宽度 */
  --table-header-border-color: var(--set-table-border-color);          /* th 的边框颜色 */
  --table-header-border-width: var(--set-table-header-border-width);   /* th 的顶部边框宽度 */
  --table-header-font: inherit;                                        /* th 的字体 */
  --table-header-size: 1rem;                                           /* th 的字体大小 */
  --table-header-weight: bold;                                         /* th 的字体宽度 */
  --table-row-last-border-width: var(--set-table-header-border-width); /* 最后一行单元格底部的边框宽度 */
  --table-text-size: 1rem;                                             /* 表格文字大小 */
  --table-white-space: normal;                                         /* 单元格内空白处理方式 */
}
/* 使表格外边框宽度可设定 */
${prefix} {
  border: var(--set-table-out-border-width) solid var(--border-color);
  border-collapse: collapse;
}
/* 行底部边框宽度 */
${prefix} > tbody > tr {
  border: 0 solid var(--set-table-border-color);
  border-bottom-width: var(--set-table-tr-border-width);
}
${prefix} >tbody > tr:last-child {
  border-bottom-width: 0;
}
/* 表头底部边框宽度 */
${prefix} th {
  border-bottom-width: var(--table-header-border-width);
}</style>

<small style="font-size: 10px; text-align: center; opacity: .3;">[---------- Table Style ${config.style} ----------]</small>`

/** 查找下一个表格
 *
 * @param {HTMLElement} currentElement 当前元素
 * @return {HTMLElement}
 */
const findTable = currentElement => {
  // 下一个兄弟节点
  let nextElement = currentElement.nextElementSibling;
  while (nextElement) {
    const table = nextElement.querySelector('table')
    if (table) {
        return table;
    }
    nextElement = nextElement.nextElementSibling;
  }
  return null; // 如果未找到表格元素,返回 null
}

// 清除 el 元素中 DMS-Table-Style- 前缀的类
const clearCls = el => {
  el.classList.forEach(cls => {
    if (cls.startsWith('DMS-Table-Style-')) {
      el.classList.remove(cls)
    }
  })
}
// 清除多次运行可能造成的残留
clearCls(dv.container.parentElement.parentElement)
// 给对应的元素添加类
if(config.table == 'next'){
  findTable(dv.container.parentElement)?.classList.add(tableClass)
}else{
  dv.container.parentElement.parentElement.classList.add(tableClass)
}

使用

通篇生效

在笔记中插入 dataviewjs 代码块

dv.view("TableStyle", { style: "Light-2-2" })

其中 style 后面的值说明选定的表格样式,参照上面样式图:

  • 浅色为:Light
  • 中等色:Normal
  • 深色为:Dark
  • 第 1 个数字是指第几行
  • 第 2 个数字是指第几列

这时候这篇笔记中所有表格都会应用此样式。

单个表格

在笔记中插入 dataviewjs 代码块

dv.view("TableStyle", { style: "Light-2-2", table: 'next' })

此时会对此代码块之后的第一个表格生效。

说明

  • 代码块编辑时会失效
  • 如果关闭 Dataview 的更新自动执行,同时使用单个表格模式,在编辑表格之后样式无法立刻生效,需重现运行代码块(让代码块进入编辑状态,再退出编辑)
  • 为了避免找不到代码块,所以这个代码块会显示一行小字。
  • 没啥侵入性,只是笔记中多了一个代码块,仅占用三行。
  • 可以使用 Obsidian 原生的表格编辑功能(理所当然的)。
©2022~2024 稻米鼠. Last build at 2024-12-21 00:00:24