0

所以我有一个我制作的程序来解析excel数据(使用Gembox)。但是,有时我想下载/提取某些工作表中的嵌入式 PDF 文件。我一直无法找到检测和下载这些对象的方法。任何人都能够指出我如何实现这一目标的正确方向?我知道微软有一个读取 excel 文件的 Office 文档提取器,但它只检测 Word 等 Office 文件。

我没有要求任何人为我做我的工作并写出代码,我只是在这里迷路了,这似乎是一个非常复杂的过程。

4

1 回答 1

1

更新 (2020-03-28)

较新版本的 GemBox.Spreadsheet 支持ExcelWorksheet.EmbeddedObjects.

因此,您现在可以使用以下内容:

var workbook = ExcelFile.Load("input.xlsx");
var worksheet = workbook.Worksheets[0];

var embeddedObjects = worksheet.EmbeddedObjects;

for (int index = 0; index < embeddedObjects.Count; index++)
{
    ExcelEmbeddedObject embeddedObject = embeddedObjects[index];
    if (embeddedObject.ContentType != "application/vnd.openxmlformats-officedocument.oleObject")
        continue;

    byte[] embeddedBytes;
    using (var memoryStream = new MemoryStream())
    {
        embeddedObject.Data.CopyTo(memoryStream);
        embeddedBytes = memoryStream.ToArray();
    }

    string embeddedContent = Encoding.ASCII.GetString(embeddedBytes);
    int pdfHeaderIndex = embeddedContent.IndexOf("%PDF");
    if (pdfHeaderIndex < 0)
        continue;

    byte[] pdfBytes = new byte[embeddedBytes.Length - pdfHeaderIndex];
    Array.Copy(embeddedBytes, pdfHeaderIndex, pdfBytes, 0, pdfBytes.Length);

    File.WriteAllBytes($"embedded-pdf-{index}.pdf", pdfBytes);
}

原来的

GemBox.Spreadsheet 目前不支持此功能,但您可以使用System.IO.PackagingWindowsBase.dll 程序集中的命名空间来满足您的要求。

尝试以下代码示例:

using System;
using System.IO;
using System.IO.Packaging;
using System.Text;

static class PdfExtractor
{
    public static void ExtractPdf(string packagePath, string destinationDirectory)
    {
        using (var package = Package.Open(packagePath))
        {
            int i = 1;
            foreach (var part in package.GetParts())
                if (part.ContentType == "application/vnd.openxmlformats-officedocument.oleObject")
                {
                    // PDF data is embedded into OLE Object package part.

                    var pdfContent = GetPdfContent(part.GetStream());
                    if (pdfContent != null)
                        File.WriteAllBytes(Path.Combine(destinationDirectory, "EmbeddedPdf" + (i++) + ".pdf"), pdfContent);
                }
        }
    }

    private static byte[] GetPdfContent(Stream stream)
    {
        // Every PDF file/data starts with '%PDF' and ends with '%%EOF'.
        const string pdfStart = "%PDF", pdfEnd = "%%EOF";

        byte[] bytes = ConvertStreamToArray(stream);

        string text = Encoding.ASCII.GetString(bytes);

        int startIndex = text.IndexOf(pdfStart, StringComparison.Ordinal);
        if (startIndex < 0)
            return null;

        int endIndex = text.LastIndexOf(pdfEnd, StringComparison.Ordinal);
        if (endIndex < 0)
            return null;

        var pdfBytes = new byte[endIndex + pdfEnd.Length - startIndex];
        Array.Copy(bytes, startIndex, pdfBytes, 0, pdfBytes.Length);

        return pdfBytes;
    }

    private static byte[] ConvertStreamToArray(Stream stream)
    {
        var buffer = new byte[16 * 1024];
        using (var ms = new MemoryStream())
        {
            int read;
            while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
                ms.Write(buffer, 0, read);

            return ms.ToArray();
        }
    }
}
于 2014-03-17T10:43:25.623 回答