Cómo guardar un archivo XLSM con Macro, usando openpyxl

Tengo archivo .xlsm con una función de macro . Lo estoy cargando con openpyxl y escribo algunos datos en el archivo y finalmente quiero guardarlos como un archivo .xlsm diferente.

Para guardar el archivo como archivo XLSM, he usado el siguiente código en mi script de Python.

wb.save('testsave.xlsm'); 

Pero no puedo abrir ese archivo si lo guardé como anteriormente. Pero si lo guardé como .xlsx , puedo abrir el archivo sin la función Macro que tenía el archivo original.

Quiero abrir una hoja de Excel que tenga la función de Macro, editar el archivo y guardarlo como un nuevo archivo .xlsm con openpyxl . ¿Cómo puedo hacer eso?

Para mí esto funcionó, junto con la versión openpyxl==2.3.0-b2

 wb = load_workbook(filename='original.xlsm', read_only=False, keep_vba=True) .. wb.save('outfile.xlsm') 

También se encuentra en la documentación aquí: http://openpyxl.readthedocs.org/en/latest/usage.html?highlight=keep_vba#write-a-workbook-from-xltm-as-xlsm

No sé si esto sigue siendo relevante para la persona que hizo la pregunta, pero estoy tratando el mismo problema y encontré una posible solución.

  1. abre el archivo original (por ejemplo: 1.xlsm ) y haz magia con openpyxl;
  2. guardar como 2.xlsx ;
  3. ambos archivos son en realidad archivos comprimidos: extráigalos a un directorio temporal;
  4. copie los archivos del directorio del archivo original al directorio de los archivos xlsx : uno de los archivos es la macro ( vbaProject.bin ) y 2 de los archivos son necesarios porque describen el tipo de archivo entre otras cosas;
  5. vuelva a colocar todos los archivos que pertenecen al directorio xlsx en un archivo zip y cambie su nombre de zip a xlsm . Este archivo contiene la macro original y se ha editado con openpyxl ;
  6. ( Opcional ) elimine los dos directorios temporales y el archivo 2.xlsx .

Código de ejemplo:

 import openpyxl import zipfile from shutil import copyfile from shutil import rmtree import os PAD = os.getcwd() wb = openpyxl.load_workbook('1.xlsm') ##### # do magic with openpyxl here and save ws = wb.worksheets[0] ws.cell(row=2, column=3).value = 'Edited' # example ##### wb.save('2.xlsx') with zipfile.ZipFile('1.xlsm', 'r') as z: z.extractall('./xlsm/') with zipfile.ZipFile('2.xlsx', 'r') as z: z.extractall('./xlsx/') copyfile('./xlsm/[Content_Types].xml','./xlsx/[Content_Types].xml') copyfile('./xlsm/xl/_rels/workbook.xml.rels','./xlsx/xl/_rels/workbook.xml.rels') copyfile('./xlsm/xl/vbaProject.bin','./xlsx/xl/vbaProject.bin') z = zipfile.ZipFile('2.zip', 'w') os.chdir('./xlsx') for root, dirs, files in os.walk('./'): for file in files: z.write(os.path.join(root, file)) z.close() #clean os.chdir(PAD) rmtree('./xlsm/') rmtree('./xlsx/') os.remove('./2.xlsx') os.rename('2.zip', '2.xlsm') 

Así es, openpyxl no puede leer y escribir código VBA.

Según este hilo :

Creo que no debes dar la extensión xlsM, porque el archivo no contendrá ningún código VBA. openpyxl se utiliza para construir archivos xlsX solamente.

Intente esta bifurcación en su lugar: si pasa keep_vba=True parámetro keep_vba=True a load_workbook , debería hacer el trabajo.

Espero que ayude.

Tuve el mismo problema al editar archivos xlsm usando openpyxl. Probé la mayoría de las soluciones / soluciones disponibles en stackoverflow y en otros foros. Pero ninguno de ellos funcionó. Luego encontré xlwings , esta biblioteca de Python maneja el documento xlsm, conserva todas las macros.

 import xlwings as xw wb = xw.Book('macro_xl.xlsm') sheet = wb.sheets['Sheet1'] sheet.range('A1').value = 'From Script' wb.save('result_file_name.xlsm') 

Si su Excel inicial se creó con Python, es posible que también deba agregar el archivo workbook.xml y analizar la hoja xlms:

 for sheet in range(1,4): with open('sheetX.xml', 'r') as myfile: 'r') as myfile: my_str=myfile.read() substr = "" idx = my_str.index(substr) my_str = my_str[:idx] + inserttxt + my_str[idx:] with open('sheetX.xml', "w") as text_file: text_file.write(my_str)