それでは、Java標準のDOM操作APIを利用して「sample.xlsx」に含まれるsheet1.xmlの内容を解析します。ダウンロードして解凍したフォルダの中から、テキストエディタで「OXMLEditor.java」ファイルを開いてください。OXMLEditor.javaの処理の流れは、次のようになります。
27 oxml.unzip("sample.xlsx"); /* sample.xlsxの解凍 */
28 document = oxml.read(
"xl/worksheets/sheet1.xml"); /* sheet1.xmlの読み込み */
29
30 oxml.showData(); /* Excelファイルデータ表示 */
31 oxml.insertData(2, "新製品名2", 2, 500); /* 2行目挿入 */
32 oxml.updateData(3, "製品名3", 10, 1200); /* 3行目更新 */
33 oxml.showData(4); /* 4行目データ表示 */
34 oxml.deleteData(4); /* 4行目削除 */
35 oxml.insertData("製品名4", 4, 2000); /* 行追加 */
36 oxml.showData(); /* Excelファイルデータ表示 */
37
/* sheet1.xml生成 */
38 oxml.saveDocument("xl/worksheets/sheet1.xml",document);
/* sample.xlsx生成 */
39 oxml.createZIPfile(fileList,"sample.xlsx"); |
1.Excelファイル「sample.xlsx」の解凍(27行目)
2.解凍されたsheet1.xmlファイルの読み込み(28行目)
3.「sample.xlsx」のファイルデータ全体の参照(30行目)
図3 編集前のデータ
4.行データの挿入(31行目)
図4 2行目に新しい行を挿入
5.行データの一部更新(32行目)
図5 3行目のデータを更新
6.「sample.xlsx」の4行目データの参照(33行目)
7.行データの削除(34行目)
図6 4行目のデータを削除
8.行データの挿入(35行目)
図7 4行目に新しい行を追加
9.更新されたsheet1.xmlの生成(38行目)
10.「sample.xlsx」の生成(39行目)
行データを参照するselectDataや行データを追加するinsertDataなど各関数について、順に説明します。
74 void selectData(int rowNum){
75 try {
76 Element root = document.getDocumentElement();
/* row要素のリスト */
77 NodeList list = root.getElementsByTagName("row");
78 Element element = (Element)list.item(rowNum - 1);
79
/* テキスト指定 */
80 NodeList textList = element.getElementsByTagName("t");
81 Element textElement = (Element)textList.item(0);
/* A列 */
82 String a = textElement.getFirstChild().getNodeValue();
83
/* 数値指定 */
84 NodeList numList = element.getElementsByTagName("v");
85 Element numElement = (Element)numList.item(0);
/* B列 */
86 String b = numElement.getFirstChild().getNodeValue();
87
88 numElement = (Element)numList.item(1);
/* C列 */
89 String c = numElement.getFirstChild().getNodeValue();
90
91 System.out.println( rowNum+"行目: "+a+", "+b+","+c);
92 } catch (Exception e) {
93 e.printStackTrace();
94 }
95 } |
selectDataの引数に参照したい行番号を設定します。77行目でrow要素、すなわち行のリストを取得し、78行目で行リストの中から参照したい行のデータを取得します。80行目でt要素を指定してA列のテキスト、84行目でv要素を指定してB列とC列の数値を取り出します。
/* 指定行に行挿入 */
109 void insertData(int rowNum, String a, int b, int c){
110 try {
111 Element root = document.getDocumentElement();
112 NodeList list = root.getElementsByTagName("row");
113 Node newRow = createRow(rowNum, a, b, c);
114 if (rowNum > list.getLength()){
115 list.item(0).getParentNode().appendChild(newRow);
116 }else {
117 list.item(0).getParentNode().insertBefore(newRow,
list.item(rowNum-1));
118 }
/* 行番号の修正 */
119 for (int i=rowNum+1; i <= list.getLength(); i++) {
120 setRowAttribute(i, (Element)list.item(i-1));
121 }
122 } catch (Exception e) {
123 e.printStackTrace();
124 }
125 } |
insertDataの引数に挿入したい行番号、A列のテキスト、B列の数値、C列の数値を順に設定します。113行目で新しい行を作成し、114〜118行目で作成した行を指定行番号に追加します。119〜121行目で、追加した行の後ろの行番号が1つずつずれているので修正します。
なお、97〜107行目の行番号指定なしのinsertDataは複数ある最後の行の次に新しい行を追加します。
127 void updateData(int rowNum, String a, int b, int c){
128 try {
129 Element root=document.getDocumentElement();
130 NodeList list = root.getElementsByTagName("row");
131 Node oldRow = list.item(rowNum - 1);
132 Node newRow = createRow(rowNum, a, b, c);
133 oldRow.getParentNode().replaceChild(newRow, oldRow);
134 } catch (Exception e) {
135 e.printStackTrace();
136 }
137 } |
updateDataの引数に更新したい行番号、A列のテキスト、B列の数値、C列の数値を順に設定します。132行目で新しい行を作成し、133行目で古い行を新しい行に更新します。
139 void deleteData(int rowNum){
140 try {
141 Element root=document.getDocumentElement();
142 NodeList list = root.getElementsByTagName("row");
143 list.item(0).getParentNode().removeChild(
list.item(rowNum - 1));
144 for (int i=rowNum; i <= list.getLength() ; i++) {
145 setRowAttribute(i, (Element)list.item(i-1));
146 }
147 } catch (Exception e) {
148 e.printStackTrace();
149 }
150 } |
deleteDataの引数に削除したい行番号を設定します。143行目で指定行を削除し、144?146行目で、削除した行の後ろの行番号が1つずつずれているので修正します。
行データについて、追加、一部更新、削除が反映されたsheet1.xmlファイルを生成後、[Content_Types].xmlやworkbook.xmlなどのファイルとともにsheet1.xmlファイルをZIP圧縮すると、次のようなExcelファイルが作成されます。
図8 編集後のサンプルExcelファイル
以上で、Javaを使ってExcelデータを操作する方法についての紹介を終わりますが、いかがでしたでしょうか?
JavaでのOfficeデータ操作といえば、いままでのMicrosoft Officeがバイナリファイルだったこともあり(前回の「いまさら聞けないOfficeファイルフォーマット」参照)、これまではオープンソースフレームワークの「Apache POI 」(以下、POI)などに頼ることが多かったと思います。しかし、今後はJava標準APIで備わっているDOMやSAXでも操作できるようになり、技術者がいままで培ったXML操作のノウハウを生かしやすいと思います。
もちろん、XML操作のノウハウがない技術者でも、「Open XML4J」というJavaのOpen XML操作用オープンソースライブラリが開発中のようなので、こちらを活用するのも1つの方法だと思います(2008年8月現在ベータ版のようですが)。
また、マイクロソフトとしても、Apache Software Foundationの主要スポンサーになったことで、Officeのオープン化とともにますますオープンソース戦略を進めています。POIを含むいくつかのプロジェクトにも技術協力し、POIプロジェクトはOpen XMLのサポートもしていく予定のようです(参考:Microsoftのオープンソース計画)。
Open XMLは今後、業務システム開発において重要な位置を占めることが予想されるので、知っておいて損はないと思います。本特集が、Office Open XMLファイルフォーマットを理解する手助けになれば幸いです。
Girier 陽子(ジリエ ヨウコ)
Office Open XML標準化作業に東芝のメンバーとして参加し、標準化組織Ecma nternationalの技術委員会「TC45」で活動。共著に「入門Office Open XML」(ソフトバンククリエイティブ)。