【发布时间】:2016-04-23 02:44:27
【问题描述】:
当我不得不使用 Python 从 PowerPivot 模型中读取一些数据时,看似微不足道的任务变成了一场真正的噩梦。我相信在过去的几天里我已经对此进行了很好的研究,但现在我碰壁了,希望 Python/SSAS/ADO 社区提供一些帮助。
基本上,我要做的就是以编程方式访问存储在 PowerPivot 模型中的原始数据 - 我的想法是通过下面列出的方法之一连接到底层 PowerPivot(即 MS Analysis Services)引擎,列出包含在模型,然后使用简单的 DAX 查询(类似于EVALUATE (table_name))从每个表中提取原始数据。很容易,对吧?好吧,也许不是。
0。一些背景资料
如您所见,我尝试了几种不同的方法。我会尽可能仔细地记录所有内容,以便那些不熟悉 PowerPivot 功能的人能够很好地了解我想要做什么。
首先,一些关于以编程方式访问 Analysis Services 引擎的背景知识(上面写着 2005 SQL Server,但所有这些都应该仍然适用):SQL Server Data Mining Programmability 和 Data providers used for Analysis Services connections。
我将在下面的示例中使用的示例 Excel/PowerPivot 文件可在此处找到:Microsoft PowerPivot for Excel 2010 and PowerPivot in Excel 2013 Samples。
另外,请注意,我使用的是 Excel 2010,因此我的一些代码是特定于版本的。例如。如果您使用的是 Excel 2013,wb.Connections["PowerPivot Data"].OLEDBConnection.ADOConnection 应该是 wb.Model.DataModelConnection.ModelConnection.ADOConnection。
我将在整个问题中使用的连接字符串基于此处找到的信息:Connect to PowerPivot engine with C#。此外,某些方法显然需要在数据检索之前对 PowerPivot 模型进行某种初始化。见这里:Automating PowerPivot Refresh operation from VBA。
最后,这里有几个链接表明这应该是可以实现的(但是请注意,这些链接主要是指 C#,而不是 Python):
- Made connection to PowerPivot DataModel, how can I fill a dataset with it?
- Connecting to PowerPivot with C#
- 2013 C# connection to PowerPivot DataModel
-
Connecting Tableau and PowerPivot. It just works.(表明外部应用程序实际上可以读取 PowerPivot 模型数据 - 请注意,Tableau 加载项安装了
Interop.ADODB.dll程序集,我猜它是用来访问 PowerPivot 数据的)
1。使用 ADOMD
import clr
clr.AddReference("Microsoft.AnalysisServices.AdomdClient")
import Microsoft.AnalysisServices.AdomdClient as ADOMD
ConnString = "Provider=MSOLAP;Data Source=$Embedded$;Locale Identifier=1033;
Location=H:\\PowerPivotTutorialSample.xlsx;SQLQueryMode=DataKeys"
Connection = ADOMD.AdomdConnection(ConnString)
Connection.Open()
在这里,问题似乎是 PowerPivot 模型尚未初始化:
AdomdConnectionException: A connection cannot be made. Ensure that the server is running.
2。使用 AMO
import clr
clr.AddReference("Microsoft.AnalysisServices")
import Microsoft.AnalysisServices as AMO
ConnString = "Provider=MSOLAP;Data Source=$Embedded$;Locale Identifier=1033;
Location=H:\\PowerPivotTutorialSample.xlsx;SQLQueryMode=DataKeys"
Connection = AMO.Server()
Connection.Connect(ConnString)
同样的故事,“服务器没有运行”:
ConnectionException: A connection cannot be made. Ensure that the server is running.
请注意,AMO 在技术上不用于查询数据,但我将其作为连接到 PowerPivot 模型的潜在方式之一。
3。使用 ADO.NET
import clr
clr.AddReference("System.Data")
import System.Data.OleDb as ADONET
ConnString = "Provider=MSOLAP;Data Source=$Embedded$;Locale Identifier=1033;
Location=H:\\PowerPivotTutorialSample.xlsx;SQLQueryMode=DataKeys"
Connection = ADONET.OleDbConnection()
Connection.ConnectionString = ConnString
Connection.Open()
这类似于What's the simplest way to access mssql with python or ironpython?。不幸的是,这也不起作用:
OleDbException: OLE DB error: OLE DB or ODBC error: The following system error occurred:
The requested name is valid, but no data of the requested type was found.
4。通过 adodbapi 模块使用 ADO
import adodbapi
ConnString = "Provider=MSOLAP;Data Source=$Embedded$;Locale Identifier=1033;
Location=H:\\PowerPivotTutorialSample.xlsx;SQLQueryMode=DataKeys"
Connection = adodbapi.connect(ConnString)
类似于Opposite Workings of OLEDB/ODBC between Python and MS Access VBA。我得到的错误是:
OperationalError: (com_error(-2147352567, 'Exception occurred.', (0, u'Microsoft OLE DB
Provider for SQL Server 2012 Analysis Services.', u'OLE DB error: OLE DB or ODBC error: The
following system error occurred: The requested name is valid, but no data of the requested
type was found...
这与上面的 ADO.NET 基本相同。
5。通过 Excel/win32com 模块使用 ADO
from win32com.client import Dispatch
Xlfile = "H:\\PowerPivotTutorialSample.xlsx"
XlApp = Dispatch("Excel.Application")
Workbook = XlApp.Workbooks.Open(Xlfile)
Workbook.Connections["PowerPivot Data"].Refresh()
Connection = Workbook.Connections["PowerPivot Data"].OLEDBConnection.ADOConnection
Recordset = Dispatch('ADODB.Recordset')
Query = "EVALUATE(dbo_DimDate)" #sample DAX query
Recordset.Open(Query, Connection)
这种方法的想法来自这篇使用 VBA 的博客文章:Export a table or DAX query from Power Pivot to CSV using VBA。请注意,此方法使用初始化模型(即“服务器”)的显式刷新命令。这是错误消息:
com_error: (-2147352567, 'Exception occurred.', (0, u'ADODB.Recordset', u'Arguments are of
the wrong type, are out of acceptable range, or are in conflict with one another.',
u'C:\\Windows\\HELP\\ADO270.CHM', 1240641, -2146825287), None)
但是,ADO 连接似乎已经建立:
-
type(Connection)返回instance -
print(Connection)返回Provider=MSOLAP.5;Persist Security Info=True;Initial Catalog=Microsoft_SQLServer_AnalysisServices;Data Source=$Embedded$;MDX Compatibility=1;Safety Options=2;ConnectTo=11.0;MDX Missing Member Mode=Error;Subqueries=2;Optimize Response=3;Cell Error Mode=TextValue
似乎问题在于 ADODB.Recordset 对象的创建。
6。通过Excel/win32com使用ADO,直接使用ADODB.Connection
from win32com.client import Dispatch
ConnString = "Provider=MSOLAP;Data Source=$Embedded$;Locale Identifier=1033;
Location=H:\\PowerPivotTutorialSample.xlsx;SQLQueryMode=DataKeys"
Connection = Dispatch('ADODB.Connection')
Connection.Open(ConnString)
类似于Connection to Access from Python [duplicate] 和Query access using ADO in Win32 platform (Python recipe)。不幸的是,Python 吐出的错误与上面两个示例中的相同:
com_error: (-2147352567, 'Exception occurred.', (0, u'Microsoft OLE DB Provider for SQL
Server 2012 Analysis Services.', u'OLE DB error: OLE DB or ODBC error: The following system
error occurred: The requested name is valid, but no data of the requested type was found.
..', None, 0, -2147467259), None)
7.通过Excel/win32com使用ADO,直接使用ADODB.Connection加模型刷新
from win32com.client import Dispatch
Xlfile = "H:\\PowerPivotTutorialSample.xlsx"
XlApp = Dispatch("Excel.Application")
Workbook = XlApp.Workbooks.Open(Xlfile)
Workbook.Connections["PowerPivot Data"].Refresh()
ConnStringInternal = "Provider=MSOLAP.5;Persist Security Info=True;Initial Catalog=
Microsoft_SQLServer_AnalysisServices;Data Source=$Embedded$;MDX
Compatibility=1;Safety Options=2;ConnectTo=11.0;MDX Missing Member
Mode=Error;Optimize Response=3;Cell Error Mode=TextValue"
Connection = Dispatch('ADODB.Connection')
Connection.Open(ConnStringInternal)
我希望我可以初始化 Excel 的一个实例,然后初始化 PowerPivot 模型,然后使用 Excel 用于嵌入式 PowerPivot 数据的内部连接字符串创建一个连接(类似于How do you copy the powerpivot data into the excel workbook as a table? - 请注意,连接字符串是不同的来自我在其他地方使用过的那个)。不幸的是,这不起作用,我的猜测是 Python 在单独的实例中启动 ADODB.Connection 进程(因为当我在没有首先初始化 Excel 的情况下执行最后三行时收到相同的错误消息等):
com_error: (-2147352567, 'Exception occurred.', (0, u'Microsoft OLE DB Provider for SQL
Server 2012 Analysis Services.', u'Either the user, ****** (masked), does not have access
to the Microsoft_SQLServer_AnalysisServices database, or the database does not exist.',
None, 0, -2147467259), None)
【问题讨论】:
-
请问为什么需要直接访问PP模型中的数据? Power Pivot 数据必须从其他来源加载,无论是公开更强大的 ODBC 接口(或其他编程连接)的数据源还是可以在 Pyhon 中本地使用的平面文件。
-
我在一个行业工作,我们经常从第三方获取 PowerPivot 数据。他们不是我们的客户,所以我们无法以更合适的格式请求原始数据等。
-
明白。 DAX Studio 能够针对打开的工作簿运行任意 DAX 查询。您或许可以深入了解其内部结构或联系维护者 Darren Gosbell,以获得更多信息帮助:daxstudio.codeplex.com
-
感谢您的建议,@greggyb!我已经看过 DAX Studio,但由于 PowerPivot/Vertipaq 数据库引擎中没有行和行索引的概念,我认为没有办法将 DAX 查询限制为记录的子集(我已经完成对此进行了相当多的研究,我认为这实际上值得提出一个全新的问题)。无论如何,这种方式可以绕过 Excel 的 1m 行限制,例如使用 VBA 脚本将 1m 块数据输出到独立工作簿中(类似于此处建议的内容:stackoverflow.com/a/33580647)。
-
我应该注意,只有当记录超过 1m 时才需要将表拆分为更小的块(例如,上面提到的示例文件中的 dbo_FactSales 表),而不是当行数为小于那个值(例如,dbo_DimProduct 表)。在这种情况下,该 SO 链接中建议的解决方案非常简单。不过,我会联系达伦,看看是否有什么我可能错过的。再次感谢!
标签: python excel ssas ado powerpivot