使用apache poi在合并的单元格中水平居中图像

时间:2016-07-25 10:31:52

标签: apache-poi

情况是,我合并了第一行的所有五个单元格,并将图像插入到第一行的第一个单元格中。我的要求是使图像水平居中于第一行。

我已经尝试了cellStyle.setAlignment(CellStyle.ALIGN_CENTER);,但它的中心是文字而不是图片。

有人可以帮忙吗?

注意:所有单元格都有不同的宽度。

1 个答案:

答案 0 :(得分:3)

将图像放在Excel工作表中是一件很棘手的事情,因为图片锚定在两个单元格上。左上角的锚单元加上delta-x和delta-y来确定图片的左上边缘的位置。右下方锚定单元加上delta-x和delta-y来确定大小。

是否合并单元格对于此过程并不重要。

因此,为了水平居中,我们需要计算哪个是左上角锚单元加上delta-x。幸运的是,通过在设置左上锚定单元格之后将图像大小调整为其原始大小,可以自动确定右下方锚定单元加上delta-x和delta-y。当然只有图片以原始尺寸出现。

评论示例:

import org.apache.poi.xssf.usermodel.*;
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;
import java.io.IOException;


class CenterImageTest {

 public static void main(String[] args) {
  try {

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

   //create the cells A1:F1 with different widths
   Cell cell = null;
   Row row = sheet.createRow(0);
   for (int col = 0; col < 6; col++) {
    cell = row.createCell(col);
    sheet.setColumnWidth(col, (col+1)*5*256);
   }

   //merge A1:F1
   sheet.addMergedRegion(new CellRangeAddress(0,0,0,5));

   //load the picture
   InputStream inputStream = new FileInputStream("/home/axel/Bilder/Unbenannt.png");
   byte[] bytes = IOUtils.toByteArray(inputStream);
   int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
   inputStream.close();

   //create an anchor with upper left cell A1
   CreationHelper helper = wb.getCreationHelper();
   ClientAnchor anchor = helper.createClientAnchor();
   anchor.setCol1(0); //Column A
   anchor.setRow1(0); //Row 1

   //create a picture anchored to A1
   Drawing drawing = sheet.createDrawingPatriarch();
   Picture pict = drawing.createPicture(anchor, pictureIdx);

   //resize the pictutre to original size
   pict.resize();

   //get the picture width
   int pictWidthPx = pict.getImageDimension().width;
System.out.println(pictWidthPx);

   //get the cell width A1:F1
   float cellWidthPx = 0f;
   for (int col = 0; col < 6; col++) {
    cellWidthPx += sheet.getColumnWidthInPixels(col);
   }
System.out.println(cellWidthPx);

   //calculate the center position
   int centerPosPx = Math.round(cellWidthPx/2f - (float)pictWidthPx/2f);
System.out.println(centerPosPx);

   //determine the new first anchor column dependent of the center position 
   //and the remaining pixels as Dx
   int  anchorCol1 = 0;
   for (int col = 0; col < 6; col++) {
    if (Math.round(sheet.getColumnWidthInPixels(col)) < centerPosPx) {
     centerPosPx -= Math.round(sheet.getColumnWidthInPixels(col));
     anchorCol1 = col + 1;
    } else {
     break;
    }
   }
System.out.println(anchorCol1);
System.out.println(centerPosPx);

   //set the new upper left anchor position
   anchor.setCol1(anchorCol1);
   //set the remaining pixels up to the center position as Dx in unit EMU
   anchor.setDx1( centerPosPx * Units.EMU_PER_PIXEL);

   //resize the pictutre to original size again
   //this will determine the new bottom rigth anchor position
   pict.resize();

   FileOutputStream fileOut = new FileOutputStream("CenterImageTest.xlsx");
   wb.write(fileOut);
   fileOut.close();

  } catch (IOException ioex) {
  }
 }
}

对于缩放图片,有一个比例因子:

   double scaleFactor = 0.25d;

然后:

   //calculate the center position
   int centerPosPx = Math.round(cellWidthPx/2f - (float)pictWidthPx/2f*(float)scaleFactor);

   //resize the pictutre to original size again
   //this will determine the new bottom rigth anchor position with original size
   pict.resize();
   //resize the pictutre to scaled size
   //this will determine the new bottom rigth anchor position with scaled size
   pict.resize(scaleFactor);

注意:首先调整大小为原始大小。因此,确定原始尺寸的右下锚位置。然后调整大小。因此,使用缩放尺寸获得右下锚位置。