Skip to content

Instantly share code, notes, and snippets.

@goldfndr
Created May 20, 2014 20:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save goldfndr/86cbf929925022c1f855 to your computer and use it in GitHub Desktop.
Save goldfndr/86cbf929925022c1f855 to your computer and use it in GitHub Desktop.
Convert a Palm VCF (vCard 2.1) to something closer to Google Contacts (vCard 3.0) while retaining Custom fields and linebreaks
'Palm VCF to Google Contacts import, by goldfndr
'Many people advocate spending a couple of hours doing search/replaces with their VCF exports.
'But I had 800+ contacts in 16 categories, and didn't want to repeat this.
'Instead, I took an hour to write this (for my Palm Tungsten T3).
'Added an additional hour to refactor and make it work with my Garmin iQue 3600.
'I did not test the ISO 8859-1 encoding or control characters, sorry.
Option Explicit
Const CustomFields="Custom1|Custom2|Custom3|Hours|Custom5|Custom6|Custom7|Custom8|Custom9"
if WScript.Arguments.Count <> 2 then
WScript.StdErr.WriteLine "Syntax: " & WScript.ScriptName & " {input} {output}" & vbLF _
& WScript.Arguments.Count & " parameters provided, need 2!"
WScript.Quit 3
end if
Dim fin : fin = WScript.Arguments(0)
Dim fout : fout = WScript.Arguments(1)
Dim FSO : Set FSO = CreateObject("Scripting.FileSystemObject")
If not FSO.FileExists(fin) Then
WScript.Echo "Input file " & fin & " does not exist, aborting!"
WScript.Quit 1
End If
Dim fi : Set fi = FSO.OpenTextFile(fin, 1)
Dim fo : Set fo = FSO.CreateTextFile(fout, True, False)
Do
Dim field, s : s = fi.ReadLine
'Show before
wscript.echo "<-" & s
'The encoding for Palm Desktop 4.1.4 doesn't seem very smart; it only appears to affect vbCRLF.
'But I'll admit that I'm not using much more than ASCII, and perhaps this is true for all vCard 2.1.
Dim n : n = Instr(s, ";ENCODING=QUOTED-PRINTABLE:")
if n > 0 Then
'I wanted to use Replace(,,,start) but that effectively does a Mid(). So split and join.
field = Left(s, n-1) : s = Mid(s, n+1)
s = Replace(s, "ENCODING=QUOTED-PRINTABLE:", "")
s = Replace(s, "=0D=0A", "\n")
s = Replace(s, ":", "\:")
s = Replace(s, ";", "\;")
s = field & ":" & s
End If
'Is there a custom field? If so then add it as an address field with custom label.
' This will ensure that multi-line is retained.
if Left(s, 13) = "X-Palm-Custom" then
n = Mid(s, 14, 1) 'The digit ([1-9] for Custom[1-9])
s = Mid(s, 16) 'The value
'AFAIK, a Garmin iQue 3600 only uses Custom4 for coordinates.
'Hopefully this won't incur false positives.
If "4" = n and "GARMIN " = Left(s, 7) then
s = CustomAddress(n, coordinates(Mid(s, 8)), "LatLon")
Else
s = CustomAddress(n, s, Split(CustomFields, "|")(n-1))
End If
end if
'Show after
wscript.echo "->" & s
fo.WriteLine s
Loop Until fi.AtEndOfStream
fi.Close
fo.Close
WScript.Quit 0
Function CustomAddress(n, value, fieldname)
'A Google export will number the custom item fields sequentially (item1, item2)
' but this is for an import so we won't care about starting with 1. Use n.
CustomAddress = "item" & n & ".ADR:;;" & value & ";;;;" _
& vbCRLF & "item" & n & ".X-ABLabel:" & fieldname
End Function
Function coordinates(s)
s = Left(s, 17) 'Only use latitude and longitude; don't check altitude/symbol
Dim Lat : Lat = coord(Left(s, 8))
Dim Lon : Lon = coord(Right(s, 8))
coordinates = Lat & "," & Lon
End Function
Function coord(h)
Dim d : d = CLng("&h" & h) 'Hex2Dec
if d > &h7FFFFFFF then d = d - &hFFFFFFFF 'Negative coordinate!
'OpenStreetMap uses 7 digits; more than that is most likely False Precision.
coord = FormatNumber(180.0 * d / &h7FFFFFFF, 7)
End Function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment