所以我有一个我制作的程序来解析excel数据(使用Gembox)。但是,有时我想下载/提取某些工作表中的嵌入式 PDF 文件。我一直无法找到检测和下载这些对象的方法。任何人都能够指出我如何实现这一目标的正确方向?我知道微软有一个读取 excel 文件的 Office 文档提取器,但它只检测 Word 等 Office 文件。
我没有要求任何人为我做我的工作并写出代码,我只是在这里迷路了,这似乎是一个非常复杂的过程。
所以我有一个我制作的程序来解析excel数据(使用Gembox)。但是,有时我想下载/提取某些工作表中的嵌入式 PDF 文件。我一直无法找到检测和下载这些对象的方法。任何人都能够指出我如何实现这一目标的正确方向?我知道微软有一个读取 excel 文件的 Office 文档提取器,但它只检测 Word 等 Office 文件。
我没有要求任何人为我做我的工作并写出代码,我只是在这里迷路了,这似乎是一个非常复杂的过程。
更新 (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.Packaging
WindowsBase.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();
}
}
}