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()