【问题标题】:Program cannot read xlsx file until it has been saved by Excel程序在 Excel 保存之前无法读取 xlsx 文件
【发布时间】:2014-09-19 17:04:19
【问题描述】:

我们有一个应用程序,它使用 Microsoft Access 数据库引擎从 Excel xlsx 文件中读取数据。 xlsx 文件由第三方软件生成。该应用程序多年来一直运行良好。

生成 xlsx 文件的公司修改了他们的软件,导致 xlsx 文件的格式发生了变化。我们的应用程序无法再读取这些文件。 但是,如果我使用 Excel 手动打开其中一个文件,然后立即单击“保存”,则新文件可以正常工作。

第三方的回复基本上是“既然你可以用Excel打开文件,那就说明它是一个有效的xlsx文件。问题一定出在你自己身上”。他们确实有道理。

我已在https://drive.google.com/file/d/0B6jNYMkptFteTmc4YU9BWU1PRUk/edit?usp=sharing 发布了其中一个 xlsx 文件的示例

这是一个重现问题的简单测试程序(VisualStudio.net 中的控制台应用程序)。

static void Main(string[] args)
{
    String fileSpec = @"C:\Temp\TestData-Original.xlsx";
    String connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileSpec + ";Extended Properties=\"Excel 12.0;HDR=No;IMEX=1\"";

    DataTable dtExcelRecords = null;

    OleDbConnection con = new OleDbConnection(connectionString);
    OleDbCommand cmd = new OleDbCommand();

    cmd.CommandType = System.Data.CommandType.Text;
    cmd.Connection = con;

    OleDbDataAdapter dAdapter = new OleDbDataAdapter(cmd);

    try
    {
        con.Open();       // Throws exception here.

        DataTable dtExcelSheetNames = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

        String sheetName = (dtExcelSheetNames.Rows[0]["Table_Name"].ToString()).Replace("''", "'");
        if (!(String.IsNullOrEmpty(sheetName)))
        {
            cmd.CommandText = "SELECT * FROM [" + sheetName + "]";
            dtExcelRecords = new DataTable();
            dAdapter.SelectCommand = cmd;
            dAdapter.Fill(dtExcelRecords);
        }
        con.Close();
        Console.WriteLine(String.Format("Found {0} records in file {1}", dtExcelRecords.Rows.Count, fileSpec));
    }
    catch (Exception ex)
    {
        Console.WriteLine("Exception: " + ex.Message);
    }
    finally
    {
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }
}

如果您使用示例 Excel 文件运行此程序,它将失败。 如果您在 Excel 中打开示例文件,然后单击“保存”,然后运行程序,它将成功读取文件。

测试程序做了 2 个假设:(1) xlsx 文件位于 C:\Temp\TestData-Original.xlsx 和 (2) Microsoft Access 数据库引擎已安装在您的计算机上。

我对此进行了研究,但没有运气。大多数讨论都围绕更改连接字符串以指定不同版本的 Excel 展开。到目前为止没有任何改变。

注意:我注意到当我使用 Excel 打开文件然后保存时,大小增加了大约 70%。

有什么想法吗?

【问题讨论】:

  • If you run this program with the sample Excel file, it will fail. 怎么会失败?它有例外吗?如果是这样,它是什么?它说什么?如果您在调试器中单步执行代码会发生什么?
  • 第三方能否为您提供所使用的确切文件格式?可以想象,“Excel 文件”有点模糊。 Excel 可以打开纯文本文件,但这很难证明纯文本是有效的 xlsx 文件。如果您在纯文本编辑器中打开前后文件,它们是否有一些指定格式信息的内部 XML?
  • 您是否对文件进行了前后比较?从理论上讲,如果您不在 excel 中执行任何操作并再次将其保存,则文件应该只有非常小的更改(例如更新总编辑时间、最后编辑时间等...计数器)。比较它们,看看发生了什么。
  • @MarcB:实际上,根据文件的生成方式,差异可能相当大。一个简单的示例是,您可以将字符串直接放入 XLSX 文件的单元格中,也可以使用字符串表。当您在 Excel 中打开文件并再次保存时,Excel 很可能会为您提取那些内联字符串并将它们放入字符串表中。
  • 另外注意,.xlsx 文件只是 .zip 文件。您可以将扩展名更改为zip 并解压缩它们。这样做并比较里面的各种(主要是xml)文件可能很有用。

标签: c# excel xls file-format


【解决方案1】:

我使用ClosedXML(OpenXML 的包装器)没有问题。

    string fileSpec = @"C:\Temp\TestData-Original.xlsx";

    var wb = new XLWorkbook(fileSpec);
    var ws = wb.Worksheet("Sheet1");

    MessageBox.Show(ws.RowCount().ToString());

【讨论】:

猜你喜欢
  • 2020-07-07
  • 1970-01-01
  • 2018-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-13
  • 1970-01-01
相关资源
最近更新 更多