Csv To Vcf Today
args = parser.parse_args()
def escape_vcf_text(self, text: str) -> str: """Escape special characters for VCF format""" if not text: return "" # VCF escaping rules text = text.replace('\\', '\\\\') text = text.replace(';', '\\;') text = text.replace(',', '\\,') text = text.replace('\n', '\\n') text = text.replace('\r', '') return text csv to vcf
def convert(self, input_file: str, output_file: Optional[str] = None, encoding: Optional[str] = None) -> int: """Convert CSV to VCF and save to file""" # Read CSV contacts = self.read_csv(input_file, encoding) if not contacts: print("No valid contacts found in CSV file") return 0 print(f"Found len(contacts) contacts") # Determine output filename if not output_file: input_path = Path(input_file) output_file = input_path.stem + '.vcf' # Write VCF file try: with open(output_file, 'w', encoding='utf-8') as f: for i, contact in enumerate(contacts, start=1): vcf_card = self.create_vcf_card(contact, i) f.write(vcf_card) if i < len(contacts): f.write('\n') print(f"Successfully converted len(contacts) contacts to output_file") return len(contacts) except Exception as e: raise Exception(f"Error writing VCF file: str(e)") args = parser
def create_vcf_card(self, contact: Dict, index: int) -> str: """Create single VCF card from contact data""" vcf_lines = [] # Begin vCard vcf_lines.append("BEGIN:VCARD") vcf_lines.append(f"VERSION:self.version") # Name (required) name = self.escape_vcf_text(contact.get('name', '')) if name: # Split name into parts name_parts = name.split(maxsplit=1) first_name = name_parts[0] if name_parts else '' last_name = name_parts[1] if len(name_parts) > 1 else '' vcf_lines.append(f"N:last_name;first_name;;;") vcf_lines.append(f"FN:name") else: vcf_lines.append(f"N:;;;index;") vcf_lines.append(f"FN:Contact index") # Phone number phone = self.format_phone(contact.get('phone', '')) if phone: vcf_lines.append(f"TEL;TYPE=CELL:phone") # Work phone (if available) work_phone = self.format_phone(contact.get('workphone', '')) if work_phone: vcf_lines.append(f"TEL;TYPE=WORK:work_phone") # Email email = self.escape_vcf_text(contact.get('email', '')) if email: vcf_lines.append(f"EMAIL;TYPE=INTERNET:email") # Company and Title company = self.escape_vcf_text(contact.get('company', '')) title = self.escape_vcf_text(contact.get('title', '')) if company: vcf_lines.append(f"ORG:company") if title: vcf_lines.append(f"TITLE:title") # Address address = self.escape_vcf_text(contact.get('address', '')) if address: vcf_lines.append(f"ADR;TYPE=WORK:;;address;;;;") # Website website = self.escape_vcf_text(contact.get('website', '')) if website: if not website.startswith(('http://', 'https://')): website = 'http://' + website vcf_lines.append(f"URL:website") # Birthday birthday = self.format_date(contact.get('birthday', '')) if birthday: vcf_lines.append(f"BDAY:birthday") # Notes notes = self.escape_vcf_text(contact.get('notes', '')) if notes: vcf_lines.append(f"NOTE:notes") # UID (unique identifier) import uuid vcf_lines.append(f"UID:uuid.uuid4()") # Revision date vcf_lines.append(f"REV:datetime.now().strftime('%Y%m%dT%H%M%SZ')") # End vCard vcf_lines.append("END:VCARD") vcf_lines.append("") # Empty line between cards return '\n'.join(vcf_lines) args = parser.parse_args() def escape_vcf_text(self
