-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.py
159 lines (127 loc) · 4.96 KB
/
main.py
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
import os
import time
import shutil
import gc
import json
import pandas as pd
from pptx import Presentation
from pptx.util import Inches
import qrcode
from PIL import Image
import comtypes.client
from multiprocessing import Pool
pd.options.mode.chained_assignment = None # default='warn'
def load_config(file_path):
with open(file_path, "r") as config_file:
config = json.load(config_file)
return config
base_path = os.path.dirname(os.path.abspath(__file__))
config = load_config("config.json")
# Extract configuration options
input_pptx = config["input_pptx"]
output_folder = config["output_folder"]
logo_path = config["logo_path"]
csv_file = config["csv_file"]
output_folder = os.path.join(base_path, output_folder)
pptx_output_folder = os.path.join(base_path, "certificates_pptx")
qr_code_folder = os.path.join(base_path, "qr_codes")
def PPT_to_PDF(input_pptx, output_pdf):
powerpoint = comtypes.client.CreateObject("Powerpoint.Application")
if output_pdf[-3:] != "pdf":
output_pdf = output_pdf + ".pdf"
deck = powerpoint.Presentations.Open(input_pptx, WithWindow=False)
deck.ExportAsFixedFormat(output_pdf, FixedFormatType=2)
deck.Close()
powerpoint.Quit()
def generate_qr_code(url, output_path):
logo = Image.open(logo_path)
basewidth = 100
wpercent = basewidth / float(logo.size[0])
hsize = int((float(logo.size[1]) * float(wpercent)))
logo = logo.resize((basewidth, hsize), Image.Resampling.LANCZOS)
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=9,
border=4,
)
qr.add_data(url)
qr.make(fit=True)
img = qr.make_image(fill_color=(85, 101, 111), back_color="white").convert("RGB")
pos = ((img.size[0] - logo.size[0]) // 2, (img.size[1] - logo.size[1]) // 2)
img.paste(logo, pos)
img = img.resize((100, 100), Image.Resampling.LANCZOS)
img.save(output_path)
def process_pptx(row):
os.makedirs(output_folder, exist_ok=True)
os.makedirs(pptx_output_folder, exist_ok=True)
os.makedirs(qr_code_folder, exist_ok=True)
prs = Presentation(input_pptx)
qr_code_url = row[3]
qr_code_path = os.path.join(qr_code_folder, f"{row[1]}.png")
generate_qr_code(qr_code_url, qr_code_path)
# Define the placeholders to replace
placeholders = {
"Placeholder_Name": row[2],
"Placeholder_refno": row[1],
}
# Iterate through slides and shapes to find and replace the placeholders
for slide in prs.slides:
for shape in slide.shapes:
if shape.has_text_frame:
for paragraph in shape.text_frame.paragraphs:
for run in paragraph.runs:
for placeholder, value in placeholders.items():
if placeholder in run.text:
run.text = run.text.replace(placeholder, value)
left = Inches(9.5)
top = Inches(7.4)
qr_code = Image.open(qr_code_path)
pic = slide.shapes.add_picture(qr_code_path, left, top, width=None, height=None)
pic.click_action.hyperlink.address = qr_code_url
# Save the modified PowerPoint presentation
updated_pptx = os.path.join(pptx_output_folder, f"{row[1]}.pptx")
prs.save(updated_pptx)
# Convert the updated PowerPoint presentation to PDF
output_pdf = os.path.join(output_folder, f"{row[1]}.pdf")
PPT_to_PDF(updated_pptx, output_pdf)
# print(f"Certificate for {row['name']} has been saved as '{output_pdf}'.")
gc.collect()
def generate_certificates_summary(df):
"""
Generate a Markdown file with a summary of the certificates generated.
Can be used to validate the certificates generated.
"""
certificates_md = "certificates.md"
# Create a DataFrame for the Markdown table
df_md = df[["id", "name", "profile_url"]]
df_md["profile_url"] = df_md["profile_url"].apply(
lambda x: f"[Link]({x})" if pd.notna(x) else ""
)
# Write the DataFrame to the Markdown file
with open(certificates_md, mode="w", newline="") as md_file:
md_file.write("# Certificates\n")
time_now = time.strftime("%d %B %Y, %H:%M:%S", time.localtime())
md_file.write(f"Generated on {time_now}\n\n")
df_md.to_markdown(md_file, index=False)
def main():
start_time = time.time()
# Load data from CSV file
df = pd.read_csv(csv_file)
print("Generating Certificates...\nPlease wait...")
# Use multiprocessing Pool to parallelize certificate generation
with Pool() as pool:
pool.map(process_pptx, df.itertuples(index=False, name=None))
shutil.rmtree(pptx_output_folder)
shutil.rmtree(qr_code_folder)
generate_certificates_summary(df)
time_elapsed = time.time() - start_time
print(
"Time elapsed for generating {} certificates: {:.2f} seconds.".format(
len(df), time_elapsed
)
)
print("All certificates have been generated.")
gc.collect()
if __name__ == "__main__":
main()