GetOleDbSchemaTable - 可以使用 .xlsx 获取工作表名称,但不能使用 Microsoft.ACE.OLEDB.12.0 获取工作表名称

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

我正在将全新服务器上的 BizTalk 2016 更新到 BizTalk 2020,并安装了 Access OleDB 提供程序。它似乎适用于 .xlsx 文件,但对于 .xls 文件,它无法动态查找工作表名称。实际例程位于从 BizTalk 调用的 C# 类库中,但为了帮助调试,我创建了以下测试方法,以便我可以在 BizTalk 之外的简单控制台应用程序中对其进行测试。我通过了 conn.open() 和库未注册的问题。

我认为 .xls 根本没有加载。如果我使用硬编码的工作表名称,它会给出此错误:“Microsoft Access 数据库引擎找不到对象‘Sheet1$’”,即使在 Excel 中,这就是工作表名称(添加了 $ 符号)。

现有代码适用于我们现有的系统,并使用我在下面显示的 connectionStringOld。如果我在 .xls 文件上尝试该版本,它会出现“未注册”错误。

我是否必须为 .xls 文件使用旧版本的提供程序?

static void testAccessOleDBAdapterForExcel()
{
    string methodPrefix = "method: testAccessOleDBAdapterForExcel  - ";

    string excelFilename = null;
    string worksheetName = null;

    int fileNumber = 1;  //switch between two files and corresponding sheet name 

    if (fileNumber == 1)
    {
        excelFilename = @"\\Share1\SampleExcelFiles\PublishPowerMeterData_-15_05012023060600_2023-05-01T06-04-02.xls";
        worksheetName = "Sheet1";
    }
    else
    {
        excelFilename = @"\\Share1\SampleExcelFiles\PublishForwardPrice_powerfolio_extract_05_01_2023_08_00_2023-05-01T14-56-04.xlsx"; 
        worksheetName = "South";
    }

    // We have to add  on the end of the actual Worksheet 
    worksheetName = worksheetName + "$"; 


    // original code on BT20106 used ACE.OLEDB.10.0 
    //var connectionStringOld = @"Provider=Microsoft.ACE.OLEDB.10.0;Data Source=" + excelFilename + ";Extended Properties=\"Excel 10.0;HDR=YES\"";
    var connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excelFilename + ";Extended Properties=\"Excel 12.0;HDR=YES\"";

    Console.WriteLine(methodPrefix + "FileName=" + excelFilename);
    Console.WriteLine(methodPrefix + "attempt spreadsheet read with Access OleDB Adapter");
    using (OleDbConnection conn = new OleDbConnection(connectionString))
    {
        conn.Open();
        Console.WriteLine(methodPrefix + "Conn.Open() succeeded");

        var schemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
        // The following if statement throws the ArgumentException with the .xls 
        if (schemaTable.Rows.Count < 1) throw new ArgumentException("The worksheet number provided cannot be found in the spreadsheet");
        string dynWorksheet = schemaTable.Rows[0]["table_name"].ToString().Replace("'", "");

        Console.WriteLine(methodPrefix + "dynWorksheet = " + dynWorksheet);

        OleDbDataAdapter objDA = new System.Data.OleDb.OleDbDataAdapter
        ("select * from [" + dynWorksheet + "]", conn);
        DataSet excelDataSet = new DataSet();
        objDA.Fill(excelDataSet);
        Console.WriteLine("method: testAccessOleDBAdapterForExcel  - was able to fill dataset object"); 
    }
    
}

调试中:

使用Visual Studio 2019(兼容BizTalk 2020), .NET Framework 4.7.2,以及这些构建选项:

尝试“Excel 8.0;HDR=Yes”时遇到同样的问题:https://www.connectionstrings.com/ace-oledb-12-0/excel-97-2003-xls-files-with-ace- oledb-120/

c# excel ms-access-2010 oledb oledbdataadapter
1个回答
0
投票

事实证明,以.xls 结尾的文件不是正确的文件。它没有标题,也没有数据,还有一个奇怪的工作表名称。当我使用正确的 .xls 文件进行测试时,它运行良好。

我把error改的更有意义,出自:

   if (schemaTable.Rows.Count < 1) throw new ArgumentException("The worksheet number provided cannot be found in the spreadsheet");

对此:

 if (schemaTable.Rows.Count < 1) throw new ArgumentException(
                        "GetOleDbSchemaTable returned schemaTable.Rows.Count<0, so could not dynamically find the excel sheetname.  " + 
                        "Potentially invalid Excel worksheet, or missing data and/or headers.");

此外,由于在 BizTalk 下运行,它可能会出现奇怪的错误并且无法捕获 SEHException(在托管代码中),因此我也加强了异常消息:

    catch (Exception ex)
    {
        // We had this issue when running in 32-bit instead of 64-bit on BizTalk 2020 install/testing 

        string messageIdentifier = "SystemException in MapExcel_To_Xml_v0100: ";
        string errorMessage = messageIdentifier + " ex.Message=" + ex.Message;

        string specialError = "External component has thrown an exception.";
        if (ex.Message.Contains(specialError))
        {
            errorMessage = messageIdentifier + "This error might be an OLDEDB Conn.Open SEHException which .NET cannot catch correctly, " +
                " and might be related to running in the 64-bit vs 32-bit mode.  " + 
                " ConnectionString=" + connectionString + 
                " ex.errorMessage=" + ex.Message; 
        }

        System.Diagnostics.EventLog.WriteEntry(strClassName + "." + strMethodName, errorMessage, System.Diagnostics.EventLogEntryType.Error);

        throw ex;
    }
© www.soinside.com 2019 - 2024. All rights reserved.