C#XLS和XLSX查询从片材选择表名称而不管

问题描述 投票:0回答:2

这是我的GetData方法:

    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);
    }

它适用于.csv文件,因为它使用的文件名,而不是表名称。

它的工作原理为有一个名为.xls工作.xlsxSheet1文件。

当我尝试并使用.xls/.xlsx文件有不同的表名称,我得到以下错误:

System.Data.OleDb.OleDbException:“”工作表Sheet1 $”不是一个有效的名称。请确保它不包括无效字符或标点并且它是不会太长。”

从另一个问题的答案:

using (OleDbConnection conn = new OleDbConnection(connString))
{
    conn.Open();
    dtSchema = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
    Sheet1= dtSchema.Rows[0].Field<string>("TABLE_NAME");
}

没有帮助,因为我不知道这应该在我的代码去也没有在回答任何指示到本应该去。

我将其添加在像这样的?

string Sheet1 = dataGridView1.Rows[0].Field<string>("TABLE_NAME");

这给了我一个错误:

错误CS1929“的DataGridViewRow”不包含关于“字段”的定义和最佳的扩展方法过载“DataRowExtensions.Field(DataRow中,字符串)”需要类型的接收器“的DataRow”

c# excel winforms datatable openfiledialog
2个回答
2
投票

我赶紧加了一些修正你的代码,但这种方法是远离beeing干净。你应该考虑从@woldemar解决方案,并得到位更深unterstanding代码。一些外观极好来源可以在这里找到:https://github.com/EbookFoundation/free-programming-books

回到你的代码。要了解你要打开在第一至XLSX文件的连接第一板的名称。然后像例如一些代码查询元数据:

using (OleDbConnection conn = new OleDbConnection(connString))
{
    conn.Open();
    dtSchema = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
    Sheet1= dtSchema.Rows[0].Field<string>("TABLE_NAME");
}

之后,你可以将接收到的纸张名到你的查询。

快速和肮脏的,你的代码看起来应该是这样得到它的使用XLSX文件的工作:

private static 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\"";
                string sheetName;
                using (OleDbConnection con = new OleDbConnection(connection))
                {
                    con.Open();
                    var dtSchema = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
                    sheetName = dtSchema.Rows[0].Field<string>("TABLE_NAME");
                }

                if (sheetName.Length <= 0) throw new InvalidDataException("No sheet found."); // abort if no sheet name was returned

                query = $"SELECT * FROM [{sheetName}]";
                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);
    }

3
投票

尝试调用这个方法在你FillData方法的末尾,而不是GetData方法,传递query是不需要,你可以看到,因为这种方法从文档架构SHEETNAME自我。

    private DataTable GetDataFromFirstSheet(string connection)
    {
        using (OleDbConnection conn = new OleDbConnection(connection))
        {
            using (DataTable dtSchema = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }))
            {
                string firstSheet = dtSchema.Rows[0].Field<string>("TABLE_NAME");

                //try to remove $ from sheetname if it will be not working
                using (OleDbCommand cmd = new OleDbCommand($"SELECT * FROM [{firstSheet}$]", conn))
                {
                    using (OleDbDataAdapter adp = new OleDbDataAdapter(cmd))
                    {
                        conn.Open();

                        DataTable dt = new DataTable();
                        adp.Fill(dt);

                        return dt;
                    }                            
                }
            }
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.