3

这是我的情况。我正在设计一个程序,它从远程网络驱动器获取 Excel 文件(可能是 csv、xls 或 xlsx 格式),处理数据,然后输出并存储该过程的结果。该程序提供了一个文件名列表框,这些文件名使用此处接受的答案中详述的方法从远程网络驱动器文件夹中获取。一旦用户从列表框中选择了一个文件名,我希望程序找到该文件并从中获取信息以进行数据处理。我曾尝试在线程安全上下文中使用方法从 Excel 文件中读取数据,但该方法失败而没有给出任何类型的错误。它似乎没有终止。我会以错误的方式解决这个问题吗?

编辑 - (最后说明:我已取出 OleDbDataAdapter 并将其替换为 EPPlus 处理。)

我能够从代码中清除敏感数据,所以这里是:

protected void GetFile(object principalObj)
    {
        if (principalObj == null)
        {
            throw new ArgumentNullException("principalObj");
        }

        IPrincipal principal = (IPrincipal)principalObj;
        Thread.CurrentPrincipal = principal;
        WindowsIdentity identity = principal.Identity as WindowsIdentity;
        WindowsImpersonationContext impersonationContext = null;
        if (identity != null)
        {
            impersonationContext = identity.Impersonate();
        }
        try
        {
            string fileName = string.Format("{0}\\" + Files.SelectedValue, @"RemoteDirectoryHere");
            string connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.14.0; data source={0}; Extended Properties=Excel 14.0;", fileName);

            OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM Sheet1", connectionString);
            DataSet ds = new DataSet();

            adapter.Fill(ds, "Sheet1");

            dataTable = ds.Tables["Sheet1"];
        }
        finally
        {
            if (impersonationContext != null)
            {
                impersonationContext.Undo();
            }
        }
    }

附加编辑

现在 xlsx 文件已添加到组合中。

第三者

在这种情况下,第三方解决方案是不可接受的(除非它们允许不受限制的商业用途)。

尝试 - (最后说明:最终我不得不放弃 OleDb 连接。)

我已经尝试了所有提供的不同连接字符串,并且一次只尝试了一种文件类型。没有一个连接字符串适用于任何文件类型。

权限

用户确实有权访问该文件及其目录。

4

4 回答 4

3

您的连接字符串可能是这里的问题。据我所知,没有 1 可以读取所有 xls、csv 和 xlsx。我认为您正在使用 XLSX 连接字符串。

当我阅读 xls 时,我使用以下连接字符串:

@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + sFilePath + ";Extended Properties='Excel 8.0;HDR=YES;IMEX=1;'"

话虽如此,我建议使用第 3 方文件读取器/解析器来读取 XLS 和 CSV,因为根据我的经验,OleDbDataAdapter 取决于正在读取的数据类型(以及它们在每列中的混合程度)。

对于 XLS,请尝试 NPOI https://code.google.com/p/npoi/

对于 CSV,请尝试http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader

对于 XLSX,请尝试 EPPlus http://epplus.codeplex.com/

我在上面的库中取得了巨大的成功。

于 2013-07-03T18:19:32.723 回答
1

OleDb为此使用接口真的很重要吗?我一直这样做Microsoft.Office.Excel.Interop,也就是说:

using System;
using Microsoft.Office.Interop.Excel;

namespace StackOverflowExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var app = new Application();
            var wkbk = app.Workbooks.Open(@"c:\data\foo.xls") as Workbook;
            var wksht = wkbk.Sheets[1] as Worksheet; // not zero-based!
            for (int row = 1; row <= 100; row++) // not zero-based!
            {
                Console.WriteLine("This is row #" + row.ToString());
                for (int col = 1; col <= 100; col++)
                {
                    Console.WriteLine("This is col #" + col.ToString());
                    var cell = wksht.Cells[row][col] as Range;
                    if (cell != null)
                    {
                        object val = cell.Value;
                        if (val != null)
                        {
                            Console.WriteLine("The value of the cell is " + val.ToString());
                        }
                    }
                }
            }
        }
    }
}
于 2013-07-11T18:14:00.140 回答
0

由于您将处理 xlsx 扩展,因此您应该选择新的连接字符串。

public static string getConnectionString(string fileName, bool HDRValue, bool WriteExcel)
{
    string hdrValue = HDRValue ? "YES" : "NO";
    string writeExcel = WriteExcel ? string.Empty : "IMEX=1";
    return "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + fileName + ";" + "Extended Properties=\"Excel 12.0 xml;HDR=" + hdrValue + ";" + writeExcel + "\"";
}

以上是获取连接字符串的代码。第一个参数需要文件位置的实际路径。第二个参数将决定是否将第一行值视为列标题。第三个参数有助于决定您是要打开连接以创建和写入数据还是只是读取数据。要读取数据,请将其设置为“FALSE”

public static ReadData(string filePath, string sheetName, List<string> fieldsToRead, int startPoint, int endPoint)
{
    DataTable dt = new DataTable();
    try
    {
        string ConnectionString = ProcessFile.getConnectionString(filePath, false, false);
        using (OleDbConnection cn = new OleDbConnection(ConnectionString))
        {
            cn.Open();
            DataTable dbSchema = cn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
            if (dbSchema == null || dbSchema.Rows.Count < 1)
            {
                throw new Exception("Error: Could not determine the name of the first worksheet.");
            }
            StringBuilder sb = new StringBuilder();
            sb.Append("SELECT *");
            sb.Append(" FROM [" + sheetName + fieldsToRead[0].ToUpper() + startPoint + ":" + fieldsToRead[1].ToUpper() + endPoint + "] ");
            OleDbDataAdapter da = new OleDbDataAdapter(sb.ToString(), cn);
            dt = new DataTable(sheetName);
            da.Fill(dt);
            if (dt.Rows.Count > 0)
            {
                foreach (DataRow row in dt.Rows)
                {
                string i = row[0].ToString();
                }
            }
            cn.Dispose();
            return fileDatas;
        }
    }
    catch (Exception)
    {
    }
}
于 2013-07-12T10:43:01.613 回答
0

这是用于将 2007 Excel 读入数据集

  DataSet ds = new DataSet();
        try
        {


            string myConnStr = "";

                myConnStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=MyDataSource;Extended Properties=\"Excel 12.0;HDR=YES\"";


            OleDbConnection myConn = new OleDbConnection(myConnStr);
            OleDbCommand cmd = new OleDbCommand("select * from [Sheet1$] ", myConn);
            OleDbDataAdapter adapter = new OleDbDataAdapter();
            adapter.SelectCommand = cmd;
            myConn.Open();
            adapter.Fill(ds);
            myConn.Close();
        }
        catch
        { }
        return ds;
于 2013-07-15T05:50:53.213 回答