From d12e39693211e5f3d00b33c339952bb7c687329b Mon Sep 17 00:00:00 2001 From: "Bobby Abellana (aider)" Date: Tue, 11 Feb 2025 09:46:39 -0800 Subject: [PATCH] feat: Add directory processing mode with recursive file handling --- src/streamlit_app.py | 114 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 106 insertions(+), 8 deletions(-) diff --git a/src/streamlit_app.py b/src/streamlit_app.py index 102ca00..748f57f 100644 --- a/src/streamlit_app.py +++ b/src/streamlit_app.py @@ -5,6 +5,8 @@ import warnings from io import BytesIO import tempfile import zipfile +from pathlib import Path +import glob from main import ( load_workbook_with_possible_passwords, copy_excel_file, @@ -49,9 +51,16 @@ with st.sidebar: ("Excel", "Word"), help="Select the type of files you want to process" ) + + processing_mode = st.radio( + "Choose processing mode:", + ("File Upload", "Directory Processing"), + help="Process uploaded files or select directories" + ) # Main content area -if file_type == "Excel": +if processing_mode == "File Upload": + if file_type == "Excel": st.header("Excel File Processing") col1, col2 = st.columns(2) @@ -159,17 +168,106 @@ if uploaded_files: mime="application/zip", ) + else: # Directory Processing + st.header("Directory Processing") + + col1, col2 = st.columns(2) + + with col1: + source_dir = st.text_input("Source Directory Path", + help="Enter the full path to the directory containing files to process") + + dest_dir = st.text_input("Destination Directory Path", + help="Enter the full path where processed files will be saved") + + with col2: + if file_type == "Excel": + password_option = st.radio( + "Password Option:", + ("No Password", "Password File") + ) + + passwords = [] + if password_option == "Password File": + password_path = st.text_input("Password File Path", + help="Enter the full path to the text file containing passwords") + if password_path and os.path.exists(password_path): + with open(password_path, 'r', encoding='utf-8') as pf: + passwords = [line.strip() for line in pf if line.strip()] + st.info(f"Loaded {len(passwords)} passwords from file") + + if source_dir and dest_dir and st.button("Process Directory", type="primary"): + if not os.path.exists(source_dir): + st.error(f"Source directory does not exist: {source_dir}") + elif not os.path.exists(os.path.dirname(dest_dir)): + st.error(f"Parent of destination directory does not exist: {os.path.dirname(dest_dir)}") + else: + os.makedirs(dest_dir, exist_ok=True) + + # Get all files recursively + if file_type == "Excel": + files = glob.glob(os.path.join(source_dir, "**/*.xlsx"), recursive=True) + files.extend(glob.glob(os.path.join(source_dir, "**/*.xlsm"), recursive=True)) + else: # Word + files = glob.glob(os.path.join(source_dir, "**/*.docx"), recursive=True) + files.extend(glob.glob(os.path.join(source_dir, "**/*.docm"), recursive=True)) + + if not files: + st.warning(f"No {file_type} files found in the source directory") + else: + progress_bar = st.progress(0) + status_text = st.empty() + + for idx, source_path in enumerate(files): + try: + # Create a container for each file + relative_path = os.path.relpath(source_path, source_dir) + dest_path = os.path.join(dest_dir, relative_path) + + with st.expander(f"Processing {relative_path}", expanded=True): + st.write(f"📝 Processing {relative_path}...") + + # Create destination directory if needed + os.makedirs(os.path.dirname(dest_path), exist_ok=True) + + # Process based on file type + if file_type == "Excel": + copy_excel_file(source_path, dest_path, passwords) + else: # Word + remove_all_protection_tags(source_path, dest_path) + + st.success("✅ Processing complete!") + + # Update progress + progress = (idx + 1) / len(files) + progress_bar.progress(progress) + status_text.text(f"Processed {idx + 1} of {len(files)} files") + + except Exception as e: + st.error(f"❌ Error processing {relative_path}: {str(e)}") + + progress_bar.empty() + status_text.text("✨ All processing complete!") + + # Show the output directory + st.success(f"Processed files are saved in: {dest_dir}") + # Footer st.sidebar.markdown("---") st.sidebar.markdown("### Instructions") st.sidebar.markdown(""" -1. Select file type (Excel or Word) -2. Upload your files by dragging them or clicking the upload area -3. For Excel files: - - Choose password option if needed - - Enter password or upload password file -4. Click the Process button -5. Download each processed file +1. Choose processing mode: + - File Upload: Process files via web upload + - Directory Processing: Process files from local directories +2. Select file type (Excel or Word) +3. For File Upload: + - Upload your files + - Set password options if needed +4. For Directory Processing: + - Enter source and destination paths + - Provide password file path if needed +5. Click Process button +6. Monitor progress and check results """) st.sidebar.markdown("---")