我正在使用 Apache POI API 将具有多个工作表的 Excel 文件拆分为多个 Excel 文件,每个文件仅包含一个工作表。 然而,当我尝试将图像从旧工作表移动到新工作表时,似乎没有任何影响;当我打开 Excel 文件时,图像应该已显示,但我看到的只是空白图像占位符,如下图所示。
这是我的代码(将图像从旧工作表复制到新工作表中):
private void copyImage(XSSFSheet srcSheet_, XSSFSheet dstSheet_) {
XSSFWorkbook srcWorkbook_ = srcSheet_.getWorkbook();
XSSFWorkbook dstWorkbook_ = dstSheet_.getWorkbook();
List<POIXMLDocumentPart> pdp = srcWorkbook_.getRelations();
List<POIXMLDocumentPart.RelationPart> rels = srcSheet_.getRelationParts();
XSSFDrawing dg = null;
for (POIXMLDocumentPart.RelationPart rp : rels) {
POIXMLDocumentPart r = rp.getDocumentPart();
if (r instanceof XSSFDrawing) {
dg = (XSSFDrawing) r;
continue;
}
addRelation(rp, dstSheet_);
}
try {
for (PackageRelationship pr : srcSheet_.getPackagePart().getRelationships()) {
if (pr.getTargetMode() == TargetMode.EXTERNAL) {
dstSheet_.getPackagePart().addExternalRelationship(pr.getTargetURI().toASCIIString(), pr.getRelationshipType(), pr.getId());
}
}
} catch (org.apache.poi.openxml4j.exceptions.InvalidFormatException e) {
throw new POIXMLException("Failed to clone sheet", e);
}
CTWorksheet ct = dstSheet_.getCTWorksheet();
if (ct.isSetLegacyDrawing()) {
log.atWarn().log("Cloning sheets with comments is not yet supported.");
ct.unsetLegacyDrawing();
}
if (ct.isSetPageSetup()) {
log.atWarn().log("Cloning sheets with page setup is not yet supported.");
ct.unsetPageSetup();
}
dstSheet_.setSelected(false);
if (dg != null) {
if (ct.isSetDrawing()) {
ct.unsetDrawing();
}
XSSFDrawing clonedDg = dstSheet_.createDrawingPatriarch();
// copy drawing contents
clonedDg.getCTDrawing().set(dg.getCTDrawing().copy());
XSSFDrawing drawingPatriarch = srcSheet_.getDrawingPatriarch();
if (drawingPatriarch != null) {
List<POIXMLDocumentPart.RelationPart> srcRels = drawingPatriarch.getRelationParts();
for (POIXMLDocumentPart.RelationPart rp : srcRels) {
POIXMLDocumentPart r = rp.getDocumentPart();
int chartNumber = r.getPackagePart().getPackage().getPartsByContentType(XSSFRelation.CHART.getContentType()).size() + 1;
int imageNumber = r.getPackagePart().getPackage().getPartsByContentType(XSSFRelation.IMAGE_PNG.getContentType()).size() + 1;
if (r instanceof XSSFChart) {
POIXMLDocumentPart.RelationPart chartPart = clonedDg.createRelationship(XSSFRelation.CHART, dstWorkbook_.getXssfFactory(), chartNumber, false);
XSSFChart chart = chartPart.getDocumentPart();
chart.importContent((XSSFChart) r);
chart.replaceReferences(dstSheet_);
}
else if (r instanceof XSSFPictureData){
XSSFPictureData img = r.createRelationship(XSSFRelation.IMAGE_PNG, dstWorkbook_.getXssfFactory(), imageNumber,true).getDocumentPart();
try (OutputStream out = img.getPackagePart().getOutputStream()){
out.write(((XSSFPictureData) r).getData());
}catch (IOException e){
throw new POIXMLException(e);
}
}
else {
addRelation(rp, clonedDg);
}
}
}
}
}
我还使用了一个技巧:将扩展名从“.xlsx”重命名为“.zip”并提取它,然后将原始文件(重命名和提取)与新的 Excel 文件进行比较。我发现在新的excel文件中,没有创建'media'文件夹和'drawings/_rel'文件夹。
你们能帮我解释一下我在这里缺少什么吗?
这对我有用。此方法复制位于特定行和列的图像,然后将其粘贴到具有相同工作表名称的不同 Excel 文件中。当然可以根据您的具体需求进行修改。
public void copyCellPicturesFromXLSX1_toXLSX2(String srcFilePath, String dstFilePath, String sheetName, int srcRowNum, int colNum, int dstRowNum)
{
try {
Workbook srcWB = WorkbookFactory.create(new FileInputStream(srcFilePath));
Workbook dstWB = WorkbookFactory.create(new FileInputStream(dstFilePath));
Sheet srcSH = srcWB.getSheet(sheetName);
Sheet dstSH = dstWB.getSheet(sheetName);
Drawing srcdraw = srcSH.createDrawingPatriarch();
Drawing dstdraw = dstSH.createDrawingPatriarch();
List<Picture> pics = new ArrayList<Picture>();
int pictureIdx, row, col;
if (srcdraw instanceof HSSFPatriarch)
{
HSSFPatriarch hp = (HSSFPatriarch)srcdraw;
for (HSSFShape hs : hp.getChildren())
{
if (hs instanceof Picture)
{
System.out.println("Picture found in HSSF");
pics.add((Picture)hs);
}
}
}
else
{
XSSFDrawing xdraw = (XSSFDrawing)srcdraw;
for (XSSFShape xs : xdraw.getShapes())
{
if (xs instanceof Picture)
{
System.out.println("Picture found in XSSF");
pics.add((Picture)xs);
XSSFClientAnchor srcanchor = (XSSFClientAnchor) xs.getAnchor();
col = srcanchor.getCol1();
row = srcanchor.getRow1();
if(row==srcRowNum && col==colNum)
{
System.out.println("Picture to get from XSSF");
System.out.println("Row:"+srcRowNum);
System.out.println("Col:"+col);
byte [] bap = ((Picture) xs).getPictureData().getData();
CreationHelper helper = dstWB.getCreationHelper();
ClientAnchor dstanchor = helper.createClientAnchor();
dstanchor.setCol1(col);
dstanchor.setRow1(dstRowNum);
pictureIdx = dstWB.addPicture(bap, Workbook.PICTURE_TYPE_PNG);
Picture pict = dstdraw.createPicture(dstanchor, pictureIdx);
pict.resize(); //now picture is anchored and sized to it's original size
}
}
}
}
dstWB.write(new FileOutputStream(new File(dstFilePath))); //Finally write the changes to the workbook
srcWB.close();
dstWB.close();
} catch (EncryptedDocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}