Band Contacts to Google Contacts v1
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
import csv
|
||||
import argparse
|
||||
import datetime
|
||||
import re
|
||||
|
||||
def get_category(instrument):
|
||||
"""Categorize the instrument into Woodwinds, Brass, Percussion, or Colorguard."""
|
||||
inst_lower = instrument.lower()
|
||||
|
||||
if any(x in inst_lower for x in ['flute', 'clarinet', 'sax', 'oboe', 'bassoon', 'piccolo']):
|
||||
return 'Woodwinds'
|
||||
if any(x in inst_lower for x in ['trumpet', 'mellophone', 'horn', 'trombone', 'baritone', 'euphonium', 'tuba', 'sousaphone']):
|
||||
return 'Brass'
|
||||
if any(x in inst_lower for x in ['percussion', 'snare', 'tenor', 'drum', 'cymbal', 'marimba', 'vibraphone', 'timpani', 'bells', 'electronics']):
|
||||
return 'Percussion'
|
||||
if 'guard' in inst_lower or 'color' in inst_lower:
|
||||
return 'Colorguard'
|
||||
|
||||
return 'Leadership' # Fallback for generic roles like Drum Major
|
||||
|
||||
def format_phone(phone_str):
|
||||
"""Clean and standardize the phone numbers."""
|
||||
phone = str(phone_str).strip()
|
||||
if not phone:
|
||||
return ""
|
||||
|
||||
# Leave non-US international codes as they are
|
||||
if phone.startswith('+') and not phone.startswith('+1'):
|
||||
return phone
|
||||
|
||||
# Standardize US numbers to XXX-XXX-XXXX
|
||||
digits = re.sub(r'\D', '', phone)
|
||||
if len(digits) == 10:
|
||||
return f"{digits[:3]}-{digits[3:6]}-{digits[6:]}"
|
||||
elif len(digits) == 11 and digits.startswith('1'):
|
||||
return f"{digits[1:4]}-{digits[4:7]}-{digits[7:]}"
|
||||
|
||||
return phone
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Convert Band Leadership CSV to Google Contacts format.")
|
||||
parser.add_argument("input_file", help="Path to the input CSV file")
|
||||
parser.add_argument("-y", "--year", type=int, default=datetime.datetime.now().year,
|
||||
help="Target year for labels and grade calculation (defaults to current year)")
|
||||
parser.add_argument("-o", "--output", default="google_contacts_import.csv",
|
||||
help="Output file name")
|
||||
args = parser.parse_args()
|
||||
|
||||
target_year = args.year
|
||||
|
||||
# Google Contacts Headers matching your expected output
|
||||
google_headers = [
|
||||
"First Name", "Middle Name", "Last Name", "Phonetic First Name", "Phonetic Middle Name",
|
||||
"Phonetic Last Name", "Name Prefix", "Name Suffix", "Nickname", "File As",
|
||||
"Organization Name", "Organization Title", "Organization Department", "Birthday", "Notes",
|
||||
"Photo", "Labels", "E-mail 1 - Label", "E-mail 1 - Value", "Phone 1 - Label",
|
||||
"Phone 1 - Value", "Phone 2 - Label", "Phone 2 - Value", "Phone 3 - Label", "Phone 3 - Value",
|
||||
"Address 1 - Label", "Address 1 - Formatted", "Address 1 - Street", "Address 1 - City",
|
||||
"Address 1 - PO Box", "Address 1 - Region", "Address 1 - Postal Code", "Address 1 - Country",
|
||||
"Address 1 - Extended Address"
|
||||
]
|
||||
|
||||
with open(args.input_file, mode='r', encoding='utf-8') as infile, \
|
||||
open(args.output, mode='w', encoding='utf-8', newline='') as outfile:
|
||||
|
||||
reader = csv.DictReader(infile)
|
||||
writer = csv.DictWriter(outfile, fieldnames=google_headers)
|
||||
writer.writeheader()
|
||||
|
||||
for row in reader:
|
||||
# Skip empty rows or the trailing blank commas in the source file
|
||||
name_field = row.get('NAME', '').strip()
|
||||
if not name_field or name_field == ',':
|
||||
continue
|
||||
|
||||
# Parse Name ("Last, First")
|
||||
name_parts = name_field.split(',')
|
||||
last_name = name_parts[0].strip() if len(name_parts) > 0 else ""
|
||||
first_name = name_parts[1].strip() if len(name_parts) > 1 else ""
|
||||
|
||||
# Parse Instrument (e.g., "04 - Tenor Sax" -> "Tenor Sax")
|
||||
section_raw = row.get('SECTION', '').strip()
|
||||
instrument = section_raw.split('-', 1)[-1].strip() if '-' in section_raw else section_raw
|
||||
if not instrument:
|
||||
instrument = "Unknown"
|
||||
|
||||
# Parse Grade and formulate Notes
|
||||
grade_raw = row.get('GRADE', '').strip()
|
||||
grade_match = re.match(r"(\d{4})\s*\((.*?)\)", grade_raw)
|
||||
if grade_match:
|
||||
grad_year = grade_match.group(1)
|
||||
grade_level = grade_match.group(2).capitalize()
|
||||
notes = f"Class of {grad_year}. A {grade_level} in {target_year}"
|
||||
else:
|
||||
notes = grade_raw
|
||||
|
||||
# Determine Label
|
||||
category = get_category(instrument)
|
||||
label = f"{target_year} {category} ::: Marching Band ::: * myContacts"
|
||||
|
||||
# Build the output row
|
||||
out_row = {key: "" for key in google_headers}
|
||||
out_row["First Name"] = first_name
|
||||
out_row["Last Name"] = f"{last_name} ({instrument})"
|
||||
out_row["Notes"] = notes
|
||||
out_row["Labels"] = label
|
||||
|
||||
# Map Email
|
||||
email = row.get('EMAIL', '').strip()
|
||||
if email:
|
||||
out_row["E-mail 1 - Label"] = "Home"
|
||||
out_row["E-mail 1 - Value"] = email
|
||||
|
||||
# Map Phone
|
||||
phone = row.get('PHONE', '').strip()
|
||||
if phone:
|
||||
out_row["Phone 1 - Label"] = "Mobile"
|
||||
out_row["Phone 1 - Value"] = format_phone(phone)
|
||||
|
||||
writer.writerow(out_row)
|
||||
|
||||
print(f"Success! Formatted contacts saved to {args.output}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user