Я подозреваю, что код, который вы здесь видите, взят из этого ответа: при добавлении изображения и текста в одну и ту же ячейку в Excel с помощью poi, а затем изображение переопределяет текст . Ваш код имеет те же комментарии, что и мой код в этом ответе. Это приводит к этому подозрению.
В ответе вы найдете четко описанное, как якоря работают над закреплением изображений, которые парят в слое над ячейками.
Чтобы разместить что-то справа от ячейки, вам нужно знать ширину ячейки (столбца). Тогда значение 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();
}
}
Результат:
Дополнение от 14 мая 2018 года:
Наличие решения, использующего XSSF
и HSSF
для этого, является сложным из-за различных странных единиц измерения, которые использует Microsoft, и того факта, что двоичная файловая система BIFF
*.xls
и Office Open XML
*.xlsx
сильно отличаются не только в хранении файлов, но и в целом. В моем ответе в apache poi XSSFClientAnchor не позиционирует картинку относительно dx1, dy1, dx2, dy2 Я уже описывал эту проблему.
Таким образом, следующий код должен работать как с XSSF
, так и с HSSF
. Это комментируется там, где используются особые подходы. Как правило, значения dx
и dy
в BIFF
зависят от коэффициента column-width
/ default column-width
и row-height
/ default row-height
. Таким образом, dx
того же количества, что и ширина столбца, кажется постоянным для всех возможных значений ширины столбца. И снова, не спрашивайте меня о факторе 14.75
, использованном в моем примере. Это просто проба и ошибка.
import java.io.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.hssf.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(Sheet sheet, int row, int col,
int picHeight/*in px*/, int picWidth/*in px*/, int pictureIdx, boolean right) throws Exception {
int DEFAULT_COL_WIDTH = 10 * 256; // 1/256th of a character width
float DEFAULT_ROW_HEIGHT = 12.75f; //255 twips = 12.75 pt
Row rowObject = sheet.getRow(row);
float rowHeight = (rowObject!=null)?rowObject.getHeightInPoints():DEFAULT_ROW_HEIGHT;
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));
int columWidth = sheet.getColumnWidth(col); // 1/256th of a character width
anchor.setCol1(col); //first anchor determines upper left position
anchor.setRow1(row);
if (sheet instanceof XSSFSheet) {
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
}
} else if (sheet instanceof HSSFSheet) {
if (right) {
anchor.setDx1((int)Math.round(
Units.DEFAULT_CHARACTER_WIDTH / 256f * 14.75 * DEFAULT_COL_WIDTH //right = constant for all possible column widths
-
picWidth * 14.75 * DEFAULT_COL_WIDTH / columWidth //wanted width = in relation to column width
)); //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 (sheet instanceof XSSFSheet) {
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
}
} else if (sheet instanceof HSSFSheet) {
if (right) {
anchor.setDx2((int)Math.round(Units.DEFAULT_CHARACTER_WIDTH / 256f * 14.75 * DEFAULT_COL_WIDTH)); //dx = right = constant for all possible column widths
anchor.setDy2((int)Math.round(picHeight * 14.75 * DEFAULT_ROW_HEIGHT / rowHeight)); //dy = top + wanted height
} else {
anchor.setDx2((int)Math.round(picWidth * 14.75 * DEFAULT_COL_WIDTH / columWidth)); //dx = left + wanted width
anchor.setDy2((int)Math.round(picHeight * 14.75 * DEFAULT_ROW_HEIGHT / rowHeight)); //dy = top + wanted height
}
}
drawing.createPicture(anchor, pictureIdx);
}
public static void main(String[] args) throws Exception {
//Workbook wb = new XSSFWorkbook();
Workbook wb = new HSSFWorkbook();
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, 20*256); //set the column width to 20 character widths
for (int r = 0; r < 10; r++ ) {
sheet.createRow(r).createCell(1).setCellValue(" Picture " + (r+1));
if ((r % 2) == 0) {
drawImageOnExcelSheet(sheet, r, 1, 16/*px*/, 16/*px*/, pictureIdx, false);
} else {
drawImageOnExcelSheet(sheet, r, 1, 16/*px*/, 16/*px*/, pictureIdx, true/*right*/);
}
}
if (wb instanceof XSSFWorkbook) {
wb.write(new FileOutputStream("ExcelDrawImagesOnCell.xlsx"));
} else if (wb instanceof HSSFWorkbook) {
wb.write(new FileOutputStream("ExcelDrawImagesOnCell.xls"));
}
wb.close();
}
}
Результат: