1#!python
2
3##############################################################################
4#
5# vba_extract - A simple utility to extract a vbaProject.bin binary from an
6# Excel 2007+ xlsm file for insertion into an XlsxWriter file.
7#
8# Copyright 2013-2021, John McNamara, jmcnamara@cpan.org
9#
10import sys
11from zipfile import ZipFile
12from zipfile import BadZipfile
13
14# The VBA project file we want to extract.
15vba_filename = 'vbaProject.bin'
16
17# Get the xlsm file name from the commandline.
18if len(sys.argv) > 1:
19    xlsm_file = sys.argv[1]
20else:
21    print("\nUtility to extract a vbaProject.bin binary from an Excel 2007+ "
22          "xlsm macro file for insertion into an XlsxWriter file."
23          "\n"
24          "See: https://xlsxwriter.readthedocs.io/working_with_macros.html\n"
25          "\n"
26          "Usage: vba_extract file.xlsm\n")
27    exit()
28
29try:
30    # Open the Excel xlsm file as a zip file.
31    xlsm_zip = ZipFile(xlsm_file, 'r')
32
33    # Read the xl/vbaProject.bin file.
34    vba_data = xlsm_zip.read('xl/' + vba_filename)
35
36    # Write the vba data to a local file.
37    vba_file = open(vba_filename, "wb")
38    vba_file.write(vba_data)
39    vba_file.close()
40
41except IOError as e:
42    print("File error: %s" % str(e))
43    exit()
44
45except KeyError as e:
46    # Usually when there isn't a xl/vbaProject.bin member in the file.
47    print("File error: %s" % str(e))
48    print("File may not be an Excel xlsm macro file: '%s'" % xlsm_file)
49    exit()
50
51except BadZipfile as e:
52    # Usually if the file is an xls file and not an xlsm file.
53    print("File error: %s: '%s'" % (str(e), xlsm_file))
54    print("File may not be an Excel xlsm macro file.")
55    exit()
56
57except Exception as e:
58    # Catch any other exceptions.
59    print("File error: %s" % str(e))
60    exit()
61
62print("Extracted: %s" % vba_filename)
63