(Aug-26-2024, 07:42 PM)deanhystad Wrote: [ -> ]Post the code. All of it. Or at least all the parts related to the pdf merge.
here is my full code, still in progress as you could see that the GCCB frame is empty,
import os
import tkinter as tk
import re
import sys
import atexit
from tkinter import filedialog, messagebox, ttk
from PIL import Image, ImageTk
from openpyxl import load_workbook
from datetime import datetime
from tqdm import tqdm
from win32com.client import DispatchEx
from PyPDF2 import PdfMerger
from pathlib import Path
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("GENERATOR")
self.geometry("1080x720")
# Initialize frames first
self.home_frame = tk.Frame(self, bg="light gray")
self.excel_frame = tk.Frame(self, bg="light gray")
self.gccb_frame = tk.Frame(self, bg="light gray")
self.PDF_frame = tk.Frame(self, bg="light gray")
# Set grid layout 1x2
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=1)
# Load images with light and dark mode image
image_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_images")
self.text_image = ImageTk.PhotoImage(Image.open(os.path.join(image_path, "Text_image.png")).resize((400, 70)))
self.image_icon_image = ImageTk.PhotoImage(Image.open(os.path.join(image_path, "logo.png")).resize((250, 175)))
self.circle_logo_image = ImageTk.PhotoImage(Image.open(os.path.join(image_path, "_logo_single.png")).resize((26, 26)))
self.home_image = ImageTk.PhotoImage(Image.open(os.path.join(image_path, "home_dark.png")).resize((20, 20)))
self.excel_image = ImageTk.PhotoImage(Image.open(os.path.join(image_path, "Excel_dark.png")).resize((20, 20)))
self.PDF_image = ImageTk.PhotoImage(Image.open(os.path.join(image_path, "PDF_dark.png")).resize((20, 20)))
self.gccb_image = ImageTk.PhotoImage(Image.open(os.path.join(image_path, "GCCB_dark.png")).resize((20, 20)))
self.reload_image = ImageTk.PhotoImage(Image.open(os.path.join(image_path, "reload_dark.png")).resize((20, 20)))
# Create navigation frame
self.navigation_frame = tk.Frame(self, bg="gray")
self.navigation_frame.grid(row=0, column=0, sticky="nsew")
self.navigation_frame.grid_rowconfigure(5, weight=1)
self.navigation_frame_label = tk.Label(self.navigation_frame, text=" KU",
image=self.KU_circle_logo_image, compound="left",
font=("Arial", 18, "bold"), fg="dark orange", bg=self.navigation_frame['bg'])
self.navigation_frame_label.grid(row=0, column=0, padx=20, pady=20)
self.home_button = tk.Button(self.navigation_frame, height=40, text="Home",
bg="light gray", fg="gray10", activebackground="gray70",
image=self.home_image, compound="left", anchor="w", padx=10, pady=5,
command=self.home_button_event)
self.home_button.grid(row=1, column=0, sticky="ew")
self.excel_button = tk.Button(self.navigation_frame, height=40, text="Excel Buyoff Book Generator",
bg="light gray", fg="gray10", activebackground="gray70",
image=self.excel_image, compound="left", anchor="w", padx=10, pady=5,
command=self.excel_button_event)
self.excel_button.grid(row=2, column=0, sticky="ew")
self.gccb_button = tk.Button(self.navigation_frame, height=40, text="GCCB Tool Checklist",
bg="light gray", fg="gray10", activebackground="gray70",
image=self.gccb_image, compound="left", anchor="w", padx=10, pady=5,
command=self.gccb_button_event)
self.gccb_button.grid(row=3, column=0, sticky="ew")
self.PDF_button = tk.Button(self.navigation_frame, height=40, text="PDF Generator",
bg="light gray", fg="gray10", activebackground="gray70",
image=self.PDF_image, compound="left", anchor="w", padx=10, pady=5,
command=self.PDF_button_event)
self.PDF_button.grid(row=4, column=0, sticky="ew")
self.reset_button = tk.Button(self.navigation_frame, height=40, text="Reload Program",
bg="light gray", fg="gray10", activebackground="gray70",
image=self.reload_image, compound="left", anchor="w", padx=10, pady=5,
command=self.reset_script)
self.reset_button.grid(row=5, column=0, sticky="ew")
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::FRAMES::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# Home frame setup
self.home_frame.grid(row=0, column=1, sticky="nsew")
self.home_frame.grid_rowconfigure(0, weight=1)
self.home_frame.grid_columnconfigure(0, weight=1)
# Create excel frame
self.excel_frame = tk.Frame(self, bg="light gray")
# Create gccb frame
self.excel_frame = tk.Frame(self, bg="light gray")
# Create gccb frame
self.gccb_frame = tk.Frame(self, bg="light gray")
# Initialize the application by showing the home frame
self.home_button_event()
#:::::::::::::::::::::::::::::::::::::::::::::::::::::::HOME DRAME LAYOUT::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# KU Text Logo
self.home_frame_large_image_label = tk.Label(self.home_frame, image=self.KU_text_image, bg=self.home_frame['bg'])
self.home_frame_large_image_label.grid(row=0, column=0, padx=20, pady=20, sticky="nsew" )
# Add a welcome message
welcome_message = (
"Welcome to GG KU Generator.\n\n"
"This tool is designed to streamline the creation of Buyoff Books,\n\n"
"PDFs, and GCCB Tools Check Lists "
"ensuring accuracy and efficiency in the process.\n\n"
"Thank you for using GG Buyoff Book Generator.\n\n"
"\n"
"\n"
"For any questions, contact:\n"
"[email protected]\n")
self.home_frame_Welcome_label = tk.Label(self.home_frame, text=welcome_message, font=("Arial", 16), bg=self.home_frame['bg'])
self.home_frame_Welcome_label.grid(row=1, column=0, padx=20, pady=20, sticky="nsew")
# GG Logo
self.home_frame_large_image_label = tk.Label(self.home_frame, image=self.image_GG_icon_image, bg=self.home_frame['bg'])
self.home_frame_large_image_label.grid(row=2, column=0, padx=20, pady=20)
# Version
self.right_corner_label = tk.Label(self.home_frame, text="Version: 2.0 - Author", bg=self.home_frame['bg'])
self.right_corner_label.grid(row=3, column=0, padx=5, pady=0, sticky="e")
#:::::::::::::::::::::::::::::::::::::::::::::::::::::::EXCEL DRAME LAYOUT::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# Initialize instance variables
self.file_paths = []
self.workbooks = {}
self.zone_cell_entries = []
self.folders = []
# Frame for Project Information
self.excel_frame_project_info_label = tk.Label(self.excel_frame, text="GG Information:", bg=self.excel_frame['bg'])
self.excel_frame_project_info_label.grid(row=0, column=0, padx=5, pady=(20,10), sticky="w")
# Create and place the "Program Name" label and entry
self.program_name_label = tk.Label(self.excel_frame, text="Program Name:", bg=self.excel_frame['bg'])
self.program_name_label.grid(row=1, column=0, padx=20, pady=5, sticky="w")
self.Program_name_entry = tk.Entry(self.excel_frame)
self.Program_name_entry.grid(row=1, column=2, padx=5, pady=5, sticky="ew")
# Create and place the "KU Controls Engineer" label and entry
self.KU_control_engineer_label = tk.Label(self.excel_frame, text="KU Controls Engineer:", bg=self.excel_frame['bg'])
self.KU_control_engineer_label.grid(row=2, column=0, padx=20, pady=5, sticky="w")
self.KU_control_engineer_entry = tk.Entry(self.excel_frame)
self.KU_control_engineer_entry.grid(row=2, column=2, padx=5, pady=5, sticky="ew")
# Create and place the "KU Controls Engineer Email" label and entry
self.KU_control_engineer_email_label = tk.Label(self.excel_frame, text="KU Controls Engineer Email:", bg=self.excel_frame['bg'])
self.KU_control_engineer_email_label.grid(row=3, column=0, padx=20, pady=5, sticky="w")
self.KU_control_engineer_email_entry = tk.Entry(self.excel_frame)
self.KU_control_engineer_email_entry.grid(row=3, column=2, padx=5, pady=5, sticky="ew")
# Create and place the "KU Controls Engineer Phone" label and entry
self.KU_control_engineer_phone_label = tk.Label(self.excel_frame, text="KU Controls Engineer Phone:", bg=self.excel_frame['bg'])
self.KU_control_engineer_phone_label.grid(row=4, column=0, padx=20, pady=5, sticky="w")
self.KU_control_engineer_phone_entry = tk.Entry(self.excel_frame)
self.KU_control_engineer_phone_entry.grid(row=4, column=2, padx=5, pady=5, sticky="ew")
# Create and place the "ME BIW/M&E Engineer" label and entry
self.me_biw_me_engineer_label = tk.Label(self.excel_frame, text="ME BIW/M&E Engineer:", bg=self.excel_frame['bg'])
self.me_biw_me_engineer_label.grid(row=5, column=0, padx=20, pady=5, sticky="w")
self.me_biw_me_engineer_entry = tk.Entry(self.excel_frame)
self.me_biw_me_engineer_entry.grid(row=5, column=2, padx=5, pady=5, sticky="ew")
# Create and place the "Destination Plant" label and entry
self.destination_plant_label = tk.Label(self.excel_frame, text="Destination Plant:", bg=self.excel_frame['bg'])
self.destination_plant_label.grid(row=6, column=0, padx=20, pady=5, sticky="w")
self.destination_plant_entry = tk.Entry(self.excel_frame)
self.destination_plant_entry.grid(row=6, column=2, padx=5, pady=5, sticky="ew")
# Create and place the "Plant Codet" label and entry
self.plant_code_label = tk.Label(self.excel_frame, text="Plant Code (Caps):", bg=self.excel_frame['bg'])
self.plant_code_label.grid(row=7, column=0, padx=20, pady=5, sticky="w")
self.plant_code_entry = tk.Entry(self.excel_frame)
self.plant_code_entry.grid(row=7, column=2, padx=5, pady=5, sticky="ew")
# Create and place the "SOP" label and entry
self.SOP_label = tk.Label(self.excel_frame, text="SOP (2 Digit):", bg=self.excel_frame['bg'])
self.SOP_label.grid(row=8, column=0, padx=20, pady=5, sticky="w")
self.SOP_entry = tk.Entry(self.excel_frame)
self.SOP_entry.grid(row=8, column=2, padx=5, pady=5, sticky="ew")
#Frame for KU Information
self.excel_frame_KU_info_label = tk.Label(self.excel_frame, text="KU Information:", bg=self.excel_frame['bg'])
self.excel_frame_KU_info_label.grid(row=9, column=0, padx=5, pady=(30,5), sticky="w")
# Create and place the "integrator" label and entry
self.integrator_label = tk.Label(self.excel_frame, text="Integrator:", bg=self.excel_frame['bg'])
self.integrator_label.grid(row=10, column=0, padx=20, pady=5, sticky="w")
self.integrator_entry = tk.Entry(self.excel_frame)
self.integrator_entry.grid(row=10, column=2, padx=5, pady=5, sticky="ew")
# Create and place the "Integrator Build Location" label and entry
self.integrator_build_location_label = tk.Label(self.excel_frame, text="Integrator Build Location:", bg=self.excel_frame['bg'])
self.integrator_build_location_label.grid(row=11, column=0, padx=20, pady=5, sticky="w")
self.integrator_build_location_entry = tk.Entry(self.excel_frame)
self.integrator_build_location_entry.grid(row=11, column=2, padx=5, pady=5, sticky="ew")
# Create and place the "KU Controls Engineer" label and entry
self.KU_control_engineer_label = tk.Label(self.excel_frame, text="KU Controls Engineer:", bg=self.excel_frame['bg'])
self.KU_control_engineer_label.grid(row=12, column=0, padx=20, pady=5, sticky="w")
self.KU_control_engineer_entry = tk.Entry(self.excel_frame)
self.KU_control_engineer_entry.grid(row=12, column=2, padx=5, pady=5, sticky="ew")
# Create and place the "KU Controls Engineer Phone" label and entry
self.KU_control_engineer_phone_label = tk.Label(self.excel_frame, text="KU Controls Engineer Phone:", bg=self.excel_frame['bg'])
self.KU_control_engineer_phone_label.grid(row=13, column=0, padx=20, pady=5, sticky="w")
self.KU_control_engineer_phone_entry = tk.Entry(self.excel_frame)
self.KU_control_engineer_phone_entry.grid(row=13, column=2, padx=5, pady=5, sticky="ew")
# Create and place the "Today's Date" label and entry
self.today_date_label = tk.Label(self.excel_frame, text="Today's Date:", bg=self.excel_frame['bg'])
self.today_date_label.grid(row=14, column=0, padx=20, pady=5, sticky="w")
self.today_date_entry = tk.Entry(self.excel_frame)
self.today_date_entry.grid(row=14, column=2, padx=5, pady=5, sticky="ew")
# Create button to load templates
self.load_excel_template = tk.Button(self.excel_frame, text="Load Templates", command=self.load_files)
self.load_excel_template.grid(row=1, column=3, padx=(100,20), pady=10, sticky="ew")
# Create button to remove templates
self.remove_excel_template = tk.Button(self.excel_frame, text="REMOVE Templates", command=self.remove_file)
self.remove_excel_template.grid(row=1, column=4, padx=20, pady=10, sticky="ew")
# Create a listbox to display loaded checklist files using tkinter's Listbox
self.excel_file_listbox = tk.Listbox(self.excel_frame, selectmode=tk.SINGLE, width=50)
self.excel_file_listbox.grid(row=2, column=3, columnspan=2, rowspan=5, padx=(90,10), pady=5, sticky="ew")
# Optional: Apply custom styling if needed, bg=backround,
self.excel_file_listbox.configure(bg="gray", fg="white", selectbackground="blue", selectforeground="white")
# Create button to add zone/cells
self.add_zone_cell = tk.Button(self.excel_frame, text="Add Zone/Cell", command=self.add_zone_cell_entry)
self.add_zone_cell.grid(row=8, column=3, padx=(100,20), pady=5, sticky="ew")
# Create button to remove zone/cells
self.remove_zone_cell = tk.Button(self.excel_frame, text="REMOVE Zone/Cell", command=self.remove_zone_cell_entry)
self.remove_zone_cell.grid(row=8, column=4, padx=20, pady=5, sticky="ew")
# Create a frame for the scrollable area
self.zone_cell_frame = tk.Frame(self.excel_frame, borderwidth=2, relief="solid", bg=self.excel_frame['bg'])
self.zone_cell_frame.grid(row=9, column=3, columnspan=2, rowspan=8, padx=(90, 0), pady=(10, 0), sticky="nsew")
# Create a canvas and a scrollbar
self.canvas = tk.Canvas(self.zone_cell_frame)
self.scrollbar = ttk.Scrollbar(self.zone_cell_frame, orient="vertical", command=self.canvas.yview)
# Pack the scrollbar and canvas in the frame
self.scrollbar.pack(side="right", fill="y")
self.canvas.pack(side="left", fill="both", expand=True)
# Create a frame inside the canvas
self.scrollable_frame = tk.Frame(self.canvas)
# Add the scrollable frame to the canvas
self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
# Update the canvas's scroll region whenever the scrollable frame is resized
self.scrollable_frame.bind("<Configure>", self.on_frame_configure)
# Set the scrollbar to update the canvas view
self.canvas.config(yscrollcommand=self.scrollbar.set)
self.scrollbar.config(command=self.canvas.yview)
# Add the first Zone/Cell entry by default
self.add_zone_cell_entry()
# Create button to generate excel sheets
self.generate_excel_sheets = tk.Button(self.excel_frame, text="Generate Excel Sheets", command=self.save_files)
self.generate_excel_sheets.grid(row=17, column=3, columnspan=3, padx=(105,20), pady=10, sticky="nsew")
self.excel_progressbar = tk.ttk.Progressbar(self.excel_frame, mode="determinate")
self.excel_progressbar.grid(row=18, column=1, columnspan=3, padx=(20,20), pady=(10,20), sticky="nsew")
#:::::::::::::::::::::::::::::::::::::::::::::::::::::::PDF FRAME LAYOUT::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# Frame to hold both the listbox and scrollbar
self.pdf_listbox_frame = tk.Frame(self.PDF_frame)
self.pdf_listbox_frame.grid(row=0, column=0, columnspan=5, rowspan=5, padx=(90, 10), pady=20, sticky="nsew")
# Create a listbox to display loaded checklist files
self.pdf_folder_listbox = tk.Listbox(self.pdf_listbox_frame, selectmode=tk.SINGLE, width=115, height=20)
self.pdf_folder_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# Optional: Apply custom styling if needed
self.pdf_folder_listbox.configure(bg="gray70", fg="black", selectbackground="blue", selectforeground="white")
# Scrollbar for the listbox
self.pdf_scrollbar = ttk.Scrollbar(self.pdf_listbox_frame, orient=tk.VERTICAL, command=self.pdf_folder_listbox.yview)
self.pdf_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# Configure the listbox to use the scrollbar
self.pdf_folder_listbox.config(yscrollcommand=self.pdf_scrollbar.set)
# Label to show selected folders
self.pdf_folder_label = tk.Label(self.PDF_frame, text="No folders selected.", bg=self.PDF_frame['bg'])
self.pdf_folder_label.grid(row=6, column=0, columnspan=5, padx=(90, 10), pady=20, sticky="nsew")
# Button to select multiple folders Directory
self.pdf_select_button = ttk.Button(self.PDF_frame, text="Select Directory Folder", command=self.select_pdf_directory)
self.pdf_select_button.grid(row=7, column=0, columnspan=5, padx=(90, 10), pady=10, sticky="ns")
# Start conversion button
self.pdf_convert_button = ttk.Button(self.PDF_frame, text="Convert and Merge PDFs", command=self.start_conversion, state=tk.DISABLED, )
self.pdf_convert_button.grid(row=8, column=0, columnspan=5, padx=(90, 10), pady=10, sticky="ns")
self.pdf_progressbar = tk.ttk.Progressbar(self.PDF_frame, mode="determinate")
self.pdf_progressbar.grid(row=9, column=0, columnspan=5, padx=(80,20), pady=(20,20), sticky="ew")
# Progress label
self.pdf_progress_label = tk.Label(self.PDF_frame, text="", bg=self.PDF_frame['bg'])
self.pdf_progress_label.grid(row=10, column=0, columnspan=5, padx=(90, 10), pady=20, sticky="nsew")
# Button to select multiple folders Directory
self.pdf_reset_button = ttk.Button(self.PDF_frame, text="RESET", command=self.clear_pdf_frame)
self.pdf_reset_button.grid(row=11, column=0, columnspan=5, padx=(90, 10), pady=10, sticky="w")
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::EXCEL CODES::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# Function to add Excel Template sheets when button pressed
def load_files(self):
new_file_paths = filedialog.askopenfilenames(filetypes=[("Excel files", "*.xlsx;*.xls")])
if new_file_paths:
for file_path in new_file_paths:
if file_path not in self.file_paths:
if file_path.endswith(".xls"):
messagebox.showwarning("Warning",
f"{os.path.basename(file_path)} is a .xls file. "
"Go to the original file and Save As .xlsx extension and reload file again.")
continue
if file_path.endswith(".xlsx"):
try:
self.workbooks[file_path] = load_workbook(file_path)
self.excel_file_listbox.insert(tk.END, os.path.basename(file_path))
self.file_paths.append(file_path) # Add file path to the list
except Exception as e:
messagebox.showerror("Error", f"Failed to load {os.path.basename(file_path)}: {e}")
messagebox.showinfo("Files Loaded", "Excel files loaded successfully.")
def remove_file(self):
selected_file_index = self.excel_file_listbox.curselection()
if selected_file_index:
selected_file = self.excel_file_listbox.get(selected_file_index)
for file_path in self.file_paths:
if os.path.basename(file_path) == selected_file:
self.file_paths.remove(file_path)
del self.workbooks[file_path]
break
self.excel_file_listbox.delete(selected_file_index)
messagebox.showinfo("File Removed", f"File {selected_file} removed successfully.")
else:
messagebox.showwarning("Warning", "Please select a file to remove.")
def on_frame_configure(self, event):
# Update the scroll region of the canvas to encompass the frame
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
# Functio to add Zone/Cell enteries when button pressed
def add_zone_cell_entry(self):
label = tk.Label(master=self.scrollable_frame, text=f"Zone/Cell {len(self.zone_cell_entries) + 1}")
label.grid(sticky='w', padx=10, pady=(5,0))
entry = tk.Entry(master=self.scrollable_frame)
entry.grid(sticky='w', padx=10, pady=(0,5))
self.zone_cell_entries.append((label, entry))
# Functio to REMOVE Zone/Cell enteries when button pressed
def remove_zone_cell_entry(self):
if self.zone_cell_entries:
label, entry = self.zone_cell_entries.pop()
label.destroy()
entry.destroy()
else:
messagebox.showwarning("Warning", "No Zone/Cell entries to remove.")
def save_files(self):
if not self.file_paths:
messagebox.showwarning("Warning", "Please load files first.")
return
# Get user inputs
program_name = self.Program_name_entry.get()
integrator = self.integrator_entry.get()
KU_control_engineer = self.KU_control_engineer_entry.get()
KU_control_engineer_email = self.KU_control_engineer_email_entry.get()
KU_control_engineer_phone = self.KU_control_engineer_phone_entry.get()
KU_control_engineer = self.KU_control_engineer_entry.get()
KU_control_engineer_phone = self.KU_control_engineer_phone_entry.get()
date = self.today_date_entry.get()
me_biw_me_engineer = self.me_biw_me_engineer_entry.get()
destination_plant = self.destination_plant_entry.get()
integrator_build_location = self.integrator_build_location_entry.get()
plant_code = self.plant_code_entry.get()
sop = self.SOP_entry.get()
# Get Zone/Cell entries
zone_cells = [entry.get() for label, entry in self.zone_cell_entries]
# Get directory to save files
save_dir = filedialog.askdirectory()
if not save_dir:
messagebox.showwarning("Warning", "Please select a directory to save the files.")
return
# Initialize progress tracking
total_files = len(self.file_paths) * len(zone_cells)
processed_files = 0
self.excel_progressbar['value'] = 0 # Set initial value to 0
self.excel_progressbar.configure(maximum=100) # Set maximum value to 100
def update_progress():
# Calculate the progress as a percentage
progress_value = (processed_files / total_files) * 100
self.excel_progressbar['value'] = progress_value
self.excel_frame.update_idletasks()
# Process files
for file_path in self.file_paths:
file_name = os.path.basename(file_path)
for zone_cell in zone_cells:
# Create a new directory for each Zone/Cell
zone_cell_dir = os.path.join(save_dir, zone_cell)
os.makedirs(zone_cell_dir, exist_ok=True)
new_file_name = os.path.join(zone_cell_dir, f"{zone_cell}_{file_name}")
if file_path.endswith(".xlsx"):
workbook = load_workbook(file_path)
ws = workbook.active
if "(0.00)" in file_name and "Cover Page" in file_name:
# Process Cover Page file
ws['C8'] = destination_plant
ws['C9'] = program_name
ws['C10'] = date
ws['D14'] = zone_cell
elif "(1.00)" in file_name and "Power_On_Checklist" in file_name:
# Process Power_On_Checklist file
ws['A2'] = program_name
ws['F2'] = integrator
ws['G2'] = KU_control_engineer
ws['A4'] = zone_cell
ws['F4'] = date
ws['G4'] = me_biw_me_engineer
elif "(1.01)" in file_name and "Tool" in file_name:
# Process Power_On_Checklist file
ws['C1'] = zone_cell
elif "(1.02)" in file_name and "Build_Checklist" in file_name:
# Process Build_Checklist file
ws['A2'] = datetime.now().strftime("%Y-%m-%d")
ws['A4'] = KU_control_engineer
ws['F4'] = destination_plant
ws['F2'] = integrator_build_location
ws['G4'] = zone_cell
ws['G2'] = f"WD-{plant_code}{sop}{zone_cell}"
elif "(1.03)" in file_name and "GCCS Checklist" in file_name:
# Process GCCS Checklist file
modified_zone_cell = zone_cell[:-3] + "C1" + zone_cell[-3:]
ws['A2'] = modified_zone_cell
ws['E2'] = f"WD-{plant_code}{sop}{zone_cell}"
ws['F2'] = date
ws['A4'] = KU_control_engineer
ws['E4'] = KU_control_engineer_email
ws['F4'] = KU_control_engineer_phone
ws['A6'] = integrator
ws['E6'] = KU_control_engineer
ws['F6'] = KU_control_engineer_phone
elif "(1.04)" in file_name and "IntegrationReverification" in file_name:
# Process IntegrationReverification file
ws['L2'] = integrator
ws['L4'] = KU_control_engineer
ws['N6'] = date
ws['N4'] = KU_control_engineer
ws['N2'] = f"{program_name}/{destination_plant}/{zone_cell}"
elif "(1.05)" in file_name and "Tput" in file_name:
# Process Power_On_Checklist file
ws['C1'] = zone_cell
elif "(1.06)" in file_name and "GKU" in file_name:
# Process Power_On_Checklist file
ws['C1'] = zone_cell
elif "(1.07)" in file_name and "AGC" in file_name:
# Process Power_On_Checklist file
ws['C1'] = zone_cell
elif "(1.08)" in file_name and "NAX 4 Hr Run" in file_name:
# Process NAX 4 Hr Run file
ws['F3'] = integrator_build_location
ws['F5'] = KU_control_engineer
ws['F7'] = me_biw_me_engineer
ws['H3'] = f"{destination_plant}/{program_name}"
ws['H5'] = zone_cell
ws['H7'] = KU_control_engineer
elif "(2.00)" in file_name and "Power_On_Checklist" in file_name:
# Process (2.00) Power_On_Checklist file
ws['A2'] = program_name
ws['F2'] = integrator
ws['G2'] = KU_control_engineer
ws['A4'] = zone_cell
ws['F4'] = date
ws['G4'] = me_biw_me_engineer
elif "(2.01)" in file_name and "IECN" in file_name:
# Process Power_On_Checklist file
ws['C1'] = zone_cell
elif "(2.02)" in file_name and "GCCS Checklist" in file_name:
# Process (2.02) GCCS Checklist file
modified_zone_cell = zone_cell[:-3] + "C1" + zone_cell[-3:]
ws['A2'] = modified_zone_cell
ws['E2'] = f"WD-{plant_code}{sop}{zone_cell}"
ws['F2'] = date
ws['A4'] = KU_control_engineer
ws['E4'] = KU_control_engineer_email
ws['F4'] = KU_control_engineer_phone
ws['A6'] = integrator
ws['E6'] = KU_control_engineer
ws['F6'] = KU_control_engineer_phone
elif "(2.03)" in file_name and "Reverification" in file_name:
# Process Power_On_Checklist file
ws['C1'] = zone_cell
elif "(2.04)" in file_name and "GKU" in file_name:
# Process Power_On_Checklist file
ws['C1'] = zone_cell
elif "(2.05)" in file_name and "AGC" in file_name:
# Process Power_On_Checklist file
ws['C1'] = zone_cell
elif "(2.06)" in file_name and "Tput" in file_name:
# Process Power_On_Checklist file
ws['C1'] = zone_cell
elif "(2.07)" in file_name and "NAX 4 Hr Run" in file_name:
# Process (2.07) NAX 4 Hr Run file
ws['F3'] = destination_plant
ws['F5'] = KU_control_engineer
ws['F7'] = me_biw_me_engineer
ws['H3'] = f"{destination_plant}/{program_name}"
ws['H5'] = zone_cell
ws['H7'] = KU_control_engineer
# Save the modified workbook
workbook.save(new_file_name)
workbook.close()
elif file_path.endswith(".xls"):
messagebox.showinfo("Notice", f"Please convert {file_name} to .xlsx manually. Modifications not saved for .xls files.")
continue
processed_files += 1
update_progress()
messagebox.showinfo("Success", "Files saved successfully.")
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::PDF CODES::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
def resource_path(self, relative_path):
# Get the absolute path to the resource, works for both script and executable.
try:
base_path = sys._MEIPASS # PyInstaller stores files here
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
def select_pdf_directory(self):
# Allow user to select a directory to get subdirectories
folder_path = filedialog.askdirectory(title="Select a Directory Folder")
if folder_path:
subfolders = [f.path for f in os.scandir(folder_path) if f.is_dir()]
for folder in subfolders:
if folder not in self.folders:
self.folders.append(folder)
self.pdf_folder_listbox.insert(tk.END, folder) # Add folder to listbox
self.update_ui()
def update_ui(self):
if self.folders:
self.pdf_convert_button.configure(state=tk.NORMAL)
self.pdf_folder_label.configure(text=f"Selected Folders: {len(self.folders)}")
else:
self.pdf_convert_button.configure(state=tk.DISABLED)
self.pdf_folder_label.configure(text="No folders selected.")
def start_conversion(self):
merged_pdf_paths = [] # List to keep track of merged PDF paths
total_files = sum(len([f for f in os.listdir(folder) if f.lower().endswith(('.xls', '.xlsx'))]) for folder in self.folders)
self.pdf_progressbar.configure(maximum=total_files)
processed_files = 0
for input_dir in self.folders:
# Ensure PDFs directory exists within the input directory
pdfs_dir = os.path.join(input_dir, 'PDFs')
mkdir(pdfs_dir)
# Convert Excel files to PDFs within the subdirectories
processed_files += self.convert_to_pdfs(input_dir, pdfs_dir)
# Always merge PDFs in this folder and store the path
merged_pdf_path = self.merge_pdfs(pdfs_dir)
if merged_pdf_path:
merged_pdf_paths.append(merged_pdf_path)
# Merge all the individual merged PDFs into a master PDF
if merged_pdf_paths:
self.create_master_pdf(merged_pdf_paths, os.path.dirname(self.folders[0]))
messagebox.showinfo("Success", "Conversion, merging, and master PDF creation completed successfully!")
self.pdf_progressbar['value'] = self.pdf_progressbar['maximum'] # Set progress bar to complete
def sanitize_filename(self, filename):
# Remove special characters from filename
return re.sub(r'[<>:"/\\|?*]', '_', filename)
def convert_to_pdfs(self, input_dir, pdfs_dir):
total_files_in_dir = 0
for dirpath, _, filenames in os.walk(input_dir):
excel_files = [os.path.join(dirpath, f) for f in filenames if f.lower().endswith(('.xls', '.xlsx'))]
total_files_in_dir += len(excel_files)
# If no Excel files found in this directory, skip
if not excel_files:
print(f"No Excel files found in {dirpath}") # Debugging output
continue
xl = DispatchEx("Excel.Application")
xl.Visible = False
xl.DisplayAlerts = 0
atexit.register(lambda: xl.Quit())
for input_file in tqdm(excel_files, desc=f"Processing files in {dirpath}"):
workbook = None
try:
workbook = xl.Workbooks.Open(input_file)
active_sheet = workbook.ActiveSheet
# Default orientation
orientation = 1 # Portrait
# Determine the orientation based on file name
filename = os.path.basename(input_file)
if "(1.04)" in filename and "IntegrationReverification" in filename:
orientation = 2 # Landscape mode
elif "(1.08)" in filename and "NAX 4 Hr Run" in filename:
orientation = 2 # Landscape mode
elif "(2.07)" in filename and "NAX 4 Hr Run" in filename:
orientation = 2 # Landscape mode
active_sheet.PageSetup.Orientation = orientation
# Sanitize the filename
sanitized_filename = self.sanitize_filename(f"{os.path.splitext(os.path.basename(input_file))[0]}_ActiveSheet.pdf")
output_file = os.path.join(pdfs_dir, sanitized_filename)
print(f"Exporting to: {output_file}") # Debugging output
active_sheet.ExportAsFixedFormat(0, output_file)
# Check if the file is created and its size
if os.path.exists(output_file) and os.path.getsize(output_file) > 0:
print(f"File successfully created: {output_file}")
else:
print(f"PDF file created but is empty: {output_file}")
# Update progress bar and label
self.pdf_progressbar['value'] += 1 # Update progress bar
self.pdf_progress_label.configure(text=f"Converted: {self.pdf_progressbar['value']} / {self.pdf_progressbar['maximum']}")
self.PDF_frame.update_idletasks() # Update the GUI
except Exception as e:
print(f"Error processing file {input_file}: {e}")
finally:
if workbook:
workbook.Close(False)
xl.Quit()
return total_files_in_dir # Return the number of processed files
def merge_pdfs(self, pdfs_dir):
pdf_merger = PdfMerger()
pdf_files = [os.path.join(pdfs_dir, f) for f in os.listdir(pdfs_dir) if f.lower().endswith('.pdf')]
if not pdf_files:
print("No PDF files found to merge.") # Debugging output
messagebox.showwarning("Warning", "No PDF files found to merge.")
return None
for pdf in pdf_files:
if os.path.exists(pdf) and os.path.getsize(pdf) > 0:
try:
pdf_merger.append(pdf)
print(f"Adding to merge: {pdf}") # Debugging output
except Exception as e:
print(f"Error adding PDF to merger: {pdf}, Error: {e}")
merged_file = os.path.join(pdfs_dir, "BuyOff Book Full PDF.pdf") # Set the merged PDF name here
try:
pdf_merger.write(merged_file)
pdf_merger.close()
# Check if the merged file is created and its size
if os.path.exists(merged_file) and os.path.getsize(merged_file) > 0:
print(f"Merged file created: {merged_file}") # Debugging output
self.pdf_progressbar['value'] += 1 # Update progress bar for merging
self.pdf_progress_label.configure(text=f"Merged: {self.pdf_progressbar['value']} / {self.pdf_progressbar['maximum']}")
self.PDF_frame.update_idletasks() # Update the GUI
return merged_file # Return the path of the merged PDF
else:
print(f"Final merged PDF is empty or not created: {merged_file}")
messagebox.showerror("Error", "The final merged PDF is empty or not created.")
return None
except Exception as e:
messagebox.showerror("Error", f"An error occurred while merging PDFs: {e}")
print(f"Error merging PDFs: {e}")
return None
def create_master_pdf(self, merged_pdf_paths, output_dir):
master_pdf_merger = PdfMerger()
for pdf in merged_pdf_paths:
if os.path.exists(pdf) and os.path.getsize(pdf) > 0:
try:
master_pdf_merger.append(pdf)
print(f"Adding to master merge: {pdf}") # Debugging output
except Exception as e:
print(f"Error adding PDF to master merger: {pdf}, Error: {e}")
master_merged_file = os.path.join(output_dir, "Master_Merged_BuyOff_Book.pdf") # Set the master merged PDF name here
try:
master_pdf_merger.write(master_merged_file)
master_pdf_merger.close()
if os.path.exists(master_merged_file) and os.path.getsize(master_merged_file) > 0:
print(f"Master merged file created: {master_merged_file}") # Debugging output
else:
print(f"Final master merged PDF is empty or not created: {master_merged_file}")
messagebox.showerror("Error", "The final master merged PDF is empty or not created.")
except Exception as e:
messagebox.showerror("Error", f"An error occurred while merging master PDFs: {e}")
print(f"Error merging master PDFs: {e}")
def home_button_event(self):
self.home_frame.grid(row=0, column=1, sticky="nsew")
self.excel_frame.grid_forget()
self.PDF_frame.grid_forget()
self.gccb_frame.grid_forget()
def excel_button_event(self):
self.excel_frame.grid(row=0, column=1, sticky="nsew")
self.home_frame.grid_forget()
self.PDF_frame.grid_forget()
self.gccb_frame.grid_forget()
def gccb_button_event(self):
self.gccb_frame.grid(row=0, column=1, sticky="nsew")
self.home_frame.grid_forget()
self.PDF_frame.grid_forget()
self.excel_frame.grid_forget()
def PDF_button_event(self):
self.PDF_frame.grid(row=0, column=1, sticky="nsew")
self.home_frame.grid_forget()
self.excel_frame.grid_forget()
self.gccb_frame.grid_forget()
def change_appearance_mode_event(self, mode):
# Implement mode change logic here
pass
def send_email_button_event(self):
# Implement email sending logic here
pass
def generate_pdf_button_event(self):
# Implement PDF generation logic here
pass
def exit_program(self):
self.destroy()
def reset_script(self):
"""Restarts the current script."""
python = sys.executable
os.execv(python, [python] + sys.argv)
def clear_pdf_frame(self):
"""Clears all entries, resets loaded files/folders, and updates the UI."""
# Example: Clear input entries (adjust these lines based on your actual entries)
# self.some_entry.delete(0, tk.END)
# self.another_entry.delete(0, tk.END)
# Clear the ListBox of folders if you are using a ListBox to display them
if hasattr(self, 'pdf_folder_listbox'):
self.pdf_folder_listbox.delete(0, tk.END)
# Reset the folders list or any other lists you're managing
self.folders = []
# Reset the progress bar and related labels
if hasattr(self, 'pdf_progressbar'):
self.pdf_progressbar['value'] = 0 # Reset progress bar to 0
if hasattr(self, 'pdf_progress_label'):
self.pdf_progress_label.configure(text="Converted: 0 / 0") # Reset progress label
# Update the label showing the number of selected folders
if hasattr(self, 'pdf_folder_label'):
self.pdf_folder_label.configure(text="No folders selected.")
# Disable buttons or other widgets as needed if there's no data
if hasattr(self, 'pdf_convert_button'):
self.pdf_convert_button.configure(state=tk.DISABLED)
# Additional resets for other states or variables you have
# Example: Clear any loaded files list or other variables
# self.loaded_files = []
# Update the GUI to reflect the cleared state
self.update_ui()
def mkdir(dir):
if not os.path.exists(dir):
os.makedirs(dir)
if __name__ == "__main__":
app = App()
app.mainloop()