You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python通过COM对象加载Excel后公式与Bloomberg数据无法刷新

解决Win32加载Excel时Bloomberg API公式无法刷新的问题

我最近在用Python的win32com库加载一个带Bloomberg Excel API公式的xlsm文件,遇到了个棘手的问题:手动打开表格时,17-65列里的BDP函数(比如=BDP(E9&" corp","CRNCY"))和除法公式都能正常刷新出正确值,但用代码加载后,这些公式驱动列要么显示0,要么是N/A。我试了启用计算、调用各种Calculate方法都没用,下面是我的相关代码:

import win32com.client as win32

def open_workbook(xlapp, xlfile, password=None):
    try:
        xlwb = xlapp.Workbooks("LAP.xlsm")
    except Exception as e:
        print("No 1. Error: ", e)
    try:
        xlwb = xlapp.Workbooks.Open(xlfile, Password=password, UpdateLinks=0)
    except Exception as e:
        print(e)
        xlwb = None
    return xlwb

def main(file, password=None):
    xlapp = win32.gencache.EnsureDispatch("Excel.Application")
    xlapp.DisplayAlerts = True
    xlapp.Visible = True
    print(check.check_file(file, xlapp))
    if not check.check_file(file, xlapp):
        xlwb = open_workbook(xlapp, xlfile=file, password=password)
    else:
        print("Error")
    # TODO 若无法打开文件该如何处理:重试、提示用户?...
    # Resources工作表包含Data工作表公式所用的货币汇率
    res = xlwb.Sheets('Resources')
    # 以下Calculate相关操作是我尝试修复问题的手段
    res.EnableCalculation = False
    res.EnableCalculation = True
    res.Calculate()
    # 这是后续要加载到Pandas DataFrame的目标主工作表
    xlws = xlwb.Sheets('Data')
    last_col = xlws.UsedRange.Columns.Count
    last_row = xlws.UsedRange.Rows.Count
    # 所有这些Calculate操作尝试修复问题,但均无效
    xlws.EnableCalculation = False
    xlws.EnableCalculation = True
    xlws.Calculate()
    xlws.Columns(17).Calculate()
    xlws.Columns(16).Calculate()
    xlws.Columns(18).Calculate()
    xlws.Range(xlws.Cells(8,17), xlws.Cells(last_row,17)).Formula = \
        xlws.Range(xlws.Cells(8,17),xlws.Cells(last_row,17)).Formula
    # 此内容将被加载到DataFrame
    content = xlws.Range(xlws.Cells(8,1), xlws.Cells(last_row, last_col)).Value
    print(len(content), type(content))
    print(content[:10])

可能的解决方案及代码调整

针对Bloomberg API这类第三方插件的公式刷新问题,Excel自带的计算方法往往不够,需要针对性处理:

  • 强制加载Bloomberg Excel插件
    手动打开Excel时插件会自动加载,但win32com启动的Excel实例可能默认不加载,需要先确保插件启用:

    # 在创建xlapp实例后添加
    bloomberg_addin = xlapp.AddIns("Bloomberg Excel Tools")
    if not bloomberg_addin.Installed:
        bloomberg_addin.Installed = True
    
  • 切换Excel计算模式为自动并等待刷新
    有些情况下Excel实例的计算模式会被设为手动,先切换为自动,并且给Bloomberg API足够的刷新时间:

    # 设置计算模式为自动
    xlapp.Calculation = win32.constants.xlCalculationAutomatic
    # 调用Bloomberg专属的刷新宏(插件内置功能)
    xlapp.Run("RefreshAllStaticData")
    # 等待15秒让数据完成刷新(时间可根据数据量调整)
    xlapp.Wait(xlapp.Now + win32.client.Variant(win32.client.constants.xlTime, 15))
    # 最后触发一次全表计算
    xlwb.CalculateFull()
    
  • 调整工作簿刷新设置
    确保工作簿允许外部数据刷新,并且禁用后台刷新(避免数据还没刷完就读取):

    # 禁用后台查询,确保数据刷新完成后再继续
    for conn in xlwb.Connections:
        if hasattr(conn, 'OLEDBConnection'):
            conn.OLEDBConnection.BackgroundQuery = False
    # 刷新所有外部数据连接
    xlwb.RefreshAll()
    # 等待异步查询完成
    xlapp.CalculateUntilAsyncQueriesDone()
    

调整后的main函数核心片段

把这些修复逻辑整合到你的代码里,比如在获取xlws之后添加:

# 加载Bloomberg插件
bloomberg_addin = xlapp.AddIns("Bloomberg Excel Tools")
if not bloomberg_addin.Installed:
    bloomberg_addin.Installed = True

# 配置计算和刷新
xlapp.Calculation = win32.constants.xlCalculationAutomatic
# 禁用后台查询
for conn in xlwb.Connections:
    if hasattr(conn, 'OLEDBConnection'):
        conn.OLEDBConnection.BackgroundQuery = False
# 刷新所有数据
xlwb.RefreshAll()
# 调用Bloomberg刷新宏
xlapp.Run("RefreshAllStaticData")
# 等待异步查询完成
xlapp.CalculateUntilAsyncQueriesDone()
# 额外等待几秒确保Bloomberg数据加载完成
xlapp.Wait(xlapp.Now + win32.client.Variant(win32.client.constants.xlTime, 10))
# 全表计算
xlwb.CalculateFull()

# 再读取数据
content = xlws.Range(xlws.Cells(8,1), xlws.Cells(last_row, last_col)).Value

注意事项

  • 确保你的机器上已经安装了Bloomberg Excel插件,并且正常登录了Bloomberg终端(否则BDP函数无法获取数据)。
  • 如果等待时间不够,可能还是会出现N/A,可以根据数据量适当延长等待时间。
  • 有些情况下,Excel的信任中心设置会阻止插件在自动化环境中运行,需要在Excel的选项里把Bloomberg插件设为信任的加载项。

内容的提问来源于stack exchange,提问作者GXZ9

火山引擎 最新活动