我的应用程序已从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数据库引擎可再发行组件。
问题到底是什么?
答案 0 :(得分:2)
关于这一点我会面对这一点,你不太可能得到一个"按下这个按钮来解决你的问题"答案。
您获得的错误是E_FAIL
,这是一个通用的COM错误代码。当软件没有对失败的根本原因进行适当的猜测时,通常由Microsoft软件使用。而猜测一个更具体的风险太大,将他们的客户送入一个兔子洞。这是COM的一般责任,它不直接支持异常,只支持错误代码。因此,丢失的一个主要特征是堆栈跟踪,这个提示可以提供有关检测到错误的特定层的大量信息。
处理它们的唯一真正方法是消除过程。这在哪里可行,代码提前失败。唯一可以做错的是提供错误的连接字符串,提供错误数据或在错误的执行上下文中运行代码。找出常见的错误:
不容易消除的不那么常见的错误:
哪个留下最可能的原因:
也许苦难也是放弃这些提供者的好理由。 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。我运行的服务帐户没有完整的读/写权限。这解决了为什么它不在本地工作,因为一旦我关闭模仿,它就很有效。然后在部署时,我只需要设置我运行的服务帐户的权限。