Lazy loaded imagePower Query功能详解之追加查询

type
status
date
slug
summary
tags
category
icon
password
notion image

PowerQuery功能详解之追加查询

“追加查询”这个功能在不同数据布局场景下有不同的应用。追加查询的威力,并不仅仅局限于处理Excel文件。下面,我为您整理一份关于“追加查询”功能的、更完整的应用场景和原理概要。

一、“追加查询”功能完整应用场景

核心思想:将多个来源、但结构相似的数据,垂直地、像叠罗汉一样堆叠在一起,形成一个行数更多的、统一的数据集。
普通职场人最常用的三种核心场景是:

1. 同一工作簿下的多个工作表

  • 场景描述:您有一个Excel报告文件,里面包含了一月、二月、三月...等多个工作表,您需要将它们汇总成一张年度总表。
  • 实现方式:通过 数据 -> 获取数据 -> 从文件 -> 从工作簿,连接到当前这个工作簿本身。Power Query会列出其中所有的工作表对象,然后您可以将它们全部选中并追加。
  • 关键技巧:下面我们会深入探讨,为了让这个查询在文件移动后依然有效,最佳实践是使用动态路径Excel.CurrentWorkbook())的方式来实现。

2. 不同工作簿下的多个工作表

  • 场景描述:您从不同的人或部门那里,收到了多个独立的Excel文件,比如华东区销售.xlsx、华北区销售.xlsx、华南区销售.xlsx。它们的内部结构完全一样,您需要将它们汇总成全国销售总表。
  • 实现方式
      1. 在Power Query中,为每一个Excel文件分别创建一个独立的数据源连接查询(查询_华东, 查询_华北, 查询_华南)。
      1. 然后,使用 “将查询追加为新查询” 功能,将这几个独立的查询,合并成一个全新的、总的查询(全国销售总表)。

3. 同一文件夹下的所有文件 - 这是最强大的用法!

  • 场景描述:您有一个专门的文件夹,比如“月度销售报告”。每个月,您都会把最新月份的、格式完全一样的Excel或CSV报告文件扔进这个文件夹。您希望有一个报表,能自动地把这个文件夹里所有的报告都汇总起来。
  • 实现方式:使用 数据 -> 获取数据 -> 从文件 -> 从文件夹
  • 神奇之处
    • 您只需要设置一次查询。Power Query会创建一个“示例文件转换”的函数。
    • 未来,当您向这个文件夹中添加新的文件(比如“四月销售.xlsx”)时,您不需要做任何修改!您只需要在最终的报表中点击一次“刷新”,Power Query会自动发现新文件,并将其内容追加到总表中。
    • 同样,如果您删除了更新了文件夹里的某个文件,刷新后结果也会自动同步。

Power Query的追加功能远不止于Excel文件。它的强大之处在于,它可以追加任何来源、只要结构能被统一的数据。

4. 不同类型的多个文件

  • 场景描述:您的销售数据一部分记录在Excel文件里,另一部分记录在CSV文件里,还有一部分记录在文本文档里。但它们的列结构是相似的。
  • 实现方式:您可以先分别建立对Excel和CSV的查询,在Power Query内部将它们的列名和数据类型清洗成完全一致的结构,然后再将这两个查询追加在一起。

5. 数据库中的多个表

  • 场景描述:在公司的SQL数据库中,由于性能或历史原因,销售数据被分成了Sales_2022、Sales_2023、Sales_2024等多张表。您需要分析近三年的总销售情况。
  • 实现方式:在Power Query中,分别连接到这三张数据库表,然后将它们追加成一个查询。

6. 网页或API的分页数据

  • 场景描述:您需要从一个网站或API接口获取数据,但这个接口为了防止服务器过载,每次只返回100条记录(即“分页”)。您需要获取全部的几千条数据。
  • 实现方式:您可以创建一个函数来获取指定页码的数据,然后调用这个函数获取第1页、第2页、第3页...的数据,并将所有返回的查询结果追加在一起,形成完整的数据集。

总结:追加查询的应用场景

场景
核心描述
解决的典型问题
同一工作簿
将一个文件内部的多个Sheet/Table垂直合并。
汇总月度、季度报表;合并不同业务分类的子表。
不同工作簿
将多个独立的、结构相同的Excel文件垂直合并。
汇总来自不同分公司、不同部门的同类报告。
文件夹
(最强自动化) 自动合并一个文件夹内所有符合条件的文件。
一劳永逸地处理定期新增的报告文件(如月报、日报)。
不同文件类型
将Excel, CSV, TXT等不同类型但结构相似的文件合并。
整合历史遗留的、格式不统一的数据源。
数据库表
将数据库中结构相同的多个分表(如按年分的表)合并。
进行跨时间周期的大范围数据分析。
Web/API分页
将网页或API返回的多个数据页面合并。
爬取和获取完整的线上数据集。
所以,追加查询的本质是“垂直堆叠结构相似的数据”,那么无论数据来自何方,您都能灵活地运用这个强大的功能。

二、同一工作簿下的多个工作表的追加查询

这种情况有3个核心关键需要搞清楚
  • ① 逻辑健壮性:通过筛选防止查询的循环引用
  • ② 路径健壮性:通过动态路径实现查询的可移植性
  • ③ 结构健壮性:通过动态列名实现查询的可扩展性

以下视频为以上3项内容的完整讲解:

本视频教案下载地:

以下为文字版和相关的代码资源:


主题①:逻辑健壮性 — 通过筛选防止查询的循环引用

1. 痛点呈现

在我们使用Power Query处理“数据源与结果在同一工作簿”的场景时,一个极其危险的“幽灵”常常不请自来。
现象:您第一次刷新查询,得到了6行正确的汇总数据。但是,当您第二次、第三次刷新时,数据量会莫名其妙地变成12行、24行,甚至更多。每一次刷新,都会让数据成倍增长,最终导致整个报表的数据完全错误,我们称之为“数据爆炸”“循环引用”。
复现场景: 假设我们已经通过动态路径连接到了当前工作簿,并展开了所有工作表的数据。此时,我们的数据看起来像这样(简化版):
Name
员工姓名
销售额
Q1_Sales
张三
5000
Q1_Sales
李四
3500
Q2_Sales
王五
8000
...
...
...
追加1
张三
5000
追加1
李四
3500
追加1
王五
8000
您会发现,Power Query不仅读取了原始的Q1_SalesQ2_Sales等工作表,还把它自己上次加载回去的那个结果表(这里假设名为追加1)也当作了新的源数据,一起给合并进来了。

2. 原因剖析

这个问题的根源在于我们使用的Excel.Workbook()函数。
  • Excel.Workbook()的工作机制:这个函数会忠实地扫描并列出指定Excel文件中所有的对象,包括所有的工作表(Sheets)、已定义的表格(Tables)和已定义名称(Defined Names)。
  • 循环的产生
      1. 我们的查询指令是:“请读取当前这个文件里所有的工作表。”
      1. 第一次运行时,它正确地读取了Q1_Sales, Q2_Sales... 并将结果加载到了一个新的工作表,比如追加1.
      1. 第二次刷新时,Power Query再次执行第一条指令。但这一次,当它扫描“当前这个文件”时,它发现工作表的列表里,除了原始的Q1_Sales等,还多了一个我们上次创建的追加1
      1. 由于我们没有告诉它要排除追加1,它便忠实地将追加1也作为原材料,和Q1_Sales等一起进行了合并。
      1. 这就形成了一个恶性循环:查询的结果,成为了下一次查询的源头之一。

3. 解决方案

解决方案的核心思想非常直接:我们必须在数据处理的早期阶段,就通过“筛选”操作,明确地告诉Power Query,哪些是“原材料”,哪些是我们自己创造的“成品”,绝对不能混淆。
操作步骤:
  1. 定位到关键步骤:在Power Query编辑器的“应用的步骤”列表中,找到并选中“源 (Source)”这一步(或者是紧接着它的某一步,只要能看到所有工作表/表格的列表即可)。
  1. 应用筛选规则
      • 此时,您的预览窗口应该有一个名为Name的列,其中列出了Q1_Sales, Q2_Sales, Config, 追加1等所有对象的名称。
      • 点击 Name 列的筛选下拉箭头
      • 在弹出的列表中,取消勾选那个代表您最终汇总结果的工作表名称(追加1),以及其他任何不属于原始数据的工作表(如Config)。
      • 点击“确定”。
  1. 代码层面的变化: 可以直接忽略,参考界面操作步骤即可。
最终效果: 通过添加这一步筛选,我们的查询“配方”里就有了一条明确的指令:“在进行任何合并操作之前,请永远忽略名为追加1Config这一类的非源数据工作表。” 这样,无论我们刷新多少次,Power Query都只会处理我们指定的、真正的原始数据,循环被彻底打破,查询的逻辑健壮性得到了保证。

主题②:路径健壮性 — 通过动态路径实现查询的可移植性

1. 痛点呈现

我们构建自动化报表的初衷,是为了“一劳永逸”。但很多初学者很快就会发现一个令人沮丧的事实:这个“一劳永逸”是有条件的,条件就是——“文件永远不能动!”
现象:您精心制作了一个Power Query自动化报表,它在您的电脑上完美运行。但是,当您遇到以下任何一种情况时,灾难就会发生:
  • 您为了整理桌面,把这个Excel文件从桌面移动到了D:\\我的工作\\报告文件夹。
  • 您将这个Excel文件通过邮件发送给您的同事
  • 您将整个项目文件夹上传到了共享网络驱动器。
在以上任何一种情况下,当您或您的同事试图点击“刷新”时,Power Query会立刻“翻脸不认人”,弹出一个冰冷的错误提示: DataSource.Error: Could not find file 'C:\\Users\\你的名字\\Desktop\\原始数据.xlsx'.
结果:整个自动化流程在第一步就宣告失败。您不得不进入每一个查询,手动修改文件路径,极大地削减了自动化的价值,也让文件协作变得异常困难。

2. 原因剖析

这个问题的根源在于,标准的“获取数据”方法,在Power Query中记录的是一个写死的、绝对的路径
  • 绝对路径 (Absolute Path):这是一个从电脑的“根目录”(如C:\\)开始的、完整的、独一无二的文件地址。它就像一个完整的家庭住址,包含了国家、省、市、街道、门牌号。
  • Power Query的默认行为:当您通过 获取数据 -> 从文件 连接到一个Excel工作簿时,Power Query的“源”步骤会忠实地记录下这个绝对路径。
    • 其M语言代码如下所示,路径部分是一个纯文本字符串
  • 问题所在:这个“地址”是硬编码 (Hard-coded) 的。Power Query就像一个只会按固定地址送信的“笨邮差”,它不知道文件已经“搬家”了。当文件位置发生任何变化,这个写死的地址就变成了一个无效地址,导致“查无此件”。

3. 解决方案

解决方案的核心思想,是把Power Query从一个“笨邮差”升级为一个“智能侦探”。我们不再给它一个写死的地址,而是赋予它一种“随时找到自己在哪”的能力
这需要Excel和Power Query的协同作战。
第一步:在Excel中创建一个“动态路径信标”
我们首先需要在Excel文件内部,创建一个能实时报告自己位置的“信标”。
  1. 新建配置工作表:在您的Excel工作簿中,新建一个工作表,命名为Config(或“路径”等您自己能看懂的名字)。
  1. 使用CELL函数:在Config工作表的任意单元格(比如A10),输入这个Excel函数: =CELL("filename", A10) 这个函数会立即返回当前工作簿的完整文件路径,例如:C:\\我的工作\\报告\\[我的分析文件.xlsx]Config。这个路径是动态的,您把文件移到哪里,它就会自动更新成新的路径。但是他是取到工作表级别的路径的,我们只需要取到工作簿路径即可。按下面的函数继续取数。=SUBSTITUTE(LEFT(CELL("filename",A10),FIND("]",CELL("filename",A10))-1),"[","")
  1. 定义名称:选中A10单元格,点击顶部 “公式” -> “定义名称”。在“名称”输入框中,给它起一个简洁、有意义的名字,比如 工作簿路径。点击“确定”。
    1. (现在,我们就在Excel内部,创建了一个名为工作簿路径的、随时可以引用的、代表当前文件路径的“全局变量”。)
第二步:在Power Query中引用这个“信标”
现在,我们回到Power Query,改造我们的“源”步骤。
  1. 定位到“源”步骤:进入Power Query编辑器,选中需要修改的查询,并点击第一步“源”。
  1. 修改M代码:看向顶部的公式栏,找到那段包含绝对路径的代码。我们的目标,是用一段Excel.CurrentWorkbook(){[Name="工作簿路径"]}[Content]{0}[Column1]能够读取Excel已定义名称的M代码,来替换掉那个写死的路径字符串
    1. 修改前:
      修改后 (针对数据源就是当前文件本身):
      • 代码解读(核心部分):
        • Excel.CurrentWorkbook(){[Name="工作簿路径"]}[Content]{0}[Column1]:这段代码的作用是:“在当前这个Excel工作簿里,找到名叫工作簿路径的对象,并把它的值(那个长长的路径文本)取出来。”
最终效果: 经过改造后,“源”步骤的指令从“去这个写死的地址找文件”,变成了“先问问Excel里的工作簿路径信标,当前文件在哪里,然后再去那个地址找文件”。
这样,无论您将这个Excel文件移动到任何地方,或者发给任何人,只要他一打开文件,CELL函数就会自动更新路径,“信标”就会指向正确的位置。当他点击“刷新”时,Power Query就会根据“信标”的最新指示,准确无误地找到数据源,从而实现了查询的完全可移植性路径健壮性

主题③:结构健壮性 — 通过动态列名实现查询的可扩展性

1. 痛点呈现

我们已经构建了一个逻辑正确、路径稳健的查询。它现在看起来似乎“完美”了。但是,一个更隐蔽的“定时炸弹”已经埋下。
现象:您的自动化报表已经稳定运行了好几个月。突然有一天,业务部门通知您:“从这个季度开始,我们的源数据表中增加了一个新的指标列,比如‘销售成本’,请把它也加到您的汇总报表里。”
您自信满满地把包含了新列的源数据文件放到指定位置,然后回到您的Power Query报表,点击“刷新”。刷新过程很顺利,没有报任何错误。但是,当您检查结果时,却沮-丧地发现——那个新的“销售成本”列,根本没有出现!
结果:您的自动化流程“选择性失明”了。它无法自动适应源数据结构的变化,您不得不再次进入Power Query编辑器,手动修改查询,这让“一劳永逸”的承诺大打折扣。

2. 原因剖析

这个问题的根源在于Power Query中 “展开列 (Expand Column)” 这个步骤的默认行为
  • “展开”操作的背后:当您使用 Excel.Workbook() 函数获取数据后,会得到一个包含[Data]列的元数据表,其中每一行的[Data]都是一个嵌套的表格。为了将它们合并,您会点击[Data]列的展开按钮。
notion image
  • 默认行为:写死列名:在您点击展开按钮时,Power Query会弹出一个菜单,让您选择要展开的列。当您点击“确定”后,Power Query会在后台生成一步M代码。这个代码会将您当前所选的所有列的名称,以一个固定的文本列表形式,硬编码 (Hard-coded) 在步骤中。
    • 这个M代码通常看起来像这样:
  • 问题所在:这个步骤的“配方”被明确地定义为:“请展开Data列,并且提取出名为员工姓名, 销售区域, 产品ID, 销售额的这几列。”
  • “定时炸弹”引爆:当您的源数据增加了新的“销售成本”列后,刷新时,Power Query引擎依然会严格按照这份“旧配方”去执行。由于“销售成本”这个名字不在那份写死的列表中,所以它就被无情地、静默地忽略了

3. 解决方案

解决方案的核心思想,是把那份“写死的列名清单”,替换成一个“动态生成的、能自动更新的列名清单”。我们不再告诉Power Query具体要展开哪些列,而是赋予它一种能力,让它在每次刷新时,自己去侦察汇总所有应该被展开的列。
这需要我们手动介入,用M语言构建一个动态列表。
操作步骤:
  1. 定位到关键步骤之前:在Power Query编辑器的“应用的步骤”列表中,找到并选中“展开列”(Expanded Data或类似名称)这一步的“上一步”。通常是您筛选完需要的工作表之后的那一步(比如在删除的其他列之后)。
      • 此时,您的预览窗口应该是一个元数据表,[Data]列里包含了所有需要被合并的嵌套表格。
  1. 插入步骤,创建动态列名列表
      • 点击公式栏左侧的 fx 按钮,插入一个新步骤。
      • 将公式栏中的内容,替换为下面这段“魔法代码”:
      • 代码解读
          1. List.Transform(..., each Table.ColumnNames(_)): 遍历每一个嵌套表([Data]),并提取出它们各自的列名列表。
          1. List.Combine(...): 将所有这些单独的列名列表,合并成一个包含所有列名(有重复)的大列表。
          1. List.Distinct(...): 对这个大列表进行去重,得到一个最终的、包含了所有源表中出现过的全部唯一列名的“超级列表”。
      • 按下回车后,这个步骤的结果就是那个动态生成的列名列表。将这个步骤重命名为一个有意义的名字,比如 列标题,是动态变动的。
  1. 改造“展开列”步骤
      • 现在,重新选中您原来的“展开列”那一步。
      • 看向顶部的公式栏,找到那段写死的列名列表 {"员工姓名", "销售区域", ...}
      • 执行关键替换:将这个写死的列表,直接替换为您上一步创建的动态列表的名称 列标题
      修改前:
      修改后:
最终效果: 经过改造后,整个查询的自动化流程变得极具弹性可扩展性
  1. 刷新时,Power Query首先会执行列标题这一步,它会重新扫描所有最新的源数据,并生成一份包含了所有新旧列名的最新“超级列表”。
  1. 紧接着,当执行“展开列”步骤时,它不再依赖于一份过时的“旧清单”,而是直接使用刚刚生成的列标题这个最新的、最全的清单来展开数据。
这样,无论未来您的源数据表增加、减少或修改了任何列,您的Power Query查询都能够自动适应这些结构上的变化,确保所有数据都能被准确无误地包含进来,从而实现了真正的“面向未来”的结构健壮性。

二、不同工作簿下的多个工作表的追加查询

 
 
在上面中,我们提到了如何汇总同一个工作簿内的多个工作表。但相信很多同学都会遇到一个更普遍的场景:数据源本身就是分散在不同Excel文件中的,比如一月销售.xlsx二月销售.xlsx... 我们需要在一个全新的汇总工作簿文件中,将它们合并起来。
下面,我们就来攻克这个难题。思路是构建一个强大的自动化报表,它不仅能汇总不同工作簿的数据,更能解决两个极其棘手的“痛点”:
  1. 动态路径问题:如何让你的查询在整个项目文件夹被移动或分享给他人后,依然能“一键刷新”?
  1. 动态列问题:当源数据增加了新的列,如何让汇总表自动把它包含进来?

第一部分:基础方法——快速合并,但隐患重重

我们先用最直接的方法来感受一下。假设我们有一个汇总分析.xlsx文件,和三个数据源文件(工作簿1.xlsx工作簿2.xlsx工作簿3.xlsx)存放在同一个文件夹中。

操作步骤:

  1. 创建独立查询:在汇总分析.xlsx中,打开Power Query编辑器。通过 “新建源” -> “文件” -> “Excel工作簿”,分别为工作簿1工作簿2工作簿3创建三个独立的查询。
  1. 追加为新查询:点击 “主页” -> “追加查询” -> “将查询追加为新查询”。在弹出的对话框中,选择“三个或更多表”,并将刚刚创建的三个查询全部添加进去。
  1. 加载数据:点击“关闭并上载”,将最终的汇总查询和三个中间查询都加载到Excel中。
此时,一个初步的汇总表就完成了。我们测试一下,在工作簿1.xlsx中增加一行数据,甚至增加一个“备注”列,回到汇总分析.xlsx点击“全部刷新”,你会发现所有更改都能被正确更新。
注意:这里的“新增列”之所以能成功刷新,是因为我们采用的是“独立查询后追加”的模式。Power Query在刷新每个独立查询时,会自动获取其最新的所有列,所以最终追加时,列信息是动态的。这与上节课Excel.Workbook()展开列的机制有所不同。

痛点演示:一碰就碎的“绝对路径”

看起来很完美,对吧?
现在,我们来模拟一个真实的工作场景:将整个项目文件夹从“桌面”移动到“C盘”
(移动文件夹...)
现在,我们重新打开汇总分析.xlsx,再次点击“全部刷新”...
砰!报错了!
Power Query会弹出错误,抱怨说“找不到位于‘桌面’的那个文件”。
这就是基础方法最致命的弱点:它在查询中记录了每个数据源文件的绝对路径。一旦文件位置发生任何变化,整个自动化流程就会立刻瘫痪。

第二部分:终极解决方案——构建“永不迷路”的动态路径查询

要解决这个问题,我们的核心思路是:不再告诉Power Query一个写死的地址,而是赋予它一种能力,让它自己去计算出数据源文件当前在哪里。

步骤一:在Excel中创建“路径配置中心”

  1. 汇总分析.xlsx文件中,新建一个工作表,命名为 配置。这个工作表将成为我们所有动态参数的“控制面板”。
  1. 我们需要为每一个数据源文件(工作簿1.xlsx 工作簿2.xlsx 工作簿3.xlsx)都生成一个动态路径。在配置工作表的A列,我们分别填入以下公式:
    1. 示例(A1, A2, A3单元格分别填入):
      =LEFT(CELL("filename",A1),FIND("[",CELL("filename",A1))-1)&"工作簿1.xlsx"
      =LEFT(CELL("filename",A2),FIND("[",CELL("filename",A2))-1)&"工作簿2.xlsx"
      =LEFT(CELL("filename",A3),FIND("[",CELL("filename",A3))-1)&"工作簿3.xlsx"
  • 公式解读:这个公式由 CELL("filename"), LEFT, FIND 等函数组合而成。它的作用是先获取当前汇总分析.xlsx文件所在的文件夹路径,然后在其后面拼接上我们已知的数据源文件名(如工作簿1.xlsx),从而动态地构建出数据源的完整路径。

步骤二:为动态路径“命名”

为了让Power Query能轻松地找到并引用这些路径,我们需要为它们“定义名称”。
  1. 选中包含“工作簿1”路径的单元格(例如A1)。
  1. 点击顶部菜单 “公式” -> “定义名称”
  1. 输入名称,例如 工作簿1 ,然后确定。
  1. 对其他几个路径单元格重复此操作,分别命名为工作簿2工作簿3

步骤三:改造Power Query查询——注入“GPS导航”

现在,我们回到Power Query编辑器,对之前创建的三个独立查询进行“升级改造”。
  1. 选中工作簿1的查询,在右侧“应用的步骤”中,点击第一步“源”
  1. 看顶部的公式栏,您会看到一个包含写死路径的M代码。
  1. 执行关键替换:将公式中写死的路径文本("C:\..." 这部分),替换为下面这段能够读取已定义名称的M函数代码:
      • 代码示例
        • = Excel.CurrentWorkbook(){[Name="工作簿1"]}[Content]{0}[Column1]
          用以上这个动态路径获取函数,获取“工作簿1”的实时路径,并且替换原来的被写死的路径。
  1. 修改后的完整“源”步骤代码应如下所示:
    1. = Excel.Workbook(File.Contents(Excel.CurrentWorkbook(){[Name="工作簿1"]}[Content]{0}[Column1]), null, true)
  1. 对工作簿2和工作簿3的查询重复此操作,确保将M代码中的Name="工作簿1"相应地修改为工作簿2工作簿3
修复完这三个查询的“源”之后,您会发现,那个最终的追加查询也自动恢复正常了!

第三部分:最终验证与总结

现在,关闭并上载您的查询。我们再来做一次“终极测试”:
  • 将整个项目文件夹再次移动到任意一个新的位置。
  • 打开汇总分析.xlsx,修改任意一个源文件的数据(增行、增列、改值)。
  • 回到汇总分析.xlsx,点击“全部刷新”。
这个时候,一切都完美刷新了!

重要注意事项与建议

  • 相对位置不变:此方法的前提是,您的汇总分析.xlsx和所有工作簿.xlsx数据源文件,必须始终保持在同一个文件夹内,作为一个整体进行移动和分享。
  • 文件名依赖:如果您重命名了某个数据源文件(例如,工作簿1.xlsx改成了第一季度.xlsx),您必须回到配置工作表中,手动更新对应的M函数公式,否则刷新会失败。
  • 给用户的建议
    • 如果您的文件位置是固定的,完全可以使用第一部分的基础方法,因为它最简单直接。
    • 如果您需要频繁移动、分享文件,或者构建一个需要长期维护的报告,那么强烈建议您花时间学习并使用第二部分的动态路径方法,它将为您节省大量后期维护的时间和精力。

三、同一文件夹下的所有文件 - 这是最强大的用法!

接着上面汇总不同工作簿下的工作表,本文将带你继续深入学习Power Query中最强大的功能之一——从文件夹合并,并为你揭开两个“骨灰级”玩家必备的技巧:
动态路径动态列
助你构建一个真正“打不死、移不走、喂不饱”的、可移植、可扩展的自动化数据汇总报告。以下为视频指引:

场景设定:汇总月度销售报告

notion image
假设我们有一个名为月度销售报告的文件夹,里面存放着多个月份的销售Excel文件。我们的任务是,在一个单独的总部分析报告.xlsx文件中,将这个文件夹里所有的销售数据自动汇总起来。
这些源文件充满了“陷阱”:
  • 文件名和内部工作表名各不相同。
  • 不同文件的列名、列数不完全统一。
我们的目标是构建一个能无视这些混乱,并能在未来自动包含新增文件和新增列的自动化流程。

第一部分:基础搭建 — 从文件夹连接

首先,我们在总部分析报告.xlsx中,通过数据 -> 获取数据 -> 从文件 -> 从文件夹 -> 转换数据,连接到月度销售报告文件夹。
进入Power Query编辑器后,你会看到一个列出了文件夹内所有文件信息的元数据表。
notion image

痛点一:如何排除“自己”,避免循环引用?

你会发现,列表里也包含了我们正在操作的总部分析报告.xlsx。如果直接合并,下一次刷新时,它就会把自己上次的结果也当作源数据合并进来,导致数据无限循环。
✅ 解决方案:筛选行
在合并之前,必须先排除掉非数据文件。
  1. Name列的筛选器中,取消勾选你的汇总文件名(总部分析报告.xlsx)。
  1. 最佳实践 使用文本筛选器,只保留文件名中包含特定关键词(如“销售”)或特定扩展名(如.xlsx)的文件。
notion image

第二部分:核心技巧一 — 解包并动态展开列

现在,我们需要“解开”每一个Excel文件,并将里面的数据合并。

步骤1:解包Excel文件

只保留包含文件二进制内容的[Content]列,然后通过 “添加列” -> “自定义列” 来解包:
  • 新列名:例如 UnpackedData
  • 自定义列公式
    • = Excel.Workbook([Content], true)
    • 代码解读:Excel.Workbook()函数读取每个文件的二进制内容([Content]),并返回一个包含其内部所有工作表和表格信息的元数据表。第二个参数true,表示让Power Query尝试自动提升每个工作表的标题行。
notion image

痛点二:新增的列,为什么刷新不出来?

现在,展开新创建的UnpackedData列,你会得到以下:
notion image
保留Table列即可,以下操作就和 第一种情况:同一工作簿下的多个工作表的追加查询一样的操作了,要解决2个问题:一个是动态获取所有列名,一个是获取用不迷路的动态路径。
notion image
以上是所有工作表合并后的结果。但这里埋着一个巨大的“坑”:这个“展开的data”步骤的M代码,会把当前所有列的名称写死
如果未来你的源文件中增加了新的列(比如“销售成本”),刷新时,由于新列名不在这个写死的列表里,它将被自动忽略
✅ 解决方案:动态获取所有列名
我们需要在“展开”之前,先用一段M代码,动态地生成一个包含所有可能列名的“超级列表”。
  1. 选中“解包Excel”那一步(“删除的其他列1”)。
  1. 点击公式栏左侧的 fx 按钮,插入一个新步骤。
  1. 将这个新步骤的公式替换为:
    1. = List.Distinct(List.Combine(List.Transform( 删除的其他列1[Data], each Table.ColumnNames(_))))
      • 代码解读:这段代码会遍历Data列中的每一个嵌套表,提取出它们各自的列名列表,然后将这些列表合并并去重,最终得到一个包含了所有唯一列名的动态列表。
notion image
将这个步骤重命名为 动态列标题

步骤2:使用动态列表展开

现在,回到你原来的“展开的“Data”那一步,修改它的M代码。
  • 修改前
= Table.ExpandTableColumn(之前的步骤名, "Data", {"列1", "列2", "列3"})
  • 修改后
= Table.ExpandTableColumn(之前的步骤名, "Data", 动态列标题)
我们用动态生成的动态列标题列表,替换掉了那个写死的列名列表。现在,你的查询已经具备了“柔性扩展”的能力!

第三部分:核心技巧二 — 构建永不迷路的动态路径

我们的查询现在很智能,但它依然很“脆弱”。如果你把整个月度销售报告文件夹移动到新的位置,刷新时就会因为“找不到文件”而报错。

痛点三:绝对路径的“诅咒”

Power Query的“源”步骤默认记录的是绝对路径(如C:\Users\Desktop\月度销售报告)。这个写死的路径,就是查询可移植性的最大障碍。
✅ 解决方案:在Excel中创建“路径信标”,让Power Query动态寻址
  1. 在Excel中创建信标
      • 总部分析报告.xlsx中,新建一个名为配置的工作表。
      • 在A1单元格,输入以下Excel公式,以获取文件夹路径:
        • =LEFT(CELL("filename",A1),FIND("[",CELL("filename",A1))-2)
      • 选中A1单元格,通过 “公式” -> “定义名称”,将其命名为 汇总文件夹路径
  1. 在Power Query中引用信标
      • 回到Power Query编辑器,选中第一步“源 (Source)”
      • 修改其M代码。
      • 修改前
        • = Folder.Files("C:\Users\Desktop\月度销售报告")
      • 修改后
        • = Folder.Files(Excel.CurrentWorkbook(){[Name="汇总文件夹路径"]}[Content]{0}[Column1])
      notion image
      • 代码解读:Excel.CurrentWorkbook()函数会在当前工作簿内部查找名叫汇总文件夹路径的对象,并提取其单元格的值(也就是那个动态的文件夹路径),然后将这个路径传递给Folder.Files函数。

结论:你的自动化工厂已建成!

恭喜!通过以上改造,你已经构建了一个真正专业的自动化数据汇总流程。它:
  • 逻辑健壮:能通过筛选,避免循环引用。
  • 结构健壮:能通过动态列,自动适应源数据结构的变化。
  • 路径健壮:能通过动态路径,实现整个项目的自由移动和分享。
从现在起,你只需将每月的新报告文件扔进那个文件夹,然后在你的汇总报告中点击一下“刷新”。所有的数据清洗、合并、更新都会在瞬间自动完成。这,就是Power Query的真正威力!瞬间自动完成。这,就是Power Query的真正威力!

如果想深入学习,可以付费¥129,加入我的知识星球,加我的微信,一对一教学。

notion image
notion image
 
 
 
上一篇
不懂成本,别做经营分析!4大业务场景下,成本核算和经营分析该如何深度融合?
下一篇
为什么仓库月末盘点需要财务一起?在一个上线了WMS系统的制造业企业,财务和仓管一起盘点需要注意什么?
Loading...
目录
文章列表
让财税成为经营的力量
管理报表
从Power Query到Power BI,入门到精通
699课程讲义
VBA小工具
电脑与网络
知识运用