MENU

Excel/csv 花名册转 vCard/vcf 通讯录名片并导入手机联系人应用

前言

在整理自己的好友电话号码时,突然产生了这样一个需求:即批量将一个表格中存储的通讯录数据导入手机联系人通讯录中。最简单的办法就是直接将表格文件转换为手机联系人支持的导入格式文件,虽然 Execl 并不支持直接导出通讯录格式文件,但既然有需求,那就肯定有对应的解决办法。

简易实现

搜寻了网上的大多数办法都比较简单,一般只支持电话号码和姓名两个项目。

  1. 新建一个 Excel 表格,你可以参考下面的:

    姓名,别名,手机,电子邮件,生日,备用邮箱,家庭地址,公司名称,备注
    张三,法外狂徒,+86 192 8888 8888,username@email.cn,2001-12-31,username@qq.com,中国北京市法外狂徒看守所,缅北人才 发展署,无
  2. 将制作好的表格另存为 CSV(*.csv) 格式,
  3. 打开 QQ 邮箱网页版,找到 通讯录 >工具 > 导入联系人文件 ,上传并导入刚刚保存的 CSV(*.csv) 表格文件
  4. 等待导入完成后,从 QQ 邮箱 通讯录 >工具 > 导出联系人 导出手机联系人应用支持的 vCard(*.vcf) 格式文件
  5. 在手机联系人应用设置中导入该 vCard(*.vcf) 格式文件

很明显的能够感觉到,上面的这种方式虽然可行,但是并不灵活。尽管有其它网站也提供类似的甚至更强大的在线转换功能,但考虑到需要上传文件,有些可能通过服务器进行处理,难免会出现泄露信息等安全风险。

进阶方式

如果不满足上面的效果,可以直接使用 Excel 功能。不过在此之前,我们需要先了解一下 vCard(*.vcf) 文件的格式以及写法:具体请参考这篇文章

BEGIN:VCARD
VERSION:3.0
N:张;三;;;
FN:法外狂徒
TEL;TYPE=CELL:+86 192 8888 8888
BDAY:2001-12-31
EMAIL;TYPE=INTERNET,HOME:username@email.cn
ADR;TYPE=HOME;CHARSET=UTF-8:;;中国北京市法外狂徒看守所;;;;
ORG: 缅北人才发展署
END:VCARD

如果不知道写法,可以直接在手机联系人应用中新建一个联系人,作为模板,填入不会被你混淆的信息,然后导出或分享该联系人文件。使用文本编辑器打开该文件即可。

当然我也做了一个简易的文档表格,请注意开启 Excel 宏功能,否则可能无法正常运行。其中带 * 的是必填项,第二行为演示数据,从第三行开始转换。

*姓,*名,昵称,*手机号,生日,邮箱,家庭住址,工作单位,备注
张,三,法外狂徒,+86 192 8888 8888,2001-12-31,username@email.cn,中国北京市法外狂徒看守所, 缅北人才发展署,无

下面是宏任务的代码:(请根据你的表格格式进行修改)

Sub SaveAsVCard()
    Dim txtFileName As Variant
    Dim lastRow As Long, r As Long
    Dim adoStream As Object
    Dim progressStep As Long

    lastRow = Cells(Rows.Count, 1).End(xlUp).Row
    If lastRow < 3 Then
        MsgBox "未找到联系人数据"
        Exit Sub
    End If

    txtFileName = Application.GetSaveAsFilename(FileFilter:="vCard 文件 (*.vcf), *.vcf", Title:="请输入要保存的文件名")
    If txtFileName = False Then Exit Sub

    Set adoStream = CreateObject("ADODB.Stream")
    adoStream.Type = 2 ' Text stream
    adoStream.Charset = "utf-8"
    adoStream.Open
    progressStep = Application.WorksheetFunction.Max(1, (lastRow - 2) \ 20)

    For r = 3 To lastRow
        adoStream.WriteText "BEGIN:VCARD" & vbLf & "VERSION:3.0" & vbLf

        adoStream.WriteText "N:" & Nz(CStr(Cells(r, 1).Value)) & ";" & Nz(CStr(Cells(r, 2).Value)) & ";;;" & vbLf
        If Not IsEmpty(Cells(r, 3).Value) Then 
            adoStream.WriteText "FN:" & Nz(CStr(Cells(r, 3).Value)) & vbLf
        Else
            adoStream.WriteText "FN:" & Nz(CStr(Cells(r, 1).Value)) & " " & Nz(CStr(Cells(r, 2).Value)) & vbLf
        End If
        
        If Not IsEmpty(Cells(r, 4).Value) Then adoStream.WriteText "TEL;TYPE=CELL:" & Nz(CStr(Cells(r, 4).Value)) & vbLf
        If Not IsEmpty(Cells(r, 5).Value) Then adoStream.WriteText "BDAY:" & Nz(CStr(Cells(r, 5).Value)) & vbLf
        If Not IsEmpty(Cells(r, 6).Value) Then adoStream.WriteText "EMAIL;TYPE=INTERNET,HOME:" & Nz(CStr(Cells(r, 6).Value)) & vbLf
        If Not IsEmpty(Cells(r, 7).Value) Then adoStream.WriteText "ADR;TYPE=HOME;CHARSET=UTF-8:;;" & Nz(CStr(Cells(r, 7).Value)) & ";;;;" & vbLf
        If Not IsEmpty(Cells(r, 8).Value) Then adoStream.WriteText "ORG:" & Nz(CStr(Cells(r, 8).Value)) & vbLf
        If Not IsEmpty(Cells(r, 9).Value) Then adoStream.WriteText "NOTE;CHARSET=UTF-8:" & Nz(CStr(Cells(r, 9).Value)) & vbLf
        
        adoStream.WriteText "END:VCARD" & vbLf
        
        If (r - 2) Mod progressStep = 0 Then
            Application.StatusBar = "正在保存联系人数据: " & Format((r - 2) / (lastRow - 2), "0%")
        End If
    Next r

    adoStream.Position = 0
    adoStream.Type = 1 ' Binary stream

    Dim binaryStream As Object
    Set binaryStream = CreateObject("ADODB.Stream")
    binaryStream.Type = 1
    binaryStream.Open
    binaryStream.Write adoStream.Read

    binaryStream.SaveToFile txtFileName, 2
    binaryStream.Close
    adoStream.Close

    Application.StatusBar = False

    Dim msg As String
    msg = "vCard 文件已保存" & vbLf & txtFileName & vbLf & vbLf & "是否打开文件所在目录?"
    If MsgBox(msg, vbYesNo + vbInformation, "文件保存成功") = vbYes Then
        Dim folderPath As String
        folderPath = Left(txtFileName, InStrRev(txtFileName, "\"))
        Shell "explorer.exe /select," & txtFileName, vbNormalFocus
    End If
End Sub

Function Nz(value As Variant, Optional defaultValue As String = "") As String
    If IsEmpty(value) Or IsNull(value) Then
        Nz = defaultValue
    Else
        Nz = CStr(value)
    End If
End Function

如果你懒得制作相应的表格,可以直接用我制作好的现成的:下载 xlsx2vcard.xlsm

一些问题

通过上面这些方法就可以快速将表格花名册转换为可以直接导入手机通讯录的名片文件。如果发现导入失败,比如说提示格式错误什么的,不必理会,格式是没有问题的,但是你需要做一些微小的调整。

使用专业的文本编辑器或代码编辑器,对文件内容的编码、换行符进行修改:

  1. 确保保存的文件是没有 BOM 的 UTF-8 编码文件,即 UTF-8 而非 UTF-8 with BOM
  2. 修改行尾序列 CRLF 为 LF

修改后,应该就不会有什么问题了

最后编辑于: 2024 年 06 月 08 日
返回文章列表 文章二维码 打赏
本页链接的二维码
打赏二维码