简体   繁体   English

Apache POI编写图像和文本Excel

[英]Apache POI write image and text excel

I am having trouble with writing image and text in a same cell and questions similar to StackOverflow on addding image and text in same cell in excel and POI Excel HSSFPicture Image and ALT TEXT , but the expected output is different and I cannot figure out what wrong with my code? 我在同一单元格中写入图像和文本时遇到麻烦,并且在excelPOI Excel HSSFPicture Image和ALT TEXT中 在同一单元格中添加图像和文本时遇到了与StackOverflow类似的问题,但是预期的输出不同,我无法弄清楚是什么错误用我的代码? and expected output like as below 和预期的输出如下

在此处输入图片说明

Here is my code; 这是我的代码;

            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();

Code Output: 代码输出: 在此处输入图片说明

image occupies entire cell and text is behind the image. 图像占据整个单元格,文本位于图像后面。

Is there any possible solution? 有没有可能的解决方案?

In Excel sheets pictures are not in cells but hovers in a layer over the cells. Excel表中,图片不在单元格中,而是悬停在单元格上方的一层中。 They are anchored to the cells in the following manner: 它们以以下方式锚定到单元:

A one cell anchor determines the upper left position of the picture. 一个单元格锚点确定图片的左上位置。 If used, the picture must be resized to its native size. 如果使用图片,则必须将其尺寸调整为原始尺寸。

A two cell anchor determines the upper left position and the size of the picture. 两个单元格的锚点确定图片的左上位置和大小。 The first anchor determines the upper left position while the second anchor determines the bottom right position. 第一锚确定左上位置,第二锚确定右下位置。 So the size of the picture is given. 因此,给出了图片的大小。

Each anchor can have a row and column given but also a dx and dy . 每个锚点可以具有给定的行和列,还可以具有dxdy The dx and dy will be added to the column's and row's position to determine the final position. dxdy将添加到列和行的位置,以确定最终位置。 The measurement unit for dx and dy is EMU . dxdy的度量单位是EMU Apache poi provides org.apache.poi.util.Units to calculate EMU from points or pixels for example. Apache poi提供org.apache.poi.util.Units来根据点或像素来计算EMU

One of the problems is that apache poi has a method to get the width of a column in pixels while it only has a method to get the height of the row in points. 问题之一是apache poi有一种方法以像素为单位来获取列的宽度,而它只有一种方法以点为单位来获取行的高度。 So we have two different measurement units to be considered. 因此,我们要考虑两个不同的度量单位。

Another problem is that if we wants to respect the aspect ratio of the picture, then we need determining the native size of the picture file first. 另一个问题是,如果我们要考虑图片的长宽比,则需要首先确定图片文件的原始大小。 There are many questions/answers how to get the native size of a jpg file in Java. 如何使用Java获取jpg文件的本机尺寸有很多问题/答案。 All answers are very complex and none is really good in my opinion. 我认为所有答案都非常复杂,没有一个是很好的答案。

The following example does positioning a picture over cell B3 anchored 20px from left cell border, 20pt from top cell border, in width up to 20px from right cell border and in height up to 10pt from bottom cell border. 下面的示例确实在单元格B3上定位了图片,该图片在距左单元格边界20px,距顶部单元格边界20pt,距右侧单元格边界20 px,高度距底部单元格边界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();
 }
}

Result: 结果:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM