*目次 [#dfe6fb13] #contents *趣旨 [#k7123aef] DDLをEXCELから生成するツール よさそうなページがあったので改造してみました。 要するに、データを格納する器を作成するツール。 参考にしたページではデータベースに対応した、いわゆるDDL生成ツールであった。 自分は、この生成ツールの生成箇所を、プラグインのように切り替えできるように、インタフェースを間に挟むようにした。 このことにより、Daoなどデータを格納する器をエクセルから生成する部分だけを作りさえすれば、生成ツールができることになると思います。 *参考にしたページ [#ze6c62e7] http://members.ld.infoseek.co.jp/mokano1/ExcelDocToDDL.htm *作り方 [#b29b1f82] **コンパイル例 [#d0ec1959] 自分はEclipseで編集して手作業でコンパイルしています。 理由は、意識して.classファイルを作りたいからです。 ***手順1 [#d55fa7a7] jxl.jar を参考ページを参考にして、とってきます。 でjxl.jarを c:\javalib フォルダを作製して保存しておきます。 ***手順2 [#c9c45302] Eclipseで編集しており、作業中のフォルダに.javaコードが古かったり、なかったりする場合の手順です。直接ローカルのファイルを編集している場合には不要の手順なんですが、 DOSプロンプトで、下記のようにローカルにコンパイルしたいファイルをコピーする。 copy C:\pleiades\workspace\prjExcelArg\src\*.java . ***手順3 [#t853cec5] 次に、今回フレームワークチックに切り出した部分、つまり、一回コンパイルしておけば、使い回しが効きそうな部分をコンパイルします。 javac -encoding UTF-8 -cp .;c:\javalib\jxl.jar ExcelDocTo.java ***手順4 [#r56e7b5c] 切り替えたい部品の箇所をコンパイル 参考にしたページに掲載されていたコードから、部品化できそうな箇所をインターフェース化して分離しました。そうすることで、プラグイン方式で最小限の労力で、いろいろと生成するバリエーションを準備できるかと思います。 javac -encoding UTF-8 -cp .;c:\javalib\jxl.jar DDL.java ***実行手順 [#f3a436c0] 引数 ExcelDocTo は、使いまわしする本体で実行するmainメソッドが含まれています。 引数 DDL は、生成担当しているクラスで、切り替えが可能です。 引数 ExcelDocTest.xls は、参考にしたページにあるエクセルの書式のままです。 書式は自分の作ったプラグイン、下記で申しますとDDLに対応した書式というわけです。 java -cp .;c:\javalib\jxl.jar ExcelDocTo DDL ExcelDocTest.xls *ソースコード [#ta7d5668] 若干、整理する箇所はのこっておりますが、(不要なインポートの削除とか) まあ、動くので掲載しておきます。 **DDL [#h4149304] import java.io.FileOutputStream; プラグインに相当します。参考にした分解前のクラス名にDDLとついていたので、 分離したという意味でDDLにしました。 import java.io.FileOutputStream; import java.util.Vector; import jxl.Sheet; public class DDL extends ExcelDocTo implements IParseSheet{ /** テーブル名の桁(A桁が1でC桁) */ public static final int table_nm_keta =3; /** テーブル名の行(1行目が1で2行目) */ public static final int table_nm_gyo =2; /** 項目の開始行=5行目から */ public static final int str_komoku_gyo =5; /** 項目の番号の桁(A桁が1) */ public static final int bango_keta =1; /** 項目の項目名の桁(A桁が1) */ public static final int komoku_keta =2; /** 項目の型の桁(A桁が1) */ public static final int kata_keta =3; /** 項目の桁数の桁(A桁が1) */ public static final int ketasu_keta =4; /** 項目の主キーの桁(A桁が1) */ public static final int key_keta =5; /** 項目のNOT NULLの桁(A桁が1) */ public static final int notnull_keta =6; /** * 1シート読み込み、テーブル作成のDDLを書き出します。<p> * @param sh 書き出し対象となるシート * @param out_folder (指定がある場合)出力先のフォルダ * @return 0 正常終了 * その他 エラー */ public int makeFile(Sheet sh,String out_folder) throws Exception { //==========================// // 引数のチェック // //==========================// // 引数チェック if ( sh == null ) return -1; if ( out_folder == null ) out_folder = ""; //==========================// // テーブル名を取得し出力ファイルOPEN // //==========================// // テーブル名の取得 String tbl_name = getCell(sh,table_nm_gyo,table_nm_keta); // テーブル名の取得 if ( tbl_name == null ) return -1; if ( tbl_name.equals("") == true) return -1; // 出力ファイル名の作成 String fpath = ""; if ( out_folder.equals("") == true) { fpath = tbl_name + ".DDL"; } else if ( out_folder.endsWith("\\") == true ) { fpath = out_folder + tbl_name + ".DDL"; } else { fpath = out_folder + "\\" + tbl_name + ".DDL"; } // ファイルオープン FileOutputStream fout = new FileOutputStream(fpath); //==========================// // テーブルのはじめの部分書き出し // //==========================// // テーブル名の部分の書き出し fout.write("CREATE TABLE ".getBytes()); fout.write(tbl_name.getBytes()); fout.write(" ( \r\n".getBytes()); //==========================// // レコードの部分の書き出し // //==========================// // レコード部分の作業領域 初期化 Vector key_list = new Vector(); for( int gyo = str_komoku_gyo; gyo <= sh.getRows();gyo++) { // 開始行でなかったら、,と改行を書く if ( gyo != str_komoku_gyo) { fout.write(",\r\n".getBytes()); } // 項目の値を取得 String komoku = getCell(sh,gyo,komoku_keta); String kata = getCell(sh,gyo,kata_keta); String ketasu = getCell(sh,gyo,ketasu_keta); String key = getCell(sh,gyo,key_keta); String notnull = getCell(sh,gyo,notnull_keta); // 大文字にしておく kata = kata.toUpperCase(); notnull = notnull.toUpperCase().replaceAll(" ",""); // 桁数に設定があれば、()を付ける ketasu = ketasu.replaceAll(" ",""); // 空白カット if ( ketasu.equals("") == false) { ketasu = "(" + ketasu + ")"; } // キーだったら、キーのリストにいれておく key = key.replaceAll(" ",""); if ( key.equals("") == false) { int key_pos = Integer.parseInt(key); // 項目が足りないとき、追加 while(key_list.size() < key_pos) { key_list.add(null); } // セット key_list.setElementAt(komoku,key_pos-1); } // NOT NULL を書き換え if ( notnull.equals("YES") == true ) notnull = " NOT NULL "; else notnull = ""; // 書き出し String rec = " " + komoku + " "+ kata + ketasu + " " + notnull; fout.write(rec.getBytes()); } //==========================// // テーブルの終わりの部分の書き出し // //==========================// // プライマリーキーの書き出し if ( key_list.size() > 0 ) { fout.write(",\r\n PRIMARY KEY".getBytes()); for(int i = 0,j = 0 ; i < key_list.size() ; i ++ ) { if ( key_list.elementAt(i) == null ) continue; // 項目の前の,または(を書く if ( j == 0 ) // はじめのレコード fout.write("(".getBytes()); else fout.write(",".getBytes()); j++; // 項目を書く fout.write(((String)key_list.elementAt(i)).getBytes()); } fout.write(")".getBytes()); } // 終わり部分の書き出し fout.write("\r\n);\r\n".getBytes()); //==========================// // あとしまつ // //==========================// // ファイルクローズ fout.close(); return 0; } } **IParseSheet [#a64f3889] import jxl.Sheet; public interface IParseSheet { public int makeFile(Sheet sh,String out_folder) throws Exception; } **ExcelDocTo.java [#i3f51beb] /** * * Excelテーブル仕様書からテーブル作成<P> * * 内容:Excelでかかれた(フォーマットの決まっている)テーブルの仕様書から、Create TableのDDLを * 自動的に生成します。 * * @author ウィリアムのいたずら */ import java.io.File; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import jxl.Cell; import jxl.Sheet; import jxl.Workbook; /** * * Excelテーブル仕様書からテーブル作成クラス<P> * */ public class ExcelDocTo { /** * ExcelからDDL作成メインメソッド。<p> * このメソッドは、一般的なもので、makeDDLを呼び出すところを変えれば、 * 1シート1ファイル形式の書き出しに流用できます。<br> * * @param args 起動時の引数<BR> * 第一引数が、対象Excelファイル(必須)、第二引数が、出力先のフォルダ(指定したければ) * @throws ClassNotFoundException */ public static void main(String[] args) { //==========================// // 引数のチェックと取得 // //==========================// // 引数チェック if ( args.length < 2 ) { System.out.println("エラー:引数が足りません 必要な引数:2 指定された引数:"+args.length); System.out.println("書式:java ExcelDocTo プラグイン 入力Excelファイルパス(必要時)出力フォルダパス"); return; } // 引数の取得 String classname = args[0]; String in_fname = args[1]; IParseSheet parser; try { ClassLoader bootstrap = ExcelDocTo.class.getClassLoader(); Class parserClass= bootstrap.loadClass(classname); parser = (IParseSheet)parserClass.newInstance(); } catch (Exception e) { System.out.println("---"); e.printStackTrace(); throw new RuntimeException(e); } String out_folder = ""; if ( args.length >= 3 ) { out_folder = args[2]; } //==========================// // 対象シート全体を取得する // //==========================// // Excelブックをオープンする Workbook wk = getWorkbook(in_fname); if ( wk == null ) { System.out.println("エラー:ブックがない パス:"+in_fname); return; } // シート名を取得する String[] sheetNameList = getAllSheetName(wk); if ( sheetNameList == null ) { System.out.println("エラー:シートがない パス:"+in_fname); return; } //==========================// // シートごとに読み込み、出力 // //==========================// for(int i = 0 ; i < sheetNameList.length ; i ++) { Sheet sh = getSheet(sheetNameList[i],wk); try { parser.makeFile(sh,out_folder); } catch(Exception e) { e.printStackTrace(); continue; } } //==========================// // あとしまつ // //==========================// wk.close(); System.out.println("normal:正常に終了しました。"); } public static String sjis(String str){ try { return URLEncoder.encode(str,"sjis");//"utf-8" } catch (UnsupportedEncodingException e) { // TODO e.printStackTrace(); return ""; } } //----------------------------------------------// // ここから先は、Excelからデータをとってくるための汎用的なメソッド // //----------------------------------------------// /** * 指定されたExcelファイルのワークブックを取得します。<p> * @param bookPath ワークブックのファイルパス * @return nullのときエラー、それ以外のときWorkbookのクラス */ public static Workbook getWorkbook(String bookPath) { if ( bookPath == null ) { return null; } try { return Workbook.getWorkbook(new File(bookPath)); } catch(Exception e) { return null; } } /** * シートを取得します。<p> * ちなみに、sheet(1)のような取得方法をしたい場合は、getAllSheetNameを呼び出し、その返り値の * 配列を使って、こいつをよびだしてください。ブックのすべてのシートが欲しいときも同様。 * @param sheetName シート名 * @param workbook シートがあるワークブック * @return nullのときエラー、それ以外のとき、シートのクラス */ public static Sheet getSheet(String sheetName,Workbook workbook) { if ( ( sheetName== null ) || ( workbook == null ) ) { return null; } try { return workbook.getSheet(sheetName); } catch(Exception e) { return null; } } /** * ブックに含まれているすべてのシート名を取得します。<p> * 同時に、この返り値の配列の大きさによって、ブック数が、わかります。 * @param workbook 対象となるワークブック * @return ワークブックの中に入っているシート名(配列で) */ public static String[] getAllSheetName(Workbook workbook) { if ( workbook == null ) { return null; } try { return workbook.getSheetNames(); } catch(Exception e) { return null; } } /** * シートからセルを読み込みます。<p> * 注意:行と列の指定が、VBAと同じようにしてあります。 * つまり、行、列の順で、1から始まります(A桁が1、1行目が1) * sheet.getCellは、列、行の順で0から始まるので、その分、補正しています。 * * @param sheet 対象となるシート * @param gyo 行、1からはじまる * @param keta 桁を、数字表現したもの。1からはじまる(A桁は1) * @return セルの値(数字項目でも何でも、テキストで) * セルが範囲外、エラーのときはnull(範囲内で何も入力されてないと、空文字) */ public static String getCell(Sheet sheet,int gyo,int keta) throws Exception { //------------------------------// // エラーチェック // //------------------------------// if ( ( keta < 1 ) || ( gyo < 1 ) ) { return null; } if ( sheet == null ) { return null; } try { //------------------------------// // データを読み込み、返す // //------------------------------// Cell cell = sheet.getCell(keta -1, gyo - 1); if ( cell == null ) { return null; } return cell.getContents(); } catch(Exception e) { return null; } } } *プラグイン作製例 [#gf323824] DDLという名前でプラグインとして、コードを用意しているで、ここでは、それをどのように応用してプラグインを作製するかという説明をします。 **参考URL [#h440252e] 入力に使うサンプルのエクセルシートは下記からダウンロード可能です。 http://members.ld.infoseek.co.jp/mokano1/index_ExcelJava.htm **ソース [#s0ebea5c] ***INS.java [#pafa4174] import java.io.FileOutputStream; import java.util.Vector; import jxl.Sheet; public class INS extends ExcelDocTo implements IParseSheet{ /** テーブル名の桁(A桁が1でC桁) */ public static final int table_nm_keta =3; /** テーブル名の行(1行目が1で2行目) */ public static final int table_nm_gyo =2; /** 項目の開始行=5行目から */ public static final int str_komoku_gyo =5; /** 項目の番号の桁(A桁が1) */ public static final int bango_keta =1; /** 項目の項目名の桁(A桁が1) */ public static final int komoku_keta =2; /** 項目の型の桁(A桁が1) */ public static final int kata_keta =3; /** 項目の桁数の桁(A桁が1) */ public static final int ketasu_keta =4; /** 項目の主キーの桁(A桁が1) */ public static final int key_keta =5; /** 項目のNOT NULLの桁(A桁が1) */ public static final int notnull_keta =6; /** 件数が書いてある行=4行目 */ public static final int kensu_gyo =4; /** データ開始の桁(A桁が1) */ public static final int str_data_keta =10; //----------------------------------------------// // ここからは、今回作成するDDLのためのメソッド // //----------------------------------------------// /** * 1シート読み込み、1テーブル分のinsert文を書き出します。<p> * @param sh 書き出し対象となるシート * @param out_folder (指定がある場合)出力先のフォルダ * @return 0 正常終了 * その他 エラー */ public int makeFile(Sheet sh,String out_folder) throws Exception { //==========================// // 引数のチェック // //==========================// // 引数チェック if ( sh == null ) return -1; if ( out_folder == null ) out_folder = ""; //==========================// // テーブル名を取得し出力ファイルOPEN // //==========================// // テーブル名の取得 String tbl_name = getCell(sh,table_nm_gyo,table_nm_keta); // テーブル名の取得 if ( tbl_name == null ) return -1; if ( tbl_name.equals("") == true) return -1; // 出力ファイル名の作成 String fpath = ""; if ( out_folder.equals("") == true) { fpath = tbl_name + ".sql"; } else if ( out_folder.endsWith("\\") == true ) { fpath = out_folder + tbl_name + ".sql"; } else { fpath = out_folder + "\\" + tbl_name + ".sql"; } // ファイルオープン FileOutputStream fout = new FileOutputStream(fpath); //==========================// // レコードの部分の書き出し // //==========================// for(int keta = str_data_keta;keta <= sh.getColumns();keta++) { // データを入れておくVectorを作成 Vector data_vec = new Vector(); // データのチェック for( int gyo = str_komoku_gyo; gyo <= sh.getRows();gyo++) { // 項目の値を取得 String komoku = getCell(sh,gyo,komoku_keta); String kata = getCell(sh,gyo,kata_keta); String ketasu = getCell(sh,gyo,ketasu_keta); String testVal = getCell(sh,gyo,keta); // テストデータになにもない項目は、セットしない if ( testVal == null ) continue; if ( testVal.trim().equals("") == true) continue; // 大文字にしておく kata = kata.toUpperCase(); // データを保存する String[] rec = new String[4]; rec[0] = komoku; rec[1] = kata; rec[2] = ketasu; rec[3] = testVal; data_vec.add(rec); } // テストデータがなければ、Insertしない if ( data_vec.size() <= 0 ) continue; // Inset文の書き出し // はじめの部分書き出し fout.write("INSERT INTO ".getBytes()); fout.write(tbl_name.getBytes()); fout.write(" ( ".getBytes()); // 項目の部分書き出し for(int i = 0 ; i < data_vec.size() ; i++) { if ( i != 0 ) { fout.write(",".getBytes()); } String[] rec = (String[])data_vec.elementAt(i); fout.write(rec[0].getBytes()); } fout.write(" ) VALUES ( ".getBytes()); // 値の書き出し for(int i = 0 ; i < data_vec.size() ; i++) { if ( i != 0 ) { fout.write(",".getBytes()); } String[] rec = (String[])data_vec.elementAt(i); if ( rec[1].indexOf("CHAR") == -1 ) { fout.write(rec[3].getBytes()); } else { fout.write("'".getBytes()); fout.write(rec[3].getBytes()); fout.write("'".getBytes()); } } // おわりの部分 fout.write(" );\r\n".getBytes()); } //==========================// // あとしまつ // //==========================// // ファイルクローズ fout.close(); return 0; } } ***コンパイル方法 [#q814a09e] 例を示します。 javac -encoding UTF-8 -cp .;c:\javalib\jxl.jar INS.java ***実行方法 [#a3890747] 例を示します。 java -cp .;c:\javalib\jxl.jar ExcelDocTo INS ExcelDocTestCompile.xls 最初に用意してあったDDLクラスをINSに置き換えただけです。