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

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

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


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

image.png

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

image.png


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

  • 思源笔记

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

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

    26078 引用 • 108271 回帖
  • Q&A

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

    10017 引用 • 45530 回帖 • 71 关注

相关帖子

被采纳的回答
  • 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 佬提供的这些 ❤️

请输入回帖内容 ...

推荐标签 标签

  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 605 关注
  • Unity

    Unity 是由 Unity Technologies 开发的一个让开发者可以轻松创建诸如 2D、3D 多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    25 引用 • 7 回帖 • 120 关注
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖 • 2 关注
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    201 引用 • 120 回帖
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 3 关注
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3455 回帖 • 149 关注
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    524 引用 • 4601 回帖 • 710 关注
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    187 引用 • 831 回帖
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    86 引用 • 165 回帖
  • Elasticsearch

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

    117 引用 • 99 回帖 • 195 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 493 关注
  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    372 引用 • 1857 回帖
  • AWS
    11 引用 • 28 回帖 • 8 关注
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    173 引用 • 414 回帖 • 363 关注
  • Access
    1 引用 • 3 回帖 • 1 关注
  • Typecho

    Typecho 是一款博客程序,它在 GPLv2 许可证下发行,基于 PHP 构建,可以运行在各种平台上,支持多种数据库(MySQL、PostgreSQL、SQLite)。

    12 引用 • 67 回帖 • 444 关注
  • PWL

    组织简介

    用爱发电 (Programming With Love) 是一个以开源精神为核心的民间开源爱好者技术组织,“用爱发电”象征开源与贡献精神,加入组织,代表你将遵守组织的“个人开源爱好者”的各项条款。申请加入:用爱发电组织邀请帖
    用爱发电组织官网:https://programmingwithlove.stackoverflow.wiki/

    用爱发电组织的核心驱动力:

    • 遵守开源守则,体现开源&贡献精神:以分享为目的,拒绝非法牟利。
    • 自我保护:使用适当的 License 保护自己的原创作品。
    • 尊重他人:不以各种理由、各种漏洞进行未经允许的抄袭、散播、洩露;以礼相待,尊重所有对社区做出贡献的开发者;通过他人的分享习得知识,要留下足迹,表示感谢。
    • 热爱编程、热爱学习:加入组织,热爱编程是首当其要的。我们欢迎热爱讨论、分享、提问的朋友,也同样欢迎默默成就的朋友。
    • 倾听:正确并恳切对待、处理问题与建议,及时修复开源项目的 Bug ,及时与反馈者沟通。不抬杠、不无视、不辱骂。
    • 平视:不诋毁、轻视、嘲讽其他开发者,主动提出建议、施以帮助,以和谐为本。只要他人肯努力,你也可能会被昔日小看的人所超越,所以请保持谦虚。
    • 乐观且活跃:你的努力决定了你的高度。不要放弃,多年后回头俯瞰,才会发现自己已经成就往日所仰望的水平。积极地将项目开源,帮助他人学习、改进,自己也会获得相应的提升、成就与成就感。
    1 引用 • 487 回帖 • 2 关注
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    151 引用 • 257 回帖
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 506 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    300 引用 • 768 回帖
  • Bug

    Bug 本意是指臭虫、缺陷、损坏、犯贫、窃听器、小虫等。现在人们把在程序中一些缺陷或问题统称为 bug(漏洞)。

    76 引用 • 1742 回帖
  • Telegram

    Telegram 是一个非盈利性、基于云端的即时消息服务。它提供了支持各大操作系统平台的开源的客户端,也提供了很多强大的 APIs 给开发者创建自己的客户端和机器人。

    5 引用 • 35 回帖
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    284 引用 • 248 回帖
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    730 引用 • 1282 回帖 • 4 关注
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    188 引用 • 319 回帖 • 240 关注
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖
  • 微软

    微软是一家美国跨国科技公司,也是世界 PC 软件开发的先导,由比尔·盖茨与保罗·艾伦创办于 1975 年,公司总部设立在华盛顿州的雷德蒙德(Redmond,邻近西雅图)。以研发、制造、授权和提供广泛的电脑软件服务业务为主。

    8 引用 • 44 回帖 • 1 关注