OpenFileDialog无法加载CSV文件,但可以加载xls / xlsx Excel文件

时间:2019-01-24 14:59:50

标签: c# excel winforms csv openfiledialog

在Windows窗体应用程序中加载Excel文件时,可以很好地加载.xls.xlsx格式,但是当我选择.CSV时出现以下错误:

  

System.NullReferenceException:“对象引用未设置为对象的实例。”   sConnectionString为空。

该错误发生在行上:

if (sConnectionString.Length > 0)

在完整的代码部分中:

public string sConnectionString;
public void FillData()
{
    if (sConnectionString.Length > 0)
    {
        OleDbConnection cn = new OleDbConnection(sConnectionString);
        {
            cn.Open();
            DataTable dt = new DataTable();
            OleDbDataAdapter Adpt = new OleDbDataAdapter("select * from [sheet1$]", cn);
            Adpt.Fill(dt);
            dataGridView1.DataSource = dt;
        }
    }
}

哪个在按钮代码之前:

private void Browse_Click(object sender, EventArgs e)
{
    OpenFileDialog op = new OpenFileDialog();
    op.InitialDirectory = @"C:\";
    op.Title = "Browse Excel Files";
    op.CheckFileExists = true;
    op.CheckPathExists = true;
    op.DefaultExt = "csv";
    op.Filter = "CSV Files (*.csv)|*.csv";
    op.FilterIndex = 2;
    op.RestoreDirectory = true;
    op.ReadOnlyChecked = true;
    op.ShowReadOnly = true;

    if (op.ShowDialog() == System.Windows.Forms.DialogResult.OK)
    {
        if (File.Exists(op.FileName))
        {
            string[] Arr = null;
            Arr = op.FileName.Split('.');
            if (Arr.Length > 0)
            {
                if (Arr[Arr.Length - 1] == "xls")
                    sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
                    op.FileName + ";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'";
            }
            else if (Arr[Arr.Length - 1] == "xlsx")
            {
                sConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + op.FileName + ";Extended Properties='Excel 12.0 Xml;HDR=YES';";
            }
        }
        FillData();
        fileTextBox.Text = op.FileName;
    }
}

修改

已添加:

else if (Arr[Arr.Length - 1] == "csv")
    {
    sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + op.FileName + 
                        ";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'";
    }

仍然出现相同的错误。

1 个答案:

答案 0 :(得分:1)

关于报告的错误

  

System.NullReferenceException:'对象引用未设置为   对象的实例。'
sConnectionString为空。

生成异常是因为Connection字符串声明为:

public string sConnectionString;

由于它从未被初始化,因为Connection字符串的初始化仅对某些文件类型执行,而不对OpenFileDialog.Filter中包含的所有文件类型执行。当代码测试字符串的长度时,字符串仍为null。可以避免设置初始值:

public string sConnectionString = string.Empty;

关于使用.CSV 操作OleDbConnection文件所需的连接字符串:

要读取CSV文件,对于所有提供商,连接字符串的组成如下:

{Provider};Data Source={Catalog}; Extended Properties="text; HDR=Yes; IMEX=1; FMT=Delimited;

位置:

  • {Provider} => 其中一个OleDb提供程序。他们中的任何一个都会做。
  • {Catalog} => 包含要打开文件的目录。
  • HDR=Yes/No => CSV文件包含标题:如果为Yes,则标题为文件的第一行
  • IMEX=1 => 将导入/导出模式设置为1(导出模式= 0;导入模式= 1,链接模式= 2),以忽略数值并仅使用字符串。在这里实际上不相关。最好保留它作为一般帮助(以防文件中没有标题和 HDR=Yes )。
  • FMT=Delimited => :文件格式:定界。标题/字段由定界符分隔。公认的定界符是逗号(,)。此设置可能取决于系统(第3部分应用可能出于自身原因修改了注册表)。要指定与默认分隔符不同的分隔符(C中的CSV表示逗号), Catalog 文件夹中必须有一个Schema.ini文件定义了特定文件的特定定界符:

    [MyFile.csv]
    Format=Delimited(;)
    
  • 由于 Data Source 是目录名(考虑为数据库),因此在查询中指定了要打开的文件的文件名:

    SELECT * FROM MyFile.csv
    

使用Microsoft.ACE.OLEDB.12.0作为提供者的示例连接字符串:

string connectionString = $@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={dirName};" +
                            "Extended Properties=\"text; HDR=Yes; IMEX=1; FMT=Delimited\";";

有关其他可用的连接字符串格式,请参见The Connection Strings Reference网站

示例代码以测试结果(在这种情况下,使用Microsoft.Jet.OLEDB.4.0

private void Browse_Click(object sender, EventArgs e)
{
    string userFileName = string.Empty;
    using (OpenFileDialog ofd = new OpenFileDialog())
    {
        ofd.RestoreDirectory = true;
        ofd.Filter = "CSV Files|*.csv|Excel '97-2003|*.xls|Excel 2007-2019|*.xlsx";
        if (ofd.ShowDialog(this) == DialogResult.OK)
            userFileName = ofd.FileName;
    }

    if (userFileName.Length == 0) return;
    this.dataGridView1.DataSource = GetData(userFileName);
}

private DataTable GetData(string userFileName)
{
    string dirName = Path.GetDirectoryName(userFileName);
    string fileName = Path.GetFileName(userFileName);
    string fileExtension = Path.GetExtension(userFileName);
    string connection = string.Empty;
    string query = string.Empty;

    switch (fileExtension)
    {
        case ".xls":
            connection = $@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={userFileName};" +
                           "Extended Properties=\"Excel 8.0; HDR=Yes; IMEX=1\"";
            query = "SELECT * FROM [Sheet1$]";
            break;
        case ".xlsx":
            connection = $@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={userFileName};" +
                           "Extended Properties=\"Excel 12.0; HDR=Yes; IMEX=1\"";
            query = "SELECT * FROM [Sheet1$]";
            break;
        case ".csv":
            connection = $@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={dirName};" +
                           "Extended Properties=\"text; HDR=Yes; IMEX=1; FMT=Delimited\"";
            query = $"SELECT * FROM {fileName}";
            break;
    }
    return FillData(connection, query);
}

private DataTable FillData(string connection, string query)
{
    DataTable dataTable = new DataTable();
    using (OleDbConnection con = new OleDbConnection(connection))
    {
        OleDbDataAdapter adapter = new OleDbDataAdapter(query, con);
        adapter.Fill(dataTable);
        adapter.Dispose();
    };
    return dataTable;
}