c# - 无法在 C# 中使用 Gembox 加载 .xls 文件

标签 c# gembox-spreadsheet

我想使用 C# 加载 .xls 文件(类型:97-2003 电子表格)。 我正在使用 Gembox 库。

当我使用下面的命令时,我遇到了“文件包含损坏的数据。”错误。

ExcelFile ef = ExcelFile.Load(filepath, XlsxLoadOptions.XlsxDefault);

当我删除 XlsxLoadOptions 参数时,出现“读取错误:文件不是有效的 OLE2 复合文件。

我是 C# 的新手,无法调试问题的根本原因。 请帮忙!

最佳答案

更新 (2020-03-28)

在较新版本的 GemBox.Spreadsheet 中,ExcelFile.Load(String)如果是“.xls”文件,将检查文件的签名。
换句话说,不再需要下面的 GetLoadOptions 方法。

此外,还有一个新的重载方法,ExcelFile.Load(Stream) .
这将始终在提供的流中检查文件的签名。

原创

这个问题在评论中得到了回答。不幸的是,它在那里不是很明显,所以这里是答案和一些关于它的额外细节。

GemBox.Spreadsheet 提供了几个 Load overload methods .使用以下内容时:

ExcelFile ef = ExcelFile.Load("C://temp//book.xls");

结果如下:

ExcelFile ef = ExcelFile.Load("C://temp//book.xls", LoadOptions.XlsDefault);

这与以下相同:

ExcelFile ef = ExcelFile.Load("C://temp//book.xls", new XlsLoadOptions());

加载选项指定如何读取输入文件,以及在使用 ExcelFile.Load(String) 方法时,选项将基于文件的扩展名。

在这种情况下,文件的扩展名为“.xls”,但它不是二进制 XLS 格式 (BIFF8),而是 HTML 格式。这是一个有点常用的技巧,您可以拥有 HTML、CSV,甚至是带有“.xls”扩展名的 XLSX 文件,MS Excel 都可以打开它。它会检测正确的文件格式,并会提示用户类似以下消息:

File format and extension of 'book.xls' don't match. The file could be corrupted or unsafe. Unless you trust its source, don't open it. Do you want to open it anyway?

请注意,此技巧仅适用于“.xls”扩展名,不适用于“.xlsx”等扩展名。然而,我们可以使用类似下面的方法来检测正确的文件格式:

private static LoadOptions GetLoadOptions(string path)
{
    string extension = Path.GetExtension(path).ToUpperInvariant();
    switch (extension)
    {
        case ".XLSX":
        case ".XLSM":
        case ".XLTX":
        case ".XLTM":
            return LoadOptions.XlsxDefault;
        case ".XLS":
        case ".XLT":
            return GetLoadOptions(path, null);
        case ".ODS":
        case ".OTS":
            return LoadOptions.OdsDefault;
        case ".TAB":
        case ".TSV":
            return new CsvLoadOptions(CsvType.TabDelimited);
        case ".CSV":
            return LoadOptions.CsvDefault;
        default:
            return null;
    }
}

private static LoadOptions GetLoadOptions(string xlsPath, LoadOptions defaultOptions)
{
    byte[] signature = new byte[8];
    using (var stream = File.OpenRead(xlsPath))
        stream.Read(signature, 0, 8);

    byte[] xlsSignature = new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
    if (signature.SequenceEqual(xlsSignature))
        return LoadOptions.XlsDefault;

    byte[] xlsxSignature = new byte[] { 0x50, 0x4B, 0x03, 0x04 };
    if (signature.Take(4).SequenceEqual(xlsxSignature))
        return LoadOptions.XlsxDefault;

    string firstLine = File.ReadLines(xlsPath)
        .First(line => !string.IsNullOrWhiteSpace(line)).TrimStart().ToUpperInvariant();
    if (firstLine.StartsWith("<!DOCTYPE") ||
        firstLine.StartsWith("<HTML") ||
        firstLine.StartsWith("<BODY"))
        return LoadOptions.HtmlDefault;

    return defaultOptions;
}

这里还有一个关于如何使用它的小演示示例:

string filepath = "C://temp//book.xls";
LoadOptions options = GetLoadOptions(filepath);

if (options == null)
    throw new FileFormatException();

ExcelFile ef = ExcelFile.Load(filepath, options);
// ...

关于c# - 无法在 C# 中使用 Gembox 加载 .xls 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47406378/

相关文章:

c# - 如何从 Web API 调用中获取响应

c# - 调用嵌套的 RepeaterItem

c# - 如何使用 openxml.wordprocessing 设置 "table direction"

c# - SignedXml 使用 SHA256 计算签名

c# - 如果是 .NET Framework 的 .NET 库,如何在 OSX 中使用 GemBox.Spreadsheet

c# - 将特殊字符从 MS-Word 或 Open Office writer 转换为记事本

c# - Gembox - 获取 ExcelCell 的地址

c# - GemBox.Spreadsheet 最后使用的行

c# - 如何从全局过滤器的 NHibernate session 中获取更新的对象

c# - 使用 Gembox.Spreadsheet 提取到数据表的无效数据值