Skip to content

Instantly share code, notes, and snippets.

@hara
Last active December 17, 2015 13:59
Show Gist options
  • Save hara/5620760 to your computer and use it in GitHub Desktop.
Save hara/5620760 to your computer and use it in GitHub Desktop.
Friends Note の CSV を Google Contacts の Google CSV 形式に変換するスクリプト
# coding: utf-8
require 'csv'
module GoogleContacts
class Contacts
attr_reader :cards
def initialize
@cards = []
end
def header
fields = []
fields << 'Given Name'
fields << 'Additional Name'
fields << 'Family Name'
fields << 'Given Name Yomi'
fields << 'Additional Name Yomi'
fields << 'Family Name Yomi'
fields << 'Name Prefix'
fields << 'Name Suffix'
fields << 'Nickname'
fields << 'Notes'
fields << 'Group Membership'
1.upto(email_header_length).each do |i|
fields << "E-mail #{i} - Type"
fields << "E-mail #{i} - Value"
end
1.upto(im_header_length).each do |i|
fields << "IM #{i} - Type"
fields << "IM #{i} - Service"
fields << "IM #{i} - Value"
end
1.upto(phone_header_length).each do |i|
fields << "Phone #{i} - Type"
fields << "Phone #{i} - Value"
end
1.upto(address_header_length).each do |i|
fields << "Address #{i} - Type"
fields << "Address #{i} - Street"
fields << "Address #{i} - City"
fields << "Address #{i} - PO Box"
fields << "Address #{i} - Region"
fields << "Address #{i} - Postal Code"
fields << "Address #{i} - Country"
end
1.upto(organization_header_length).each do |i|
fields << "Organization #{i} - Type"
fields << "Organization #{i} - Name"
fields << "Organization #{i} - Yomi Name"
fields << "Organization #{i} - Title"
fields << "Organization #{i} - Department"
fields << "Organization #{i} - Symbol"
fields << "Organization #{i} - Location"
fields << "Organization #{i} - Job Description"
end
fields
end
def records
rows = []
rows << header
cards.each do |card|
fields = []
fields << card.given_name
fields << card.additional_name
fields << card.family_name
fields << card.given_name_yomi
fields << card.additional_name_yomi
fields << card.family_name_yomi
fields << card.name_prefix
fields << card.name_suffix
fields << card.nickname
fields << card.notes
fields << card.group
card.emails.each do |email|
fields << email.type
fields << email.value
end
1.upto(email_header_length - card.emails.length).each do
fields << '' << ''
end
card.ims.each do |im|
fields << im.type
fields << im.service
fields << im.value
end
1.upto(im_header_length - card.ims.length).each do
fields << '' << '' << ''
end
card.phones.each do |phone|
fields << phone.type
fields << phone.value
end
1.upto(phone_header_length - card.phones.length).each do
fields << '' << ''
end
card.addresses.each do |address|
fields << address.type
fields << address.street
fields << address.city
fields << address.pobox
fields << address.region
fields << address.postal
fields << address.country
end
1.upto(address_header_length - card.addresses.length).each do
fields << '' << '' << '' << '' << '' << '' << ''
end
card.organizations.each do |organization|
fields << organization.type
fields << organization.name
fields << organization.yomi_name
fields << organization.title
fields << organization.department
fields << organization.symbol
fields << organization.location
fields << organization.description
end
1.upto(organization_header_length - card.organizations.length).each do
fields << '' << '' << '' << '' << '' << '' << '' << ''
end
rows << fields
end
rows
end
private
def email_header_length
self.cards.max_by { |card| card.emails.length }.emails.length
end
def im_header_length
self.cards.max_by { |card| card.ims.length }.ims.length
end
def phone_header_length
self.cards.max_by { |card| card.phones.length }.phones.length
end
def address_header_length
self.cards.max_by { |card| card.addresses.length }.addresses.length
end
def organization_header_length
self.cards.max_by { |card| card.organizations.length }.organizations.length
end
end
class Email
attr_accessor :type, :value
end
class IM
attr_accessor :type, :service, :value
end
class Phone
attr_accessor :type, :value
end
class Address
attr_accessor :type,
:street,
:city,
:pobox,
:region,
:postal,
:country
end
class Organization
attr_accessor :type,
:name,
:yomi_name,
:title,
:department,
:symbol,
:location,
:description
end
class Card
attr_accessor :given_name,
:additional_name,
:family_name,
:given_name_yomi,
:additional_name_yomi,
:family_name_yomi,
:name_prefix,
:name_suffix,
:nickname,
:notes,
:group
attr_reader :emails,
:ims,
:phones,
:addresses,
:organizations
def initialize
@emails = []
@ims = []
@phones = []
@addresses = []
@organizations = []
end
def add_email(type, value)
email = Email.new
email.type = type
email.value = value
emails << email
end
def add_im(type, service, value)
im = IM.new
im.type = type
im.service = service
im.value = value
ims << im
end
def add_phone(type, value)
phone = Phone.new
phone.type = type
phone.value = value
phones << phone
end
end
end
def fields_empty?(row, *labels)
labels.all? { |label| row[label] == "" }
end
include GoogleContacts
if ARGV.length != 2
abort 'Usage: ruby fn2google.rb FriendsNote_export_yyyymmddHHMMSS.csv output.csv'
end
contacts = Contacts.new
CSV.foreach(ARGV[0], encoding: 'Shift_JIS:UTF-8', headers: true) do |row|
card = Card.new
card.given_name = row['名']
card.given_name_yomi = row['名(フリガナ)']
card.additional_name = row['ミドルネーム']
card.additional_name_yomi = row['ミドルネーム(フリガナ)']
card.family_name = row['姓']
card.family_name_yomi = row['姓(フリガナ)']
card.name_prefix = row['プリフィックス']
card.name_suffix = row['サフィックス']
card.nickname = row['ニックネーム']
card.notes = row['メモ']
card.group = 1.upto(10).map { |i| row["グループ#{i}"] }.delete_if { |group| group == "" }.join(' ::: ')
1.upto(10).each do |i|
next if fields_empty?(row,
"メールアドレス#{i}の属性",
"メールアドレス#{i}")
card.add_email(row["メールアドレス#{i}の属性"],
row["メールアドレス#{i}"])
end
1.upto(10).each do |i|
next if fields_empty?(row,
"IM#{i}の属性",
"IMアカウント#{i}",
"IM#{i}のプロトコル種別")
card.add_im(row["IM#{i}の属性"],
row["IM#{i}のプロトコル種別"],
row["IMアカウント#{i}"])
end
1.upto(10).each do |i|
next if fields_empty?(row,
"電話番号#{i}の属性",
"電話番号#{i}")
card.add_phone(row["電話番号#{i}の属性"],
row["電話番号#{i}"])
end
1.upto(10).each do |i|
next if fields_empty?(row,
"住所#{i}の属性",
"住所#{i}(郵便番号)",
"住所#{i}(国)",
"住所#{i}(県)",
"住所#{i}(市区町村)",
"住所#{i}(番地)",
"住所#{i}(部屋番号)",
"住所#{i}(私書箱)")
address = Address.new
address.type = row["住所#{i}の属性"]
address.postal = row["住所#{i}(郵便番号)"]
address.country = row["住所#{i}(国)"]
address.region = row["住所#{i}(県)"]
address.city = row["住所#{i}(市区町村)"]
address.street = row["住所#{i}(番地)"] + "\n" + row["住所#{i}(部屋番号)"]
address.pobox = row["住所#{i}(私書箱)"]
card.addresses << address
end
1.upto(10).each do |i|
next if fields_empty?(row,
"企業#{i}の属性",
"企業#{i}(企業名)",
"企業#{i}(肩書)",
"企業#{i}(所在地)",
"企業#{i}(会社名フリガナ)",
"企業#{i}(部署名)",
"企業#{i}(職種)",
"企業#{i}(会社名略称)")
organization = Organization.new
organization.type = row["企業#{i}の属性"]
organization.name = row["企業#{i}(企業名)"]
organization.title = row["企業#{i}(肩書)"]
organization.location = row["企業#{i}(所在地)"]
organization.yomi_name = row["企業#{i}(会社名フリガナ)"]
organization.department = row["企業#{i}(部署名)"]
organization.description = row["企業#{i}(職種)"]
organization.symbol = row["企業#{i}(会社名略称)"]
card.organizations << organization
end
contacts.cards << card
end
CSV.open(ARGV[1], 'wb') do |csv|
contacts.records.each do |record|
csv << record
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment