Power Query 真經(jīng) - 第 9 章 - 批量合并文件
合并來自多個文件數(shù)據(jù)的傳統(tǒng)方法是極其繁瑣和容易出錯的。每個文件都需要經(jīng)歷導(dǎo)入、轉(zhuǎn)換、復(fù)制和粘貼的過程。根據(jù)轉(zhuǎn)換數(shù)據(jù)量的大小和復(fù)雜程度、文件的數(shù)量以及解決方案運行的時長,這些問題可能形成可怕的積累效應(yīng)。
前面章節(jié)已經(jīng)看到使用 Power Query 后不再需要復(fù)制/粘貼,盡管它能夠逐一導(dǎo)入和追加文件,但還是仍然有一些不完美的問題要應(yīng)對。
手動導(dǎo)入多個文件是很麻煩的。
手動重復(fù)復(fù)雜的轉(zhuǎn)換步驟很容易出錯。
幸好,Power Query 也有辦法來解決這兩個問題的。
9.1 示例文件背景介紹
在這一章中,將研究如何為一家制造公司【導(dǎo)入】、【逆透視】和【追加】一系列的季度零件需求數(shù)據(jù)。生產(chǎn)區(qū)域每季度提交一份以其區(qū)域命名的數(shù)據(jù)報告,這些數(shù)據(jù)報告被存儲在一個文件夾中,結(jié)構(gòu)如圖9-1所示。

圖9-1 每個季度有四個文件,包含在“第 09 章 示例文件\Source Data”文件夾中
在每個工作簿中都有一個名為“Forecast”的工作表,其中包含如圖9-2所示透視的數(shù)據(jù)結(jié)構(gòu)。這里最大的問題是,這個數(shù)據(jù)的格式像一個 Excel 表格,但它實際上只是一個區(qū)域,盡管文件中也存在另一個名為“Parts”的表格。

圖9-2 在“2019 Q1\East.xlsx”工作簿的“Forecast”工作表數(shù)據(jù)
目標(biāo)是創(chuàng)建一個可刷新的自動化解決方案,以如圖9-3所示的格式返回數(shù)據(jù)。

圖9-3 被要求生成的表
這將很棘手,因為此時面臨以下問題。
這些文件都存儲在“第 09 章 示例文件/Source Files”文件夾的子文件夾中。
每個文件的內(nèi)容需要【逆透視】才能被【追加】。
不是所有的區(qū)域都會生產(chǎn)相同的產(chǎn)品,所以文件的列數(shù)也不相同。
文件名中的區(qū)域名稱必須被保留。
需要從子文件夾名稱中保留日期格式(例如“2019 Q4”)。
當(dāng)以后添加一個新的子文件夾時,用戶需要能夠刷新解決方案。
然而,即使有這些挑戰(zhàn),用戶最后也會發(fā)現(xiàn) Power Query 可以勝任這項任務(wù)。
9.1 過程概述
在深入探討構(gòu)建解決方案的結(jié)構(gòu)之前,需要快速瀏覽一下 Power Query 如何處理這項任務(wù)。
9.2.1 合并文件的標(biāo)準(zhǔn)流程
合并文件的過程遵循五步標(biāo)準(zhǔn)模式。
步驟 0:連接到文件夾。
步驟 1:篩選文件。
步驟 2:合并文件。
步驟 3:對示例轉(zhuǎn)換文件進(jìn)行數(shù)據(jù)清洗。
步驟 4:通過主查詢進(jìn)行數(shù)據(jù)清洗。
在這一章中,將通過這個標(biāo)準(zhǔn)模式的每個部分,向用戶展示它是如何工作的,以及為什么這些步驟很重要。然而,在這之前,理解將要構(gòu)建的內(nèi)容體系結(jié)構(gòu)是很重要的。
9.2.2 合并文件的通用架構(gòu)
讓許多用戶感到害怕的事情之一是,Power Query 并不只是通過使用一個單一的查詢來合并文件。相反,當(dāng)單擊合并文件按鈕時,它會要求用戶選擇一個【示例文件】,然后創(chuàng)建四個新的查詢來完成這項工作。如果用戶沒有發(fā)現(xiàn)這點,這可能會讓用戶有點迷惑。
假設(shè)已經(jīng)創(chuàng)建了一個名為“FilesList”的特定查詢來顯示想合并的文件,以及一個包含合并文件的結(jié)果(將在本章后面討論)“Master Query”,查詢體系結(jié)構(gòu)最終將看起來如圖9-4所示。

圖9-4 當(dāng)合并文件時,將創(chuàng)建四個新的查詢(顯示在下半部分)
雖然每個新查詢都是這個過程中的關(guān)鍵組成部分,但其中三個查詢將被放在一個【幫助程序查詢】文件夾中,用戶不需要創(chuàng)建它們。它們很容易被識別為以下內(nèi)容。
它們將儲存在一個名為【幫助程序查詢】的文件夾中。
它們用一個看起來不像表格的圖標(biāo)來表示。
如果看上面的圖表,會注意到列出的三個查詢顯示了一個表格圖標(biāo)。
文件列表:這個查詢只包含用戶希望合并的文件列表。正如在后面將了解到的,這可以是一個獨立的查詢,也可以是主查詢的一部分。無論采取哪種方法,這都是合并文件的地方。
轉(zhuǎn)換示例:在合并步驟中,用戶會被要求選擇一個文件作為示例文件,這個查詢將【引用】該示例,向用戶顯示選擇的文件內(nèi)容。它的目的是讓用戶在將所有文件追加到單個表之前,對單個文件執(zhí)行數(shù)據(jù)轉(zhuǎn)換(用戶在這里執(zhí)行的步驟會自動在轉(zhuǎn)換函數(shù)中自動照搬運行并合并,以便它們可以應(yīng)用于文件夾中的所有文件)。
主查詢:這個查詢的目的是將“FilesList”(步驟或查詢)中包含的每個文件,傳遞給轉(zhuǎn)換函數(shù)(基于【轉(zhuǎn)換示例文件】中的步驟),并返回每個文件的重塑結(jié)果。然后,擴(kuò)展這些表格,將它們【追加】到一個長的數(shù)據(jù)表中,并允許用戶在必要時做進(jìn)一步的轉(zhuǎn)換。
這聽起來可能有點復(fù)雜,但正如看到的,它提供了令人難以置信的靈活性,而且一旦理解了它是如何合并在一起的,實際上使用起來非常簡單。最重要的是,這種設(shè)置遵循如下流程。
在表被添加之前進(jìn)行數(shù)據(jù)轉(zhuǎn)換。
在表被添加后進(jìn)行數(shù)據(jù)轉(zhuǎn)換。
保留文件屬性,包括名稱或日期。
【注意】
這種方法不僅適用于 Excel 文件。它適用于 Power Query 中的任何其他文件類型的連接器(CSV、TXT、PDF 文件和更多文件類型)。
現(xiàn)在開始,把這個概述應(yīng)用于示例數(shù)據(jù)。
9.3 步驟 0:連接到文件夾
需要做的第一件事是連接到數(shù)據(jù)文件夾。如果還記得第一章的內(nèi)容,每次連接到一個數(shù)據(jù)源時,Power Query 都要經(jīng)歷如圖9-5所示的四個不同的步驟。

圖9-5 連接到數(shù)據(jù)源
從設(shè)置開始,在這里選擇和配置需要使用的連接器,來連接到相應(yīng)的文件夾。接下來,Power Query 會檢查用戶是否需要對數(shù)據(jù)源進(jìn)行驗證(如果需要,會提示用戶進(jìn)行驗證)。在驗證了用戶可以訪問數(shù)據(jù)源之后,用戶會得到初始預(yù)覽窗口,此時用戶可以選擇【加載數(shù)據(jù)】,或者在加載前到 Power Query 編輯器中重新塑造數(shù)據(jù)。
這里再次提到這一點的原因,以及本標(biāo)準(zhǔn)流程有步驟 0 的全部原因是,實際上有多個不同的連接器可以用來從一個文件夾中讀取數(shù)據(jù),這取決于用戶存放文件的系統(tǒng)。雖然根據(jù)系統(tǒng)的類型(Windows、SharePoint、Azure),入口點是不同的,但一旦用戶進(jìn)入數(shù)據(jù)預(yù)覽,為合并文件而建立的解決方案都利用相同的模式,如表9-1所示。
| 列 | 包含 |
|---|---|
| 內(nèi)容 | 對實際文件內(nèi)容的引用 |
| 文件名稱 | 給定文件的名稱 |
| 擴(kuò)展名 | 文件類型 |
| 訪問日期 | 文件最后一次被訪問的日期 |
| 修改日期 | 文件最后修改的日期 |
| 創(chuàng)建日期 | 文件創(chuàng)建的日期 |
| 屬性 | 包含文件大小、可見性狀態(tài)等項的記錄 |
| 文件夾路徑 | 文件夾的完整路徑 |
表9-1 任何【從文件夾】風(fēng)格的解決方案背后信息
因此,一旦完成了特定數(shù)據(jù)源的配置和身份驗證步驟,會發(fā)現(xiàn)本章中顯示的步驟可以應(yīng)用于各種不同的數(shù)據(jù)源。
9.3.1 連接到本地/網(wǎng)絡(luò)文件夾
到目前為止,最容易創(chuàng)建【從文件夾】的場景是,將文件組合在本地 PC 或映射網(wǎng)絡(luò)驅(qū)動器的文件夾中。由于 Windows 已經(jīng)對文件夾訪問進(jìn)行了驗證,所以不會提示用戶填寫任何憑據(jù)。
在本章中,將使用這種方法來連接到“第 09 章 示例文件/Source Data”文件夾。按如下步驟即可做到這一點。
創(chuàng)建一個新的查詢,【來自文件】【從文件夾】。
瀏覽并選擇【文件夾名稱】(“第 09 章 示例文件\Source Data”)【打開】。
此時,會彈出預(yù)覽窗口,不僅顯示用戶選擇的文件夾中的所有文件,而且還顯示任何子文件夾中的文件,如圖9-6所示。

圖9-6 顯示文件夾(和子文件夾)中所有文件的預(yù)覽窗口
需要認(rèn)識到的重要一點是,這個視圖遵循前面顯示的模式,所有列出的列的順序完全相同。
只要連接到一個本地文件夾就行了。剩下的唯一選擇是確定加載數(shù)據(jù)的位置。由于要控制輸出,將選擇通過【轉(zhuǎn)換數(shù)據(jù)】按鈕來編輯查詢。
【注意】
【從文件夾】連接器可用于從個人電腦上的本地文件夾、映射的網(wǎng)絡(luò)驅(qū)動器、甚至從“UNC”文件路徑中讀取數(shù)據(jù)。
9.3.2 連接到 SharePoint 文件夾
如果用戶將數(shù)據(jù)存儲在 SharePoint 站點中,應(yīng)該知道,有如下兩個選項可以連接到數(shù)據(jù)。
如果將該文件夾同步到電腦上,則可以使用前面描述的本地文件夾連接器。
如果連接到云端托管版本的 SharePoint 文件夾,則可以用一個 SharePoint 專用連接器來實現(xiàn)。
與連接本地同步版本的文件夾相比,SharePoint 連接器的運行速度較慢,因為在執(zhí)行查詢時需要下載文件,但不需要將文件存儲在電腦上。按如下步驟來設(shè)置它。
創(chuàng)建一個新的查詢【來自文件】【從 SharePoint 文件夾】。
輸入【站點 URL】的根目錄(不是本地庫或文件夾路徑)。
挑戰(zhàn)在于,與使用本地文件夾不同,用戶不能直接連接到一個子文件夾。而是必須連接到根目錄,然后向下查找,直到找到需要的文件夾。那么,如何找到這個根目錄呢?
最簡單的方法是通過用戶喜愛的網(wǎng)絡(luò)瀏覽器登錄 SharePoint 站點,然后檢查 URL ,如圖9-7所示。將單詞“Forms”左邊的第二個“/”開始前面的 URL 復(fù)制到【站點 URL】。

圖9-7 提取 SharePoint 網(wǎng)址的根目錄
因此,如果域名是 https://monkey.sharepoint.com ,那么將連接到 https://monkey.sharepoint.com/sites/projects。
【注意】
如果用戶公司使用的是 Microsoft 365 ,SharePoint 域名將采用?
.sharepoint.com 的格式。如果用戶 SharePoint 是由自己的 IT 部門管理,它可以是任何東西。
確認(rèn)根目錄后,如果用戶以前從未連接到該網(wǎng),則會提示用戶進(jìn)行身份驗證。此時,用戶需要用適當(dāng)?shù)膽{證登錄,如圖9-8所示。

圖9-8 連接到 Office 365 上的 SharePoint
成功瀏覽此對話框的關(guān)鍵是確保選擇正確的賬戶類型進(jìn)行登錄。由于 SharePoint 的配置方式不同,無法完全預(yù)測用戶需要使用哪種認(rèn)證方式,但以下內(nèi)容應(yīng)有助于提高首次選擇正確登錄方法的幾率。
如果 SharePoint 托管在 Office 365 上,則必須選擇微軟賬戶,用于 Office365 的電子郵件登錄。
如果 SharePoint 是由 IT 部門托管,用戶甚至都不需要登錄就可以匿名訪問。當(dāng)然,如果這不起作用,則需要使用 Windows 憑據(jù)登錄。
【注意】
如果用戶的公司是使用 Office 365 且域名是以 sharepoint.com 結(jié)尾的,那么選擇微軟帳戶,并輸入常規(guī)工作電子郵件憑據(jù)。
【警告】
憑據(jù)會存儲在用戶電腦上的一個文件中,所以選擇錯誤的憑據(jù)會讓用戶進(jìn)入一個【無法連接】狀態(tài)。要管理或更改憑據(jù),需要進(jìn)入【數(shù)據(jù)】【獲取數(shù)據(jù)】【數(shù)據(jù)源設(shè)置】【全局權(quán)限】。選擇它并選擇【清除權(quán)限】。然后在下次嘗試連接時,會被再次提示輸入【站點 URL】。
一旦用戶憑據(jù)通過驗證,Power Query 將嘗試連接到文件夾。如果輸入的是一個有效的 URL,它將展示預(yù)覽窗口。但如果沒有輸入 URL 或者提供的 URL 不是根路徑,那么將會得到一個錯誤信息,并需要再次嘗試。
【注意】
連接到 SharePoint 還有一個細(xì)微的差別,那就是人們實際上也可以在 SharePoint 域的根中存儲文件。要連接到這些文件,仍然要使用從 SharePoint 文件夾連接器,但要輸入 https://
(沒有尾部的文件夾)的 URL。請注意,這并不會枚舉各站點的內(nèi)部數(shù)據(jù)。
9.3.3 連接到 OneDrive for Business
OneDrive for Business 的最大秘密是,它實際上是一個在 SharePoint 上運行的個人網(wǎng)站。這意味著,用戶在連接 OneDrive for Business 的文件夾時,與連接 SharePoint 站點時有相同的選擇:通過【來自文件】選項(如果它同步到用戶的桌面),或通過【來自 SharePoint 文件夾】(如果沒有的話)。
訣竅在于理解要連接到正確的 URL,因為它與 SharePoint【站點URL】不同。當(dāng)通過【來自 SharePoint 文件夾】選項進(jìn)行連接時,用戶需要輸入以下格式的 URL:
https://<SharePointDomain>/personal/<email>用戶還應(yīng)知道,電子郵件地址中的“.”和“@”字符都將被替換為下劃線字符。
【注意】
如果用戶公司使用 Microsoft 365,那么 SharePoint 域名將采用“
-my.sharepoint.com”的格式,但如果用戶的 SharePoint 是由 IT 部門管理,它可能是任何東西。到目前為止,獲得正確 URL 的最簡單方法是在網(wǎng)絡(luò)瀏覽器中登錄 OneDrive for Business,并將所有內(nèi)容復(fù)制到電子郵件地址的末尾,因為這將為用戶獲取正確 URL。
9.3.4 連接到其他文件系統(tǒng)
雖然已經(jīng)介紹了最常見的連接器,但也有其他連接器在連接時返回相同的文件夾模式,包括(但不限于)Blob Storage、Azure Data Lake Gen 1 和 Azure Data Lake Gen 2。每個連接器都需要通過自己的特定 URL 進(jìn)行連接,并要求進(jìn)行身份驗證,但一旦完成,就會進(jìn)入與前面列出的那些連接器相同的界面。
但是,如果用戶在不同的在線存儲系統(tǒng)中存儲文件呢?也許把文件保存在 Google Drive、DropBox、Box、Onedrive(個人版),或者其他幾十個存儲的解決方案中的任何一個。即使不存在與該文件系統(tǒng)的特定連接器,只要供應(yīng)商提供一個應(yīng)用程序,可以將文件同步到用戶 PC 上的本地副本,用戶就可以通過【從文件夾】連接器連接到這些文件。
9.4 步驟 1:篩選文件
在選擇適當(dāng)?shù)牟襟E 1 并在連接到數(shù)據(jù)文件夾后,可以查看到該文件夾下以及任何子文件夾中的所有文件的列表。問題是存儲在這個文件夾中的任何文件都將被包括在內(nèi),但 Power Query 一次只能合并一種類型的文件。
為了防止由于合并多種文件類型而產(chǎn)生的錯誤,需要確保將文件列表限制為單一的文件類型。即使用戶在文件夾中只看到一種類型的文件,也應(yīng)該這樣做,因為用戶永遠(yuǎn)不知道會計部的喬伊(Joey)什么時候會決定把他的 MP3 收藏存儲和需要合并的 Excel 文件存放在同一個文件夾里。更大的問題是,Power Query 還會區(qū)分文字的大小寫,所以如果將列表限制為“.xlsx”文件,當(dāng)喬伊將文件保存為“.XLSX”時,它們會將被篩選掉。這需要更好的可行性,畢竟喬伊很可能就是自己部門的同事。
9.4.1 標(biāo)準(zhǔn)模式
步驟 1 是關(guān)于篩選想合并的文件,并在將來針對不相關(guān)的文件對解決方案進(jìn)行校對。它可以被提煉成一個標(biāo)準(zhǔn)模式,看起來如下所示。
篩選到適當(dāng)?shù)淖游募A級別(如有必要)。
將擴(kuò)展名轉(zhuǎn)換為小寫字母。
將擴(kuò)展名篩選限定為同一種文件類型。
在名稱中通過篩選排除臨時文件(以“~”開頭的文件名)。
執(zhí)行任何需要的額外篩選。
可選:將查詢重命名為“FilesList”,并將其作為一個僅限連接的加載(無需實際加載數(shù)據(jù))。
接下來更詳細(xì)地探討這個問題。
9.4.2 應(yīng)用于示例場景
當(dāng)使用本地【從文件夾】連接器連接到一個文件夾時,能夠直接連接到一個特定的子文件夾。這是很方便的,因為用戶通??梢灾苯虞斎肽繕?biāo)文件夾的直接路徑。另一方面,如果使用的是一個從 SharePoint 或 Azure 中提取數(shù)據(jù)的連接器,就沒有這么幸運了,需要向下篩選到相應(yīng)的子文件夾。這可以通過篩選【文件夾路徑】列來完成,但這里有一點需要注意:每個文件的整個文件夾路徑都包含在這些單元格中。雖然在本地文件系統(tǒng)中很容易閱讀,但在 SharePoint 解決方案中,每個文件名前面都有整個網(wǎng)站的 URL。為了解決這個問題,本書建議用戶采取以下方法來篩選文件列表,只保留所需的子文件夾。
右擊“Folder Path”【替換值】。
【要查找的值】“<原始文件夾路徑或站點 URL>”加上文件夾分隔符。
【替換為】什么都不寫。
因此,在本地文件夾解決方案的情況下【追加】如下路徑數(shù)據(jù):
“C:\MYD\第 09 章 示例文件\Source Data”。
把下面的內(nèi)容替換成空(【替換為】什么都不寫):
“C:\MYD\第 09 章 示例文件\Source Data\”。
單擊【確定】后結(jié)果將如圖9-9所示。

圖9-9 在“Folder Path”列現(xiàn)在只顯示子文件夾名稱
如果用戶連接的是一個本地文件夾,并且需要在子文件夾級別進(jìn)行連接,不用擔(dān)心,根本不需要這樣做。但如果用戶是通過 SharePoint、OneDrive 或 Azure 工作,這個技巧可以更容易看到和篩選到適當(dāng)?shù)淖游募A結(jié)構(gòu)。事實上,對于更深層的文件路徑或有大量文件的場景,用戶可能要重復(fù)這個過程幾次,以便進(jìn)入需要的子文件夾。
將“當(dāng)前”文件夾路徑替換為空(【替換為】什么都不寫)。
篩選到下一個子文件夾級別。
為了找到正確的文件夾,可以多次轉(zhuǎn)到 1。
一旦下鉆到包含用戶預(yù)期文件的特定文件夾或子文件夾,需要確保將列表限制為只有一種文件類型。在這個過程中,需要確保永遠(yuǎn)不會被大小寫敏感性問題所困擾,而且篩選掉臨時文件也是一個很好的做法,特別是如果正在打開著 Excel 文件。按如下步驟即可做到這一點。
右擊“Extension”列【轉(zhuǎn)換】【小寫】。
篩選“Extension”列【文本過濾器】【等于】。
單擊【高級】。
【柱】選擇“Extension”,【運算符】選擇【等于】,【值】輸入“.xlsx”。
【柱】選擇“Name”,【運算符】選擇【開頭不是】,【值】輸入“~”。
此時結(jié)果如圖9-10所示。

圖9-10 通過限制只有有效的 xlsx 文件,來驗證解決方案是可行的
【注意】
在本地硬盤上打開 Excel 文件時,會在文件夾中創(chuàng)建一個以“~”字符為開頭的第二個副本。當(dāng) Excel 關(guān)閉時,該文件會自動消失,但在崩潰的情況下,這并不總是這樣的。通過篩選刪除以“~”開頭的文件,可以避免這些文件。如果不合并 Excel 文件,可以跳過這一步,但無論如何,做這一步?jīng)]有任何影響或問題。
此時,應(yīng)該仔細(xì)檢查列表中保留的文件。為了合并這些文件,它們不僅需要有相同的文件類型,而且必須有一致的內(nèi)部結(jié)構(gòu)。如果仍然有混合的文件(如銷售報告、財務(wù)報表和預(yù)算準(zhǔn)備文件等),可能需要在這個階段做一些額外的篩選,來限制列表中只有那些想要合并的文件,并且具有一致結(jié)構(gòu)。
【注意】
請記住,用戶可以根據(jù)需要對文件名、文件夾、甚至日期進(jìn)行篩選。然而,到目前為止,確保只包括相關(guān)文件的最簡單方法是事先建立一個清晰的文件夾結(jié)構(gòu),以可預(yù)測和可篩選的方式收集文件。
對于這個場景,現(xiàn)在處于一個很好的情況,查看任意 Excel 文件的列表。盡管這些文件仍在主源數(shù)據(jù)文件夾的子文件夾中,但也可以這樣做,并繼續(xù)下一步。
本節(jié)的最后一步是可選的。
將查詢重命名為“FilesList”。
將查詢加載為【僅限連接】查詢。
這些步驟是 Ken 更喜歡構(gòu)建【從文件夾】方案的方式,因為它提供了以下兩個好處。
它構(gòu)建了一個非常明顯的結(jié)構(gòu),在那里可以去查看哪些文件被合并,而不必通過查詢的一部分來確定細(xì)節(jié)。
它只在解決方案中硬編碼一次文件路徑。
雖然解決方案將使用這種方法進(jìn)行說明,但請注意,可以跳過它,繼續(xù)進(jìn)行下一步,無論如何一切都會順利進(jìn)行,如圖9-11所示。

圖9-11 將“FilesList”查詢作為“暫存”查詢加載
9.5 步驟 2:合并文件
隨著對文件列表的整理,現(xiàn)在是時候?qū)ξ募M(jìn)行合并了。
9.5.1 標(biāo)準(zhǔn)模式
該過程的步驟 2 包括以下操作。
可選:【引用】“FilesList”查詢來創(chuàng)建主查詢。
重命名主查詢。
單擊【合并文件】按鈕。
選擇【示例文件】。
此時,Power Query 將執(zhí)行它的魔法,創(chuàng)建四個新的查詢,并在主查詢中添加一系列步驟。
9.5.2 應(yīng)用于示例場景
強(qiáng)烈建議用戶在觸發(fā)【合并文件】過程之前,一定要重新命名主查詢,因為主查詢的名稱可能會被用于一些創(chuàng)建的文件夾和查詢的名稱中。(如果用戶最終在同一個解決方案中合并了多個不同的文件夾,這將使事情更容易被管理)這里的關(guān)鍵是提供一個描述性的名字,不要太長,而且是用戶樂意加載到工作表或數(shù)據(jù)模型中的。在示例場景中,試圖想出一個需要訂購的零件清單,所以像“Parts Required”或“Parts Order”這樣的名稱可能是有意義的。在這個示例中,將保持簡短和干凈,把主查詢稱為“Orders”。
那么,到底哪個查詢是主查詢?這取決于用戶是否決定使用創(chuàng)建專用“FilesList”暫存查詢的可選步驟,步驟如圖9-12所示。
如果加載了“FilesList”查詢作為暫存查詢,主查詢將被稱為“FilesList (2)”,并通過【引用】“FilesList”查詢(右擊【引用】)來創(chuàng)建。
如果沒有把“FilesList”查詢作為一個暫存查詢加載,那么“FilesList”查詢就是主查詢,一旦確定哪個查詢是主查詢,就可以開始【合并文件】的過程。
選擇主查詢并將其重命名為“Orders”。
單擊“Content”列頂部的合并文件(雙箭頭)按鈕。

圖9-12合并一個 Excel 文件中的文件夾
單擊【合并文件】按鈕(上圖中的 #1 ),會彈出一個預(yù)覽窗口。在這個預(yù)覽中,用戶會被要求選擇作為【示例文件】的文件(上圖中的 #2 )。一旦選擇【第一個文件】,還會看到【示例文件】中的全部內(nèi)容(上圖中的 #3 )和所選擇對象的數(shù)據(jù)預(yù)覽(上圖中的 #4 )。
【注意】
使用單獨的“FilesList”查詢的一個缺點是,只能選擇【第一個文件】作為這里的樣本文件選項。如果跳過整個這個步驟,文件夾中的任何文件都可以被選為樣本文件使用。當(dāng)然,這不是什么問題,用戶會發(fā)現(xiàn)還是有技巧使用任何文件作為樣本文件,只需要返回到“FilesList”查詢并進(jìn)行排序或篩選,來獲得想要的文件作為【第一個文件】,再將它作為樣本文件即可。
在這些工作簿的示例中,會注意到它們中有一個名為“Parts”的表格,以及一個“Forecast”和“Matrix”工作表。不幸的是,雖然“Parts”表很好很干凈,但這實際上是作為“Forecast”表上所包含的數(shù)據(jù)范圍的查詢表。因此,看起來需要導(dǎo)入不太整潔的數(shù)據(jù),即“Forecast”工作表,并執(zhí)行一些手動清理,現(xiàn)在就開始。
選擇“Forecast”工作表【確定】。
Power Query 會計算一小段時間,然后合并文件,結(jié)果將如圖9-13所示。

圖9-13 突然間,主查詢中出現(xiàn)了四個新查詢和五個新步驟
這里有很多需要注意的地方。
實際上,這里發(fā)生的事情是,Power Query 創(chuàng)建了一個“幫助程序查詢”的集合,然后在主查詢中添加步驟來使用用它們。在左邊,會看到一個叫做“幫助程序查詢”的文件夾,它包含一個“參數(shù)”、“示例文件”和“轉(zhuǎn)換文件”功能。在這下面,還有一個非常重要的“轉(zhuǎn)換示例文件”。
用戶還應(yīng)該注意,查詢預(yù)覽仍然停留在主查詢上,可以進(jìn)一步在此處窗口進(jìn)行合并文件操作。在本章的步驟 4 中,將進(jìn)一步解釋右邊的步驟,但要認(rèn)識到的重要事情是,Power Query 基本上已經(jīng)提取了每個文件的“Forecast”內(nèi)容,并將它們追加到后面?,F(xiàn)在,如果數(shù)據(jù)已經(jīng)處于縱向追加的目標(biāo)狀態(tài),就算完成了,但是如果看一下圖片中顯示的第一個和第二個文件,會注意到 Power Query 實際上追加了兩個透視表結(jié)構(gòu)的數(shù)據(jù),而且每個數(shù)據(jù)集的標(biāo)題都不同。
一旦閱讀并掌握了整本書的內(nèi)容,就會意識到,用一個查詢來處理這樣的透視表結(jié)構(gòu)羅列的數(shù)據(jù)集其實也是可能的。話雖如此,但這樣做太過于復(fù)雜。如果能在追加數(shù)據(jù)之前對這些數(shù)據(jù)進(jìn)行【逆透視】,從而避免那種令人頭痛的問題,那不是很好嗎?好消息是,可以做到。更好的消息是,當(dāng)利用這些輔助查詢時,它是非常容易的。
【注意】
專業(yè)提示:雖然看起來在合并步驟中只能訪問每個文件中的一個對象,但實際上并非如此。如果需要合并多個工作簿中的多個工作表,或者是每個工作簿中的第二個工作表,而且的確可以做到。只要選擇【轉(zhuǎn)換示例文件】的“Source”步驟,這將提取一個列出所有工作簿對象的表格,類似于第 6 章和第 8 章中所示的 CurrentWorkbook 的示例。
9.6 步驟 3:轉(zhuǎn)換示例文件
在觸發(fā)原始合并之后,要做的下一件事是清洗數(shù)據(jù)。這一步的總體目標(biāo)是做以下工作,來創(chuàng)建一個規(guī)范化的數(shù)據(jù)集。
將數(shù)據(jù)拆分成若干列。
從數(shù)據(jù)集中刪除垃圾行和垃圾列。
為分析而清洗數(shù)據(jù)。
當(dāng)然,每個數(shù)據(jù)集需要處理的方式都不同,但最終的結(jié)果是相同的:將其重塑為一個具有描述性標(biāo)題的數(shù)據(jù)表,并且每行和每列的交叉點有一個數(shù)據(jù)點。
9.6.1 使用轉(zhuǎn)換示例文件的原因
在這個擴(kuò)展的查詢集合中,有如下兩個地方用戶可以重塑數(shù)據(jù)。
“轉(zhuǎn)換示例文件”。
主查詢(Orders)。
本書鼓勵用戶盡可能多地在“轉(zhuǎn)換示例文件”中進(jìn)行數(shù)據(jù)清洗,而不是在主查詢中?!稗D(zhuǎn)換示例文件”的主要好處是,用戶可以根據(jù)一個“示例文件”構(gòu)建查詢,從而使數(shù)據(jù)清洗更加容易。完全避免了追加數(shù)據(jù)集的混亂,因為在數(shù)據(jù)被追加之前,轉(zhuǎn)換會被應(yīng)用到數(shù)據(jù)集上。在像透視、逆透視或分組這樣的操作中,這可能會對減低復(fù)雜性產(chǎn)生巨大影響。
更棒的是,當(dāng)用戶在“轉(zhuǎn)換示例文件”中執(zhí)行數(shù)據(jù)清洗時,這些步驟都會同步到“轉(zhuǎn)換文件”函數(shù)中。然后在追加之前,對文件列表中的所有其他文件調(diào)用這個函數(shù),并且它會自動神奇地執(zhí)行。
【注意】
經(jīng)驗法則是盡可能地使用“轉(zhuǎn)換示例文件”。
9.6.2 使用轉(zhuǎn)換示例文件的方法
使用“轉(zhuǎn)換示例文件”來清洗其中一個工作表。單擊【查詢】導(dǎo)航窗格中的“轉(zhuǎn)換示例文件”查詢,會被帶入如圖9-14所示的視圖。

圖9-14 基于“FilesList”查詢的第一個文件“轉(zhuǎn)換示例文件”的所有 13 行
當(dāng)用戶第一次轉(zhuǎn)到“轉(zhuǎn)換示例文件”時,理解 Power Query 自動創(chuàng)建的步驟很重要。在這種情況下,應(yīng)用步驟如下所示。
Source:包含 Excel 文件中所有可用對象的原始表。
Navigation:導(dǎo)航到表示“Forecast”工作表的表格中去。
Promoted Headers:將第一行提升為標(biāo)題。
在仔細(xì)觀察數(shù)據(jù)時,被提升標(biāo)題的那一行似乎并沒有什么價值,接下來的五行數(shù)據(jù)也是如此。用戶想要的列標(biāo)題實際上包含在文件的第七行中(假設(shè)第一行沒有被提升為標(biāo)題)。按如下解決這個問題。
刪除“Promoted Headers”步驟。
進(jìn)入【主頁】【刪除行】【刪除最前面幾行】“6”。
轉(zhuǎn)到【主頁】【將第一行用作標(biāo)題】。
此時,Power Query 做了一件非常危險的事情如圖9-15所示。發(fā)現(xiàn)它了嗎?

圖9-15 其中“Change Type”步驟不是用戶自己構(gòu)建的
每當(dāng)一行被提升到標(biāo)題時,Power Query 都會幫助用戶自動判別并轉(zhuǎn)換數(shù)據(jù)類型。雖然這很有用,但它也將列的名稱硬編碼到步驟中。問題出在哪里?在本章開頭的案例背景中提到過這個問題:并非所有的區(qū)域都產(chǎn)生相同的產(chǎn)品,所以列的數(shù)量因文件而不同。
那么,當(dāng)用戶遇到另一個不生產(chǎn)產(chǎn)品“A”、“B”或“C”的區(qū)域時會發(fā)生什么?如圖9-16所示的“North”分部,將發(fā)生步驟級錯誤。

圖9-16 了解數(shù)據(jù)將有助于在合并文件時預(yù)測和避免問題
【注意】
在更改“轉(zhuǎn)換示例文件”時要小心,特別是在文件之間列名可能不同的情況下。只有在確保在所有情況下都會存在的同樣列名時才能硬編碼。
事實上,在這個階段,并不需要聲明數(shù)據(jù)類型,而需要繼續(xù)準(zhǔn)備數(shù)據(jù),以便進(jìn)行【逆透視】,但要以安全的方式。
刪除“Changed Type”步驟。
篩選“Part Nbr”列,取消勾選“Total”。
找到“Total”列并刪除。
右擊“Part Nbr”列【逆透視其他列】。
結(jié)果將如圖9-17所示。

圖9-17 【逆透視】的數(shù)據(jù)集
【注意】
等一下,剛剛在刪除“Total”列的時候,不是已經(jīng)把它的名字硬編碼了嗎?的確,是這樣做了。但是這樣做安全嗎?這里的答案有點微妙,但既然它似乎在東部和北部的數(shù)據(jù)范圍內(nèi)都出現(xiàn)了,那么也許可以假設(shè)它將出現(xiàn)在所有的數(shù)據(jù)集中。如果沒有,我們可以通過將它留在數(shù)據(jù)中進(jìn)行【逆透視】,然后從“屬性”列中篩選掉“Total”來解決這個問題,即使那時不存在“Total”,也不會產(chǎn)生任何錯誤的。
隨著數(shù)據(jù)被正確的【逆透視】,此時可以更改列名,設(shè)置數(shù)據(jù)類型,如下所示即可。
重命名“屬性”列為“Product”。
重命名“值”列為“Units”。
選擇所有列【轉(zhuǎn)換】【檢測數(shù)據(jù)類型】。
此時結(jié)果將如圖9-18所示。

圖9-18 為“示例文件”生成的 36 行最終輸出的一部分
忽略“Forecast”硬編碼列名的潛在問題所帶來的挑戰(zhàn),當(dāng)把它保持在單個文件的范圍內(nèi)時,這是一個相當(dāng)直接的【逆透視】工作。如果試圖在主查詢中這樣做,那就會復(fù)雜得多了。
【警告】
如果在運行合并時未能預(yù)料到問題,并在其中一個文件中出現(xiàn)步驟級錯誤,會發(fā)生什么?當(dāng)然,用戶需要調(diào)試它,回到“FilesList”并插入臨時步驟,保留前“x”行或刪除前“x”行,直到用戶找到是哪個查詢導(dǎo)致錯誤。一旦把它作為“FilesList”中的第一個查詢,就可以在“轉(zhuǎn)換示例文件”中調(diào)試它,看看哪里出了問題。
9.7 步驟 4:通過主查詢規(guī)范數(shù)據(jù)
現(xiàn)在,回到主查詢,看看目前的效果。當(dāng)這樣做時,會看到一個步驟級錯誤。
9.7.1 修復(fù)主查詢中的錯誤
不幸的是,這看起來很熟悉,如圖9-19所示。

圖9-19 這到底是怎么回事
這個錯誤的根本原因是主查詢的“Changed Type”步驟。還記得 Power Query 的“Promoted Headers”步驟嗎?這生成了“Production Forecast”、“Column 2”等標(biāo)題列,而由于 Power Query 在主查詢中也硬編碼了一個“Changed Type”步驟,這些列名會在這步自動使用。可以在公式欄中去掉那個列名,只將其他列名提升為標(biāo)題。
這個錯誤非常常見,只要刪除主查詢中的“Changed Type”步驟就可以輕松解決。此時結(jié)果將如圖9-20所示。

圖9-20 步驟級錯誤消失
【注意】
專業(yè)提示:有經(jīng)驗的用戶提前知道要在“轉(zhuǎn)換示例文件”中會重命名列,可以提前主查詢中刪除“Changed Type”步驟。
9.7.2 保存文件屬性
雖然“轉(zhuǎn)換示例文件”在最后包含了 36 行的預(yù)覽,但這里的預(yù)覽窗口顯示 288 行,表明它將數(shù)據(jù)轉(zhuǎn)換模式應(yīng)用于文件列表中的每個文件,然后將它們【追加】到一個長表中。這真是太棒了,但仍有一個問題。
提交的每個文件都屬于不同的區(qū)域,但區(qū)域名稱并不包含在文件本身中。相反,該文件是使用區(qū)域的名稱命名的。挑戰(zhàn)在于,似乎在這個過程中的某個地方丟失了這個名字。此外,雖然原文件包含了季度末的日期,但這些數(shù)據(jù)被保存在通過“轉(zhuǎn)換示例文件”刪除的前幾行中。能夠?qū)@些原文件采取一些方法來解決,讓每個部門都存儲在一個子文件夾中,并以“yyyy-qq”格式命名。但是,在這個過程中,似乎也丟失了文件夾名稱。那么如何把這些信息找回來呢?
在這一點上,回顧一下 Power Query【合并文件】時在主查詢中生成的步驟是有幫助的,其中第一個步驟是“Filtered Hidden Files1”。
【注意】
如果用戶選擇創(chuàng)建一個單獨的“FilesList”查詢,“Filtered Hidden Files1”步驟將是第二個步驟。如果用戶選擇跳過這一步,它將出現(xiàn)在查詢的后面,但將緊接在用戶觸發(fā)【合并文件】過程的位置之后。
下面是后續(xù)步驟的內(nèi)容。
Filtered Hidden Files1(篩選的隱藏文件1):添加一個篩選器,從文件列表中刪除任何隱藏的文件(是的,Power Query 也會列出存儲在文件夾中的隱藏文件和系統(tǒng)文件)。
Invoke Custom Function1(調(diào)用自定義函數(shù)1):添加一個新的列,該列利用基于“轉(zhuǎn)換示例文件”中的操作而生成的“轉(zhuǎn)換文件”函數(shù)。這一步的作用是創(chuàng)建一個列,生成從每個文件轉(zhuǎn)換后的表。
Removed Other Columns1(刪除的其他列1):此步驟刪除了所有的列,除了通過調(diào)用自定義函數(shù)步驟創(chuàng)建的那一列。正是這一步,文件名和文件夾名消失了。
Expanded Table Column1(擴(kuò)展的表格列1):這個步驟擴(kuò)展了通過“Invoke Custom Function 1”步驟添加的列的結(jié)果。其結(jié)果是每個表都被【追加】到一個長表中。
理解了這一點,此時將知道只需要修改“Removed Other Columns 1”步驟,來保留 Power Query 認(rèn)為不需要的任何文件屬性。
選擇“Removed Other Columns1”步驟,單擊齒輪圖標(biāo)。
勾選“Name”和“Folder Path”旁邊的復(fù)選框【確定】。
此時,結(jié)果將如圖9-21所示,現(xiàn)在已經(jīng)將“Name”和“Folder Path”列恢復(fù)到數(shù)據(jù)集中。

圖9-21 修改“Removed Other Columns1”步驟,使關(guān)鍵列重新出現(xiàn)
9.7.3 添加更多的步驟
現(xiàn)在,可以對需要應(yīng)用于所有文件的操作的查詢做進(jìn)一步的修改。將采取的具體操作如下。
選擇“Expanded Table Column1”步驟(只是為了避免在下面的每個操作上都被提示插入一個新的步驟)。
將“Name”列重命名為“Division”。
右擊“Division”列【替換值】【要查找的值】輸入“.xlsx”【替換為】什么都不填,【確定】。
右擊“Folder Path”列【拆分列】【按分隔符】【最左側(cè)的分隔符】【確定】。
【警告】
在拆分列時,Power Query 會自動添加一個“Changed Type”步驟。用戶應(yīng)該考慮一下這是否有必要。如果它可能會在將來引起問題,那么請刪除它,并在加載到最終目的地之前將數(shù)據(jù)類型作為最后一步來應(yīng)用。
由于“Changed Type”在這里似乎沒有必要,所以將刪除它,即使它不會引起任何問題。
刪除“Changed Type”步驟。
將“Folder Path.1”列重命名為“Year”。
將“Folder Path.2”列重命名為“Quarter”。
右擊“Quarter”列【替換值】【要查找的值】輸入“\”,【替換為】什么都不輸入【確定】。
選擇所有列【轉(zhuǎn)換】【檢測數(shù)據(jù)類型】。
此時,主查詢已經(jīng)完成,對數(shù)據(jù)進(jìn)行【逆透視】并【追加】,同時保留了文件名和文件夾的部分內(nèi)容。來增加分析所需的關(guān)鍵元素,如圖9-22所示。

圖9-22 【逆透視】數(shù)據(jù)集的前四列是由文件夾和文件名驅(qū)動的
【警告】
數(shù)據(jù)類型永遠(yuǎn)不會從“轉(zhuǎn)換示例文件”中繼承。在加載到工作表或數(shù)據(jù)模型之前,一定要確保將更改數(shù)據(jù)類型作為查詢的最后一步來設(shè)置。
隨著數(shù)據(jù)的成功轉(zhuǎn)換,現(xiàn)在是時候加載它,以便用戶可以使用它來做報告。這一次將把它加載到數(shù)據(jù)模型中,如下步驟所示。
在 Power BI 中,只需單擊【關(guān)閉并應(yīng)用】。
在 Excel 中,進(jìn)入【主頁】【關(guān)閉并上載至】,選擇【僅創(chuàng)建連接】,同時勾選【將此數(shù)據(jù)添加到數(shù)據(jù)模型】復(fù)選框,如圖9-23所示。

圖9-23 加載數(shù)據(jù)到數(shù)據(jù)模型
將會注意到,盡管在一個會話中創(chuàng)建了多個查詢,但只有主查詢被加載到目的地。所有的輔助查詢,包括“轉(zhuǎn)示例文件”,默認(rèn)情況下都是作為“暫存”查詢僅保持連接的。
9.8 更新解決方案
隨著數(shù)據(jù)的加載,現(xiàn)在可以構(gòu)建一些可重復(fù)使用的商業(yè)智能。
9.8.1 使用數(shù)據(jù)
為了演示從導(dǎo)入到刷新的完整周期,需要使用“矩陣”或“數(shù)據(jù)透視表”建立一個快速報告。創(chuàng)建這個對象的步驟將取決于用戶使用的是哪種應(yīng)用程序。
如果使用的是 Power BI。
在【報表】頁面,進(jìn)入【可視化】面板【矩陣】。
如果使用的是 Excel。
在一個空白工作表上選擇 B3 【插入】【數(shù)據(jù)透視表】。
選擇【來自數(shù)據(jù)模型】【確定】。
一旦創(chuàng)建了這個對象,從右邊的“Orders”表中拖動以下列,到字段區(qū)域,如下所示。
值:“Units”。
行:“Part Nbr”。
列:“Year”,“Quarter”。
結(jié)果(在 Excel 和 Power BI 中)如圖9-24所示。此時 Power BI 中展開到了季度級別來顯示季度數(shù)據(jù)。

圖9-24 比較 Excel 和 Power BI 的結(jié)果
9.8.2 添加新文件
現(xiàn)在是時候探索一下當(dāng)解決方案中添加新數(shù)據(jù)時會發(fā)生什么。
如果在 Windows 資源管理器中打開“第 09 章示例文件”文件夾,會發(fā)現(xiàn)它不僅包含連接的示例數(shù)據(jù)文件夾;還有一個“2019 Q4”文件夾,它包含不同區(qū)域的更新數(shù)據(jù)。將該文件夾拖入“Source Data”文件夾中,這樣在驅(qū)動解決方案的文件夾中就有四個季度的文件夾,如圖9-25所示。

圖9-25 現(xiàn)在是時候向解決方案添加一些新的數(shù)據(jù)了
移動文件夾后,返回解決方案并點擊【刷新】。
Power BI:轉(zhuǎn)到【主頁】【刷新】。
Excel:轉(zhuǎn)到【數(shù)據(jù)】【全部刷新】。
幾秒鐘后,可以看到數(shù)據(jù)結(jié)果已經(jīng)包括了第四季度的數(shù)據(jù),如圖9-26所示。

圖9-26數(shù)據(jù)已更新
這是多么令人難以置信,不僅可以很容易地【追加】多個文件,而且剛剛創(chuàng)建了一個可【刷新】的商業(yè)智能報表,當(dāng)加入新的數(shù)據(jù)時,只需單擊幾下就可以更新文件,這就是現(xiàn)在的解決方案。
在這里,需要真正要認(rèn)識到的是,用戶可以根據(jù)接收數(shù)據(jù)的方式選擇構(gòu)建和更新解決方案。考慮一下如圖9-27所示的圖表,它顯示了在更新外部文件上的解決方案時可用的靈活性和更新方法。

圖9-27 更新連接到外部文件的解決方案
無論用戶直接用同一文件覆蓋舊文件,或者想建立一個不斷增長(或滾動)的積累文件的解決方案,Power Query 都能滿足這些需求。
9.8.3 只用最后 x 個文件以提升速度
盡管【從文件夾】的解決方案很神奇,但用戶需要考慮,如果只是不斷向源數(shù)據(jù)文件夾添加新的文件,它最終會變慢。處理一百個文件的時間要比處理十個文件的時間長,這也是合理的。特別是考慮到 Power Query 不能被配置為只更新新的或數(shù)據(jù)發(fā)生改變的文件。每次用戶單擊【刷新】按鈕時,Power Query 都會重新加載文件夾中所有文件的所有數(shù)據(jù)。
想象一下,把以前構(gòu)建的解決方案,保持運行 10 年。每年有 16 個數(shù)據(jù)文件( 4 個區(qū)域 x 4 個季度),從 2020 年到 2030 年結(jié)束時,將會處理超過 176 個文件。現(xiàn)在,公平地說,這些文件是相當(dāng)小的,但如果每個文件需要 5 秒鐘來刷新呢?現(xiàn)在超過 14 分鐘來刷新解決方案,這個時間比較長,會讓人感覺就像永遠(yuǎn)一樣。
在構(gòu)建這些解決方案時,用戶必須問自己的第一個問題是,是否真的需要所有這些數(shù)據(jù)。在 2030 年,真的會關(guān)心 2019 年的數(shù)據(jù)嗎?如果要與前一年的數(shù)據(jù)進(jìn)行比較,可能最多需要 32 個文件。那么,為什么不限制解決方案來做到這一點呢?
限制文件的秘訣是回到查詢的文件列表部分,按如下步驟操作。
按日期的降序?qū)ξ募M(jìn)行排序。
使用【保留最前面幾行】來保留需要的前幾個文件。
訣竅實際上是要弄清楚哪一個字段要用于日期排序。在這個示例中,可以使用“Folder Path”列,因為用戶是按照邏輯順序來命名這些文件的。如果沒有這樣的結(jié)構(gòu),那么可能想依靠“創(chuàng)建日期”或“修改日期”字段中的一個。
【注意】
請記住,保存的文件數(shù)量可以在一個合理需要的任何數(shù)量之間變化。根據(jù)過去多個項目的經(jīng)驗,一般只保留過去 24 個滾動月的數(shù)據(jù)。
【警告】
如果用戶只是把新的數(shù)據(jù)文件復(fù)制和粘貼到一個文件夾中,在排序時使用“創(chuàng)建日期”屬性應(yīng)該是安全的,但是,要注意“創(chuàng)建日期”字段可能比“修改日期”要新。其原因是,通過復(fù)制和粘貼創(chuàng)建的文件在粘貼時將被“創(chuàng)建”,盡管它在源文件最后一次被修改時已經(jīng)被“修改”。依靠“最后修改日期”也可能是危險的,因為僅僅是打開某些文件類型就可能算是修改。
正在學(xué)習(xí) Power Query 嗎?可以加入本主題的交流群一些交流分享。

Power Query 真經(jīng)連載
往期推薦
Power BI 終極系列課程《BI真經(jīng)》

BI真經(jīng) - 讓數(shù)據(jù)真正成為你的力量
掃碼與精英一起討論 Power BI,驗證碼:data2022
掃碼與精英一起學(xué)習(xí) Power Query,驗證碼:PQ真經(jīng)
點擊“閱讀原文”進(jìn)入學(xué)習(xí)中心
↙
