#!/usr/bin/env python3
# file: unlock-excel.py
# vim:fileencoding=utf-8:fdm=marker:ft=python
#
# Copyright © 2020 R.F. Smith <rsmith@xs4all.nl>
# Created: 2020-03-10T09:35:46+0100
# Last modified: 2020-03-10T20:58:38+0100
"""Remove passwords from modern excel 2007+ files (xlsx, xlsm)."""

import zipfile
import re
import sys
import logging
import shutil

__version__ = '0.2'


def main(argv):
    logging.basicConfig(level='INFO', format='%(levelname)s: %(message)s')
    if not argv:
        logging.info(f'unlock-excel.py v{__version__}; no files to unlock')
        print('Usage: unlock-excel.py <file> <file> ...')
        sys.exit(0)
    for path in argv:
        try:
            backup_path = backup_file(path)
            remove_excel_password(backup_path, path)
        except (ValueError, shutil.SameFileError) as e:
            logging.info(e)


def backup_file(path):
    first, last = path.rsplit('.', maxsplit=1)
    backup = first + '-orig' + '.' + last
    logging.info(f'moving "{path}" to "{backup}"')
    shutil.move(path, backup)
    return backup


def remove_excel_password(origpath, path):
    if not zipfile.is_zipfile(origpath):
        raise ValueError(f'"{origpath}" is not a valid zip-file.')
    with zipfile.ZipFile(origpath, mode="r") as inzf, zipfile.ZipFile(
        path, mode="w", compression=zipfile.ZIP_DEFLATED, compresslevel=1
    ) as outzf:
        infos = [name for name in inzf.infolist()]
        for info in infos:
            logging.debug(f'working on "{info.filename}"')
            data = inzf.read(info)
            if b'sheetProtect' in data:
                regex = r'<sheetProtect.*?/>'
                logging.info(f'worksheet "{info.filename}" is protected')
            elif b'workbookProtect' in data:
                regex = r'<workbookProtect.*?/>'
                logging.into('the workbook is protected')
            else:
                outzf.writestr(info, data)
                continue
            text = data.decode('utf-8')
            newtext = re.sub(regex, '', text)
            if len(newtext) != len(text):
                outzf.writestr(info, newtext)
                logging.info(f'removed password from "{info.filename}"')


if __name__ == '__main__':
    main(sys.argv[1:])

@@ -1,27 +1,4 @@
-#!/usr/bin/env python3%0A
 # fi
@@ -113,16 +113,48 @@
 4all.nl%3E
+.%0A# SPDX-License-Identifier: MIT
 %0A# Creat
@@ -172,16 +172,16 @@
 -10T
-09:35:46
+13:47:43
 +010
@@ -215,14 +215,14 @@
 10T2
-0:58:3
+3:07:5
 8+01

Add missing license.