Java ApachePOI编写图像和文本excel

Java ApachePOI编写图像和文本excel,java,excel,apache-poi,Java,Excel,Apache Poi,我在同一个单元格中书写图像和文本时遇到问题,问题类似于StackOverflow 和 ,但预期的输出不同,我无法找出我的代码出了什么问题? 预期产量如下所示 这是我的密码 Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet1"); //FileInputStream obtains input bytes fr

我在同一个单元格中书写图像和文本时遇到问题,问题类似于StackOverflow 和 ,但预期的输出不同,我无法找出我的代码出了什么问题? 预期产量如下所示

这是我的密码

            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("Sheet1");

            //FileInputStream obtains input bytes from the image file
            InputStream inputStream = new FileInputStream(k_pipe_img_file);
            //Get the contents of an InputStream as a byte[].
            byte[] bytes = IOUtils.toByteArray(inputStream);
            //Adds a picture to the workbook
            int pictureIdx = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
            //close the input stream
            inputStream.close();

            //Returns an object that handles instantiating concrete classes
            CreationHelper helper = workbook.getCreationHelper();

            //Creates the top-level drawing patriarch.
            Drawing drawing = sheet.createDrawingPatriarch();

            ClientAnchor anchor1 = new XSSFClientAnchor();
            anchor1.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);

            anchor1.setCol1(1);
            anchor1.setCol2(1);
            anchor1.setRow1(2);
            anchor1.setRow2(2);

            //Creates a picture
            Picture pict = drawing.createPicture(anchor1, pictureIdx);
            pict.resize(1, 1);

            Row row = sheet.createRow(2);
            row.setHeight((short) 4000);

            sheet.setColumnWidth(0, 4000);
            Cell cell = row.createCell(0, CellType.STRING);
            cell.setCellValue("Task 1");

            sheet.setColumnWidth(1, 5000);
            cell = row.createCell(1, CellType.STRING);
            cell.setCellValue("Replace Kemplon-Pipe");
            CellStyle style=row.getSheet().getWorkbook().createCellStyle();
            style.setVerticalAlignment(VerticalAlignment.TOP);
            cell.setCellStyle(style);

            //Write the Excel file
            FileOutputStream fileOut = new FileOutputStream(k_Task_file);
            workbook.write(fileOut);
            fileOut.close();
代码输出:

图像占据整个单元格,文本位于图像后面


有什么可能的解决方案吗?

Excel
表格中,图片不在单元格中,而是悬浮在单元格上方的一层中。它们以以下方式固定到单元:

单单元格定位确定图片的左上角位置。如果使用,必须将图片大小调整为其原始大小

双单元定位点确定图片的左上位置和大小。第一个定位点确定左上位置,而第二个定位点确定右下位置。因此给出了图片的大小

每个锚点可以有给定的行和列,但也可以有
dx
dy
dx
dy
将添加到列和行的位置,以确定最终位置。
dx
dy
的测量单位为
EMU
。ApachePOI提供了从点或像素计算EMU的功能

问题之一是ApachePOI有一个以像素为单位获取列宽度的方法,而它只有一个以点为单位获取行高度的方法。所以我们要考虑两种不同的测量单位

另一个问题是,如果我们想要尊重图片的纵横比,那么我们需要首先确定图片文件的本机大小。如何在Java中获得jpg文件的本机大小有很多问题/答案。所有的答案都非常复杂,在我看来没有一个是好的

以下示例将图片定位在单元格
B3
上,从左单元格边框定位20px,从上单元格边框定位20pt,从右单元格边框定位20px,从下单元格边框定位10pt

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 ExcelDrawImagesOverCell {

 private static void drawImageOnExcelSheet(XSSFSheet sheet, int row, int col, 
  int left/*in px*/, int top/*in pt*/, int width/*in px*/, int height/*in pt*/, int pictureIdx) throws Exception {

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

  Drawing drawing = sheet.createDrawingPatriarch();

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

  anchor.setCol1(col); //first anchor determines upper left position
  anchor.setRow1(row);
  anchor.setDx1(Units.pixelToEMU(left)); //dx = left in px
  anchor.setDy1(Units.toEMU(top)); //dy = top in pt

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

  drawing.createPicture(anchor, pictureIdx);

 }

 public static void main(String[] args) throws Exception {

  Workbook wb = new XSSFWorkbook();

  CellStyle styleVertAlingTop = wb.createCellStyle();
  styleVertAlingTop.setVerticalAlignment(VerticalAlignment.TOP);

  Sheet sheet = wb.createSheet();
  sheet.setColumnWidth(0, 15 * 256); //15 default characters width
  sheet.setColumnWidth(1, 30 * 256); //30 default characters width

  Row row = sheet.createRow(2);
  row.setHeight((short)(100 * 20)); //100pt height * 20 = twips (twentieth of an inch point)

  Cell cell = row.createCell(0);
  cell.setCellValue("Task 1");

  cell = row.createCell(1);
  cell.setCellValue("Replace Kemplon-Pipe");
  cell.setCellStyle(styleVertAlingTop);

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

  int left = 20; // 20px
  int top = 20; // 20pt
  int width = Math.round(sheet.getColumnWidthInPixels(1) - left - left); //width in px
  int height = Math.round(row.getHeightInPoints() - top - 10/*pt*/); //height in pt

  drawImageOnExcelSheet((XSSFSheet)sheet, 2, 1, left, top, width, height, pictureIdx);

  wb.write(new FileOutputStream("ExcelDrawImagesOverCell.xlsx"));
  wb.close();
 }
}
结果:


Excel
表格中,图片不在单元格中,而是悬浮在单元格上方的一层中。它们以以下方式固定到单元:

单单元格定位确定图片的左上角位置。如果使用,必须将图片大小调整为其原始大小

双单元定位点确定图片的左上位置和大小。第一个定位点确定左上位置,而第二个定位点确定右下位置。因此给出了图片的大小

每个锚点可以有给定的行和列,但也可以有
dx
dy
dx
dy
将添加到列和行的位置,以确定最终位置。
dx
dy
的测量单位为
EMU
。ApachePOI提供了从点或像素计算EMU的功能

问题之一是ApachePOI有一个以像素为单位获取列宽度的方法,而它只有一个以点为单位获取行高度的方法。所以我们要考虑两种不同的测量单位

另一个问题是,如果我们想要尊重图片的纵横比,那么我们需要首先确定图片文件的本机大小。如何在Java中获得jpg文件的本机大小有很多问题/答案。所有的答案都非常复杂,在我看来没有一个是好的

以下示例将图片定位在单元格
B3
上,从左单元格边框定位20px,从上单元格边框定位20pt,从右单元格边框定位20px,从下单元格边框定位10pt

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 ExcelDrawImagesOverCell {

 private static void drawImageOnExcelSheet(XSSFSheet sheet, int row, int col, 
  int left/*in px*/, int top/*in pt*/, int width/*in px*/, int height/*in pt*/, int pictureIdx) throws Exception {

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

  Drawing drawing = sheet.createDrawingPatriarch();

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

  anchor.setCol1(col); //first anchor determines upper left position
  anchor.setRow1(row);
  anchor.setDx1(Units.pixelToEMU(left)); //dx = left in px
  anchor.setDy1(Units.toEMU(top)); //dy = top in pt

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

  drawing.createPicture(anchor, pictureIdx);

 }

 public static void main(String[] args) throws Exception {

  Workbook wb = new XSSFWorkbook();

  CellStyle styleVertAlingTop = wb.createCellStyle();
  styleVertAlingTop.setVerticalAlignment(VerticalAlignment.TOP);

  Sheet sheet = wb.createSheet();
  sheet.setColumnWidth(0, 15 * 256); //15 default characters width
  sheet.setColumnWidth(1, 30 * 256); //30 default characters width

  Row row = sheet.createRow(2);
  row.setHeight((short)(100 * 20)); //100pt height * 20 = twips (twentieth of an inch point)

  Cell cell = row.createCell(0);
  cell.setCellValue("Task 1");

  cell = row.createCell(1);
  cell.setCellValue("Replace Kemplon-Pipe");
  cell.setCellStyle(styleVertAlingTop);

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

  int left = 20; // 20px
  int top = 20; // 20pt
  int width = Math.round(sheet.getColumnWidthInPixels(1) - left - left); //width in px
  int height = Math.round(row.getHeightInPoints() - top - 10/*pt*/); //height in pt

  drawImageOnExcelSheet((XSSFSheet)sheet, 2, 1, left, top, width, height, pictureIdx);

  wb.write(new FileOutputStream("ExcelDrawImagesOverCell.xlsx"));
  wb.close();
 }
}
结果: