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

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

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

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

Q&A

解決済

1回答

9042閲覧

Apache POIのClientAnchorで、オフセットが正しく指定できない

yuji38kwmt

総合スコア437

Java

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

0グッド

0クリップ

投稿2016/09/01 15:33

編集2016/09/11 02:18

背景

Apache POI3.14で、以下のコードでExcelに画像を挿入しています。

java

1 private static void addPicture(Workbook workbook) throws IOException { 2 //画像を読み込む 3 Path path = Paths.get("input/sample1.jpg"); 4 BufferedImage image = ImageIO.read(path.toFile()); 5 byte[] bytes = Files.readAllBytes(path); 6 //画像をworkbookに追加 7 int pictureIndex = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG); 8 Sheet sheet = workbook.getSheetAt(0); 9 Drawing drawing = sheet.createDrawingPatriarch(); 10 11 //セルA1にぴったり合うように画像を貼り付ける 12 int col1 = 0; 13 int row1 = 0; 14 int col2 = 1; 15 int row2 = 1; 16 17 //横方向に5pxずらす 18 int dx1 = 5 * Units.EMU_PER_PIXEL; 19 ClientAnchor anchor = drawing.createAnchor(dx1,0,0,0, col1, row1, col2, row2); 20 Picture picture = drawing.createPicture(anchor, pictureIndex); 21 }

問題

画像の左端位置を、A1セルの左端から5px右に移動させたいです。
しかし、上記のコードを実行すると、以下のエラーが発生しました。

Exception in thread "main" java.lang.IllegalArgumentException: dx1 must be between 0 and 1023, but was: 47625 at org.apache.poi.hssf.usermodel.HSSFClientAnchor.checkRange(HSSFClientAnchor.java:271) at org.apache.poi.hssf.usermodel.HSSFClientAnchor.<init>(HSSFClientAnchor.java:66) at org.apache.poi.hssf.usermodel.HSSFPatriarch.createAnchor(HSSFPatriarch.java:518) at org.apache.poi.hssf.usermodel.HSSFPatriarch.createAnchor(HSSFPatriarch.java:59) at mytest.gui.Console.addPicture(Console.java:48) at mytest.gui.Console.main(Console.java:26)

公式サイトには、以下のように記載されています。
https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/ClientAnchor.html#setDx1(int)

Sets the x coordinate within the first cell Note - XSSF and HSSF have a slightly different coordinate system, values in XSSF are larger by a factor of Units.EMU_PER_PIXEL

また、下記のサイトを参考にしました。

http://d.hatena.ne.jp/happy_ryo/20090531/1243743698

http://ohbarye.hatenablog.jp/entry/2014/04/28/100400

質問

5px左にオフセットさせるには、どのうように記述すればよいでしょうか?
「設定した値が範囲外」と言われたので、5 * Units.EMU_PER_PIXELという式が間違っている気がします。

補足事項

例外発生箇所のソースを添付します。
https://github.com/cuba-platform/apache-poi/blob/master/poi/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java

java:HSSFClientAnchor.java

1 2 public HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2) { 3 super(dx1, dy1, dx2, dy2); 4 5 checkRange(dx1, 0, 1023, "dx1"); 6 checkRange(dx2, 0, 1023, "dx2"); 7 checkRange(dy1, 0, 255, "dy1"); 8 checkRange(dy2, 0, 255, "dy2"); 9 checkRange(col1, 0, 255, "col1"); 10 checkRange(col2, 0, 255, "col2"); 11 checkRange(row1, 0, 255 * 256, "row1"); 12 checkRange(row2, 0, 255 * 256, "row2"); 13 14 setCol1((short) Math.min(col1, col2)); 15 setCol2((short) Math.max(col1, col2)); 16 setRow1((short) Math.min(row1, row2)); 17 setRow2((short) Math.max(row1, row2)); 18 19 if (col1 > col2){ 20 _isHorizontallyFlipped = true; 21 } 22 if (row1 > row2){ 23 _isVerticallyFlipped = true; 24 } 25 } 26 27 28 private void checkRange(int value, int minRange, int maxRange, String varName) { 29 if (value < minRange || value > maxRange) 30 throw new IllegalArgumentException(varName + " must be between " + minRange + " and " + maxRange); 31 }

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

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

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

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

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

guest

回答1

0

ベストアンサー

推測ですが、古いExcelフォーマット自体がピクセル単位の位置指定に対応していないのではないでしょうか。
どちらにしてもPOIではHSSFについては操作できないんだと思います。

dx1512に設定してみると、セルの右半分に縮小されて貼り付けられます。
つまり、セルを1024等分しての相対指定をするしか無いかも知れません。

下記のコード例では、列の幅のピクセル値と指定したいピクセルの比を1024に当てはめて、相対サイズを算出しています。
当然、正確なピクセル値にはなりません。

lang

1sheet.setActiveCell(CellAddress.A1); 2float columnWidthInPixels = sheet.getColumnWidthInPixels(0); 3double rate = 5 / columnWidthInPixels; 4int dx1 = (int)(1024 * rate);

投稿2016/09/01 20:05

argius

総合スコア9388

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

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

yuji38kwmt

2016/09/11 02:15

解答ありがとうございます。 xlsxでオフセットできるか、確認してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問