在单元格中插入图像会导致打开文件时出错

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

我正在使用 OpenXml(版本 3.0.1)在单元格中插入图像。虽然代码运行时没有任何错误,但当我导出 Excel 文件并打开它时,我收到一条错误消息,并且图像没有出现在预期的单元格 (A2) 中。

Excel error message

我提到了这个 msdn-code-gallery 但该代码似乎不起作用,或者可能在最新版本的 OpenXml 中已过时。

这是我的代码

using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
using A = DocumentFormat.OpenXml.Drawing;

public byte[] AddImageToExcel(SheetExport sheetExport)
{
    using var memoryStream = new MemoryStream();
    var spreadSheetDocument = SpreadsheetDocument.Create(memoryStream, SpreadsheetDocumentType.Workbook);

    var workbookPart = spreadSheetDocument.AddWorkbookPart();
    workbookPart.Workbook = new Workbook();

    // Add a WorksheetPart to the WorkbookPart.
    WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
    worksheetPart.Worksheet = new Worksheet(new SheetData());

    Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());

    var sheetToAppend = new Sheet()
    { Name = sheetExport.SheetName, SheetId = 1, Id = workbookPart.GetIdOfPart(worksheetPart) };
    sheets.Append(sheetToAppend);

    // Adding image to the worksheet
    InsertImageInCell(worksheetPart);

    workbookPart.Workbook.Save();
    spreadSheetDocument.Dispose();

    return memoryStream.ToArray();

}

private (long Width, long Height) GetImageExtents(string imagePath)
{
    using System.Drawing.Image image = System.Drawing.Image.FromFile(imagePath);
    long width = (long)((image.Width / image.HorizontalResolution) * 914400L);
    long height = (long)((image.Height / image.VerticalResolution) * 914400L);

    return (width, height);
}

private void InsertImageInCell(WorksheetPart worksheetPart)
{
    DrawingsPart drawingsPart;
    if (worksheetPart.DrawingsPart == null)
    {
        drawingsPart = worksheetPart.AddNewPart<DrawingsPart>();
        worksheetPart.Worksheet.Append(new Drawing { Id = worksheetPart.GetIdOfPart(drawingsPart) });
        worksheetPart.Worksheet.Save();
    }
    else
    {
        drawingsPart = worksheetPart.DrawingsPart;
    }

    var imagePath = Path.Combine(Directory.GetCurrentDirectory(), "Resources", "Banner.png");
    var imageExtents = GetImageExtents(imagePath);

    // Add the image
    ImagePart imagePart = drawingsPart.AddImagePart(ImagePartType.Png);
    using (var imageFileStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
    {
        imagePart.FeedData(imageFileStream);
    }

    // Create the drawing elements
    var nvdp = new PIC.NonVisualDrawingProperties()
    {
        Id = (UInt32Value)1025U,
        Name = "Picture 1"
    };

    var nvpd = new PIC.NonVisualPictureDrawingProperties(new A.PictureLocks() { NoChangeAspect = true });

    var nvpp = new PIC.NonVisualPictureProperties()
    {
        NonVisualDrawingProperties = nvdp,
        NonVisualPictureDrawingProperties = nvpd
    };

    var blip = new A.Blip()
    {
        Embed = drawingsPart.GetIdOfPart(imagePart),
        CompressionState = A.BlipCompressionValues.Print
    };

    var blipFill = new PIC.BlipFill()
    {
        Blip = blip,
        SourceRectangle = new A.SourceRectangle()
    };

    blipFill.Append(new A.Stretch() { FillRectangle = new A.FillRectangle() });

    var sp = new PIC.ShapeProperties()
    {
        BlackWhiteMode = A.BlackWhiteModeValues.Auto
    };

    var transform2D = new A.Transform2D();
    var offset = new A.Offset() { X = 0L, Y = 0L };
    var extents = new A.Extents() { Cx = imageExtents.Width, Cy = imageExtents.Height };

    transform2D.Append(offset);
    transform2D.Append(extents);

    sp.Append(transform2D);
    sp.Append(new A.PresetGeometry(new A.AdjustValueList())
    {
        Preset = A.ShapeTypeValues.Rectangle
    });

    var picture = new PIC.Picture()
    {
        NonVisualPictureProperties = nvpp,
        BlipFill = blipFill,
        ShapeProperties = sp
    };

    var position = new Position() { X = 0L, Y = 0L };
    var extent = new Extent() { Cx = imageExtents.Width, Cy = imageExtents.Height };

    var absoluteAnchor = new AbsoluteAnchor()
    {
        Position = position,
        Extent = extent
    };

    absoluteAnchor.Append(picture);
    absoluteAnchor.Append(new ClientData());

    WorksheetDrawing worksheetDrawing = drawingsPart.WorksheetDrawing;
    if (worksheetDrawing == null)
    {
        worksheetDrawing = new WorksheetDrawing();
        drawingsPart.WorksheetDrawing = worksheetDrawing;
    }

    worksheetDrawing.Append(absoluteAnchor);
    drawingsPart.WorksheetDrawing.Save();

}

drawingPart.WorkSheetDrawing

的内部xml
<xdr:absoluteAnchor
    xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing">
    <xdr:pos x="0" y="0" />
    <xdr:ext cx="1781423" cy="628737" />
    <pic:pic
        xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
        <pic:nvPicPr>
            <pic:cNvPr id="1025" name="Picture 1" />
            <pic:cNvPicPr>
                <a:picLocks noChangeAspect="1"
                    xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" />
                </pic:cNvPicPr>
            </pic:nvPicPr>
            <pic:blipFill>
                <a:blip r:embed="R3a1e7131d49045f5" cstate="print"
                    xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
                    xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" />
                    <a:srcRect
                        xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" />
                        <a:stretch
                            xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
                            <a:fillRect />
                        </a:stretch>
                    </pic:blipFill>
                    <pic:spPr bwMode="auto">
                        <a:xfrm
                            xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
                            <a:off x="0" y="0" />
                            <a:ext cx="1781423" cy="628737" />
                        </a:xfrm>
                        <a:prstGeom prst="rect"
                            xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
                            <a:avLst />
                        </a:prstGeom>
                    </pic:spPr>
                </pic:pic>
                <xdr:clientData />
            </xdr:absoluteAnchor>

我无法使用任何其他第三方,如 EPPlus 或 ClosedXml,它必须通过 OpenXml 完成。

c# openxml openxml-sdk
1个回答
0
投票

您使用

using PIC = DocumentFormat.OpenXml.Drawing.Pictures;

我认为这是错误的命名空间。

例如:

var nvdp = new PIC.NonVisualDrawingProperties()
一定是
var nvpp = new DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualPictureProperties()

检查您在哪里使用 PIC 并使用

DocumentFormat.OpenXml.Drawing.Spreadsheet

© www.soinside.com 2019 - 2024. All rights reserved.