import osimport pandas as pdimport vobjectdef excel_to_vcf(excel_path, out_vcf): """ Excel通讯录批量导出为标准vCard VCF3.0文件 Excel表头必须严格:姓名,手机号码,邮箱,备注,分组,公司,职位,生日,地址 """ # 校验Excel文件是否存在 if not os.path.exists(excel_path): print(f"错误:文件 {excel_path} 不存在,请确认文件放在脚本同一目录!") return # 读取Excel全部转为字符串,空值填充空字符串 try: df = pd.read_excel(excel_path, dtype=str).fillna("") except Exception as e: print(f"读取Excel失败:{e}") return total_count = len(df) success_count = 0 fail_count = 0 required_cols = ["姓名", "手机号码", "邮箱", "备注", "分组", "公司", "职位", "生日", "地址"] # 校验表头是否齐全 missing_cols = [col for col in required_cols if col not in df.columns] if missing_cols: print(f"Excel缺少必要表头:{missing_cols}") print(f"当前Excel表头:{list(df.columns)}") return print(f"开始转换,总计 {total_count} 条数据") # UTF-8写入vcf with open(out_vcf, "w", encoding="utf-8") as f: for idx, row in df.iterrows(): try: card = vobject.vCard() card.add("VERSION").value = "3.0" # 1. 姓名 full_name = row["姓名"].strip() if full_name: card.add("FN").value = full_name # 简单拆分姓与名(简单适配,复杂姓名可自行改写) #name_parts = full_name #card.add("N").value = ["", name_parts, "", "", ""] # 2. 手机号 phone = row["手机号码"].strip() if phone: tel_item = card.add("TEL") tel_item.value = phone tel_item.type_param = "CELL" # 3. 邮箱 email = row["邮箱"].strip() if email: email_item = card.add("EMAIL") email_item.value = email email_item.type_param = "WORK" # 4. 备注 note_text = row["备注"].strip() if note_text: card.add("NOTE").value = note_text # 5. 分组:把中文逗号换成英文逗号,手机才能识别多标签 group_text = row["分组"].strip() if group_text: group_text = group_text.replace(",", ",") card.add("X-CATEGORIES").value = group_text # 6. 公司、职位 company = row["公司"].strip() if company: card.add("ORG").value = company job_title = row["职位"].strip() if job_title: card.add("TITLE").value = job_title # 7. 生日 birthday = row["生日"].strip() if birthday: card.add("BDAY").value = birthday # 8. 地址 addr_text = row["地址"].strip() if addr_text: addr_item = card.add("ADDR") # ADDR格式:邮编;国家;省;市;街道;门牌号;备注 addr_item.value = ["", "", "", "", addr_text, "", ""] addr_item.type_param = "HOME" # 写入vcf文本 vcf_content = card.serialize() f.write(vcf_content) success_count += 1 if (idx + 1) % 20 == 0: print(f"已处理 {idx+1}/{total_count}") except Exception as e: fail_count += 1 print(f"【异常】第{idx+1}行:{str(e)}") # 统计结果 print("\n====================转换完成====================") print(f"总条数:{total_count}") print(f"成功:{success_count}") print(f"失败:{fail_count}") print(f"输出文件路径:{os.path.abspath(out_vcf)}")if __name__ == "__main__": EXCEL_FILE = "contacts.xlsx" VCF_OUTPUT = "contacts.vcf" try: excel_to_vcf(EXCEL_FILE, VCF_OUTPUT) except Exception as top_err: print(f"程序顶层致命异常:{top_err}") # 防止双击运行窗口直接闪退,执行完毕等待回车再关闭 # input("\n按回车键关闭窗口...")