hemal p.shah Ответов: 1

Я получаю неправильные результаты в datagridview при извлечении значений из файла excel


Привет,
Я не получаю правильных результатов в элементе управления datagridview при извлечении данных из файла Excel. Это происходит при попытке получить данные с 2-х листов одной и той же рабочей книги. Ошибка заключается в том, что элемент управления datagridview показывает повторение строк. Это происходит только тогда, когда я пытаюсь получить данные с двух листов. Я получаю правильные результаты только в том случае, если пишу select query для 1 листа.

Пожалуйста, предложите мне правильный способ получения данных из нескольких рабочих листов.

Что я уже пробовал:

public DataTable ReadExcel(string fileName, string fileExt)
        {
            string conn = string.Empty;
            DataTable dtexcel = new DataTable();


           

            if (fileExt.CompareTo(".xls") == 0)
                conn = @"provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fileName + ";Extended Properties='Excel 8.0;HRD=Yes;IMEX=1';"; //for below excel 2007  
            else
                conn = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties='Excel 12.0;HDR=NO';"; //for above excel 2007  
            using (OleDbConnection con = new OleDbConnection(conn))
            {
                try
                {
                    
                        OleDbDataAdapter oleAdpt = new OleDbDataAdapter("select * from [Sheet1$],[Sheet2$] ", con); 
                  
                        oleAdpt.Fill(dtexcel); //fill excel data into dataTable  
                    
                }
                catch { }
            }
            return dtexcel;
        }


private void btnReadFile_Click(object sender, EventArgs e)
        {
            string filePath = string.Empty;
            string fileExt = string.Empty;
            OpenFileDialog file = new OpenFileDialog(); //open dialog to choose file  
            if (file.ShowDialog() == System.Windows.Forms.DialogResult.OK) //if there is a file choosen by the user  
            {
                filePath = file.FileName; //get the path of the file  
                fileExt = Path.GetExtension(filePath); //get the file extension  
                if (fileExt.CompareTo(".xls") == 0 || fileExt.CompareTo(".xlsx") == 0)
                {
                    try
                    {
                        DataTable dtExcel = new DataTable();
                        dtExcel = ReadExcel(filePath, fileExt); //read excel file  
                        dataGridView1.Visible = true;
                        dataGridView1.DataSource = dtExcel;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message.ToString());
                    }
                }
                else
                {
                    MessageBox.Show("Please choose .xls or .xlsx file only.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error); //custom messageBox to show error  
                }
            }
        }

Richard MacCutchan

Я только что попробовал образец этого, и он работает правильно. Вам нужно предоставить более подробную информацию о том, в чем именно заключается ваша проблема.

hemal p.shah

предположим, у меня есть два листа sheet1 и sheet2 одной и той же книги.
Теперь лист1 имеет следующие данные в столбце А
имя
hemal
лист 2 содержит следующие данные в колонке а
отдел
Инженерное искусство
теперь я хочу получить данные в элементе управления datagridview следующим образом,
название отдела
hemal технических
но он показывает данные вот так
название отдела
департамент hemal
наименование технических
hemal технических
Вот в чем проблема.

1 Ответов

Рейтинг:
9

Richard Deeming

Цитата:
select * from [Sheet1$],[Sheet2$]
Вы указываете соединение без предиката. Это даст перекрестное произведение двух листов-каждая строка из листа 1 будет соединена с каждой строкой на листе 2.

К сожалению, похоже, что нет никакого применимого предиката, к которому вы могли бы присоединиться, поскольку вы связываете данные на основе их номера строки. Вам нужно будет загрузить данные с обоих листов отдельно, а затем объединить их.

Добавьте несколько вспомогательных методов:
private static DataTable LoadAllDataFromSheet(OleDbConnection connection, string sheetName)
{
    using (var command = new OleDbCommand($"SELECT * FROM [{sheetName}$]", connection))
    {
        var table = new DataTable();
        var adapter = new OleDbDataAdapter(command);
        adapter.Fill(table);
        return table;
    }
}

private static object[] CombineRows(object[] row1, object[] row2)
{
    object[] result = new object[row1.Length + row2.Length];
    row1.CopyTo(result, 0);
    row2.CopyTo(result, row1.Length);
    return result;
}

private static DataTable MergeTables(DataTable sheet1, DataTable sheet2)
{
    var result = new DataTable();
    
    result.BeginInit();
    foreach (DataColumn column in sheet1.Columns)
    {
        result.Columns.Add($"Sheet1.{column.ColumnName}", column.DataType);
    }
    foreach (DataColumn column in sheet2.Columns)
    {
        result.Columns.Add($"Sheet2.{column.ColumnName}", column.DataType);
    }
    result.EndInit();
    
    result.BeginLoadData();
    foreach (object[] row in sheet1.Rows.Cast<DataRow>().Zip(sheet2.Rows.Cast<DataRow>(), (r1, r2) => CombineRows(r1.ItemArray, r2.ItemArray)))
    {
        result.Rows.Add(row);
    }
    result.EndLoadData();
    
    return result;
}
Затем используйте их для загрузки данных:
using (OleDbConnection con = new OleDbConnection(conn))
{
    DataTable sheet1 = LoadAllDataFromSheet(con, "Sheet1");
    DataTable sheet2 = LoadAllDataFromSheet(con, "Sheet2");
    dtexcel = MergeTables(sheet1, sheet2);
}
Выход:
Sheet1.F1  |  Sheet2.F1
=======================
name       |  department
hemal      |  Engineering
NB: Предполагая, что значения в первой строке являются заголовками столбцов, вы можете изменить строку подключения, чтобы указать HDR=YES, и вы получите:
Sheet1.name  |  Sheet2.department
=================================
hemal        |  Engineering
Если заголовки столбцов уникальны, то вы можете изменить MergeTables функция такова, что она не ставит префикс имен столбцов с именами листов.


hemal p.shah

Это прекрасно работает. Спасибо за помощь.