使用POI在Java中的Excel中包含单元格右侧的图像

时间:2018-04-30 13:01:22

标签: java excel apache-poi

无论如何,其中一个人可以使用poi通过java将图像移动到excel中的单元格右侧。尝试了所有可能的锚位置和坐标,但图像保持在单元格的左侧

Actual

但所需职位是

Expected

以下是用于在java中将图像绘制为excel的代码: -

private static void drawImageOnExcelSheet(XSSFSheet sheet, int row, int col, int height, int width, int pictureIdx)
        throws Exception {

    CreationHelper helper = sheet.getWorkbook().getCreationHelper();

    Drawing drawing = sheet.createDrawingPatriarch();

    ClientAnchor anchor1 = helper.createClientAnchor();
    anchor1.setAnchorType(AnchorType.DONT_MOVE_AND_RESIZE);

    anchor1.setRow2(row); // second anchor determines bottom right position
    anchor1.setCol2(col);
    anchor1.setDx2(Units.toEMU(width)); // dx = left + wanted width
    anchor1.setDy2(Units.toEMU(height)); // dy= top + wanted height

    Picture pic = drawing.createPicture(anchor1, pictureIdx);
    pic.resize();

}

1 个答案:

答案 0 :(得分:1)

我怀疑您在此处显示的代码取自此答案:on addding image and text in same cell in excel using poi then image override the text。您的代码与我在此答案中的代码具有相同的注释。这导致了这种怀疑。

在答案中,您会清楚地描述锚点如何用于锚定在图像上悬停在图像上的图片。

要在单元格的右侧放置某些东西,您需要知道单元格(列)的宽度。然后必须将第二个锚点的dx设置为与单元格宽度相同的量。因为dx将被添加到列的位置以确定最终位置,因此它将位于单元格的右边缘。

但是肯定你需要一个两个单元格的锚点,所以你应该pic.resize(),因为两个单元格锚点已经确定了大小。

示例:

import java.io.*;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;

import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Units;

public class ExcelDrawImagesOnCell {

 private static void drawImageOnExcelSheet(XSSFSheet sheet, int row, int col, 
  int picHeight/*in px*/, int picWidth/*in px*/, int pictureIdx, boolean right) throws Exception {

  CreationHelper helper = sheet.getWorkbook().getCreationHelper();

  Drawing drawing = sheet.createDrawingPatriarch();

  ClientAnchor anchor = helper.createClientAnchor();
  anchor.setAnchorType(AnchorType.MOVE_AND_RESIZE);

  int columWidthInPx = Math.round(sheet.getColumnWidthInPixels(col));

  anchor.setCol1(col); //first anchor determines upper left position
  anchor.setRow1(row);
  if (right) {
   anchor.setDx1(Units.pixelToEMU(columWidthInPx) - Units.pixelToEMU(picWidth)); //dx = right - wanted width
   anchor.setDy1(0); //dy = top
  } else {
   anchor.setDx1(0); //dx = left
   anchor.setDy1(0); //dy = top
  }

  anchor.setCol2(col); //second anchor determines bottom right position
  anchor.setRow2(row); 
  if (right) {
   anchor.setDx2(Units.pixelToEMU(columWidthInPx)); //dx = right
   anchor.setDy2(Units.pixelToEMU(picHeight)); //dy = top + wanted height
  } else {
   anchor.setDx2(Units.pixelToEMU(picWidth)); //dx = left + wanted width
   anchor.setDy2(Units.pixelToEMU(picHeight)); //dy = top + wanted height
  }

  drawing.createPicture(anchor, pictureIdx);

 }

 public static void main(String[] args) throws Exception {
  Workbook wb = new XSSFWorkbook();
  Sheet sheet = wb.createSheet();

  InputStream is = new FileInputStream("samplePict.jpeg");
  byte[] bytes = IOUtils.toByteArray(is);
  int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
  is.close();

  sheet.setColumnWidth(1, 15*256); //set the column width to 15 character widths
  for (int r = 0; r < 10; r++ ) {
   sheet.createRow(r).createCell(1).setCellValue("Picture " + (r+1));
   //drawImageOnExcelSheet((XSSFSheet)sheet, r, 1, 16/*px*/, 16/*px*/, pictureIdx, false);
   drawImageOnExcelSheet((XSSFSheet)sheet, r, 1, 16/*px*/, 16/*px*/, pictureIdx, true/*right*/);
  }

  wb.write(new FileOutputStream("ExcelDrawImagesOnCell.xlsx"));
  wb.close();
 }
}

结果:

enter image description here

补充2018年5月14日:

使用XSSF以及HSSF来解决此问题很复杂,因为Microsoft正在使用不同的奇怪测量单位以及二进制文件系统BIFF {{ 1}}和*.xls Office Open XML不仅在文件存储方面非常不同,而且在一般方法中也是如此。我在apache poi XSSFClientAnchor not positioning picture with respect to dx1, dy1, dx2, dy2的答案中已经描述了这个问题。

因此,以下代码应与*.xlsx以及XSSF一起使用。评论它使用特殊方法。一般来说,HSSFdxdy的值取决于BIFF / column-widthdefault column-width / {{1}的因素}。因此,对于所有可能的列宽,与列宽相同量的row-height似乎是常量。再一次,不要问我在我的例子中使用的因子default row-height。这只是试验和错误。

dx

结果:

enter image description here