質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

3回答

23356閲覧

poiでテンプレートのExcelを読み込んでダウンロードする時

退会済みユーザー

退会済みユーザー

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2016/09/19 16:11

お世話になっております。

java の poi3.14を使用して、テンプレートExcelを読み込んで、データを書き込んでファイルをダウンロードするSevletを実装しました。

ただ、以下のようなコードですと、
例えば、データ貼り付けのシートに
1回目のリクエストは
1-10行目にデータが張り付き、
2回目のリクエストでは、パラメータが代わり貼り付けデータが
1-5行目となると、
6-10行目が前回の不要なデータが入ってしまいます。

java

1 // ファイルパスを取得します 2 String filePath = getServletContext() 3 .getRealPath("/WEB-INF/excel/" + getServiceType() + "/" + getExcelFileName()); 4 5// テンプレートからExcel読み込み 6 wb = new XSSFWorkbook(filePath); 7

そのあと、シート指定して、wbにデータ書込をごにょごにょ行った後、
以下、ダウンロード処理をします。

java

1 response.setContentType("application/vnd.ms-excel.sheet.macroEnabled.12"); 2 String fileName = null; 3 try { 4 fileName = new String(getExcelFileName().getBytes("Windows-31J"), "ISO-8859-1"); 5 } catch (UnsupportedEncodingException e1) { 6 e1.printStackTrace(); 7 } 8 response.setHeader("Content-Disposition", "attachments; filename=\"" + fileName + "\""); 9 response.setHeader("Cache-Control", "no-cache"); 10 response.setHeader("Pragma", "no-cache"); 11 response.setDateHeader("Expires", 0); 12 13 try { 14 OutputStream out = response.getOutputStream(); 15 wb.write(out); 16 out.close(); 17 } catch (IOException e) { 18 e.printStackTrace(); 19 } finally { 20 wb.close(); 21 } 22

対応として
wbで読み込んでいる前回のExcelがあれば、削除してから開くようにする。
としたいですが、前回読み込んでいるExcelファイルパスが不明のため、
実装方法がわからない状態です。

上記以外の対応として、以下のようなコードを参考に、
new File("テンプレートExcelファイルパス") して、新しく読込
それを、FileInputStreamにいれて
FileOutputStreamで書き出しすれば、うまく動くかと思い試してみましたが、書き出し部分が、new FileOutputStream( f );では、空のExcelファイルがダウンロードされてしまい、response.getOutputStream()でないと正常ファイルがダウンロードされませんでした。

java

1 2import java.io.*; 3import org.apache.poi.ss.usermodel.*; 4 5public class PoiEdit{ 6public static void main(String[] args) throws Exception{ 7File f = new File("Book1.xls"); // 既存のExcelファイル名を指定 8InputStream is = new FileInputStream( f ); 9Workbook wb = WorkbookFactory.create( is ); // メモリ上に展開 10is.close(); //ここで入力ストリームを閉じる 11 12// 編集したいシート、列、セルを指定 13Sheet s =wb.getSheetAt(0); 14Row r = s.getRow(1); 15Cell c = r.getCell(1); 16// この場合B2セルに「あいう」をセット 17c.setCellValue( "あいう" ); 18c.setCellType( Cell.CELL_TYPE_STRING ); 19 20// 編集した内容の書き出し 21OutputStream os = new FileOutputStream( f ); 22wb.write( os ); 23} 24

対応方法について、教えて頂ければ幸いです。
大変お手数をお掛けしますが、ご回答いただければ幸いでごす。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

どうやら、前回の内容が保存されてしまうのは、
poi3.11から、そう変わったようです。

3.10.1にすると、保存されてしまう現象は
ありませんでした。

ご相談に乗って頂き、感謝します!
ありがとうございました!

投稿2016/09/20 11:59

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

回答ありがとうございます。

テンプレートを取得するfilePathをダンプしますと、eclipesの関係か実態がある位置とは別のパスからエクセルが作成されており、そのファイルが
前回保存したもののようです。

パスがおかしくなるのは、初回もでしょうか?
それとも初回は想定通りのパスでしょうか?

あと、EclipseでWTPなどで起動しないで、
warファイルをTomcat等に直接デプロイした場合は
どのような挙動になるか確かめてもらうことは可能でしょうか?

投稿2016/09/20 06:53

ijufumi

総合スコア276

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/09/20 09:54

ご回答ありがとうございます!! ```java // ファイルパスを取得します String filePath = getServletContext() .getRealPath("/WEB-INF/excel/" + getServiceType() + "/" + getExcelFileName()); System.out.println("filePath: " + filePath); ``` 実際テンプレファイルを配置した場所は、以下になるのですが、 C:\Users\win7\workspace\app\src\main\webapp\WEB-INF\excel\test\xxx.xlsm system.out.printinでは、以下のパスが出力されます。 C:\Users\win7\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\app\WEB-INF\excel\test\xxx.xlsm ↑に前回の状態で保存されているようで、warで書き出したアプリも同じ動作をしました。
guest

0

XSSFWorkbookは自動で保存はしないので、最初のコードでもうまくいく気がします。
どこかで、wb.writeを実行してファイルを保存していたりしませんか?

あと、XSSFWorkbookの変数wbはどこで定義していますか?
Servletのインスタンス変数として定義していませんか?

Servletのインスタンスは、リクエスト毎に生成されるものではなく
1つのインスタンスを複数のリクエストで共有して使うので、
インスタンス変数で定義されていた場合想定外の更新が行われたりするので、
メソッド内のローカル変数として定義した方が良いです。

投稿2016/09/20 03:50

ijufumi

総合スコア276

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/09/20 09:39

ご回答ありがとうございます。 最初のコードで、ダウンロードのヘッダー追加処理後にwb.writeをしています。それ以外ではしておりません。 はい、変数は、関数内で宣言して、関数どおしで使いまわしているだけで、サーブレットのメンバ変数には定義していません。 テンプレートを取得するfilePathをダンプしますと、eclipesの関係か実態がある位置とは別のパスからエクセルが作成されており、そのファイルが 前回保存したもののようです。 ただ、これを手動で消してしまうと、 今度、ファイルがみつからないになります。 ビルドやクリーンで生成されるものでもなく、 生成タイミングが不明です。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問