前言
在许多网站上都会有常见问题解答模块(FAQ),以回答一些用户经常会遇到或提问的问题,而这其实也很适合用在PowerBI报表上面,可以提供一些用户指引或使用等信息。
因此本篇文章将分享一个通过HTML实现的FAQ模块,支持答案的展开与折叠,可将其作为报表的最后一页来提供一些常见问题与回答,效果如下图所示:

FAQ模块实现
首先,新建一个包含:Question、Answer、Order三个字段且表名为FAQ的表,每一行代表一个问题与回答,其中的Order字段用于对问题设置按列排序,也可以去掉该字段而直接按Question字段排序。
本案例使用计算表来创建FAQ表,如下图所示:

计算表的表达式如下:
FAQ =
DATATABLE(
"Order", INTEGER,
"Question", STRING,
"Answer", STRING,
{
{ 1, "如何刷新报表数据", "在 Power BI 服务中可使用计划刷新或手动刷新。连接本地数据源需通过网关并在数据集设置里配置凭据与计划刷新。" },
{ 2, "为什么看不到最新数据", "先查看数据集的刷新历史是否成功;若使用 DirectQuery 还可能受缓存影响,可刷新浏览器。确保你正在查看的工作区和应用为最新发布版本。" },
{ 3, "如何提交问题或建议", "可在报表中使用反馈入口或联系数据团队邮箱 data-team@company.com,建议附上页面链接、截图、筛选条件和期望结果,便于快速定位。" },
{ 4, "如何筛选并定位我关心的数据", "使用页面上的切片器和搜索框,鼠标点击图表可进行交叉筛选。可在筛选窗格中清除或重置筛选,快速回到默认视图。" },
{ 5, "如何导出报表或数据", "可在服务中导出为 PDF 或图片。导出数据时受权限与行级安全限制,若导出项不可用,请联系管理员开通权限或在数据策略允许范围内操作。" },
{ 6, "如何查看指标口径和字段定义", "在报表的口径说明页或数据字典中查看指标定义、口径说明与更新时间。若没有该页面,请联系报表负责人索取文档链接。" },
{ 7, "如何共享报表给同事", "可将报表发布为应用并为目标受众分配权限,或在工作区中添加成员。若对方无许可或无数据权限,需要管理员协助开通。" },
{ 8, "移动端如何查看", "在 Power BI 移动应用中打开对应应用或报表,建议使用手机布局并横屏查看。若布局拥挤,可通过筛选缩小范围后阅读。" },
{ 9, "报表加载较慢怎么办", "检查网络状况,减少多重筛选与过多的可视化交互。仍然缓慢时请反馈页面链接、时间点、问题描述与筛选条件,便于性能排查与优化。" },
{ 10, "如何切换日期范围与时间对比", "使用日期切片器选择绝对或相对日期;若需要本期对比同期或环比,请使用报表提供的对比开关或专用度量的切换控件。" }
}
)
然后,新建一个FAQ度量值,度量值的表达式如下:
FAQ =
VAR css =
"<style>
:root{
--faq-primary:#2563eb;
--faq-text:#0f172a;
--faq-muted:#475569;
--divider:#e2e8f0;
--hover:#f8fafc;
--open-bg:#f0f7ff;
}
/* 防止宽度 + padding 溢出 */
*, *::before, *::after{ box-sizing:border-box; }
.faq-wrap{
width:100%;
max-width:100%;
margin:0;
padding:10px;
overflow-x:hidden; /* 避免横向滚动 */
font-family:'Segoe UI', -apple-system, system-ui, 'Helvetica Neue', Arial, sans-serif;
color:var(--faq-text);
}
.faq-list{ margin:0; padding:0; width:100%; }
.faq-item{
margin:0; padding:0;
border-top:1px solid var(--divider);
}
.faq-list .faq-item:first-child{ border-top:none; }
.faq-item summary{
display:flex; align-items:flex-start; gap:10px;
cursor:pointer; list-style:none;
/* 不设 width:100%,避免与 padding 组合时溢出 */
padding:14px 2px;
}
.faq-item summary::-webkit-details-marker{ display:none; }
.faq-item summary:hover{ background:var(--hover); }
.faq-icon{
width:18px; height:18px; flex:0 0 18px;
display:inline-flex; align-items:center; justify-content:center;
color:var(--faq-muted); transition:transform .2s ease, color .2s ease;
}
.faq-q{
flex:1; font-weight:500; transition:color .2s ease;
word-break:break-word; overflow-wrap:anywhere;
}
.faq-item[open] .faq-icon{ transform:rotate(90deg); color:var(--faq-primary); }
.faq-item[open] .faq-q{ color:var(--faq-primary); }
.faq-a{
padding:6px 0 18px 30px; /* 缩进答案 */
color:var(--faq-muted); line-height:1.75;
word-break:break-word; overflow-wrap:anywhere;
}
.faq-empty{
padding:16px; text-align:center; color:var(--faq-muted);
border:1px dashed var(--divider); border-radius:8px; background:#fcfcfc;
}
</style>"
VAR faqWrapOpen = "<div class='faq-wrap'><div class='faq-list'>"
VAR faqWrapClose = "</div></div>"
VAR faqRowsTbl =
SUMMARIZE(
ALLSELECTED(FAQ),
FAQ[Order],
FAQ[Question],
FAQ[Answer]
)
VAR faqItemsHtml =
CONCATENATEX(
faqRowsTbl,
VAR qRaw = COALESCE(FAQ[Question], "")
VAR aRaw = COALESCE(FAQ[Answer], "")
VAR q = SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TRIM(qRaw), "&", "&"), "<", "<"), ">", ">"), """", """)
VAR a0 = SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(aRaw, "&", "&"), "<", "<"), ">", ">"), """", """)
VAR a = SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(a0, UNICHAR(13) & UNICHAR(10), "<br/>"), UNICHAR(10), "<br/>"), UNICHAR(13), "<br/>")
RETURN
"<details class='faq-item'><summary><span class='faq-icon'>›</span><span class='faq-q'>" & q & "</span></summary><div class='faq-a'>" & a & "</div></details>",
"",
FAQ[Order],
ASC
)
VAR faqHtmlOut =
IF(
LEN(faqItemsHtml) = 0,
"<div class='faq-empty'>暂无匹配的问答</div>",
faqWrapOpen & faqItemsHtml & faqWrapClose
)
RETURN
css & faqHtmlOut
然后从视觉对象商店中添加HTML Content视觉对象,如下图所示:

最后,将上面的FAQ度量值放入到HTML Content视觉对象中即可,如下图所示:

总结
如果需要修改FAQ模块的样式等,可以将代码扔给AI进行修改。此外,也可以结合切片器等来实现问题的筛选与分类等等。

















