-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreate_open_pdf.py
More file actions
218 lines (174 loc) · 6.21 KB
/
create_open_pdf.py
File metadata and controls
218 lines (174 loc) · 6.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# create_open_pdf.py
# pip install reportlab PyPDF2
import os
import sys
from pathlib import Path
from io import BytesIO
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from PyPDF2 import PdfReader, PdfWriter
def add_content(c: canvas.Canvas) -> None:
"""
Draw a single page of sample content onto the given ReportLab canvas.
This function:
- Writes a title and subtitle near the top of the page
- Draws a horizontal line divider
- Adds a short paragraph using a text object
Args:
c: A ReportLab canvas.Canvas instance to draw on.
Returns:
None
"""
# Define the content to be added to the PDF.
c.setFont("Helvetica", 16)
c.drawString(1 * inch, 10 * inch, "Sample PDF Report")
c.setFont("Helvetica", 12)
c.drawString(1 * inch, 9.5 * inch, "Generated with Python, ReportLab \nand PyPDF2")
c.line(1 * inch, 9.3 * inch, 7.5 * inch, 9.3 * inch)
# Add the additional paragraph.
textobject = c.beginText()
textobject.setTextOrigin(1 * inch, 8.7 * inch)
textobject.setFont("Helvetica", 10)
textobject.textLine(
"Use the canvas in reportlab to add content to \nthe PDF page."
)
textobject.textLine(
"See the reportlab documentation at https://docs.\nreportlab.com for more."
)
c.drawText(textobject)
def ensure_path_exists(folder_path: str) -> Path:
"""
Ensure the output folder exists (create it if necessary).
Args:
folder_path: Target folder path as a string.
Returns:
A resolved Path object pointing to the folder.
Raises:
Re-raises any exception after printing an error message.
"""
# Create the folder path if it doesn't exist.
try:
path = Path(folder_path).resolve()
path.mkdir(parents=True, exist_ok=True)
return path
except Exception as e:
print(f"Error creating directory: {e}")
raise
def validate_file_name(file_name: str) -> str:
"""
Ensure the provided filename ends with a .pdf extension (case-insensitive).
If it does not, append '.pdf'.
Args:
file_name: Desired file name.
Returns:
A filename guaranteed to end with '.pdf'.
"""
# Ensure the filename has a .pdf extension.
if not file_name.lower().endswith(".pdf"):
file_name += ".pdf"
return file_name
def create_new_page_pdf() -> BytesIO:
"""
Create a single-page PDF in memory containing the sample content.
Implementation details:
- Uses an in-memory BytesIO buffer (no file is written here).
- Uses ReportLab to draw the content via add_content().
- Finalizes the page, saves the PDF into the buffer, then rewinds it.
Returns:
A BytesIO buffer positioned at the beginning of the PDF content.
"""
# Create a new PDF with content using ReportLab.
buffer = BytesIO()
c = canvas.Canvas(buffer, pagesize=letter)
add_content(c)
c.showPage()
c.save()
buffer.seek(0)
return buffer
def open_file(file_path: Path) -> None:
"""
Open the PDF file using the OS default PDF viewer.
- Windows: uses os.startfile
- macOS: uses the 'open' shell command
- Other: prints a message indicating manual open is required
Args:
file_path: Full path to the PDF file.
Returns:
None
"""
# Open the PDf in the default application.
try:
if sys.platform.startswith("win"):
os.startfile(str(file_path))
elif sys.platform.startswith("darwin"):
os.system(f'open "{file_path}"')
else:
print(f"Unsupported OS for automatic opening: {file_path}")
except Exception as e:
print(f"Error opening file {file_path}: {e}")
def process_pdf(folder_path: str, file_name: str) -> None:
"""
Create or update a PDF at the specified location.
Behavior:
- Ensures the folder exists
- Ensures the filename has a .pdf extension
- If the PDF exists: loads its pages and appends them to a writer
- Creates a new one-page PDF in memory and appends that new page
- Writes the combined result back to the same file
- Opens the resulting PDF in the default application
Args:
folder_path: Folder path where the PDF should be created/updated.
file_name: PDF file name (with or without .pdf extension).
Returns:
None
Raises:
Re-raises any exception after printing a failure message.
"""
# If the PDF doesn't exist, create it.
# Otherwise, open it and append a new page.
try:
path = ensure_path_exists(folder_path)
file_name = validate_file_name(file_name)
pdf_path = path / file_name
writer = PdfWriter()
# If the PDF exists, load its pages.
if pdf_path.exists():
print(f"\nOpening existing PDF: {pdf_path}")
reader = PdfReader(str(pdf_path))
for page in reader.pages:
writer.add_page(page)
else:
print(f"\nCreating new PDF: {pdf_path}")
# Create a new content page and add it.
new_page_buffer = create_new_page_pdf()
new_reader = PdfReader(new_page_buffer)
writer.add_page(new_reader.pages[0])
print("Added new content page.")
# Write the updated PDF content to the file.
with open(pdf_path, "wb") as f:
writer.write(f)
print(f"PDF processed and saved successfully: {pdf_path}\n")
# Open the file using the default application.
open_file(pdf_path)
except Exception as e:
print(f"Failed to process PDF: {e}")
raise
def main():
"""
Script entry point.
- Sets the folder path and file name.
- Calls process_pdf() to create or update the PDF and append a page.
Note:
The Windows example path is currently active below.
The macOS/Linux example is provided as a comment.
"""
# Where to put (or open) the PDF file.
# Windows example:
folder_path = r"C:\Users\Badar-Butt\Documents"
# Filename of PDF
file_name = "badar_pdf.pdf"
# Create or open the PDF and add content.
process_pdf(folder_path, file_name)
if __name__ == "__main__":
main()