如何将旧工作表中的图像复制到新工作表中

问题描述 投票:0回答:1

我正在使用 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'文件夹。

你们能帮我解释一下我在这里缺少什么吗?

java apache-poi
1个回答
0
投票

这对我有用。此方法复制位于特定行和列的图像,然后将其粘贴到具有相同工作表名称的不同 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();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.