通过 ODBC 将 pandas 输出连接到 Excel 工作表
Posted
技术标签:
【中文标题】通过 ODBC 将 pandas 输出连接到 Excel 工作表【英文标题】:Connect pandas output to excel sheet via ODBC 【发布时间】:2018-02-28 17:11:51 【问题描述】:下面的查询执行以下操作:通过 ODBC 连接到 SQL Server 数据库,运行 SQL 脚本(许多查询由“;”分隔),为两个特定查询结果创建两个数据框,然后将它们导出到内部的两个选项卡一个 Excel 工作簿:
import pyodbc
import pandas as pd
import time
name= 'ouput' + str(time.strftime("%Y-%b-%d__%H_%M_%S",time.localtime()))
print ("Connecting via ODBC")
conn = pyodbc.connect('DSN=Server DB Prod', autocommit=True)
print ("Connected!\n")
inputdir = 'H:\\Queries\\ADS'
#for script in os.listdir(inputdir):
with open(inputdir+'\\' + 'query' +'.sql','r') as inserts:
sqlScript = inserts.read()
for statement in sqlScript.split(';'):
with conn.cursor() as cur:
cur.execute(statement)
query1="Select * from #leadership"
data1=pd.read_sql_query(query1, conn).sort_values(['channel','terr_code'], ascending=[0,1]).reset_index(drop=True)
#print(data1.head(n=100))
query2="Select * from #ml"
data2=pd.read_sql_query(query2, conn).sort_values(['channel','terr_code','client_name'], ascending=[0,1,1]).reset_index(drop=True)
print('query finished')
conn.close()
writer = pd.ExcelWriter(name+ '.xlsx')
data1.to_excel(writer,'Leadership Summary')
data2.to_excel(writer,'ML Detail')
writer.save()
print("Results were succesfully exported")
但是,我希望能够通过 ODBC 连接到现有的 excel 文件,以便动态更新我的工作簿的选项卡,并且不会丢失格式和图表 - 以实现真正的自动化。任何其他允许相同的解决方案肯定会起作用。
背景:我正在尝试自动化在 SQL Server 中运行查询(通过 Python)的过程,并让输出更新现有 excel 工作表的选项卡 - 我正在考虑通过 ODBC 连接。该工作表具有特定的格式,以及基于数据构建的公式+图表。
注意:我没有写权限,只有读权限,所以我无法通过 ODBC 将“最终”SQL 表连接到 excel。我正在从 Python 中的其他来源进行一些额外的数据混合(未显示),因此通过 ODBC 将 SQL 查询连接到 excel 将不起作用。
非常感谢任何帮助。
【问题讨论】:
【参考方案1】:最好的策略是访问 Excel 工作簿并使用它的工具而不是外部工具来保持所有其他对象不变。因此,考虑win32com
客户端,您可以在其中访问Excel 对象库,例如其CopyFromRecordset 方法。
使用 Window 的 ADODB API 代替 pyodbc
作为数据库 API,它可以使用 ODBC 连接。此外,不需要pandas
,因为工作表对象用于保存数据。注意:此解决方案仅适用于 Windows 机器。
import win32com.client as win32
try:
# INITIALIZE OBJECTS
xlapp = win32.gencache.EnsureDispatch('Excel.Application')
ado_conn = win32.gencache.EnsureDispatch('ADODB.Connection')
ado_rst = win32.gencache.EnsureDispatch('ADODB.Recordset')
# OPEN CONNECTION
ado_conn.Open('DSN=Server DB Prod')
# RUN QUERIES
with open(inputdir+'\\' + 'query' +'.sql','r') as inserts:
sqlScript = inserts.read()
for statement in sqlScript.split(';'):
ado_conn.Execute(statement)
# OPEN WORKBOOK AND UPDATE SHEETS
xlwb = xlapp.Workbooks.Open(r'C:\Full\Path\To\Workbook.xlsx')
ls = xlwb.Worksheets('Leadership Summary')
ls.Cells.ClearContents()
ado_rst.Open("Select * from #leadership", ado_conn)
for i in range(ado_rst.Fields.Count):
ls.Cells(1, i+1).Value = ado_rst.Fields(i).Name # COLUMNS
ls.Range("A2").CopyFromRecordset(ado_rst) # DATA ROWS
ado_rst.Close()
ml = xlwb.Worksheets('ML Detail')
ml.Cells.ClearContents()
ado_rst.Open("Select * from #ml", ado_conn)
for i in range(ado_rst.Fields.Count):
ml.Cells(1, i+1).Value = ado_rst.Fields(i).Name # COLUMNS
ml.Range("A2").CopyFromRecordset(ado_rst) # DATA ROWS
ado_rst.Close()
ado_conn.Close()
xlapp.Visible = True # OPENS WORKBOOK WITH ABOVE CHANGES TO SCREEN
except Exception as e:
print(e)
finally:
# RELEASE RESOURCES
ls = None; ml = None
ado_rst = None; ado_conn = None
xlwb = None; xlapp = None
希望这能揭穿任何认为 VBA(也是一种 COM 接口语言)是 Excel 唯一编码语言的人!
【讨论】:
我收到一个错误“'int' object is not callable”,但没有提及发生错误的行。这绝对不是 SQL 脚本,因为它按照我提供的版本运行得很好。有什么想法吗?此外,“希望这能揭穿任何认为 VBA(也是一种 COM 接口语言)是 Excel 唯一编码语言的人!”。这是什么魔法? 归结为列的编写方式。.Count()
和 .Name()
不可调用,因此应将括号删除为 .Count
和 .Name
。见编辑。
你是对的 - 它运行成功。谢谢!。 2 个问题:#1 我将查询中的 A2 更改为 B8,这是数据开始写入的位置。但是,标题仍填充在第 1 行(A1 及以上)中。有没有办法不填充标题? #2 ClearContents 从选项卡中删除所有数据。但是,我想将数据保留在 1:7 行中,其中第 7 行是具有特定格式的标题。有什么方法可以指定我想保留/删除的内容吗?非常感谢!
在两个列循环中,如果您知道您的 Excel 对象将是 .Cells(7, 2)
对应于 B7
,只需移动 .Cells(row, column)。所以循环.Cells(7, i+2).Value
。并删除 ClearContents
行,但请注意,如果新的 shorter 查询替换它,之前的 longer 查询的最后几行可能会保留。
太棒了!而不是删除 ClearContents 我使用 ls.Range("B8:Z1000000").ClearContents() 来指定我想要清除的范围。有没有办法只写数据,没有列标题?对于这部杰作,这将是我最不需要的东西。 pywin32 功能绝对很酷以上是关于通过 ODBC 将 pandas 输出连接到 Excel 工作表的主要内容,如果未能解决你的问题,请参考以下文章
在哪里下载 sun.jdbc.odbc.JdbcOdbcDriver(尝试将输出 csv 从 Spoon 连接到 SSMS)
无法通过 ODBC 将 Access 连接到 SQLlite