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

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

ただいまの
回答率

89.13%

【Apache POI】XSSFShapeGroup.createPicture(anchor,pictIdx) 画像が0x0で(0,0)未満に配置されてしまう

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,950

take2016

score 8

前提・実現したいこと

Apache Poi を使用し、
テキストボックスと画像を1つのグループに設定し、
xlsx形式でファイルを出力したい。

発生している問題・エラーメッセージ

①patriarch.createPicture(pict_anchor, pictureIdx);
②group.createPicture(pict_anchor, pictureIdx);

①指定した場所に、画像がセットできる。
②座標(0,0)あたりに画像オブジェクトはあるが、0x0となり見えない。
※エクセルでサイズを大きくすると①と同じ画像であることがわかる

該当のソースコード

1つにまとめました

import java.awt.Color;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFChildAnchor;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFShapeGroup;
import org.apache.poi.xssf.usermodel.XSSFTextBox;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;

public class POITest {

    public static void main(String[] args) {
        String exportPath = "exportelsx/TestWorkbook.xlsx";
        String imagePath = "img/image.jpg";

        // 1.WorkBook、Sheet 作成
        Workbook testWb = new XSSFWorkbook();
        Sheet testsheet = testWb.createSheet();

        // 2.グループ作成
        XSSFDrawing testdraw = (XSSFDrawing) testsheet.createDrawingPatriarch();

        XSSFClientAnchor test_Groupanchor = new XSSFClientAnchor(0,0,0,0,1,1,10,10);
        XSSFShapeGroup testGroup = testdraw.createGroup(test_Groupanchor);
        //testGroup.setCoordinates(1, 1, 10, 10);

        // 3.グループに従属するEMU_PER_POINTボックスの作成
        int pic_x1 = 72*2 *XSSFShape.EMU_PER_POINT;
        int pic_y1 = 25*2 *XSSFShape.EMU_PER_POINT;
        int pic_x2 = 72*5 *XSSFShape.EMU_PER_POINT;
        int pic_y2 = 25*3 *XSSFShape.EMU_PER_POINT;
        XSSFTextBox test_textbox = testGroup.createTextbox(new XSSFChildAnchor(x1,y1,x2,y2));
        Color col = Color.LIGHT_GRAY;
        test_textbox.setFillColor(col.getRed(),col.getGreen(),col.getBlue());
        test_textbox.setText("テキスト");

        // テキストのフォント設定
        CTTextCharacterProperties rpr = test_textbox.getCTShape().getTxBody().getPArray(0).getRArray(0).getRPr();
        rpr.addNewLatin().setTypeface("Trebuchet MS");
        rpr.setSz(900); // 9 pt
        col = Color.pink;
        rpr.addNewSolidFill()
           .addNewSrgbClr()
           .setVal(new byte[] { (byte) col.getRed(), (byte) col.getGreen(), (byte) col.getBlue() });

        try{
            //4.Image追加
            FileInputStream jpeg = new FileInputStream(imagePath);

            byte[] bytes = IOUtils.toByteArray(jpeg);
            int picIndex = testWb.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
            jpeg.close();

            XSSFClientAnchor anchor = new XSSFClientAnchor(0,0,0,0,2,3,6,10);

            //picと同じ結果になるようにpic2を設定したい。
            //Picture pic = drawing.createPicture(anchor, picIndex);
            Picture pic2 = testGroup.createPicture(anchor, picIndex);


        }catch(Exception e){
            System.out.println("picture Error");
        }
        try{
            FileOutputStream fout = new FileOutputStream(exportPath);
            testWb.write(fout);
            fout.close();
            System.out.println("保存完了");
        }catch(Exception e){
            System.out.println("保存失敗");
        }
    }
}

投降時のソース

//group は XSSFShapeGroup型で引き渡されてきます
try {
  byte[] bytes = FileUtils.readFileToByteArray(imageFile);
  int pictureIdx = workbook.addPicture(bytes,Workbook.PICTURE_TYPE_JPEG);

  XSSFDrawing patriarch = (XSSFDrawing) sheet.createDrawingPatriarch();

  int dx1 = XSSFShape.EMU_PER_PIXEL * 10;
  int dy1 = XSSFShape.EMU_PER_PIXEL * 10;
  int dx2 = XSSFShape.EMU_PER_PIXEL * 10;
  int dy2 = XSSFShape.EMU_PER_PIXEL * 10;
  int col1 = 0;
  int row1 = 0;
  int col2 = 1;
  int row2 = 1;

  XSSFClientAnchor anchor = new XSSFClientAnchor(dx1,dy1,dx2,dy2,col1,row1,col2,row2);

  //① 0x0 、 (0,0)未満に配置
  group.createPicture(anchor, pictureIdx);

  //② 指定箇所に、指定サイズで配置
  patriarch.createPicture(anchor, pictureIdx);

} catch (IOException e) {
  this.log.error(e.getMessage(), e);
}

試したこと

dx1~row2 まで、それぞれ値を適当に変更し、位置が変わるか確認。結果は変わらず。
表示したい画像は同じなので、Anchorの扱い方に問題があると思っておりますが、どうしたら扱えるのかがつかめません。
よろしくお願いいたします。

使用しているlib/

poi-3.14-20160307.jar
poi-ooxml-3.14-20160307.jar
poi-ooxml-schemas-3.14-20160307.jar

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

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

  • ただいまの回答率 89.13%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる