2017-08-02 48 views
0

すべてのワークシートのすべてのイメージを既存のExcelファイルから新しいExcelファイルにコピーしようとしています。このために、私は既存のExcelファイルからすべてのシートを読み、新しいExcelファイルに画像をコピーします。次のコードはすべてのシートにアクセスし、すべてのイメージを新しいシートにコピーしようとします。Apache POIを使用してすべてのExcelワークシートからイメージを読み取る

public static void modifyExcelFile(XSSFWorkbook xssfWorkbook) throws InvalidFormatException, IOException, XmlException{ 
    String newFileName = "outputexcelfile.xlsx"; 
    XSSFWorkbook dest = new XSSFWorkbook("test.xlsx"); 

    int numSheets = xssfWorkbook.getNumberOfSheets(); 

    // clone the template sheet additional number of times required 
    for(int i=1; i<numSheets; i++){ 
     dest.cloneSheet(0); 
    } 

    for(int i=0; i<numSheets; i++) { 
     XSSFSheet destSheet = dest.getSheetAt(i); 
     dest.setSheetName(i, xssfWorkbook.getSheetName(i)); 

     XSSFSheet sheet = xssfWorkbook.getSheetAt(i); 
     // copy images 
     System.out.println("Copying images ..."); 
     copyImages(sheet, destSheet); 

    } 

    writeFile(dest, newFileName); 

} 

test.xlsxは1枚のテンプレートファイルです。次のcopyImages関数は、すべての画像を1つのシートから別のシートにコピーしようとします。

public static void copyImages(XSSFSheet from, XSSFSheet to) throws IOException, XmlException, InvalidFormatException{ 
    Drawing drawingPatriarch = to.createDrawingPatriarch(); 
    XSSFWorkbook destWorkbook = to.getWorkbook(); 

    // Add image 
    for (POIXMLDocumentPart pdp : from.getRelations()) { 
     if (!XSSFRelation.DRAWINGS.getRelation().equals(pdp.getPackageRelationship().getRelationshipType())) continue; 

     PackagePart drawPP = pdp.getPackagePart(); 
     WsDrDocument draw = WsDrDocument.Factory.parse(drawPP.getInputStream()); 


     for (CTTwoCellAnchor twoAnc : draw.getWsDr().getTwoCellAnchorList()) { 
      String picId = twoAnc.getPic().getBlipFill().getBlip().getEmbed(); 
      PackageRelationship pr = drawPP.getRelationship(picId); 
      PackagePart imgPP = drawPP.getRelatedPart(pr); 

      System.out.println(imgPP.getPartName() + ": contentType: " + imgPP.getContentType() + " size: " + imgPP.getSize() 
        + ": picId: " + picId 
        +" - Col1: "+twoAnc.getFrom().getCol() 
        +" - Row1: "+twoAnc.getFrom().getRow() 
        +" - Col2: "+twoAnc.getTo().getCol() 
        +" - Row2: "+twoAnc.getTo().getRow() 
      ); 

      // skip the logo 
      if(twoAnc.getFrom().getCol()==0 && twoAnc.getFrom().getRow()==0) 
       continue; 

      try { 
       InputStream is = imgPP.getInputStream(); 
       byte[] bytes = IOUtils.toByteArray(is); 
       int pictureIdx = destWorkbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG); 
       is.close(); 

       CreationHelper helper = destWorkbook.getCreationHelper(); 

       //add a picture shape 
       ClientAnchor anchor = helper.createClientAnchor(); 
       //set top-left corner of the picture, 

       anchor.setCol1(twoAnc.getFrom().getCol()); 
       anchor.setRow1(twoAnc.getFrom().getRow()); 
       anchor.setRow2(twoAnc.getTo().getRow()); 
       anchor.setCol2(twoAnc.getTo().getCol()); 
       Picture pict = drawingPatriarch.createPicture(anchor, pictureIdx); 

      }catch(IOException ioEx){ 
       System.out.println("Failed to add icons. Details: " + ioEx.getMessage()); 
      } 

     } 
    } 
} 

コードを実行すると、最初のシートの画像のみが正常にコピーされます。他のすべてのシートについては、画像はありません。コードはエラーなしで正常に実行されます。どんな助けでも大歓迎です。ありがとう!

答えて

0

pict.resize()を追加するだけです。 Picture pict = ...の後の関数呼び出しで問題を解決します。したがって、変更されたコードは次のようになります。

Picture pict = drawingPatriarch.createPicture(anchor, pictureIdx); 
    pict.resize(); 

resize()呼び出しがないと機能しない理由はわかりません。

+0

[ClientAnchor](https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/ClientAnchor.html)は、左上のアンカーセルから右下のアンカーセルまでではなく、上端のアンカーセル左アンカーセル+このセルの右下のアンカーセルへのx/yオフセット+このセルのx/yオフセット。オフセットは 'apache poi'の' Dx1'、 'Dy1'と' Dx2'、 'Dy2'という名前です。 –

+0

@AxelRichter:resize()関数を呼び出さないと、常にDx1-2、Dy1-2について言及する必要はありますか? – Masum

+1

はい、ピクチャが** one **セルに収まる場合、左上のアンカーセルと右下のアンカーセルは同じになるため、オフセットがなければ、ピクチャサイズはアンカーに依存します。その後、resize()だけがネイティブサイズに修正されます。 –

関連する問題