Power Query 系列 (20) - 如何在外部使用Power Query提供的服務(wù)

Power Query 作為桌面端數(shù)據(jù)清理和轉(zhuǎn)換的工具件甥,能極大解放生產(chǎn)力藏研,將繁瑣的數(shù)據(jù)處理工作從重復(fù)的勞動中解放出來漠嵌。那么咐汞,Power Query 能否對外提供計算服務(wù)呢判哥?或者說 Power Query 有沒有對外提供的編程接口? 根據(jù)我的探索碉考,似乎沒有,但在網(wǎng)絡(luò)上找到下面的兩種 walkaround 方式挺身,都比較小眾侯谁。所以如果真的需要數(shù)據(jù)處理、數(shù)據(jù)分析服務(wù)的話章钾,不如選擇其他的方案墙贱,比如 pandas 等等,擁有更大的自由度贱傀。

  • 方式:將數(shù)據(jù)加載到 Power Pivot惨撇,通過 ADO 方式調(diào)用 Power Pivot 的編程接口
  • 方式:利用微軟的 Power Query SDK,在 .NET 平臺使用 M 語言府寒,獲取查詢結(jié)果魁衙。

本篇主要介紹第一種方式,第二種方式給出一些參考鏈接株搔。

利用 Power Pivot 的數(shù)據(jù)模型編程接口

貌似 PQ 沒有對外的編程接口剖淀,但是 Power Pivot 有通過 Excel 工作簿的編程接口,所以我們可以將數(shù)據(jù)加載到 Power Pivot纤房, 然后在外部調(diào)用纵隔。因為本文主要是講 Power Query ,所以對 Power Pivot 不做展開炮姨。Power Pivot 是微軟推出的 Excel COM 加載項 (COM Add-in)捌刮,可以在微軟官方免費(fèi)下載并安裝,然后啟用加載項即可舒岸。安裝之后绅作,啟用方法如下:通過【文件】>【選項】打開如下界面,選擇加載項類型的【COM加載項】蛾派,點(diǎn)擊轉(zhuǎn)到按鈕棚蓄。

image

然后在出現(xiàn)的對話框中,勾上"Microsoft Power Pivot for Excel"碍脏。如果想不啟用該插件梭依,也是通過相同的路徑進(jìn)入該界面,去掉這個勾典尾。

image

接下來役拴,以之前文章講解的 PQ 實現(xiàn)的進(jìn)出存查詢為例,進(jìn)一步講解如何通過 VBA + ADO 調(diào)用 PQ 的查詢結(jié)果钾埂。打開上一篇示例數(shù)據(jù)的 Excel 文件河闰,選擇 stock_balance 查詢科平,點(diǎn)擊右鍵菜單的【加載到】菜單:

image

選擇“將此數(shù)據(jù)添加到數(shù)據(jù)模型”:

image

然后在【數(shù)據(jù)】選項卡,點(diǎn)擊【管理數(shù)據(jù)模型】功能項:

image

這樣就進(jìn)入了 Power Pivot 的界面姜性。暫時不對 Power Pivot 的細(xì)節(jié)展開瞪慧。

image

打開一個新的 Excel 工作簿,按下 Alt + F11 進(jìn)入 VBE (Visual Basic Editor) 環(huán)境部念。在 VBE 環(huán)境中弃酌,通過【工具】>【引用】添加 Microsoft ActiveX Data Model 的引用。這個是 COM 庫儡炼,運(yùn)行 ADO 需要妓湘。

image

新建一個模塊 (Module),在模塊中新建一個函數(shù) ExportExcelDataModel乌询。該函數(shù)實現(xiàn)將 Excel Data Model 導(dǎo)出到工作表:

Public Function ExportExcelDataModel(
    excelFilePath As String, 
    modelName As String, 
    targetSheet As Worksheet)
    
    '''Reference: Microsoft ActiveX Data Objects
 
    Dim wbTarget As Workbook  'target workbook
    Dim ws As Worksheet
    Dim conn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim sQueryString As String

    'Suppress alerts and screen updates
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False

    Err.Clear
    On Error GoTo ErrHandler
    
    Set wbTarget = Application.Workbooks.Open(excelFilePath)
 
    'Make sure the model is loaded
    wbTarget.Model.Initialize
    wbTarget.Model.Refresh

    Set conn = wbTarget.Model.DataModelConnection.ModelConnection.ADOConnection
    sQueryString = "EVALUATE '" & modelName & "'"
    
    Set rs = New ADODB.Recordset
    rs.CursorLocation = adUseClient
    rs.Open sQueryString, conn
    
    targetSheet.Cells.ClearContents
    ' Write header
    Dim colIndex As Integer
    For colIndex = 0 To rs.Fields.Count - 1
        targetSheet.Range("A1").Offset(0, colIndex).Value = rs.Fields(colIndex).Name
    Next
    
    ' Write Lines
    targetSheet.Range("A1").Offset(1, 0).CopyFromRecordset rs
 
    rs.Close
    Set rs = Nothing    
    ' Close workbook
    wbTarget.Close
 
ExitPoint:
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True

    Set rs = Nothing
    Exit Function
 
ErrHandler:
    MsgBox "An error occured - " & Err.Number & "," & Err.Description, vbOKOnly
    Resume ExitPoint
End Function

因為本文的主題是 PQ榜贴,所以不對代碼的細(xì)節(jié)進(jìn)行講解,只稍微提一下 ADO 讀取 Excel Data Model 的要點(diǎn):

  • 通過 someWorkbook.Model.DataModelConnection.ModelConnection.ADOConnection 獲得數(shù)據(jù)連接
  • CopyFromRecordSet 方法要求 RecordSet 的 Cursor Location 為 adUseClient妹田,否則結(jié)果錯誤唬党,并沒有拋出 Exception 或 Error,而是數(shù)據(jù)出現(xiàn)錯誤鬼佣。如果手工代碼循環(huán)的方式獲取初嘹,則沒有問題。

然后再添加一個子例程沮趣,調(diào)用函數(shù) ExportExcelDataModel屯烦,下面的調(diào)用過程既是調(diào)用代碼,也能體現(xiàn)函數(shù)的調(diào)用方法房铭。

Public Sub DoExport()
    Dim filePath As String
    filePath = ThisWorkbook.Path & "\pqservice.xlsx"

    Dim conn As New ADODB.Connection
    conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        "Extended Properties=""Excel 12.0;HDR=No"";" & _
        "data source=" & filePath
    
    ' Update cell in another excel workbook
    Dim sql As String
    sql = "UPDATE [Criteria$A1:B3] SET F2=5 WHERE F1='month'"
    conn.Open
    conn.Execute sql
    conn.Close
    
    ' Retrieve data
    Dim sht As Worksheet
    Set sht = Sheet1    
    Call ExportExcelDataModel(filePath, "stock_balance", sht)
    
    sht.Activate
End Sub

因為需要將篩選條件:月份驻龟,從當(dāng)前工作簿傳遞到目標(biāo)工作簿,我采用了 ADO 直接讀寫 Excel 工作表的方法缸匪。但我平時很少用到 ADO 讀寫 Excel 工作表的方式翁狐,因為數(shù)據(jù)盡可能存放在數(shù)據(jù)庫中,而不是 Excel凌蔬。在目標(biāo)工作簿 -- 即提供 Power Query 服務(wù)的 Excel 工作表中露懒,篩選條件界面如下:

image

所以用

sql = "UPDATE [Criteria$A1:B3] SET F2=5 WHERE F1='month'"

表示更新的 SQL 語句。連接字符串中 HDR = No砂心,表示不啟用 Header Row懈词,所以此語句 F1 表示 A 列,F(xiàn)2 表示 B 列辩诞。Criteria 是工作表名稱 (worksheet name)坎弯。

本示例代碼提供的功能:

  • 將目標(biāo)工作表的 B3 單元格值修改為 5 (月份條件)
  • 然后對數(shù)據(jù)據(jù)模型進(jìn)行刷新操作,確保獲取的是最新計算的結(jié)果
  • 將 Data Model 的計算結(jié)果寫入 RecordSet 對象,再將 RecordSet 對象數(shù)據(jù)寫入當(dāng)前工作簿的 Sheet1 (函數(shù)的功能)

從理論上來說抠忘,這種方法適用于所有能操作 COM 對象 (ADO ActiveX) 的編程語言撩炊。

Power Query SDK

微軟提供了 Power Query SDK,從而賦予了在 .net 平臺中可以直接使用 M 語言的功能崎脉。盡管官方的說法拧咳,Power Query SDK 已經(jīng)在 Visual Studio 2019 中可以使用,但我在安裝的時候沒有成功囚灼,也不打算在 Visual Studio 2017 或更老的版本中折騰骆膝,這里只能給出相關(guān)的連接,有興趣的讀者請自行探索啦撮。

Power Query SDK 是一擴(kuò)展名為 vsix 的文件,在 Visual Studio 中安裝的方法請參考:vs2015如何安裝vsix擴(kuò)展工具

網(wǎng)上為數(shù)不多的參考文章:

示例數(shù)據(jù)和代碼

github - Consuming Power Query Service

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末汪厨,一起剝皮案震驚了整個濱河市赃春,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌劫乱,老刑警劉巖织中,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異衷戈,居然都是意外死亡狭吼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門殖妇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刁笙,“玉大人,你說我怎么就攤上這事谦趣∑N” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵前鹅,是天一觀的道長摘悴。 經(jīng)常有香客問我,道長舰绘,這世上最難降的妖魔是什么蹂喻? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮捂寿,結(jié)果婚禮上口四,老公的妹妹穿的比我還像新娘。我一直安慰自己秦陋,他們只是感情好窃祝,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般粪小。 火紅的嫁衣襯著肌膚如雪大磺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天探膊,我揣著相機(jī)與錄音杠愧,去河邊找鬼。 笑死逞壁,一個胖子當(dāng)著我的面吹牛流济,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腌闯,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼绳瘟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了姿骏?” 一聲冷哼從身側(cè)響起糖声,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎分瘦,沒想到半個月后蘸泻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嘲玫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年悦施,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片去团。...
    茶點(diǎn)故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡抡诞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出土陪,到底是詐尸還是另有隱情沐绒,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布旺坠,位于F島的核電站乔遮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏取刃。R本人自食惡果不足惜蹋肮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望璧疗。 院中可真熱鬧坯辩,春花似錦、人聲如沸崩侠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至改抡,卻和暖如春矢炼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背阿纤。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工句灌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人欠拾。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓胰锌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親藐窄。 傳聞我的和親對象是個殘疾皇子资昧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容