Compare commits

...

11 Commits

2 changed files with 63 additions and 19 deletions

View File

@ -54,15 +54,20 @@ def load_workbook_with_possible_passwords(filepath, passwords, keep_vba=False, d
raise ValueError(f"None of the provided passwords worked for '{filepath}'") raise ValueError(f"None of the provided passwords worked for '{filepath}'")
def copy_excel_file(source_path, destination_path, passwords): def copy_excel_file(source_path, destination_path, passwords, original_filename=None):
logging.info(f"Processing Excel file: {source_path}") logging.info(f"Processing Excel file: {source_path}")
is_xlsm = source_path.lower().endswith('.xlsm')
source_wb = load_workbook_with_possible_passwords( # Skip password attempts if this is already a processed file
filepath=source_path, if os.path.basename(source_path).startswith('processed_'):
passwords=passwords, source_wb = load_workbook(filename=source_path, keep_vba=False, data_only=False)
keep_vba=is_xlsm, else:
data_only=False is_xlsm = source_path.lower().endswith('.xlsm')
) source_wb = load_workbook_with_possible_passwords(
filepath=source_path,
passwords=passwords,
keep_vba=is_xlsm,
data_only=False
)
dest_wb = Workbook() dest_wb = Workbook()
if len(dest_wb.sheetnames) == 1 and dest_wb.active.title == 'Sheet': if len(dest_wb.sheetnames) == 1 and dest_wb.active.title == 'Sheet':
@ -75,6 +80,11 @@ def copy_excel_file(source_path, destination_path, passwords):
# Create new sheet in destination workbook # Create new sheet in destination workbook
from openpyxl.chartsheet import Chartsheet from openpyxl.chartsheet import Chartsheet
if isinstance(source_sheet, Chartsheet): if isinstance(source_sheet, Chartsheet):
# Use original_filename if provided, otherwise use source_path
display_filename = original_filename or os.path.basename(source_path)
if '_processed' in display_filename: # If it's a temp file, get original name
display_filename = display_filename.split('_processed')[0]
chartsheet_warning = f"Chartsheet detected in '{display_filename}' on sheet '{sheet_name}'."
# For chartsheets, we need to create a worksheet instead # For chartsheets, we need to create a worksheet instead
dest_sheet = dest_wb.create_sheet(title=sheet_name) dest_sheet = dest_wb.create_sheet(title=sheet_name)
@ -179,6 +189,8 @@ def copy_excel_file(source_path, destination_path, passwords):
logging.info(f"Saved copied file to: {destination_path}") logging.info(f"Saved copied file to: {destination_path}")
dest_wb.close() dest_wb.close()
source_wb.close() source_wb.close()
return chartsheet_warning # Return the warning message if any chartsheets were found
def remove_all_protection_tags(docx_path, output_path): def remove_all_protection_tags(docx_path, output_path):
logging.info(f"Processing Word document: {docx_path}") logging.info(f"Processing Word document: {docx_path}")

View File

@ -1,4 +1,5 @@
import streamlit as st import streamlit as st
from streamlit import components
import os import os
import logging import logging
import warnings import warnings
@ -24,8 +25,8 @@ def is_running_locally():
# Configure page # Configure page
st.set_page_config( st.set_page_config(
page_title="Office Protection Remover", page_title="SHV Car Wash",
page_icon="🔓", page_icon="🧼🚘",
layout="wide" layout="wide"
) )
@ -150,8 +151,8 @@ def create_zip_file(files_dict):
return zip_buffer return zip_buffer
# Main UI # Main UI
st.title("🔓 Office File Protection Remover") st.title("🧼🚘 SHV Car Wash")
st.write("Remove protection from Excel and Word files easily") st.write("Removes Word Read Only Password - Creates a Clean Copy of Excel")
# Sidebar # Sidebar
with st.sidebar: with st.sidebar:
@ -371,7 +372,12 @@ if input_method == "Upload Files" and uploaded_files and st.button("Process File
temp_output_path = f"{temp_input_path}_processed" temp_output_path = f"{temp_input_path}_processed"
if file_type == "Excel": if file_type == "Excel":
copy_excel_file(temp_input_path, temp_output_path, passwords) # Pass original filename to copy_excel_file
chartsheet_warning = copy_excel_file(temp_input_path, temp_output_path, passwords, original_filename=uploaded_file.name)
if chartsheet_warning:
warning_msg = f"⚠️ {chartsheet_warning} Please check the processed file against the original to ensure data was copied correctly."
st.warning(warning_msg)
st.session_state.error_log[uploaded_file.name] = warning_msg
else: # Word else: # Word
remove_all_protection_tags(temp_input_path, temp_output_path) remove_all_protection_tags(temp_input_path, temp_output_path)
@ -455,7 +461,11 @@ elif input_method == "Select Directory" and source_dir and dest_dir and st.butto
os.makedirs(os.path.dirname(dest_path), exist_ok=True) os.makedirs(os.path.dirname(dest_path), exist_ok=True)
if file_type == "Excel": if file_type == "Excel":
copy_excel_file(source_path, dest_path, passwords) chartsheet_warning = copy_excel_file(source_path, dest_path, passwords)
if chartsheet_warning:
warning_msg = f"⚠️ {chartsheet_warning} Please check the processed file against the original to ensure data was copied correctly."
st.warning(warning_msg)
st.session_state.error_log[relative_path] = warning_msg
else: # Word else: # Word
remove_all_protection_tags(source_path, dest_path) remove_all_protection_tags(source_path, dest_path)
@ -512,15 +522,37 @@ if st.session_state.error_log:
error_text = "\n\n".join([f"File: {path}\nError: {error}" for path, error in st.session_state.error_log.items()]) error_text = "\n\n".join([f"File: {path}\nError: {error}" for path, error in st.session_state.error_log.items()])
st.text_area("Error Details", error_text, height=200) st.text_area("Error Details", error_text, height=200)
# Add copy button # Add copy button with JavaScript to copy to clipboard
if st.button("Copy Error Log"): copy_button = st.button("Copy Error Log")
st.write("Error log copied to clipboard!") if copy_button:
st.session_state.error_log_copied = error_text # Create a JavaScript function to copy the text
# Escape any backticks in the error text first
escaped_error_text = error_text.replace('`', '\u0060')
js_code = f"""
<script>
var textArea = document.createElement("textarea");
textArea.value = `{escaped_error_text}`;
document.body.appendChild(textArea);
textArea.select();
try {{
document.execCommand('copy');
textArea.remove();
window.parent.document.querySelector('iframe').contentWindow.postMessage({{copied: true}}, '*');
}} catch (err) {{
console.error('Failed to copy text: ', err);
textArea.remove();
}}
</script>
<div id="result"></div>
"""
st.components.v1.html(js_code, height=0)
st.success("✅ Error log copied to clipboard!")
# Add clear button # Add clear button
if st.button("Clear Error Log"): if st.button("Clear Error Log"):
st.session_state.error_log = {} st.session_state.error_log = {}
st.experimental_rerun() st.rerun()
else: else:
st.success("No errors encountered in current session") st.success("No errors encountered in current session")