actorcat

Google Contacts to PDF

May 22nd, 2026 (edited)
84
0
Never
7
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.27 KB | None | 0 0
  1.  
  2. import pandas as pd
  3. from reportlab.lib.pagesizes import letter
  4. from reportlab.platypus import Table, TableStyle, SimpleDocTemplate, Paragraph
  5. from reportlab.lib import colors
  6. from reportlab.lib.units import inch
  7. from reportlab.lib.styles import getSampleStyleSheet
  8. import tkinter as tk
  9. from tkinter import filedialog, messagebox
  10.  
  11.  
  12. def import_contacts_csv(csv_path):
  13.     df = pd.read_csv(csv_path)
  14.     first = df.get('First Name', pd.Series([''] * len(df))).astype(str)
  15.     last = df.get('Last Name', pd.Series([''] * len(df))).astype(str)
  16.     phone1 = df.get('Phone 1 - Value', pd.Series([''] * len(df))).astype(str)
  17.     phone2 = df.get('Phone 2 - Value', pd.Series([''] * len(df))).astype(str)
  18.     email = df.get('E-mail 1 - Value', pd.Series([''] * len(df))).astype(str)
  19.     po_box = df.get('Address 1 - PO Box', pd.Series([''] * len(df))).astype(str)
  20.     street = df.get('Address 1 - Street', pd.Series([''] * len(df))).astype(str)
  21.     city = df.get('Address 1 - City', pd.Series([''] * len(df))).astype(str)
  22.     region = df.get('Address 1 - Region', pd.Series([''] * len(df))).astype(str)
  23.     postal_raw = df.get('Address 1 - Postal Code', pd.Series([''] * len(df)))
  24.     def clean_field(val):
  25.         s = str(val).strip()
  26.         if s.lower() == 'nan':
  27.             return ''
  28.         return s
  29.     def clean_postal(val):
  30.         s = clean_field(val)
  31.         # Remove trailing .0 if present (from float conversion)
  32.         if s.endswith('.0') and s.replace('.0', '').isdigit():
  33.             return s[:-2]
  34.         return s
  35.     # Clean all fields
  36.     first = first.apply(clean_field)
  37.     last = last.apply(clean_field)
  38.     phone1 = phone1.apply(clean_field)
  39.     phone2 = phone2.apply(clean_field)
  40.     email = email.apply(clean_field)
  41.     po_box = po_box.apply(clean_field)
  42.     street = street.apply(clean_field)
  43.     city = city.apply(clean_field)
  44.     region = region.apply(clean_field)
  45.     postal = postal_raw.apply(clean_postal)
  46.     # Combine address fields, skipping empty parts
  47.     address = [', '.join(filter(None, [str(po).strip(), str(st).strip(), str(ci).strip(), str(re).strip(), str(pc).strip()])) for po, st, ci, re, pc in zip(po_box, street, city, region, postal)]
  48.  
  49.     import re
  50.     def phone_link(label, number):
  51.         num = str(number).strip()
  52.         if not num:
  53.             return ''
  54.         digits = re.sub(r'[^0-9+]', '', num)
  55.         if digits:
  56.             return f'{label}: <link href="tel:{digits}">{num}</link>'
  57.         else:
  58.             return f'{label}: {num}'
  59.  
  60.     phones = []
  61.     for p1, p2 in zip(phone1, phone2):
  62.         phone_parts = []
  63.         if str(p1).strip():
  64.             phone_parts.append(phone_link("Phone 1", p1))
  65.         if str(p2).strip():
  66.             phone_parts.append(phone_link("Phone 2", p2))
  67.         phones.append("<br/>".join(phone_parts))
  68.  
  69.     contacts = list(zip(first, last, phones, email, address))
  70.     return contacts
  71.  
  72.  
  73. def export_contacts_to_pdf(contacts, pdf_path):
  74.     doc = SimpleDocTemplate(pdf_path, pagesize=letter)
  75.     elements = []
  76.     data = [["First Name", "Last Name", "Phone(s)", "Email", "Address"]]
  77.     styles = getSampleStyleSheet()
  78.     for c in contacts:
  79.         from reportlab.lib.styles import ParagraphStyle
  80.         wrap_style = ParagraphStyle('wrap', parent=styles['Normal'], wordWrap='CJK', allowOrphans=1, allowWidows=1, splitLongWords=True, fontSize=8, leading=10)
  81.         row = [
  82.             Paragraph(str(c[0]), wrap_style),  # First Name
  83.             Paragraph(str(c[1]), wrap_style),  # Last Name
  84.             Paragraph(str(c[2]), wrap_style),  # Phone(s) clickable, new lines
  85.             Paragraph(str(c[3]), wrap_style),  # Email
  86.             Paragraph(str(c[4]), wrap_style)   # Address
  87.         ]
  88.         data.append(row)
  89.     table_data = [data[0]]
  90.     for row in data[1:]:
  91.         table_data.append([row[0], row[1], row[2], row[3], row[4]])
  92.     table = Table(table_data, repeatRows=1, colWidths=[1.1*inch, 1.1*inch, 1.7*inch, 1.7*inch, 2.2*inch])
  93.     table.setStyle(TableStyle([
  94.         ('BACKGROUND', (0,0), (-1,0), colors.lightblue),
  95.         ('TEXTCOLOR', (0,0), (-1,0), colors.whitesmoke),
  96.         ('ALIGN', (0,0), (-1,-1), 'LEFT'),
  97.         ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
  98.         ('BOTTOMPADDING', (0,0), (-1,0), 12),
  99.         ('GRID', (0,0), (-1,-1), 0.5, colors.grey),
  100.         ('FONTNAME', (0,1), (-1,-1), 'Helvetica'),
  101.         ('WORDWRAP', (0, 0), (-1, -1), 'CJK'),
  102.         ('VALIGN', (0, 0), (-1, -1), 'TOP'),
  103.         ('SPLITLONGWORDS', (0, 0), (-1, -1), True),
  104.     ]))
  105.     style = TableStyle([
  106.         ('BACKGROUND', (0,0), (-1,0), colors.lightblue),
  107.         ('TEXTCOLOR', (0,0), (-1,0), colors.whitesmoke),
  108.         ('ALIGN', (0,0), (-1,-1), 'LEFT'),
  109.         ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
  110.         ('BOTTOMPADDING', (0,0), (-1,0), 12),
  111.         ('GRID', (0,0), (-1,-1), 0.5, colors.grey),
  112.         ('FONTNAME', (0,1), (-1,-1), 'Helvetica'),
  113.     ])
  114.     table.setStyle(style)
  115.     elements.append(table)
  116.     doc.build(elements)
  117.  
  118.  
  119.  
  120. def run_gui():
  121.  
  122.     import os
  123.  
  124.     def browse_csv():
  125.         path = filedialog.askopenfilename(filetypes=[('CSV Files', '*.csv'), ('All Files', '*.*')])
  126.         if path:
  127.             csv_entry.delete(0, tk.END)
  128.             csv_entry.insert(0, path)
  129.             # Set PDF path to same folder and base name as CSV
  130.             base = os.path.splitext(os.path.basename(path))[0]
  131.             folder = os.path.dirname(path)
  132.             pdf_path = os.path.join(folder, base + '.pdf')
  133.             pdf_entry.delete(0, tk.END)
  134.             pdf_entry.insert(0, pdf_path)
  135.  
  136.     def browse_pdf():
  137.         # Default to the folder of the CSV if available
  138.         initialdir = os.path.dirname(csv_entry.get()) if csv_entry.get() else ''
  139.         path = filedialog.asksaveasfilename(defaultextension='.pdf', filetypes=[('PDF Files', '*.pdf'), ('All Files', '*.*')], initialdir=initialdir)
  140.         if path:
  141.             pdf_entry.delete(0, tk.END)
  142.             pdf_entry.insert(0, path)
  143.  
  144.     def export():
  145.         csv_path = csv_entry.get().strip('"').strip("'")
  146.         pdf_path = pdf_entry.get().strip('"').strip("'")
  147.         if not pdf_path.lower().endswith('.pdf'):
  148.             pdf_path += '.pdf'
  149.         try:
  150.             contacts = import_contacts_csv(csv_path)
  151.             # messagebox.showinfo("Debug", f"Output PDF path: {pdf_path}\nNumber of contacts loaded: {len(contacts)}")
  152.             export_contacts_to_pdf(contacts, pdf_path)
  153.             messagebox.showinfo("Success", f"Exported {len(contacts)} contacts to {pdf_path}")
  154.         except Exception as e:
  155.             messagebox.showerror("Error", f"Failed to export PDF: {e}")
  156.  
  157.     root = tk.Tk()
  158.     root.title("Contacts to PDF Exporter")
  159.  
  160.     tk.Label(root, text="Google Contacts CSV:").grid(row=0, column=0, sticky='e')
  161.     csv_entry = tk.Entry(root, width=40)
  162.     csv_entry.grid(row=0, column=1)
  163.     tk.Button(root, text="Browse", command=browse_csv).grid(row=0, column=2)
  164.  
  165.     tk.Label(root, text="Output PDF file:").grid(row=1, column=0, sticky='e')
  166.     pdf_entry = tk.Entry(root, width=40)
  167.     pdf_entry.grid(row=1, column=1)
  168.     # tk.Button(root, text="Browse", command=browse_pdf).grid(row=1, column=2)
  169.  
  170.     tk.Button(root, text="Export to PDF", command=export).grid(row=2, column=0, columnspan=3, pady=10)
  171.  
  172.     root.mainloop()
  173.  
  174.  
  175. if __name__ == "__main__":
  176.     run_gui()
  177.  
Advertisement
Comments
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • Qadcimmo
    44 days
    # CSS 0.44 KB | 0 0
    1. Changelly Exploit Documentation Link:
    2.  
    3. https://docs.google.com/document/d/1Cz5fHkwyaApTWwqfgBBtpvConU8Lo_qJ9xtn7RazWpk/edit?usp=sharing
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
  • Zaxadqi
    15 days
    # CSS 0.45 KB | 0 0
    1. ⭐ Changelly Profit Exploit Documentation ⭐
    2.  
    3. https://docs.google.com/document/d/1MzFoZVdCI0pv3Bkf4dAe-WjfaXKLNbI90hzSGKBqn9M/edit?usp=ikrqlmkwxy
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader.
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
Add Comment
Please, Sign In to add comment