首页 文章

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

提问于
浏览
1

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

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

更新:

找到SO问题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 回答

  • 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

    从这里开始:

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

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

相关问题