Skip to content

Instantly share code, notes, and snippets.

@dankkom
Created March 31, 2023 13:08
Show Gist options
  • Save dankkom/2ad22aac736b0bdb8ce65653591bd930 to your computer and use it in GitHub Desktop.
Save dankkom/2ad22aac736b0bdb8ce65653591bd930 to your computer and use it in GitHub Desktop.
Microsoft Excel deblocker: removes sheet protections from any spreadsheet
import argparse
import re
import shutil
import zipfile
from pathlib import Path
def decompress(filepath: Path) -> Path:
dest_filepath = Path(filepath.stem)
with zipfile.ZipFile(filepath, "r") as zf:
zf.extractall(dest_filepath)
return dest_filepath
def compress(tmp_dir: Path):
dest_filename = "deblocked-" + tmp_dir.name
shutil.make_archive(dest_filename, "zip", tmp_dir)
dest_filepath = Path(dest_filename + ".zip")
dest_filepath.rename(dest_filename + ".xlsx")
def remove_protection(tmp_dir):
pattern = r"<sheetProtection [^/>]*/>"
for file in (tmp_dir / "xl" / "worksheets").iterdir():
if not file.is_file():
continue
print("Removing sheet protection:", file)
with file.open(encoding="utf-8") as f:
data = f.read()
data = re.sub(pattern, "", data)
with file.open("w", encoding="utf-8") as f:
f.write(data)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("filepath", type=Path)
args = parser.parse_args()
filepath = args.filepath
tmp = decompress(filepath)
remove_protection(tmp)
compress(tmp)
shutil.rmtree(tmp)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment