[AppleScript] MacでExcelからUTF-8でxml書き出しをするAppleScript

2012/05/16

こんにちは。きんくまです。
タイトルが長いです。

必要になったので、作りました。
MacでExcelからUTF-8でxml書き出しをするAppleScriptです。

こんな感じのデータを

excel_xml

こんな感じのxmlに変換

<?xml version="1.0" encoding="utf-8"?>
<root>
  <row>
    <id>001</id>
    <age>15.0</age>
    <name>田中</name>
    <hobby>野球</hobby>
  </row>
  <row>
    <id>002</id>
    <age>32.0</age>
    <name>斎藤</name>
    <hobby>サッカー</hobby>
  </row>
以下略
  <row>
    <id>010</id>
    <age>30.0</age>
    <name>なまえ5</name>
    <hobby>登山</hobby>
  </row>
</root>

>> ソースコード一式と使い方セットのダウンロード


12/05/16更新
セルの値が数値のとき、常用対数形式(1.3E+3)から10進数表記(13000)へ自動変換
Brati’sLover numberToString

以前にWinで同じことをするやつをVBAで作ったような気がするのですが、
ソースコードがどっかいっちゃったのと、xml書き出すためだけにWinのExcel立ち上げるのが
面倒だなと思いまして。(Win版は私のParalellsには入っていないのです。)

Mac版のExcelで別名で保存できるxml形式だと余計なタグが入っていたり、
VBAでテキスト出力だとShift-JISで出力されたりと困ったなあという状態になっておりました。

それでMac版のVBAの書き出し方法をさらに調べていたら、WinにはあるADODB.Streamというのがないそうです。
そんなとき、ARKA ROYさんという方のこのエントリを発見
>> Excel on Mac: Goodbye VBA, Hello AppleScript

どうやらMac版ExcelのVBA使うよりもAppleScript使った方がいいよ。
とのこと。

>> AppleScriptのリファレンスはこことか

AppleScript使ったことなかったけど、オリジナルのソースがあったので、
必要なところだけリファレンスで調べてなんとか完成したのが下のソースです。

これでデータの取り込み作業が楽になるといいなって。

あと、このページのリンク先のWordドキュメント
http://bernard.rey.free.fr/ExcelVBA-AppleScript.doc
によるとAppleScriptとVBAで関数呼び出したり呼び出されたりできるらしいっす。(試してないので未確認。スミマセン)

(*
author Tasuku Maeda @KinkumaDesign 2012
http://www.kuma-de.com

Mac版ExcelからUTF8で改行コードLFのXMLを出力します。
1階層のみ対応しています。

まずMac版Excelで変換したいファイルを開いてから、このAppleScriptを実行(Run)します。
実行はRunボタンを押せば可能です。
書き出されたxmlファイルはExcelファイルと同じフォルダに出力されます。
このAppleScriptは同階層に置く必要はありません。


例)
同梱されているsampledata.xlsxを開いてRunを押すと、
output.xmlが同じフォルダに出力されます。

Thanks for ARKA ROY who wrote this article
http://talesoftech.blogspot.jp/2011/05/excel-on-mac-goodbye-vba-hello.html

And also thanks for Brati'sLover who is numberToString's author
http://applescript.bratis-lover.net/library/number/#numberToString

*)

-- 設定
-- settings

-- 出力ファイル名
-- output file name
set outputFileName to "output9.xml"

-- ルートエレメント名
-- root element name
set rootEleName to "root"

-- 行エレメント名
-- row element name
set rowEleName to "row"

-- タブスペース。タブとしてのスペースの数を変更したい場合はこれを変更。
-- tab space. If you want to adjust number of space as tab, modify this.
set tabspace to "  "

-- //settings



set outputStr to ""

tell application "Microsoft Excel"
	activate
	
	local decimal_adjust, first_part, second_part, converted_number
	
	set outFile to (path of active workbook)
	set outFile to (outFile & ":" & outputFileName)
	--	set openFile to open for access file outFile with write permission
	--	set eof openFile to 0
	set outputStr to outputStr & "<?xml version=\"1.0\" encode=\"utf-8\"?>" & linefeed & "<" & rootEleName & ">" & linefeed
	--	write "<?xml version=\"1.0\" encoding=\"utf-8\"?>" & linefeed & "<" & rootEleName & ">" & linefeed to openFile as «class utf8»
	
	set numColumn to 0
	set elementNames to {}
	
	repeat
		set numColumn to (numColumn + 1)
		set cellVal to (value of cell 1 of column numColumn of active sheet)
		if (cellVal = "") then
			exit repeat
		else
			copy cellVal to the end of elementNames
		end if
	end repeat
	set numColumn to (numColumn - 1)
	
	set rowIdx to 2
	repeat
		set rowStr to (tabspace & "<" & rowEleName & ">" & linefeed)
		set emptyFlags to 0
		repeat with columnIdx from 1 to numColumn
			set cellVal to (value of cell rowIdx of column columnIdx of active sheet)
			if (cellVal is not "") then
				set cellVal to my numberToString(cellVal)
			end if
			set eleName to (item columnIdx of elementNames)
			set rowStr to rowStr & tabspace & tabspace & "<" & eleName & ">" & cellVal & "</" & eleName & ">" & linefeed
			if (cellVal is not "") then
				set emptyFlags to (emptyFlags + 1)
			end if
		end repeat
		set rowStr to rowStr & tabspace & "</" & rowEleName & ">" & linefeed
		if emptyFlags > 0 then
			set outputStr to outputStr & rowStr
			--			write rowStr to openFile as «class utf8»
		else
			exit repeat
		end if
		
		set rowIdx to (rowIdx + 1)
	end repeat
	
	set outputStr to outputStr & ("</" & rootEleName & ">" & linefeed)
	--	write ("</" & rootEleName & ">" & linefeed) to openFile as «class utf8»
	--close access openFile
	
	set openFile to open for access file outFile with write permission
	set eof openFile to 0
	write outputStr to openFile as «class utf8»
	close access openFile
end tell




--This function is from Brati'sLover
--http://applescript.bratis-lover.net/library/number/#numberToString
on decPt()
	return character 2 of (0.0 as string)
end decPt

on numberToString(this_number)
	local this_number, decimal_adjust, first_part, second_part, converted_number
	try
		set this_number to this_number as string
		if this_number contains "E+" then
			set x to offset of my decPt() in this_number
			set y to offset of "+" in this_number
			set z to offset of "E" in this_number
			set decimal_adjust to characters (y - (length of this_number)) thru ¬
				-1 of this_number as string as number
			if x is not 0 then
				set first_part to characters 1 thru (x - 1) of this_number as string
			else
				set first_part to ""
			end if
			set second_part to characters (x + 1) thru (z - 1) of this_number as string
			set converted_number to first_part
			repeat with i from 1 to decimal_adjust
				try
					set converted_number to ¬
						the converted_number & character i of second_part
				on error
					set converted_number to converted_number & "0"
				end try
			end repeat
			return converted_number
		else
			return this_number
		end if
	on error eMsg number eNum
		error "Can't numberToString: " & eMsg number eNum
	end try
end numberToString

LINEで送る
Pocket

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る