001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.plugin.io; 017 018import java.io.PrintWriter; 019 020import org.odftoolkit.odfdom.OdfFileDom; 021import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument; 022import org.odftoolkit.odfdom.doc.office.OdfOfficeAutomaticStyles; 023import org.odftoolkit.odfdom.doc.office.OdfOfficeSpreadsheet; 024import org.odftoolkit.odfdom.doc.table.OdfTable; 025import org.odftoolkit.odfdom.doc.table.OdfTableCell; 026import org.odftoolkit.odfdom.doc.table.OdfTableRow; 027import org.odftoolkit.odfdom.doc.text.OdfTextParagraph; 028import org.odftoolkit.odfdom.dom.attribute.office.OfficeValueTypeAttribute; 029import org.opengion.fukurou.model.NativeType; 030import org.opengion.fukurou.util.StringUtil; 031import org.opengion.hayabusa.common.HybsSystemException; 032import org.opengion.hayabusa.db.DBTableModel; 033import org.w3c.dom.Node; 034 035/** 036 * Calcファイルの書き出しクラスです。 037 * 038 * DefaultTableWriter を継承していますので,ラベル,名前,データの出力部のみ 039 * オーバーライドして,OpenOfficeのCalcファイルの出力機能を実現しています。 040 * 041 * @og.group ファイル出力 042 * 043 * @version 5.0 044 * @author Hiroki Nakamura 045 * @since JDK6.0, 046 */ 047public class TableWriter_Calc extends TableWriter_Default { 048 //* このプログラムのVERSION文字列を設定します。 {@value} */ 049 private static final String VERSION = "5.5.2.6 (2012/05/25)" ; 050 051 protected OdfSpreadsheetDocument wb = null; 052 protected OdfTable sheet = null; 053 protected OdfFileDom contentDom = null; 054 protected OdfOfficeSpreadsheet officeSpreadsheet = null; 055 protected OdfOfficeAutomaticStyles contentAutoStyles = null; 056 057 protected boolean useNumber = true; 058 059 private String sheetName = "Sheet1"; 060 private String refSheetName = null; 061 private String filename = null; 062 private String refFilename = null; 063// private String fontName = null; // 現時点では未使用 064// private short fontPoint = -1; // 現時点では未使用 065 066 /** 067 * DBTableModel から 各形式のデータを作成して,PrintWriter に書き出します。 068 * このメソッドは、Calc 書き出し時に使用します。 069 * 070 * @see #isExcel() 071 */ 072 @Override 073 public void writeDBTable() { 074 if( !createDBColumn() ) { return; } 075 076 useNumber = isUseNumber(); 077 078 if( filename == null ) { 079 String errMsg = "ファイルが指定されていません。"; 080 throw new HybsSystemException( errMsg ); 081 } 082 083 /* 以下は未実装 ***********************************************/ 084 if( isAppend() ) { 085 String errMsg = "Calcの場合はAppend利用できません。"; 086 throw new HybsSystemException( errMsg ); 087 } 088 089 if( ( refFilename != null && refFilename.length() > 0 ) || ( refSheetName != null && refSheetName.length() >= 0 ) ) { 090 String errMsg = "Calcの場合は,refFilenamerefSheetName利用できません。"; 091 throw new HybsSystemException( errMsg ); 092 } 093 094 // if( fontName != null && fontName.length() > 0 ) { 095 // String errMsg = "Calcの場合はfontNameは、利用できません。"; 096 // throw new HybsSystemException( errMsg ); 097 // System.err.println( errMsg ); 098 // } 099 100 // if( fontPoint >= 0 ) { 101 // String errMsg = "Calcの場合はfontPointは、利用できません。"; 102 // throw new HybsSystemException( errMsg ); 103 // System.err.println( errMsg ); 104 // } 105 /* *************************************************************/ 106 107 // 新規の場合 108 try { 109 wb = OdfSpreadsheetDocument.newSpreadsheetDocument(); 110 // コンテンツのルートとDOMを取得 111 contentDom = wb.getContentDom(); 112 officeSpreadsheet = wb.getContentRoot(); 113 contentAutoStyles = contentDom.getOrCreateAutomaticStyles(); 114 115 // デフォルトで用意されているノードを削除 116 Node childNode = officeSpreadsheet.getFirstChild(); 117 while( childNode != null ) { 118 officeSpreadsheet.removeChild( childNode ); 119 childNode = officeSpreadsheet.getFirstChild(); 120 } 121 } 122 catch( Exception ex ) { 123 String errMsg = "Calcの文書宣言ができません。"; 124 throw new HybsSystemException( errMsg, ex ); 125 } 126 127 //デフォルトで用意されているStyles調整 128 resetAutoStylesAndMasterStyles(); 129 130 sheet = new OdfTable( contentDom ); 131 sheet.setTableNameAttribute( sheetName ); 132 133 super.writeDBTable( null ); 134 135 officeSpreadsheet.appendChild( sheet ); 136 137 try { 138 wb.save( filename ); 139 wb.close(); 140 } 141 catch( Exception ex ) { 142 String errMsg = "Calcの文書saveができません。"; 143 throw new HybsSystemException( errMsg, ex ); 144 } 145 finally { 146 if( null != sheet ) { sheet = null; } 147 if( null != wb ) { wb = null; } 148 } 149 } 150 151 /** 152 * DBTableModel から データを作成して,PrintWriter に書き出します。 153 * 154 * @param writer PrintWriterオブジェクト 155 */ 156 @Override 157 public void writeDBTable( final PrintWriter writer ) { 158 String errMsg = "このクラスでは実装されていません。"; 159 throw new UnsupportedOperationException( errMsg ); 160 } 161 162 /** 163 * PrintWriter に DBTableModelのラベル情報を書き込みます。 164 * 第一カラム目は、ラベル情報を示す "#Label" を書き込みます。 165 * この行は、出力形式に無関係に、TableWriter.TAB_SEPARATOR で区切られます。 166 * 167 * @param table DBTableModelオブジェクト 168 * @param writer PrintWriterオブジェクト 169 */ 170 @Override 171 protected void writeLabel( final DBTableModel table, final PrintWriter writer ) { 172 OdfTableRow row = new OdfTableRow( contentDom ); 173 174 if( useNumber ) { 175 row.appendCell( createTextCell( contentDom, "#Label", false, false ) ); 176 } 177 178 for( int i = 0; i < numberOfColumns; i++ ) { 179 int clm = clmNo[i]; 180 String val = dbColumn[clm].getLabel(); 181 if( i == 0 && !useNumber ) { 182 val = "#" + val; 183 } 184 row.appendCell( createTextCell( contentDom, val, false, false ) ); 185 } 186 row.setStyleName( "ro1" ); 187 sheet.appendRow( row ); 188 } 189 190 /** 191 * PrintWriter に DBTableModelの項目名情報を書き込みます。 192 * 第一カラム目は、項目名情報を示す "#Name" を書き込みます。 193 * この行は、出力形式に無関係に、TableWriter.TAB_SEPARATOR で区切られます。 194 * 195 * @param table DBTableModelオブジェクト 196 * @param writer PrintWriterオブジェクト 197 */ 198 @Override 199 protected void writeName( final DBTableModel table, final PrintWriter writer ) { 200 OdfTableRow row = new OdfTableRow( contentDom ); 201 202 if( useNumber ) { 203 row.appendCell( createTextCell( contentDom, "#Name", false, false ) ); 204 } 205 206 for( int i = 0; i < numberOfColumns; i++ ) { 207 int clm = clmNo[i]; 208 String val = table.getColumnName( clm ); 209 if( i == 0 && !useNumber ) { 210 val = "#" + val; 211 } 212 row.appendCell( createTextCell( contentDom, val, false, false ) ); 213 } 214 row.setStyleName( "ro1" ); 215 sheet.appendRow( row ); 216 } 217 218 /** 219 * PrintWriter に DBTableModelのサイズ情報を書き込みます。 220 * 第一カラム目は、サイズ情報を示す "#Size" を書き込みます。 221 * この行は、出力形式に無関係に、TableWriter.TAB_SEPARATOR で区切られます。 222 * 223 * @param table DBTableModelオブジェクト 224 * @param writer PrintWriterオブジェクト 225 */ 226 @Override 227 protected void writeSize( final DBTableModel table, final PrintWriter writer ) { 228 OdfTableRow row = new OdfTableRow( contentDom ); 229 230 if( useNumber ) { 231 row.appendCell( createTextCell( contentDom, "#Size", false, false ) ); 232 } 233 234 for( int i = 0; i < numberOfColumns; i++ ) { 235 int clm = clmNo[i]; 236 String val = String.valueOf( dbColumn[clm].getTotalSize() ); 237 if( i == 0 && !useNumber ) { 238 val = "#" + val; 239 } 240 row.appendCell( createTextCell( contentDom, val, true, false ) ); 241 } 242 row.setStyleName( "ro1" ); 243 sheet.appendRow( row ); 244 } 245 246 /** 247 * PrintWriter に DBTableModelのクラス名情報を書き込みます。 248 * 第一カラム目は、サイズ情報を示す "#Class" を書き込みます。 249 * この行は、出力形式に無関係に、TableWriter.TAB_SEPARATOR で区切られます。 250 * 251 * @param table DBTableModelオブジェクト 252 * @param writer PrintWriterオブジェクト 253 */ 254 @Override 255 protected void writeClass( final DBTableModel table, final PrintWriter writer ) { 256 OdfTableRow row = new OdfTableRow( contentDom ); 257 258 if( useNumber ) { 259 row.appendCell( createTextCell( contentDom, "#Class", false, false ) ); 260 } 261 262 for( int i = 0; i < numberOfColumns; i++ ) { 263 int clm = clmNo[i]; 264 String val = dbColumn[clm].getClassName(); 265 if( i == 0 && !useNumber ) { 266 val = "#" + val; 267 } 268 row.appendCell( createTextCell( contentDom, val, false, false ) ); 269 } 270 row.setStyleName( "ro1" ); 271 sheet.appendRow( row ); 272 } 273 274 /** 275 * PrintWriter に セパレーターを書き込みます。 276 * 第一カラム目は、サイズ情報を示す "#----" を書き込みます。 277 * この行は、出力形式に無関係に、TableWriter.TAB_SEPARATOR で区切られます。 278 * 279 * @param table DBTableModelオブジェクト 280 * @param writer PrintWriterオブジェクト 281 */ 282 @Override 283 protected void writeSeparator( final DBTableModel table, final PrintWriter writer ) { 284 String sep = "----"; 285 286 OdfTableRow row = new OdfTableRow( contentDom ); 287 row.appendCell( createTextCell( contentDom, "#----", false, false ) ); 288 for( int i = 0; i < numberOfColumns; i++ ) { 289 if( i == 0 && !useNumber ) { 290 continue; 291 } 292 row.appendCell( createTextCell( contentDom, sep, false, false ) ); 293 } 294 sheet.appendRow( row ); 295 } 296 297 /** 298 * PrintWriter に DBTableModelのテーブル情報を書き込みます。 299 * このクラスでは,データを ダブルコーテーション(")で囲みます。 300 * PrintWriter に DBTableModelのテーブル情報を書き込みます。 301 * 302 * @og.rev 5.2.1.0 (2010/10/01) useRenderer 対応 303 * 304 * @param table DBTableModelオブジェクト 305 * @param writer PrintWriterオブジェクト 306 */ 307 @Override 308 protected void writeData( final DBTableModel table,final PrintWriter writer ) { 309 int numberOfRows = table.getRowCount(); 310 311 boolean[] nvar = new boolean[numberOfColumns]; 312 boolean[] cellType = new boolean[numberOfColumns]; 313 for( int i=0; i<numberOfColumns; i++ ) { 314 int clm = clmNo[i]; 315 NativeType nativeType = dbColumn[clm].getNativeType(); 316 switch( nativeType ) { 317 case INT : 318 case LONG : 319 case DOUBLE : 320 cellType[i] = true ; 321 break; 322 case STRING : 323 case CALENDAR : 324 default : 325 cellType[i] = false ; 326 break; 327 } 328 nvar[i] = "NVAR".equals( dbColumn[clm].getDbType() ); 329 } 330 boolean useRenderer = isUseRenderer(); // 5.2.1.0 (2010/10/01) 331 332 for( int r = 0; r < numberOfRows; r++ ) { 333 OdfTableRow row = new OdfTableRow( contentDom ); 334 335 if( useNumber ) { 336 row.appendCell( createTextCell( contentDom, String.valueOf( r + 1 ), true, true ) ); 337 } 338 339 for( int i = 0; i < numberOfColumns; i++ ) { 340 int clm = clmNo[i]; 341 String val = table.getValue( r, clm ); 342 if( nvar[i] ) { 343 val = StringUtil.getReplaceEscape( val ); 344 } 345 // 5.2.1.0 (2010/10/01) useRenderer 対応 346 else if( useRenderer ) { 347 val = StringUtil.spanCut( dbColumn[clm].getRendererValue( val ) ); 348 } 349 row.appendCell( createTextCell( contentDom, val, cellType[i], false ) ); 350 } 351 row.setStyleName( "ro1" ); 352 sheet.appendRow( row ); 353 } 354 } 355 356 /** 357 * テキストコンテンツ用のセルを生成する 358 * 359 * @param contentDom OdfFileDomオブジェクト 360 * @param content コンテンツ 361 * @param isCellTypeNumber [true:数字型/false:文字型] 362 * @param isNumberList [true:数字リスト=999/false:通常] 363 * 364 * @return OpenOfficeのセルテーブルオブジェクト 365 */ 366 protected OdfTableCell createTextCell( final OdfFileDom contentDom, 367 final String content, 368 final Boolean isCellTypeNumber, 369 final Boolean isNumberList ) { 370 OdfTableCell cell = new OdfTableCell( contentDom ); 371 if( isCellTypeNumber ) { 372 cell.setOfficeValueAttribute( Double.parseDouble( content ) ); 373 cell.setOfficeValueTypeAttribute( OfficeValueTypeAttribute.Value.FLOAT.toString() ); 374 } 375 else { 376 cell.setOfficeValueTypeAttribute( OfficeValueTypeAttribute.Value.STRING.toString() ); 377 } 378 OdfTextParagraph paragraph = new OdfTextParagraph( contentDom, null, content ); 379 cell.appendChild( paragraph ); 380 return cell; 381 } 382 383 /** 384 * デフォルトで用意されているStylesを調整します。 385 * ※ここでは何もしません。 386 * 387 */ 388 protected void resetAutoStylesAndMasterStyles(){ 389 // Document empty method 対策 390 } 391 392 /** 393 * DBTableModelのデータとして読み込むときのシート名を設定します。 394 * 初期値は、"Sheet1" です。 395 * これは、Calc追加機能として実装されています。 396 * 397 * @param sheetName シート名 398 */ 399 @Override 400 public void setSheetName( final String sheetName ) { 401 if( sheetName != null ) { 402 this.sheetName = sheetName; 403 } 404 } 405 406 /** 407 * Calc雛型参考ファイルのシート名を設定します。 408 * これは、Calc追加機能として実装されています。 409 * 410 * Calcファイルを書き出す時に、雛型として参照するシート名を指定します。 411 * これにより、複数の形式の異なるデータを順次書き出したり(appendモードを併用)する 412 * ことや、シートを指定して新規にCalcを作成する場合にフォームを設定する事が可能になります。 413 * 初期値は、null(第一シート) です。 414 * 415 * @param sheetName シート名 416 */ 417 @Override 418 public void setRefSheetName( final String sheetName ) { 419 if( sheetName != null ) { 420 refSheetName = sheetName; 421 } 422 } 423 424 /** 425 * このクラスが、Calc対応機能(=Excel対応機能)を持っているかどうかを返します。 426 * 427 * Calc対応機能とは、シート名のセット、雛型参照ファイル名のセット、 428 * 書き込み元ファイルのFileオブジェクト取得などの、特殊機能です。 429 * 本来は、インターフェースを分けるべきと考えますが、taglib クラス等の 430 * 関係があり、問い合わせによる条件分岐で対応します。 431 * 432 * @return Calc対応機能(=Excel対応機能)を持っているかどうか(true 固定) 433 */ 434 @Override 435 public boolean isExcel() { 436 return true; 437 } 438 439 /** 440 * 出力先ファイル名をセットします。(DIR + Filename) 441 * これは、Calc追加機能として実装されています。 442 * 443 * @param filename Calc雛型参考ファイル名 444 */ 445 @Override 446 public void setFilename( final String filename ) { 447 this.filename = filename; 448 } 449 450 /** 451 * Calc雛型参考ファイル名をセットします。(DIR + Filename) 452 * これは、Calc追加機能として実装されています。 453 * 454 * @param filename Calc雛型参考ファイル名 455 */ 456 @Override 457 public void setRefFilename( final String filename ) { 458 refFilename = filename; 459 } 460 461 /** 462 * Calc出力時のデフォルトフォント名を設定します。 463 * Calcの場合はfontNameは、利用できません。 464 * 465 * Calcファイルを書き出す時に、デフォルトフォント名を指定します。 466 * フォント名は、Calcのフォント名をそのまま使用してください。 467 * に設定されます。 468 * 初期値は、システムリソース の TABLE_WRITER_DEFAULT_FONT_NAME です。 469 * 470 * @og.rev 5.5.2.6 (2012/05/25) findbugs対応 471 * 472 * @param fontName デフォルトフォント名 473 */ 474 @Override 475 public void setFontName( final String fontName ) { 476// this.fontName = fontName ; 477 String errMsg = "Calcの場合はfontNameは、利用できません。fontName=[" + fontName + "]"; 478 System.err.println( errMsg ); 479 } 480 481 /** 482 * Calc出力時のデフォルトフォントポイント数を設定します。 483 * Calcの場合はfontPointは、利用できません。 484 * 485 * Calcファイルを書き出す時に、デフォルトポイント数を指定します。 486 * に設定されます。 487 * 初期値は、システムリソース の TABLE_WRITER_DEFAULT_FONT_POINTS です。 488 * 489 * @og.rev 5.5.2.6 (2012/05/25) findbugs対応 490 * 491 * @param point デフォルトフォントポイント数 492 */ 493 @Override 494 public void setFontPoint( final short point ) { 495// fontPoint = point; 496 String errMsg = "Calcの場合はfontPointは、利用できません。fontPoint=[" + point + "]"; 497 System.err.println( errMsg ); 498 } 499}