top of page

Csv To Vcf !!hot!! -

def read_csv(self, file_path: str, encoding: Optional[str] = None) -> List[Dict]: """Read CSV file and return list of dictionaries""" if not encoding: encoding = self.detect_encoding(file_path) print(f"Detected encoding: encoding") contacts = [] try: with open(file_path, 'r', encoding=encoding) as f: # Detect delimiter sample = f.read(1024) f.seek(0) delimiter = self.detect_delimiter(sample) print(f"Detected delimiter: delimiter") reader = csv.DictReader(f, delimiter=delimiter) # Normalize column names reader.fieldnames = [self.normalize_column_name(col) for col in reader.fieldnames] for row_num, row in enumerate(reader, start=2): contact = self.normalize_contact(row) if contact.get('name') or contact.get('phone'): contacts.append(contact) else: print(f"Warning: Row row_num skipped - missing name or phone") except Exception as e: raise Exception(f"Error reading CSV file: str(e)") return contacts

1. CSV Format Requirements The converter expects CSV files with the following columns (case-insensitive): csv to vcf

def convert_to_string(self, input_file: str, encoding: Optional[str] = None) -> str: """Convert CSV to VCF string (without saving to file)""" contacts = self.read_csv(input_file, encoding) vcf_strings = [] for i, contact in enumerate(contacts, start=1): vcf_strings.append(self.create_vcf_card(contact, i)) return '\n'.join(vcf_strings) def main(): parser = argparse.ArgumentParser( description='Convert CSV contacts to VCF (vCard) format', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: python csv_to_vcf.py contacts.csv python csv_to_vcf.py contacts.csv -o output.vcf python csv_to_vcf.py contacts.csv -e iso-8859-1 """ ) encoding: Optional[str] = None) -&gt

def normalize_column_name(self, col: str) -> str: """Normalize column names to standard format""" col = col.lower().strip() mapping = 'name': 'name', 'fullname': 'name', 'displayname': 'name', 'phone': 'phone', 'mobile': 'phone', 'telephone': 'phone', 'cell': 'phone', 'workphone': 'phone', 'email': 'email', 'emailaddress': 'email', 'company': 'company', 'organization': 'company', 'title': 'title', 'jobtitle': 'title', 'position': 'title', 'address': 'address', 'street': 'address', 'website': 'website', 'url': 'website', 'webpage': 'website', 'birthday': 'birthday', 'bday': 'birthday', 'dob': 'birthday', 'notes': 'notes', 'comment': 'notes', 'description': 'notes' return mapping.get(col, col) row in enumerate(reader

def format_phone(self, phone: str) -> str: """Format phone number for VCF""" if not phone: return "" # Remove spaces and common separators phone = re.sub(r'[\(\)\s\-\.]', '', phone) # Add international prefix if missing if phone.startswith('0') and not phone.startswith('+'): phone = '+1' + phone[1:] # Default to US/Canada, customize as needed return self.escape_vcf_text(phone)

def detect_delimiter(self, sample: str) -> str: """Detect CSV delimiter (comma, semicolon, or tab)""" common_delimiters = [',', ';', '\t', '|'] delimiter_counts = {} for delimiter in common_delimiters: if delimiter in sample: # Count occurrences in first line first_line = sample.split('\n')[0] delimiter_counts[delimiter] = first_line.count(delimiter) if delimiter_counts: return max(delimiter_counts, key=delimiter_counts.get) return ',' # Default to comma

bottom of page