diff --git a/1.make_csdrg_pdf.vbs b/V1/1.make_csdrg_pdf.vbs
similarity index 98%
rename from 1.make_csdrg_pdf.vbs
rename to V1/1.make_csdrg_pdf.vbs
index dbdf2a3..d4bab42 100644
--- a/1.make_csdrg_pdf.vbs
+++ b/V1/1.make_csdrg_pdf.vbs
@@ -1,2 +1,2 @@
-Set objShell = CreateObject("WScript.Shell")
-objShell.Run "python.exe """ & CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName) & "\make_csdrg_pdf.py""", 1, True
+Set objShell = CreateObject("WScript.Shell")
+objShell.Run "python.exe """ & CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName) & "\make_csdrg_pdf.py""", 1, True
diff --git a/2.run_pdf_validation.vbs b/V1/2.run_pdf_validation.vbs
similarity index 83%
rename from 2.run_pdf_validation.vbs
rename to V1/2.run_pdf_validation.vbs
index fa86a74..e4a318c 100644
--- a/2.run_pdf_validation.vbs
+++ b/V1/2.run_pdf_validation.vbs
@@ -1,16 +1,16 @@
-Option Explicit
-
-Dim shell
-Dim fso
-Dim folder
-
-Set shell = CreateObject("WScript.Shell")
-Set fso = CreateObject("Scripting.FileSystemObject")
-
-folder = fso.GetParentFolderName(WScript.ScriptFullName)
-
-shell.CurrentDirectory = folder
-
-shell.Run "py pdf_checker.py", 0, True
-
-MsgBox "PDF QA Finished!", vbInformation
\ No newline at end of file
+Option Explicit
+
+Dim shell
+Dim fso
+Dim folder
+
+Set shell = CreateObject("WScript.Shell")
+Set fso = CreateObject("Scripting.FileSystemObject")
+
+folder = fso.GetParentFolderName(WScript.ScriptFullName)
+
+shell.CurrentDirectory = folder
+
+shell.Run "py pdf_checker.py", 0, True
+
+MsgBox "PDF QA Finished!", vbInformation
diff --git a/README.md b/V1/README.md
similarity index 100%
rename from README.md
rename to V1/README.md
diff --git a/Report.html b/V1/Report.html
similarity index 85%
rename from Report.html
rename to V1/Report.html
index 578bdf8..a6b8308 100644
--- a/Report.html
+++ b/V1/Report.html
@@ -1,99 +1,98 @@
-
-
-
-
-
-
-
-
-
-PDF QA Validation Report
-
-
-
-
-
-
-
-PDF QA Validation Report
-
-
-
-
-
-Folder
-
-J:\bdm\sandbox\kevin\RG
-
-
-
-Total PDF : 1
-PASS : 0
-FAIL : 1
-
-
-
-
-
-
-| File |
-Pages |
-Fast Web View |
-Title |
-Author |
-Subject |
-Keywords |
-Result |
-Reason |
-
-
-
-
-| csdrg.pdf |
-27 |
-No |
-Empty |
-Empty |
-Empty |
-Empty |
-FAIL |
-Fast Web View |
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+PDF QA Validation Report
+
+
+
+
+
+
+
+PDF QA Validation Report
+
+
+
+
+
+Folder
+
+J:\bdm\sandbox\kevin\RG
+
+
+
+Total PDF : 1
+PASS : 0
+FAIL : 1
+
+
+
+
+
+
+| File |
+Pages |
+Fast Web View |
+Title |
+Author |
+Subject |
+Keywords |
+Result |
+Reason |
+
+
+
+
+| csdrg.pdf |
+27 |
+No |
+Empty |
+Empty |
+Empty |
+Empty |
+FAIL |
+Fast Web View |
+
+
+
+
+
+
+
+
diff --git a/make_csdrg_pdf.py b/V1/make_csdrg_pdf.py
similarity index 97%
rename from make_csdrg_pdf.py
rename to V1/make_csdrg_pdf.py
index 2e1f070..a683d67 100644
--- a/make_csdrg_pdf.py
+++ b/V1/make_csdrg_pdf.py
@@ -1,139 +1,139 @@
-"""
-make_csdrg_pdf.py
-=================
-Converts csdrg.docx -> csdrg.pdf following CSDRG Completion Guidelines v1.4:
-
- - Uses Microsoft Word COM (ExportAsFixedFormat) to preserve heading bookmarks
- - Sets initial view to show Bookmarks Panel on open
- - Clears Title / Author / Subject / Keywords per CSDRG guidelines (p.21)
- - Verifies PDF version <= 1.7 (FDA eCTD requirement)
-
-Requirements: pip install pywin32 pikepdf
-"""
-
-import os
-import sys
-import shutil
-import time
-
-try:
- import win32com.client
- import pikepdf
- from pikepdf import Dictionary, Name
-except ImportError as e:
- print(f"Missing library: {e}")
- print("Run: python -m pip install pywin32 pikepdf")
- sys.exit(1)
-
-# ── Paths ──────────────────────────────────────────────────────────────────────
-SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
-DOCX_SRC = os.path.join(SCRIPT_DIR, "csdrg.docx")
-FINAL_PDF = os.path.join(SCRIPT_DIR, "csdrg.pdf")
-TEMP_DIR = os.path.join(os.environ.get("TEMP", "C:\\Temp"), "csdrg_build")
-TEMP_DOCX = os.path.join(TEMP_DIR, "csdrg.docx")
-TEMP_PDF = os.path.join(TEMP_DIR, "csdrg.pdf")
-
-# ── Step 1: Copy docx to temp (avoids OneDrive/space path issues) ──────────────
-print("=" * 60)
-print("CSDRG PDF Builder")
-print("=" * 60)
-
-if not os.path.exists(DOCX_SRC):
- print(f"ERROR: csdrg.docx not found at:\n {DOCX_SRC}")
- sys.exit(1)
-
-os.makedirs(TEMP_DIR, exist_ok=True)
-shutil.copy2(DOCX_SRC, TEMP_DOCX)
-print(f"[1/4] Copied docx to temp: {TEMP_DOCX}")
-
-# ── Step 2: Word COM -> PDF with heading bookmarks ─────────────────────────────
-print("[2/4] Converting Word -> PDF via Microsoft Word...")
-word = win32com.client.Dispatch("Word.Application")
-word.Visible = False
-try:
- doc = word.Documents.Open(TEMP_DOCX)
- doc.ExportAsFixedFormat(
- OutputFileName = TEMP_PDF,
- ExportFormat = 17, # wdExportFormatPDF
- OpenAfterExport = False,
- OptimizeFor = 0, # wdExportOptimizeForPrint
- Range = 0, # wdExportAllDocument
- From = 1,
- To = 1,
- Item = 0, # wdExportDocumentContent
- IncludeDocProps = True,
- KeepIRM = True,
- CreateBookmarks = 1, # wdExportCreateHeadingBookmarks
- DocStructureTags = True,
- BitmapMissingFonts = True,
- UseISO19005_1 = False,
- )
- doc.Close(False)
- print(f" PDF created: {TEMP_PDF}")
-finally:
- word.Quit()
-
-time.sleep(2)
-
-# ── Step 3: pikepdf post-processing ───────────────────────────────────────────
-print("[3/4] Setting PDF properties (bookmarks panel + clear metadata)...")
-with pikepdf.open(TEMP_PDF, allow_overwriting_input=True) as pdf:
-
- # Show Bookmarks Panel when opened (CSDRG guideline requirement)
- pdf.Root["/PageMode"] = Name("/UseOutlines")
-
- # ViewerPreferences: default page layout and magnification
- if "/ViewerPreferences" not in pdf.Root:
- pdf.Root["/ViewerPreferences"] = Dictionary()
-
- # Clear Title, Author, Subject, Keywords (CSDRG Completion Guidelines p.21)
- info = pdf.docinfo
- for key in ["/Title", "/Author", "/Subject", "/Keywords", "/Creator", "/Producer"]:
- if key in info:
- info[key] = ""
-
- # Report bookmark count
- if "/Outlines" in pdf.Root:
- print(" Bookmarks: found OK")
- else:
- print(" WARNING: No bookmarks found.")
- print(" Ensure csdrg.docx uses built-in Word Heading 1/2/3 styles.")
-
- pdf.save(TEMP_PDF)
-
-# ── Step 4: Verify PDF version and copy to destination ────────────────────────
-print("[4/4] Verifying PDF version...")
-with open(TEMP_PDF, "rb") as f:
- header = f.read(8).decode("ascii", errors="replace").strip()
-print(f" PDF header: {header}")
-
-version_ok = any(v in header for v in ["1.4", "1.5", "1.6", "1.7"])
-if version_ok:
- print(" Version <= 1.7: OK")
-else:
- print(f" WARNING: Version may exceed 1.7. Check before submission.")
-
-# Copy to final destination (retry if locked)
-for attempt in range(5):
- try:
- shutil.copy2(TEMP_PDF, FINAL_PDF)
- break
- except PermissionError:
- if attempt < 4:
- print(f" File locked, retrying in 3s... (attempt {attempt+1}/5)")
- time.sleep(3)
- else:
- print(f"\nERROR: Could not write to {FINAL_PDF}")
- print("Please close any program that has csdrg.pdf open, then re-run.")
- sys.exit(1)
-
-print()
-print("=" * 60)
-print(f"Done! Output: {FINAL_PDF}")
-print()
-print("Checklist:")
-print(f" [{'OK' if version_ok else '!!'}] PDF version <= 1.7")
-print( " [OK] Bookmarks panel shown on open")
-print( " [OK] Title/Author/Subject/Keywords cleared")
-print( " [OK] File named csdrg.pdf")
-print("=" * 60)
+"""
+make_csdrg_pdf.py
+=================
+Converts csdrg.docx -> csdrg.pdf following CSDRG Completion Guidelines v1.4:
+
+ - Uses Microsoft Word COM (ExportAsFixedFormat) to preserve heading bookmarks
+ - Sets initial view to show Bookmarks Panel on open
+ - Clears Title / Author / Subject / Keywords per CSDRG guidelines (p.21)
+ - Verifies PDF version <= 1.7 (FDA eCTD requirement)
+
+Requirements: pip install pywin32 pikepdf
+"""
+
+import os
+import sys
+import shutil
+import time
+
+try:
+ import win32com.client
+ import pikepdf
+ from pikepdf import Dictionary, Name
+except ImportError as e:
+ print(f"Missing library: {e}")
+ print("Run: python -m pip install pywin32 pikepdf")
+ sys.exit(1)
+
+# ── Paths ──────────────────────────────────────────────────────────────────────
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+DOCX_SRC = os.path.join(SCRIPT_DIR, "csdrg.docx")
+FINAL_PDF = os.path.join(SCRIPT_DIR, "csdrg.pdf")
+TEMP_DIR = os.path.join(os.environ.get("TEMP", "C:\\Temp"), "csdrg_build")
+TEMP_DOCX = os.path.join(TEMP_DIR, "csdrg.docx")
+TEMP_PDF = os.path.join(TEMP_DIR, "csdrg.pdf")
+
+# ── Step 1: Copy docx to temp (avoids OneDrive/space path issues) ──────────────
+print("=" * 60)
+print("CSDRG PDF Builder")
+print("=" * 60)
+
+if not os.path.exists(DOCX_SRC):
+ print(f"ERROR: csdrg.docx not found at:\n {DOCX_SRC}")
+ sys.exit(1)
+
+os.makedirs(TEMP_DIR, exist_ok=True)
+shutil.copy2(DOCX_SRC, TEMP_DOCX)
+print(f"[1/4] Copied docx to temp: {TEMP_DOCX}")
+
+# ── Step 2: Word COM -> PDF with heading bookmarks ─────────────────────────────
+print("[2/4] Converting Word -> PDF via Microsoft Word...")
+word = win32com.client.Dispatch("Word.Application")
+word.Visible = False
+try:
+ doc = word.Documents.Open(TEMP_DOCX)
+ doc.ExportAsFixedFormat(
+ OutputFileName = TEMP_PDF,
+ ExportFormat = 17, # wdExportFormatPDF
+ OpenAfterExport = False,
+ OptimizeFor = 0, # wdExportOptimizeForPrint
+ Range = 0, # wdExportAllDocument
+ From = 1,
+ To = 1,
+ Item = 0, # wdExportDocumentContent
+ IncludeDocProps = True,
+ KeepIRM = True,
+ CreateBookmarks = 1, # wdExportCreateHeadingBookmarks
+ DocStructureTags = True,
+ BitmapMissingFonts = True,
+ UseISO19005_1 = False,
+ )
+ doc.Close(False)
+ print(f" PDF created: {TEMP_PDF}")
+finally:
+ word.Quit()
+
+time.sleep(2)
+
+# ── Step 3: pikepdf post-processing ───────────────────────────────────────────
+print("[3/4] Setting PDF properties (bookmarks panel + clear metadata)...")
+with pikepdf.open(TEMP_PDF, allow_overwriting_input=True) as pdf:
+
+ # Show Bookmarks Panel when opened (CSDRG guideline requirement)
+ pdf.Root["/PageMode"] = Name("/UseOutlines")
+
+ # ViewerPreferences: default page layout and magnification
+ if "/ViewerPreferences" not in pdf.Root:
+ pdf.Root["/ViewerPreferences"] = Dictionary()
+
+ # Clear Title, Author, Subject, Keywords (CSDRG Completion Guidelines p.21)
+ info = pdf.docinfo
+ for key in ["/Title", "/Author", "/Subject", "/Keywords", "/Creator", "/Producer"]:
+ if key in info:
+ info[key] = ""
+
+ # Report bookmark count
+ if "/Outlines" in pdf.Root:
+ print(" Bookmarks: found OK")
+ else:
+ print(" WARNING: No bookmarks found.")
+ print(" Ensure csdrg.docx uses built-in Word Heading 1/2/3 styles.")
+
+ pdf.save(TEMP_PDF)
+
+# ── Step 4: Verify PDF version and copy to destination ────────────────────────
+print("[4/4] Verifying PDF version...")
+with open(TEMP_PDF, "rb") as f:
+ header = f.read(8).decode("ascii", errors="replace").strip()
+print(f" PDF header: {header}")
+
+version_ok = any(v in header for v in ["1.4", "1.5", "1.6", "1.7"])
+if version_ok:
+ print(" Version <= 1.7: OK")
+else:
+ print(f" WARNING: Version may exceed 1.7. Check before submission.")
+
+# Copy to final destination (retry if locked)
+for attempt in range(5):
+ try:
+ shutil.copy2(TEMP_PDF, FINAL_PDF)
+ break
+ except PermissionError:
+ if attempt < 4:
+ print(f" File locked, retrying in 3s... (attempt {attempt+1}/5)")
+ time.sleep(3)
+ else:
+ print(f"\nERROR: Could not write to {FINAL_PDF}")
+ print("Please close any program that has csdrg.pdf open, then re-run.")
+ sys.exit(1)
+
+print()
+print("=" * 60)
+print(f"Done! Output: {FINAL_PDF}")
+print()
+print("Checklist:")
+print(f" [{'OK' if version_ok else '!!'}] PDF version <= 1.7")
+print( " [OK] Bookmarks panel shown on open")
+print( " [OK] Title/Author/Subject/Keywords cleared")
+print( " [OK] File named csdrg.pdf")
+print("=" * 60)
diff --git a/pdf_checker.py b/V1/pdf_checker.py
similarity index 90%
rename from pdf_checker.py
rename to V1/pdf_checker.py
index 2d74318..92bbf58 100644
--- a/pdf_checker.py
+++ b/V1/pdf_checker.py
@@ -1,199 +1,199 @@
-from pathlib import Path
-import html
-import webbrowser
-import pikepdf
-
-
-ROOT = Path.cwd()
-REPORT = ROOT / "Report.html"
-
-
-def is_linearized(pdf_file):
- """
- Detect Fast Web View (Linearized PDF)
- """
- try:
- with open(pdf_file, "rb") as f:
- header = f.read(4096)
- return b"/Linearized" in header
- except Exception:
- return False
-
-
-def get_metadata(pdf_file):
-
- result = {
- "Pages": "",
- "Title": "",
- "Author": "",
- "Subject": "",
- "Keywords": "",
- "Fast Web View": "No"
- }
-
- try:
-
- with pikepdf.open(pdf_file) as pdf:
-
- info = pdf.docinfo
-
- result["Pages"] = len(pdf.pages)
- result["Title"] = str(info.get("/Title", "") or "")
- result["Author"] = str(info.get("/Author", "") or "")
- result["Subject"] = str(info.get("/Subject", "") or "")
- result["Keywords"] = str(info.get("/Keywords", "") or "")
-
- if is_linearized(pdf_file):
- result["Fast Web View"] = "Yes"
-
- except Exception as e:
-
- result["Error"] = str(e)
-
- return result
-
-
-pdfs = sorted(ROOT.glob("*.pdf"))
-
-rows = []
-
-pass_count = 0
-fail_count = 0
-
-for pdf in pdfs:
-
- m = get_metadata(pdf)
-
- issues = []
-
- if m["Title"] != "":
- issues.append("Title")
-
- if m["Author"] != "":
- issues.append("Author")
-
- if m["Subject"] != "":
- issues.append("Subject")
-
- if m["Keywords"] != "":
- issues.append("Keywords")
-
- if m["Fast Web View"] != "Yes":
- issues.append("Fast Web View")
-
- result = "PASS" if len(issues) == 0 else "FAIL"
-
- if result == "PASS":
- pass_count += 1
- else:
- fail_count += 1
-
- rows.append(f"""
-
-| {html.escape(pdf.name)} |
-{m["Pages"]} |
-{m["Fast Web View"]} |
-{"Empty" if m["Title"]=="" else "Exists"} |
-{"Empty" if m["Author"]=="" else "Exists"} |
-{"Empty" if m["Subject"]=="" else "Exists"} |
-{"Empty" if m["Keywords"]=="" else "Exists"} |
-{result} |
-{", ".join(issues)} |
-
-""")
-
-
-html_text = f"""
-
-
-
-
-
-
-
-
-PDF QA Validation Report
-
-
-
-
-
-
-
-PDF QA Validation Report
-
-
-
-
-
-Folder
-
-{ROOT}
-
-
-
-Total PDF : {len(pdfs)}
-PASS : {pass_count}
-FAIL : {fail_count}
-
-
-
-
-
-
-| File |
-Pages |
-Fast Web View |
-Title |
-Author |
-Subject |
-Keywords |
-Result |
-Reason |
-
-
-{''.join(rows)}
-
-
-
-
-
-
-"""
-
-REPORT.write_text(html_text, encoding="utf-8")
-
-print("Finished.")
-
-webbrowser.open(REPORT.as_uri())
\ No newline at end of file
+from pathlib import Path
+import html
+import webbrowser
+import pikepdf
+
+
+ROOT = Path.cwd()
+REPORT = ROOT / "Report.html"
+
+
+def is_linearized(pdf_file):
+ """
+ Detect Fast Web View (Linearized PDF)
+ """
+ try:
+ with open(pdf_file, "rb") as f:
+ header = f.read(4096)
+ return b"/Linearized" in header
+ except Exception:
+ return False
+
+
+def get_metadata(pdf_file):
+
+ result = {
+ "Pages": "",
+ "Title": "",
+ "Author": "",
+ "Subject": "",
+ "Keywords": "",
+ "Fast Web View": "No"
+ }
+
+ try:
+
+ with pikepdf.open(pdf_file) as pdf:
+
+ info = pdf.docinfo
+
+ result["Pages"] = len(pdf.pages)
+ result["Title"] = str(info.get("/Title", "") or "")
+ result["Author"] = str(info.get("/Author", "") or "")
+ result["Subject"] = str(info.get("/Subject", "") or "")
+ result["Keywords"] = str(info.get("/Keywords", "") or "")
+
+ if is_linearized(pdf_file):
+ result["Fast Web View"] = "Yes"
+
+ except Exception as e:
+
+ result["Error"] = str(e)
+
+ return result
+
+
+pdfs = sorted(ROOT.glob("*.pdf"))
+
+rows = []
+
+pass_count = 0
+fail_count = 0
+
+for pdf in pdfs:
+
+ m = get_metadata(pdf)
+
+ issues = []
+
+ if m["Title"] != "":
+ issues.append("Title")
+
+ if m["Author"] != "":
+ issues.append("Author")
+
+ if m["Subject"] != "":
+ issues.append("Subject")
+
+ if m["Keywords"] != "":
+ issues.append("Keywords")
+
+ if m["Fast Web View"] != "Yes":
+ issues.append("Fast Web View")
+
+ result = "PASS" if len(issues) == 0 else "FAIL"
+
+ if result == "PASS":
+ pass_count += 1
+ else:
+ fail_count += 1
+
+ rows.append(f"""
+
+| {html.escape(pdf.name)} |
+{m["Pages"]} |
+{m["Fast Web View"]} |
+{"Empty" if m["Title"]=="" else "Exists"} |
+{"Empty" if m["Author"]=="" else "Exists"} |
+{"Empty" if m["Subject"]=="" else "Exists"} |
+{"Empty" if m["Keywords"]=="" else "Exists"} |
+{result} |
+{", ".join(issues)} |
+
+""")
+
+
+html_text = f"""
+
+
+
+
+
+
+
+
+PDF QA Validation Report
+
+
+
+
+
+
+
+PDF QA Validation Report
+
+
+
+
+
+Folder
+
+{ROOT}
+
+
+
+Total PDF : {len(pdfs)}
+PASS : {pass_count}
+FAIL : {fail_count}
+
+
+
+
+
+
+| File |
+Pages |
+Fast Web View |
+Title |
+Author |
+Subject |
+Keywords |
+Result |
+Reason |
+
+
+{''.join(rows)}
+
+
+
+
+
+
+"""
+
+REPORT.write_text(html_text, encoding="utf-8")
+
+print("Finished.")
+
+webbrowser.open(REPORT.as_uri())