尝试通过Microsoft.ACE.OLEDB驱动程序读取xlsx信息时出现未指定的错误

时间:2015-03-26 14:00:49

标签: visual-studio-2013 oledb xlsx

我的应用程序已从Visual Studio 2010(在Windows Server 2003上运行)升级到Visual Studio 2013(现在在Windows Server 2008上运行)。该应用程序的一个方面允许用户将xlsx工作表上传到文件夹,并且脚本验证其内容。

我有这个方法:

Private Function GetValuesFromExcel(ByVal strFileIn As String) As DataSet

    Dim ds As DataSet = New DataSet
    Dim strConn As String = ""
    Try

        If strFileIn.ToLower().EndsWith(".xlsx") Then
            'This one is good for files that are saved with Excel
            strConn = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source='" + strFileIn + "'; Extended Properties=Excel 12.0 Xml;"

        Else
            strConn = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source='" + strFileIn + "'; Extended Properties=Excel 8.0;"
        End If

        Dim conn = New OleDb.OleDbConnection(strConn)

        conn.Open()
        Dim dtExcelTables As DataTable = conn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, New Object() {Nothing, Nothing, Nothing, "TABLE"})

        Dim strExcel As String = "select * from [" + dtExcelTables.Rows(0)("TABLE_NAME").ToString() + "]"

        Dim myCommand = New OleDb.OleDbDataAdapter(strExcel, strConn)
        myCommand.TableMappings.Add("Table", "table1")
        'myCommand.Fill(ds, "table1")
        myCommand.Fill(ds)
        conn.Close()

    Catch ex As Exception
        DBUtils.WriteToLog("Error", "GetValuesFromExcel", ex.Message, Security.GetCurrentUser())
        Throw ex
    End Try

    Return ds

End Function

conn.Open()上,它会抛出错误。具体来说,是“未指定错误”中最优秀的错误。非常有帮助。

我们正在使用Office 2007,并且已经检查以确保确实安装了32位Access数据库引擎可再发行组件。

问题到底是什么?

3 个答案:

答案 0 :(得分:2)

关于这一点我会面对这一点,你不太可能得到一个"按下这个按钮来解决你的问题"答案。

您获得的错误是E_FAIL,这是一个通用的COM错误代码。当软件没有对失败的根本原因进行适当的猜测时,通常由Microsoft软件使用。而猜测一个更具体的风险太大,将他们的客户送入一个兔子洞。这是COM的一般责任,它不直接支持异常,只支持错误代码。因此,丢失的一个主要特征是堆栈跟踪,这个提示可以提供有关检测到错误的特定层的大量信息。

处理它们的唯一真正方法是消除过程。这在哪里可行,代码提前失败。唯一可以做错的是提供错误的连接字符串,提供错误数据或在错误的执行上下文中运行代码。找出常见的错误:

  • 错误的连接字符串语法。不是你的问题。
  • 文件的路径无效。不是你的问题,产生了一个好消息
  • 文件实际上不是Excel文件。不是你的问题,产生了一个好消息
  • 尝试在64位进程中运行它。不是你的问题,好消息。

不容易消除的不那么常见的错误:

  • 程序作为服务运行,其帐户具有可访问性问题。通过使用一个小型控制台模式应用程序进行测试来消除它。
  • 该文件是.xlsx文件,但它已被巧妙地破坏。通过使用一组其他.xlsx文件进行测试来消除它。

哪个留下最可能的原因:

  • 未正确安装OleDb提供程序。经典也是Microsoft代码放弃像E_FAIL这样的通用错误的常见原因。当然很难诊断,你可能通过使用SysInternals'来到达某个地方。进程监视并将良好的跟踪与坏跟踪进行比较。很高兴发现丢失的文件或注册表项。请记住,在安装Office之后安装32位Access数据库引擎可再发行的并不是一个好主意,它只能用于没有Office可用的计算机上。你必须至少旋转一次重装轮子。

也许苦难也是放弃这些提供者的好理由。 EPPlus library获得了相当不错的评价,在服务器上也可以很好地扩展。

答案 1 :(得分:1)

我要提出第二个汉斯可能放弃这些提供商并寻找替代方案的想法。

我最近遇到了类似的问题。我开发了一种在我的机器上运行良好的解决方案,但由于没有安装必需的驱动程序,所以没有在其他机器上运行。

我的情况是Winforms应用程序将安装在客户端计算机上,我无法控制安装了哪些外部提供程序(ACE,JET等)。我们也不知道他们安装了哪些版本的Office。要么我们提供一个复杂的解决方案,能够使用任何安装的驱动程序......或寻找替代品。

我们选择了后者,然后选择了Excel Data Reader。大约30分钟后,该解决方案现在无需依赖其部署的机器配置即可运行。

我的代码需要简单地将Excel文件(从SSRS报告生成)中的数据读入内存DataTable中,以进行一些数据比较。我们最终得到的方法显示了实现的简单程度;

        /// <summary>
        /// Read data from MS Excel saved as an export from their SSRS reports.
        /// This method uses ExcelDataReader <link>https://github.com/ExcelDataReader/ExcelDataReader</link>
        /// to avoid dependencies on OleDb Jet or ACE drivers. Given we can't control what is installed on 
        /// client machines, we can't assume they'll have the correct drivers installed, and therefore we'll
        /// make use of ExcelDataReader. 
        /// </summary>
        /// <param name="filename">Filename to the path of the Excel (xls or xlsx) file.</param>
        /// <returns>DataTable containing the required data or null if no data is found.</returns>
        private DataTable ReadDataFromUsingExcelReader(string filename)
        {
            DataTable returnval = null;
            DataSet result = null;

            using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read))
            {
                if (filename.EndsWith("xls", StringComparison.OrdinalIgnoreCase))
                {
                    using (IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream))
                    {
                        result = excelReader.AsDataSet();
                    }
                }
                else if (filename.EndsWith("xlsx", StringComparison.OrdinalIgnoreCase))
                {
                    using (IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream))
                    {
                        result = excelReader.AsDataSet();
                    }
                }
            }

            returnval = result != null && result.Tables[0] != null ? result.Tables[0].Copy() : null;

            return returnval;
        } 

答案 2 :(得分:0)

好的,所以我想出了问题,因为它与我的情况有关......我坚持使用ACE.OLEDB驱动程序,因为我知道我可以让它们在这种情况下工作。而且,我认为这是一个愚蠢和小的东西。它是。

xlsx工作表被写入名为“admin-&gt; excel_uploads”的文件夹中。事实证明我在配置文件中将身份模拟设置为true。我运行的服务帐户没有完整的读/写权限。这解决了为什么它不在本地工作,因为一旦我关闭模仿,它就很有效。然后在部署时,我只需要设置我运行的服务帐户的权限。