How to save XLSM file with Macro, using openpyxl

后端 未结 6 1375
一个人的身影
一个人的身影 2020-11-29 11:32

I have .xlsm file with a Macro function. I\'m loading it using openpyxl and write some data to the file and finally want t

6条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-11-29 11:49

    I don't know if this is still relevant for the person that asked the question, but I am dealing with the same problem and found a possible solution.

    1. open the original file (say: 1.xlsm) and do magic with openpyxl;
    2. save as 2.xlsx;
    3. both files are actually zipped files: extract them to a temporary directory;
    4. copy files from the directory of the original file to the directory of the xlsx files: one of the files is the macro (vbaProject.bin) and 2 of the files are necessary because they describe the type of the file among other things;
    5. put all of the files that belong to the xlsx directory back into a zip file and rename this from zip to xlsm. This file contains the original macro and has been edited with openpyxl;
    6. (Optional) delete the two temporary directories and the 2.xlsx file.

    Example code:

    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')
    

提交回复
热议问题