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



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

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

错误发生在以下行:

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'";
}

仍然会出现同样的错误。

关于报告的错误

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

由于Connection字符串声明为:,因此生成异常

public string sConnectionString;

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

public string sConnectionString = string.Empty;

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

  • 所有OleDb提供程序都将执行以下操作:
    • Microsoft.Jet.OLEDB.4.0
    • Microsoft.ACE.OLEDB.12.0
    • Microsoft.ACE.OLEDB.16.0
  • 如果某些旧格式(旧Access.mdb文件)需要Microsoft.Jet.OLEDB.4.0,则应用程序必须编译为32Bit,因此安装其他提供程序的相应32Bit版本:

Microsoft数据库引擎2010可再分发
Microsoft数据库引擎2016可再分发

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

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

其中:

  • {Provider} =>OleDb提供商之一。他们中的任何一个都可以。

  • {Catalog} =>包含要打开的文件的目录。

  • HDR=Yes/No =>CSV文件包含一个Header:如果是Yes,则Header是文件的第一行

  • IMEX=1 =>导入/导出模式设置为1(导出模式=0;导入模式=1,链接模式=2),以忽略数值并仅使用字符串。实际上与此无关。最好保留它,作为一般帮助(以防文件中没有Header和HDR=Yes)。

  • FMT=Delimited =>文件格式:分隔。标题/字段由分隔符分隔。识别的分隔符是逗号(,)。此设置可能取决于系统(第三方应用程序可能出于自身原因修改了注册表)。要指定不同于默认值的分隔符(CSV中的C表示逗号),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";";

有关其他可用的连接字符串格式,请参阅连接字符串参考网站。

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

private void Browse_Click(object sender, EventArgs e)
{
string userFileName = string.Empty;
using (var ofd = new OpenFileDialog()) {
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;
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 conString = string.Empty;
string query = string.Empty;
switch (fileExtension)
{
// Can also use Microsoft.ACE.OLEDB.12 or Microsoft.ACE.OLEDB.16
case ".xls":
conString = $@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={userFileName};" +
"Extended Properties="Excel 8.0; HDR=Yes; IMEX=1"";
query = "SELECT * FROM [Sheet1$]";
break;
// Can also use Microsoft.ACE.OLEDB.16
case ".xlsx":
conString = $@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={userFileName};" +
"Extended Properties="Excel 12.0; HDR=Yes; IMEX=1"";
query = "SELECT * FROM [Sheet1$]";
break;
// Can also use Microsoft.ACE.OLEDB.16
case ".csv":
conString = $@"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(conString, query);
}
private DataTable FillData(string conString, string query)
{
var dt = new DataTable();
using (var con = new OleDbConnection(conString)) { 
con.Open();
using (var cmd = new OleDbCommand(query, con))
using (var reader = cmd.ExecuteReader()) {
dt.Load(reader);
};
}
return dt;
}

最新更新