You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Xlwings通过Excel按钮运行Python脚本遇ModuleNotFoundError求助

Excel中通过Xlwings运行Python脚本报错ModuleNotFoundError

我是来自哥伦比亚的医生,近期正在学习Python并将其应用于工作中。我正在构建一个肥胖治疗的成本效益模型,第一步是通过代码设定减重目标(%TWL):在Excel表格的输入区域填写数据,脚本基于这些数据计算治疗目标(%TWL)。

该代码在PyCharm中运行完全正常,医学逻辑没问题,已实现将计算得到的目标写入Excel文件的F2单元格。

但当我尝试在Excel中添加按钮,通过Xlwings点击运行脚本以根据输入区域的值更新F2单元格的目标时,出现错误,报错信息为:

Traceback (most recent call last):
File "", line 1, in
ModuleNotFoundError: No module named 'Error'

我使用的设备是MacBook Air M2,已安装最新版Python及Xlwings相关组件和Excel插件,尝试修改VBA代码、主脚本、文件路径等方法均未解决问题,特此求助。

我的Python代码

import pandas as pd
import xlwings as xw

def main ():
    # Cargar el archivo Excel
    ruta_archivo = "/FULL ROUTE/COBESE.xlsm"
    df = pd.read_excel(ruta_archivo, sheet_name='Input')

    # Antropometría
    antropometria_peso = df.loc[4, "C"]  # Peso en kg
    antropometria_talla = df.loc[5, "C"]  # Talla en metros
    print()
    print("Antropometría:")
    print(f"Peso: {antropometria_peso}, Talla: {antropometria_talla}")
    print()

    # Comorbilidades
    # Diabetes
    diabetes_diagnostico = df.loc[10, "C"] == "si"  # ¿El paciente tiene diabetes?
    diabetes_duracion = df.loc[11, "C"]  # Duración de la diabetes en años
    diabetes_num_medicamentos = df.loc[12, "C"]  # Número de medicamentos para diabetes
    diabetes_usa_insulina = df.loc[13, "C"] == "si"  # ¿El paciente usa insulina?
    print("Comorbilidades:")
    print(
        f"Diabetes: {diabetes_diagnostico}, Duración diabetes: {diabetes_duracion}, "
        f"Num. medicamentos diabetes: {diabetes_num_medicamentos}, Usa insulina: {diabetes_usa_insulina}"
    )

    # Hígado graso
    higado_graso_diagnostico = df.loc[24, "C"] == "si"  # ¿El paciente tiene hígado graso?
    higado_graso_grado = df.loc[25, "C"]  # Grado de hígado graso
    print(f"Hígado graso: {higado_graso_diagnostico}, Grado hígado graso: {higado_graso_grado}")

    # Hipertensión arterial (HTA)
    hta_diagnostico = df.loc[15, "C"] == "si"  # ¿El paciente tiene HTA?
    hta_num_medicamentos = df.loc[16, "C"]  # Número de medicamentos para HTA
    print(f"HTA: {hta_diagnostico}, Num. medicamentos HTA: {hta_num_medicamentos}")

    # Dislipidemia
    dislipidemia_diagnostico = df.loc[18, "C"] == "si"  # ¿El paciente tiene Dislipidemia?
    dislipidemia_num_medicamentos = df.loc[19, "C"]  # Número de medicamentos para Dislipidemia
    print(f"Dislipidemia: {dislipidemia_diagnostico}, Num. Medicamentos: {dislipidemia_num_medicamentos}")
    print()

    def clasificar_diabetes(duracion, num_medicamentos, usa_insulina):
        if duracion < 3 and num_medicamentos < 3 and not usa_insulina:
            return 'Leve'
        elif 3 <= duracion <= 5 and num_medicamentos >= 3 and not usa_insulina:
            return 'Moderada'
        elif duracion > 5 and num_medicamentos > 4 or usa_insulina:
            return 'Severa'
        else:
            return 'Sin clasificar'

    def clasificar_hta(num_medicamentos):
        if num_medicamentos <= 2:
            return 'Leve'
        elif 2 < num_medicamentos <= 4:
            return 'Moderada'
        elif num_medicamentos > 4:
            return 'Severa'
        else:
            return 'Sin clasificar'

    def clasificar_dislipidemia(num_medicamentos2):
        if num_medicamentos2 <= 2:
            return 'Leve'
        elif 2 < num_medicamentos2 <= 4:
            return 'Moderada'
        elif num_medicamentos2 > 4:
            return 'Severa'
        else:
            return 'Sin clasificar'

    # Clasificar pacientes por comorbilidades
    clasificacion_diabetes = ''
    clasificacion_hta = ''
    clasificacion_dislipidemia = ''

    if diabetes_diagnostico:
        clasificacion_diabetes = clasificar_diabetes(diabetes_duracion, diabetes_num_medicamentos,
                                                     diabetes_usa_insulina)

    if hta_diagnostico:
        clasificacion_hta = clasificar_hta(hta_num_medicamentos)

    if dislipidemia_diagnostico:
        clasificacion_dislipidemia = clasificar_dislipidemia(dislipidemia_num_medicamentos)

    # Cálculo de la meta de TWL
    def calcular_meta(peso, talla, diabetes, grado_higado_graso, hta, dislipidemia):

        # Convertir la severidad de la diabetes y la HTA en un número
        enfermedad_mapping = {'Leve': {'Diabetes': 10, 'HTA': 5, 'Dislipidemia': 5},
                              'Moderada': {'Diabetes': 20, 'HTA': 12.5, 'Dislipidemia': 5},
                              'Severa': {'Diabetes': 35, 'HTA': 20, 'Dislipidemia': 10}}

        diabetes_severidad = enfermedad_mapping.get(diabetes, {}).get('Diabetes', 0)
        hta_severidad = enfermedad_mapping.get(hta, {}).get('HTA', 0)
        dislipidemia_severidad = enfermedad_mapping.get(dislipidemia, {}).get('Dislipidemia', 0)

        # Verificar si los diagnósticos son True o False
        if not diabetes_diagnostico:
            diabetes_severidad = 0
        if not hta_severidad:
            hta_severidad = 0
        if not dislipidemia_diagnostico:
            dislipidemia_severidad = 0

        # Calcular el peso necesario para alcanzar un IMC de 30
        peso_objetivo_imc30 = 30 * (talla ** 2)

        # Calcular la meta de %TWL para alcanzar un IMC de 30
        twl_para_imc30 = ((peso - peso_objetivo_imc30) / peso) * 100

        # Mapear el grado de hígado graso a su correspondiente meta
        if not higado_graso_diagnostico:
            twl_para_higado_graso = 0
        else:
            higado_graso_mapping = {"Grado 1": 10, "Grado 2": 20, "Grado 3": 40}
            twl_para_higado_graso = higado_graso_mapping.get(grado_higado_graso, 0)

        # Escoger la meta más grande
        return max(twl_para_imc30, diabetes_severidad, twl_para_higado_graso, hta_severidad, dislipidemia_severidad)

    meta = calcular_meta(
        antropometria_peso,
        antropometria_talla,
        clasificacion_diabetes,
        higado_graso_grado,
        clasificacion_hta,
        clasificacion_dislipidemia
    )

    print(f"La meta de este paciente debe ser TWL: {meta:.2f}%.")
    print()

    # Obtén la aplicación Excel y abre el archivo
    app = xw.apps.active
    wb = app.books.open(ruta_archivo)

    # Selecciona la hoja de cálculo donde deseas escribir el resultado
    sheet = wb.sheets['Input']

    # Escribe el resultado en una celda específica formateado como cadena
    sheet.range('F2').value = "{:.2f}".format(meta).replace('.', ',')

    # Guarda los cambios y cierra el archivo
    wb.save()
    wb.close()
    app.quit()

# Llamar a la función main()
if __name__ == '__main__':
    main()

我的VBA代码

Public Sub Python()
    RunPython "import Error; Error.main ()"
 End Sub

问题根源及解决方法

1. 核心错误修复

VBA代码里的import Error是错误的——这里的Error应该替换成你的Python脚本实际文件名(不含.py后缀)。比如如果你的Python脚本叫twl_calculator.py,修改后的VBA代码应为:

Public Sub Python()
    RunPython "import twl_calculator; twl_calculator.main ()"
 End Sub

2. 脚本优化建议

  • 移除硬编码路径:原脚本中固定的文件路径容易出错,建议直接通过Xlwings获取当前活动工作簿,避免手动指定路径:

    def main():
        # 获取当前活动的Excel应用和工作簿
        app = xw.apps.active
        wb = app.books.active
        sheet = wb.sheets['Input']
        
        # 直接从工作表读取数据(注意:pandas的df.loc[4]对应Excel第5行,因为pandas索引从0开始)
        antropometria_peso = sheet.range('C5').value
        antropometria_talla = sheet.range('C6').value
        # 后续所有df.loc[...]都替换为对应的Excel单元格,比如df.loc[10, "C"] → sheet.range('C11').value
    

    这样修改后,脚本会直接操作当前打开的Excel文件,无需依赖固定路径。

  • 避免关闭Excel程序:原代码中的app.quit()会关闭整个Excel窗口,这在Excel内运行脚本时非常不友好,建议删除wb.close()和app.quit(),只保留wb.save()即可。

3. Mac环境配置检查

  • 确认Xlwings Excel插件已正确安装,在Excel的「工具」菜单中能看到Xlwings选项。
  • 打开Excel → 工具 → Xlwings → Settings,检查Python路径是否指向你安装的最新版Python(比如虚拟环境路径或系统Python路径)。

内容的提问来源于stack exchange,提问作者Dr.Mateo95

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 09:32:36