求助将数据库中的内容渲染为表格

求助一个将数据库内容渲染为表格的方法

起因是看到了这一篇帖子利用 数据库 和 Chart(图表) 做小朋友身高管理 - 链滴,就想着是否有方法可以将数据库中的内容做成表格。


比如有这样一个数据库,每个主键有横坐标(A-B)和纵坐标(1-9)两个字段。

image.png

是否可以根据每个主键的横坐标和纵坐标两个字段,通过图表渲染成类似下面这种表格呢?感觉做一个物品管理蛮有意思的,数据库中添加其他字段描述物品信息,根据表格找到物品存放位置或者坐标(比如中药柜)

image.png


大家有什么好的方法吗(代码这方面我是真没时间学,之前也没接触过 😂)

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    25991 引用 • 107843 回帖
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    9980 引用 • 45371 回帖 • 75 关注

相关帖子

被采纳的回答
  • wilsons 3 1 赞同

    那个帖子是根据 [js] 图表如何和表格联动 - wilsons 的回帖 这个改造的,这种方式需要自己手动解析数据库 json 数据,较为麻烦。

    建议使用简单查询,实现起来更方便,可参考 震惊,思源表格和数据库竟然可以用 SQL 查询

    然后,分别新建一个数据和表格,并复制数据库块 id 和表格块 id,然后在当前文档输入 {{}} 在弹出的对话框中,输入以下代码,并把刚才复制的 id 填入到下面的相应参数中即可

    //!js // 数据库块id const avBlockId = '20250311063435-9066xpv'; // 表格块id const tableBlockId = '20250311063452-p03kxva'; // 数据库变更后自动更新延迟,单位是毫秒,默认是1秒,0则不自动更新 // 注意:更新该参数后需要刷新页面才能生效 const autoFreshDelay = 1000; // 监听数据库变化 observeAvChange(); return query( "select * from ?", [fromAv(avBlockId), item], '', ({ rawData, updateTable, renderSuccess }) => { let tableData = transformData(rawData); tableData = toMarkdownTable(tableData); updateTable(tableBlockId, tableData); return renderSuccess('更新完成', item); } ); function toMarkdownTable(data) { // 提取所有列名(包括空列 "") const columns = Array.from( data.reduce((set, row) => { Object.keys(row).forEach(key => set.add(key)); return set; }, new Set()) ).sort((a, b) => (a === "" ? -1 : a.localeCompare(b))); // 确保空列 "" 在最前面 // 构造表头行 const headerRow = `| ${columns.map(col => (col === "" ? "" : col)).join(" | ")} |`; // 构造分隔符行 const separatorRow = `| ${columns.map(() => "---").join(" | ")} |`; // 构造数据行 const dataRows = data.map(row => { return `| ${columns.map(col => row[col] || "").join(" | ")} |`; }); // 拼接所有部分 return [headerRow, separatorRow, ...dataRows].join("\n"); } function transformData(input) { // 创建一个 Map 来按横坐标分组 const groupedData = new Map(); // 遍历输入数组,按横坐标分组 input.forEach(item => { const { 主键, 横坐标, 纵坐标 } = item; // 如果横坐标不存在于 Map 中,则初始化 if (!groupedData.has(横坐标)) { groupedData.set(横坐标, { "": 横坐标 }); } // 将纵坐标和主键添加到对应的横坐标分组中 groupedData.get(横坐标)[纵坐标] = 主键; }); // 将 Map 转换为数组并返回 return Array.from(groupedData.values()); } function observeAvChange() { // 监听av变化,当数据库块被修改时,重新获取数据 if(autoFreshDelay > 0 && !window['__table_observe__' + avBlockId]) { window['__table_observe__' + avBlockId] = observeDOMChanges(document.querySelector('div[data-node-id="'+avBlockId+'"]'), ()=>{ setTimeout(() => { item.querySelector('.protyle-action__reload').click(); }, 100); }, autoFreshDelay, {attributes: false}); } } // 监听dom变化 function observeDOMChanges(targetNode, callback, debounceTime = 1000, options = {}) { // 默认配置 const defaultOptions = { attributes: true, childList: true, subtree: true, }; // 合并默认配置与传入的配置 const config = Object.assign({}, defaultOptions, options); // 创建一个观察器实例 const observer = new MutationObserver((mutationsList) => { // 使用防抖函数确保单位时间内最多只调用一次回调 if(window['__table_observeTimer__' + avBlockId]) { clearTimeout(window['__table_observeTimer__' + avBlockId]); } window['__table_observeTimer__' + avBlockId] = setTimeout(() => { // 处理变化 callback(mutationsList); }, debounceTime); }); // 开始观察目标节点 observer.observe(targetNode, config); // 返回一个函数,以便在不需要时能够停止观察 return () => { observer.disconnect(); }; }

    r118.gif

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • 这个插件可能可以,但我完全不知道怎么用:

    image.png

    1 回复
  • auric

    我也看到这个插件,但是我也不知道咋用 😭 ,还是我太笨了。

  • wilsons 3 1 赞同

    那个帖子是根据 [js] 图表如何和表格联动 - wilsons 的回帖 这个改造的,这种方式需要自己手动解析数据库 json 数据,较为麻烦。

    建议使用简单查询,实现起来更方便,可参考 震惊,思源表格和数据库竟然可以用 SQL 查询

    然后,分别新建一个数据和表格,并复制数据库块 id 和表格块 id,然后在当前文档输入 {{}} 在弹出的对话框中,输入以下代码,并把刚才复制的 id 填入到下面的相应参数中即可

    //!js // 数据库块id const avBlockId = '20250311063435-9066xpv'; // 表格块id const tableBlockId = '20250311063452-p03kxva'; // 数据库变更后自动更新延迟,单位是毫秒,默认是1秒,0则不自动更新 // 注意:更新该参数后需要刷新页面才能生效 const autoFreshDelay = 1000; // 监听数据库变化 observeAvChange(); return query( "select * from ?", [fromAv(avBlockId), item], '', ({ rawData, updateTable, renderSuccess }) => { let tableData = transformData(rawData); tableData = toMarkdownTable(tableData); updateTable(tableBlockId, tableData); return renderSuccess('更新完成', item); } ); function toMarkdownTable(data) { // 提取所有列名(包括空列 "") const columns = Array.from( data.reduce((set, row) => { Object.keys(row).forEach(key => set.add(key)); return set; }, new Set()) ).sort((a, b) => (a === "" ? -1 : a.localeCompare(b))); // 确保空列 "" 在最前面 // 构造表头行 const headerRow = `| ${columns.map(col => (col === "" ? "" : col)).join(" | ")} |`; // 构造分隔符行 const separatorRow = `| ${columns.map(() => "---").join(" | ")} |`; // 构造数据行 const dataRows = data.map(row => { return `| ${columns.map(col => row[col] || "").join(" | ")} |`; }); // 拼接所有部分 return [headerRow, separatorRow, ...dataRows].join("\n"); } function transformData(input) { // 创建一个 Map 来按横坐标分组 const groupedData = new Map(); // 遍历输入数组,按横坐标分组 input.forEach(item => { const { 主键, 横坐标, 纵坐标 } = item; // 如果横坐标不存在于 Map 中,则初始化 if (!groupedData.has(横坐标)) { groupedData.set(横坐标, { "": 横坐标 }); } // 将纵坐标和主键添加到对应的横坐标分组中 groupedData.get(横坐标)[纵坐标] = 主键; }); // 将 Map 转换为数组并返回 return Array.from(groupedData.values()); } function observeAvChange() { // 监听av变化,当数据库块被修改时,重新获取数据 if(autoFreshDelay > 0 && !window['__table_observe__' + avBlockId]) { window['__table_observe__' + avBlockId] = observeDOMChanges(document.querySelector('div[data-node-id="'+avBlockId+'"]'), ()=>{ setTimeout(() => { item.querySelector('.protyle-action__reload').click(); }, 100); }, autoFreshDelay, {attributes: false}); } } // 监听dom变化 function observeDOMChanges(targetNode, callback, debounceTime = 1000, options = {}) { // 默认配置 const defaultOptions = { attributes: true, childList: true, subtree: true, }; // 合并默认配置与传入的配置 const config = Object.assign({}, defaultOptions, options); // 创建一个观察器实例 const observer = new MutationObserver((mutationsList) => { // 使用防抖函数确保单位时间内最多只调用一次回调 if(window['__table_observeTimer__' + avBlockId]) { clearTimeout(window['__table_observeTimer__' + avBlockId]); } window['__table_observeTimer__' + avBlockId] = setTimeout(() => { // 处理变化 callback(mutationsList); }, debounceTime); }); // 开始观察目标节点 observer.observe(targetNode, config); // 返回一个函数,以便在不需要时能够停止观察 return () => { observer.disconnect(); }; }

    r118.gif

    3 回复
    2 操作
    wilsons 在 2025-03-11 09:50:26 更新了该回帖
    wilsons 在 2025-03-11 09:46:42 更新了该回帖
  • auric

    感谢 w 佬,之前的两篇简单查询的帖子我也学习过,但是实际应用的时候还是丈二和尚摸不着头脑,这方面我基本没有基础 😂 。非常感谢 w 佬花时间帮助我们!

  • auric

    W 佬,我用这个查询的时候出现了一点问题。我想要一个 9×9 的表格,渲染出来的结果主键移位了,数据库中的数据是这样的,但是表格中 A3 A4 的主键数据跳到了 I8 I9,往后继续输入主键内容也是错位的。

    image.png

    image.png

    1 回复
  • auric

    w 佬,有点奇怪,我换到其他的数据库和表格后就没有出现这个错误求助将数据库中的内容渲染为表格 - auric 的回帖 - 链滴,不知道怎么回事。

  • 你把这个有问题的文件导出来看看,我刚才也在尝试复现,还没尝试出来。

    2 回复
  • auric

    测试.sy.zip 这是我测试好像有问题的文件,根据字段的插入块相应位置的代码。然后我用另外的两个数据库和表格,能够正确渲染到表格,但是添加之后就不能显示在正常的表格对应位置。

    1 回复
  • auric

    不知道是不是我代码改的不对,这是错误的录屏:

    20250311173219.gif

    另外可以正确导出表格的数据库,新增数据后,新增的数据直接出现在表格的第一个格里,也没有出现在相应的格子 😂

  • wilsons 1

    这个问题,是思源笔记渲染结果和 api 解析不一致导致的。

    已向官方提交了 issue Issue #14345 · siyuan-note/siyuan

    暂时解决不了,你可以关注下这个 issue,等待官方回复后再看怎么解决。

    2 回复
  • auric

    ok,谢谢 w 佬 ❤️

  • auric

    哈喽,w 佬,我看了 GitHub 上的 issue,这个问题好解决么,不好解决的话,我今天发现直接新建数据库,不要改动排序,输入的内容不会有太大问题 😂 ,就是用的时候需要小心 😂

    1 回复
  • 是的,就是渲染数据和存储数据不一致导致的。这个要改成读渲染数据。这两种数据格式完全不一样,由于是底层,上层依赖较多,修改后影响较大,要做中间兼容层,改动较麻烦。

    2 回复
  • auric

    谢谢 w 佬 🙏

  • auric

    w 佬,现在的这个方法,只要渲染好了,修改条目的字段内容时不会有影响,如果在没有内容的条目字段里输入,就会渲染到表格的第一个空格内 😂 ,不过这个方法对我目前的需求来讲算不上很难接受,再次谢谢 w 佬提供的这些 ❤️

请输入回帖内容 ...

推荐标签 标签

  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 2 关注
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖 • 1 关注
  • 旅游

    希望你我能在旅途中找到人生的下一站。

    98 引用 • 903 回帖
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 370 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 569 关注
  • Anytype
    3 引用 • 31 回帖 • 24 关注
  • VirtualBox

    VirtualBox 是一款开源虚拟机软件,最早由德国 Innotek 公司开发,由 Sun Microsystems 公司出品的软件,使用 Qt 编写,在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。

    10 引用 • 2 回帖 • 17 关注
  • NetBeans

    NetBeans 是一个始于 1997 年的 Xelfi 计划,本身是捷克布拉格查理大学的数学及物理学院的学生计划。此计划延伸而成立了一家公司进而发展这个商用版本的 NetBeans IDE,直到 1999 年 Sun 买下此公司。Sun 于次年(2000 年)六月将 NetBeans IDE 开源,直到现在 NetBeans 的社群依然持续增长。

    78 引用 • 102 回帖 • 707 关注
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 435 关注
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 36 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 190 关注
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    91 引用 • 59 回帖 • 5 关注
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 50 关注
  • FFmpeg

    FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

    23 引用 • 32 回帖 • 1 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    19 引用 • 23 回帖 • 737 关注
  • CodeMirror
    2 引用 • 17 回帖 • 167 关注
  • gRpc
    11 引用 • 9 回帖 • 99 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 614 关注
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    76 引用 • 258 回帖 • 627 关注
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 79 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖 • 3 关注
  • 自由行
    1 关注
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 50 关注
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 196 关注
  • OpenCV
    15 引用 • 36 回帖 • 8 关注