Quiero poner una imagen en el centro de una celda de Excel, uso XSSFClientAnchor para anclar la posición de la imagen, pero todavía no funciona como la imagen 1.
Cómo hacer que la imagen se establezca en el centro de una celda, como la imagen 2.
InputStream iStream = new FileInputStream(iList.get(q.getProductID()));
byte[] bytes = IOUtils.toByteArray(iStream);
int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
XSSFDrawing patriarch = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = new XSSFClientAnchor();
anchor.setCol1(1);
anchor.setRow1(row);
anchor.setCol2(2);
anchor.setRow2(row + 1);
Picture pic = patriarch.createPicture(anchor, pictureIdx);
pic.resize();
Las imágenes no son contenido de la celda, sino que se ciernen sobre la hoja en una capa separada llamada dibujo. Están anclados a las células. A ClientAnchor
proporciona la siguiente configuración:
col1
= índice de columna donde está anclado el borde izquierdo de la imagen. Entonces el borde izquierdo de la imagen está anclado en el borde izquierdo de la columna de col1
.
dx1
= diferencia en la dirección x. Entonces el borde izquierdo de la imagen está anclado en el borde izquierdo de la columna de col1
+ dx1
.
row1
= índice de fila donde está anclado el borde superior de la imagen. Entonces el borde superior de la imagen está anclado en el borde de la fila superior de row1
.
dy1
= diferencia en la dirección y. Por lo tanto, el borde superior de la imagen está anclado en el borde de la fila superior de row1
+ dy1
.
col2
= índice de columna donde está anclado el borde derecho de la imagen. Entonces el borde derecho de la imagen está anclado en el borde izquierdo de la columna de col2
.
dx2
= diferencia en la dirección x. Entonces el borde derecho de la imagen está anclado en el borde izquierdo de la columna de col1
+ dx2
.
row2
= índice de fila donde está anclado el borde inferior de la imagen. Entonces el borde inferior de la imagen está anclado en el borde de la fila superior de row2
.
dy2
= diferencia en la dirección y. Entonces, el borde inferior de la imagen está anclado en el borde de la fila superior de row2
+ dy2
.
Por lo tanto, dado un anclaje completo de dos celdas, esto determina la posición de la imagen y su tamaño.
Si el tamaño de la imagen debe ser su tamaño nativo, entonces solo se necesita un anclaje de una celda. Allí col1
+ dx1
y row1
+ dy1
determinan la posición del borde superior izquierdo de la imagen. El tamaño viene dado por el tamaño nativo de la imagen.
Si solo col1
y row1
se establece sin dx1
y dy1
, entonces el borde superior izquierdo de la imagen siempre está anclado al borde izquierdo de col1
y al borde superior de row1
. Entonces, si se necesita centrar sobre una celda, entonces, dx1
y dy1
debe calcularse. Para calcular dx1
y dy1
uno necesita saber el ancho y alto de la imagen, así como el ancho y alto de la celda. Suena simple, pero hay varias unidades de medida diferentes utilizadas para el ancho y la altura de la celda y hay grandes diferencias entre el sistema de archivos binario BIFF
( *.xls
) y el sistema de archivos Office Open XML
( *.xlsx
).
El siguiente código proporciona un putPictureCentered
método que coloca una imagen en el dibujo de la hoja anclada a una celda dada por colIdx
y rowIdx
. Si es posible, calcula dx1
y de dy1
modo que la imagen se ancla centrada sobre la celda. Utiliza píxeles como la unidad de medida común. Considera las diferencias entre el sistema de archivos binario BIFF
( *.xls
) y el sistema de archivos Office Open XML
( *.xlsx
). Entonces funciona para Sheet
, puede ser XSSFSheet
o HSSFSheet
.
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Units;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class CenterImageOverCell {
static void putPictureCentered(Sheet sheet, String picturePath, int pictureType, int colIdx, int rowIdx) throws Exception {
Workbook wb = sheet.getWorkbook();
//load the picture
InputStream inputStream = new FileInputStream(picturePath);
byte[] bytes = IOUtils.toByteArray(inputStream);
int pictureIdx = wb.addPicture(bytes, pictureType);
inputStream.close();
//create an anchor with upper left cell colIdx/rowIdx, only one cell anchor since bottom right depends on resizing
CreationHelper helper = wb.getCreationHelper();
ClientAnchor anchor = helper.createClientAnchor();
anchor.setCol1(colIdx);
anchor.setRow1(rowIdx);
//create a picture anchored to colIdx and rowIdx
Drawing drawing = sheet.createDrawingPatriarch();
Picture pict = drawing.createPicture(anchor, pictureIdx);
//get the picture width in px
int pictWidthPx = pict.getImageDimension().width;
//get the picture height in px
int pictHeightPx = pict.getImageDimension().height;
//get column width of column in px
float columnWidthPx = sheet.getColumnWidthInPixels(colIdx);
//get the height of row in px
Row row = sheet.getRow(rowIdx);
float rowHeightPt = row.getHeightInPoints();
float rowHeightPx = rowHeightPt * Units.PIXEL_DPI / Units.POINT_DPI;
//is horizontal centering possible?
if (pictWidthPx <= columnWidthPx) {
//calculate the horizontal center position
int horCenterPosPx = Math.round(columnWidthPx/2f - pictWidthPx/2f);
//set the horizontal center position as Dx1 of anchor
if (wb instanceof XSSFWorkbook) {
anchor.setDx1(horCenterPosPx * Units.EMU_PER_PIXEL); //in unit EMU for XSSF
} else if (wb instanceof HSSFWorkbook) {
//see https://stackoverflow.com/questions/48567203/apache-poi-xssfclientanchor-not-positioning-picture-with-respect-to-dx1-dy1-dx/48607117#48607117 for HSSF
int DEFAULT_COL_WIDTH = 10 * 256;
anchor.setDx1(Math.round(horCenterPosPx * Units.DEFAULT_CHARACTER_WIDTH / 256f * 14.75f * DEFAULT_COL_WIDTH / columnWidthPx));
}
} else {
System.out.println("Picture is too width. Horizontal centering is not possible.");
//TODO: Log instead of System.out.println
}
//is vertical centering possible?
if (pictHeightPx <= rowHeightPx) {
//calculate the vertical center position
int vertCenterPosPx = Math.round(rowHeightPx/2f - pictHeightPx/2f);
//set the vertical center position as Dy1 of anchor
if (wb instanceof XSSFWorkbook) {
anchor.setDy1(Math.round(vertCenterPosPx * Units.EMU_PER_PIXEL)); //in unit EMU for XSSF
} else if (wb instanceof HSSFWorkbook) {
//see https://stackoverflow.com/questions/48567203/apache-poi-xssfclientanchor-not-positioning-picture-with-respect-to-dx1-dy1-dx/48607117#48607117 for HSSF
float DEFAULT_ROW_HEIGHT = 12.75f;
anchor.setDy1(Math.round(vertCenterPosPx * Units.PIXEL_DPI / Units.POINT_DPI * 14.75f * DEFAULT_ROW_HEIGHT / rowHeightPx));
}
} else {
System.out.println("Picture is too height. Vertical centering is not possible.");
//TODO: Log instead of System.out.println
}
//resize the picture to it's native size
pict.resize();
}
public static void main(String[] args) throws Exception {
//Workbook wb = new HSSFWorkbook(); String resultName = "CenterImageTest.xls";
Workbook wb = new XSSFWorkbook(); String resultName = "CenterImageTest.xlsx";
Sheet sheet = wb.createSheet("Sheet1");
int colIdx = 1;
int colWidth = 20; //in default character widths
int rowIdx = 1;
float rowHeight = 100; //in points
//========================prepare sheet
//create cell
Row row = sheet.createRow(rowIdx);
Cell cell = row.createCell(colIdx);
//set column width of colIdx in default character widths
sheet.setColumnWidth(colIdx, colWidth * 256);
//set row height of rowIdx in points
row.setHeightInPoints(rowHeight);
//========================end prepare sheet
//put image centered
String picturePath = "./pict100x100.png"; // small image
//String picturePath = "./pict100x200.png"; // image too height
//String picturePath = "./pict200x100.png"; // image too width
//String picturePath = "./pict200x200.png"; // image too big
putPictureCentered(sheet, picturePath, Workbook.PICTURE_TYPE_PNG, colIdx, rowIdx);
FileOutputStream fileOut = new FileOutputStream("./" + resultName);
wb.write(fileOut);
fileOut.close();
wb.close();
}
}
Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.
En caso de infracción, por favor [email protected] Eliminar
Déjame decir algunas palabras