Apache POI写图像和文字的excel
我在写图像和文本在同一个单元格中的问题和类似于StackOverflow的问题添加图像和文本在Excel和POI Excel HSSFPicture图像和ALT TEXT的 同一单元格中 ,但期望的输出是不同的,我不明白什么是错的用我的代码? 并预期如下输出
这是我的代码;
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();
代码输出:
图像占据整个单元格,文字在图像后面。
有没有可能的解决scheme?
在Excel
表中,图片不在单元格中,而是在单元格上的图层中hover。 它们以如下方式锚定在细胞上:
一个单元锚点决定图片的左上angular位置。 如果使用,图片必须调整到原始大小。
两个单元格锚点确定图片的左上angular位置和大小。 第一个锚点确定左上angular位置,而第二个锚点确定右下angular位置。 所以图片的大小是给定的。
每个锚可以有一个行和列给出,但也是一个dx
和dy
。 dx
和dy
将被添加到列和行的位置来确定最终位置。 dx
和dy
的测量单位是EMU
。 例如,Apache poi提供了org.apache.poi.util.Units来从点或像素计算EMU
。
其中一个问题是,apache poi有一个方法来获得像素的列宽,而它只有一个方法来获得点的高度。 所以我们有两个不同的度量单位要考虑。
另一个问题是,如果我们想要尊重图片的宽高比,那么我们首先需要确定图片文件的本地大小。 有很多问题/答案如何在Java中获得一个JPG文件的原生大小。 所有的答案都非常复杂,我认为没有一个是真的。
下面的示例将图片放置在单元格B3
左侧单元格边界20px,距顶部单元格边界20pt,宽度最高20px,距离右侧单元格边界20英尺,高度最高到底部单元格边界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(); } }
结果: