如何使用Apache POI从xls文件获取带有名称的图片

时间:2014-11-19 07:53:15

标签: java excel apache-poi

使用workbook.getAllPictures()我可以获得picture data的数组,但不幸的是,它只是数据,而且这些对象没有方法可以访问图片名称或任何其他相关信息。

有一个HSSFPicture class可以包含图片的所有细节但是如何从xls中获取这些对象的数组?

更新

找到了问题How can I find a cell, which contain a picture in apache poi,它有一个循环遍历工作表中所有图片的方法。这很有效。

现在我能够尝试HSSFPicture类,我发现getFileName()方法返回的文件名没有扩展名。我可以使用getPictureData().suggestFileExtension()来获取建议的文件扩展名,但我真的需要获得图片在添加到xls文件时的扩展名。有没有办法得到它?

更新2:

使用宏将图片添加到xls中。这是将图像添加到工作表中的宏的一部分。 fname是完整路径,imageName是文件名,两者都包含扩展名。

Set img = Sheets("Receipt images").Pictures.Insert(fname)
img.Left = 10
img.top = top + 10
img.Name = imageName
Set img = Nothing

检查图片是否已存在于Excel文件中的例程。

For Each img In Sheets("Receipt images").Shapes
    If img.Name = imageName Then
        Set foundImage = img
        Exit For
    End If
Next

这表明" image.jpg"与" image.gif"不同,因此img.Name包含扩展名。

2 个答案:

答案 0 :(得分:1)

形状名称不在默认的POI对象中。因此,如果我们需要它们,我们必须处理底层对象。那就是HSSF中的形状主要是EscherAggregate(http://poi.apache.org/apidocs/org/apache/poi/hssf/record/EscherAggregate.html),我们可以从工作表中获得。从它的父类AbstractEscherHolderRecord,我们可以获得包含形状选项的所有EscherOptRecords。在这些选项中还可以找到groupshape.shapenames。

我的例子不是完整的解决方案。它仅用于显示可以使用哪些对象来实现此目的。

示例:

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;

import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;

import org.apache.poi.hssf.record.*;
import org.apache.poi.ddf.*;

import java.util.List;
import java.util.ArrayList;

class ShapeNameTestHSSF {

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

   InputStream inp = new FileInputStream("workbook1.xls");
   Workbook wb = WorkbookFactory.create(inp);

   Sheet sheet = wb.getSheetAt(0);

   EscherAggregate escherAggregate = ((HSSFSheet)sheet).getDrawingEscherAggregate();

   EscherContainerRecord escherContainer = escherAggregate.getEscherContainer().getChildContainers().get(0); 
   //throws java.lang.NullPointerException if no Container present

   List<EscherRecord> escherOptRecords = new ArrayList<EscherRecord>();

   escherContainer.getRecordsById(EscherOptRecord.RECORD_ID, escherOptRecords);

   for (EscherRecord escherOptRecord : escherOptRecords) {
    for (EscherProperty escherProperty : ((EscherOptRecord)escherOptRecord).getEscherProperties()) {
     System.out.println(escherProperty.getName());
     if (escherProperty.isComplex()) {
      System.out.println(new String(((EscherComplexProperty)escherProperty).getComplexData(), "UTF-16LE"));
     } else {
      if (escherProperty.isBlipId()) System.out.print("BlipId = ImageId = ");
      System.out.println(((EscherSimpleProperty)escherProperty).getPropertyValue());
     }
     System.out.println("=============================");
    }
    System.out.println(":::::::::::::::::::::::::::::");
   }


   FileOutputStream fileOut = new FileOutputStream("workbook1.xls");
   wb.write(fileOut);
   fileOut.flush();
   fileOut.close();

  } catch (InvalidFormatException ifex) {
  } catch (FileNotFoundException fnfex) {
  } catch (IOException ioex) {
  }
 }
}

再次:这不是一个随时可用的解决方案。由于EscherRecords的复杂性,此处无法提供随时可用的解决方案。也许要为图像形状及其相关的EscherOptRecords获取正确的EscherRecords,您可以递归遍历EscherAggregate中的所有EscherRecords,检查它们是否为ContainerRecords,如果是,则循环遍历其子项等等。

答案 1 :(得分:1)

从这里开始:

http://poi.apache.org/spreadsheet/quick-guide.html#Images

本教程可以帮助您使用Apache POI从xls电子表格中提取图像信息