将图像添加到遵循排序和过滤规则的工作表中

时间:2019-07-08 18:12:44

标签: java excel apache-poi

编辑:这可能是Excel的一般问题,我在这里进行跟踪:https://superuser.com/questions/1457518/adding-images-to-excel-that-obey-both-filtering-and-sorting-rules

我正在生成工作表,其中某些行将嵌入图像。根据我嵌入图像的方式,当隐藏其余行数据时图像不会隐藏,或者在对工作表进行排序时图像不会排序。

示例应用程序演示了此问题:https://github.com/dan-kirberger/poi-excel-image-issue-它生成两个工作表。每个都展示了我的问题之一。如果您只想查看生成的工作簿,那么还有一个slave-jenkins-node文件夹包含预先生成的工作表。

在应用任何排序/过滤之前,工作表如下所示:

enter image description here

通过以下方式在工作表上启用排序/筛选:

examples

添加图像的代码(也在上面的github链接中):

sheet.setAutoFilter(new CellRangeAddress(sheet.getFirstRowNum(), sheet.getLastRowNum(), 0, 2));

在该代码段中, Drawing drawing = cell.getSheet().createDrawingPatriarch(); XSSFClientAnchor anchor = new XSSFClientAnchor(); anchor.setAnchorType(imageAnchorType); anchor.setCol1(cell.getColumnIndex()); anchor.setRow1(cell.getRowIndex()); Picture picture = drawing.createPicture(anchor, pictureId); picture.resize(1, 1); 是决定因素,如果设置为imageAnchorType,则在过滤器中使用排序功能时,图像将不会排序: enter image description here

请注意,图像不再与“文本”列匹配。 (带有图片“ 1”的图像现在位于“两位”的文本旁边)

如果将MOVE_AND_RESIZE设置为imageAnchorType,则图像会适当排序,但是当应用删除图像行的过滤器时,图像将保留: enter image description here

我们应用了一个过滤器来显示“仅文本”列,因此“一个”和“三”行数据消失了,但它们的图像仍然保留。

我是否应该设置其他属性以使其按我想要的方式工作?

1 个答案:

答案 0 :(得分:1)

问题不仅仅在于锚类型。同时提供排序和过滤,ClientAnchor.AnchorType.MOVE_AND_RESIZE是正确的。为了进行排序,必须进行移动,并且对于过滤,必须进行大小调整(不可见行的行高为0)。

但是要支持排序,图片还必须适合已排序的单元格。它们不能确定单元格的大小,否则它们将不会与单元格一起排序。因此picture.resize是不可能的,因为调整大小会将图片调整为原始尺寸,该尺寸可能会大于图片所锚定的单元格的尺寸。

ClientAnchor提供以下设置:

setCol1,是锚点锚定的第一列。图片的左上边缘从该列的左边缘开始。

setDx1是添加到锚点锚定的第一列左边缘的值。它将图片从第一列的左边缘水平移开。

setRow1,即锚点锚定的第一行。图片的左上边缘从该行的上边缘开始。

setDy1是添加到锚点锚定的第一行顶部边缘的值。它将图片垂直移离第一行的顶部边缘。

setCol2,是锚点锚定的第二列。图片的右下边缘在该列的左边缘结束。

setDx2是添加到锚点锚定的第二列左边缘的值。它将图片的右下边缘水平移离第二列的左边缘。这将水平放大图片。

setRow2,即锚点锚定的第二行。图片的右下边缘在该行的上边缘结束。

setDy1是添加到锚点锚定的第二行顶部的值。它将图片的右下边缘垂直移离第二行的上边缘。这将垂直拉伸图片。

要支持排序,Row1Row2必须在同一行。这样,在对该行进行排序时,图片就属于该行。这意味着图片高度只能由Dy2确定。图片高度必须适合行高。

以下代码显示了一个示例。我从您的github下载的图片。

代码:

import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.Units;
import org.apache.poi.xssf.usermodel.*;

class CreateExcelPictures {

 static String excelPath = "ExcelWithPictures.xlsx";
 static String[][] data = new String[][]{
  new String[]{"Image", "Text", "Type"},
  new String[]{"", "One", "One and Three"},
  new String[]{"", "Two", "Two only"},
  new String[]{"", "Three", "One and Three"}
 };
 static String[] pictureFileNames = new String[]{"one.png", "two.png", "three.png"};
 static int pictureWidthPx = 30;
 static int pictureHeightPx = 25;
 static XSSFWorkbook workbook;
 static XSSFSheet sheet;

 static void addImage(int col1, int row1, int col2, int row2, 
  int dx1, int dy1, int dx2, int dy2,
  String imageFileName, ClientAnchor.AnchorType anchorType) throws Exception {

  InputStream imageInputStream = new FileInputStream(imageFileName);
  byte[] bytes = IOUtils.toByteArray(imageInputStream);
  int pictureId = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
  imageInputStream .close();

  XSSFClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();
  anchor.setAnchorType(anchorType);
  // set Col1, Dx1, Row1, Dy1, Col2, Dx2, Row2, Dy2
  // only this determines the picture's size then
  anchor.setCol1(col1);
  anchor.setDx1(dx1);
  anchor.setRow1(row1);
  anchor.setDy1(dy1);
  anchor.setCol2(col2);
  anchor.setDx2(dx2);
  anchor.setRow2(row2);
  anchor.setDy2(dy2);

  XSSFDrawing drawing = sheet.createDrawingPatriarch();

  XSSFPicture picture = drawing.createPicture(anchor, pictureId);

 }

 public static void main(String args[]) throws Exception {

  workbook = new XSSFWorkbook();
  sheet = workbook.createSheet();
  int r = 0;
  for (String[] rowData : data) {
   XSSFRow row = sheet.createRow(r);
   int c = 0;
   for (String cellData : rowData) {
    XSSFCell cell = row.createCell(c++);
    cell.setCellValue(cellData);
   }
   if (r > 0) {
    float rowHeight = (float)Units.pixelToPoints(pictureHeightPx); // picture's height must fit into row height
    row.setHeightInPoints(rowHeight);
    addImage(0, r, 0, r, /*all fits in one cell*/
     /*Dx1 = 0 and Dy1 = 0, picture's top left edge starts on top left of the cell*/
     Units.pixelToEMU(0), Units.pixelToEMU(0), 
     /*Dx2 is picture's width and Dy2 is picture's height, picture's bottom right edge ends on that point into the cell*/
     Units.pixelToEMU(pictureWidthPx), Units.pixelToEMU(pictureHeightPx),
     pictureFileNames[r-1], ClientAnchor.AnchorType.MOVE_AND_RESIZE);
   }
   r++; 
  }

  sheet.setColumnWidth(2, 15*256);
  sheet.setAutoFilter(new CellRangeAddress(0, 3, 0, 2));

  FileOutputStream fos = new FileOutputStream(excelPath);
  workbook.write(fos);
  fos.close();
  workbook.close();

 }
}

结果:

enter image description here

可以进行排序和过滤。