it-roy-ru.com

Как импортировать все листы Excel в DataSet в C #

Я искал в интернете это и не мог найти такой вопрос. Каждый искал способ импортировать отдельный лист в файл Excel, но я хочу импортировать все листы в файле в DataTable в DataSet, не зная имен листов.

Я не делал много вещей с Excel раньше. Это пример и частично рабочий код, который я нашел в интернете, и он анализирует только заданное имя листа:

public static DataSet Parse(string fileName, string workSheetName)
{
    string connectionString = string.Format("provider=Microsoft.Jet.OLEDB.4.0; data source={0};Extended Properties=Excel 8.0;", fileName);
    string query = string.Format("SELECT * FROM [{0}$]", workSheetName);

    DataSet data = new DataSet();
    using (OleDbConnection con = new OleDbConnection(connectionString))
    {
        con.Open();
        OleDbDataAdapter adapter = new OleDbDataAdapter(query, con);
        adapter.Fill(data);
    }

    return data;
}

В приведенном выше коде, как вы видите, должно быть передано workSheetName, чтобы запрос мог знать, куда обратиться для импорта. В моем случае я хочу, чтобы он прошел все листы независимо от того, как они названы, и импортировал их в отдельные DataTable из DataSet.

Таким образом, по сути, последняя вещь будет DataSet, в которой каждая DataTable содержит строки для каждого листа в импортированном файле.

8
Tarik

Это код, который я придумал, и он прекрасно работает, но я видел, что кто-то еще добавил ответ

static DataSet Parse(string fileName)
{
    string connectionString = string.Format("provider=Microsoft.Jet.OLEDB.4.0; data source={0};Extended Properties=Excel 8.0;", fileName);


    DataSet data = new DataSet();

    foreach(var sheetName in GetExcelSheetNames(connectionString))
    {
        using (OleDbConnection con = new OleDbConnection(connectionString))
        {    
            var dataTable = new DataTable();
            string query = string.Format("SELECT * FROM [{0}]", sheetName);
            con.Open();
            OleDbDataAdapter adapter = new OleDbDataAdapter(query, con);
            adapter.Fill(dataTable);
            data.Tables.Add(dataTable);
        }
    }

    return data;
}

static string[] GetExcelSheetNames(string connectionString)
{
        OleDbConnection con = null;
        DataTable dt = null;
        con= new OleDbConnection(connectionString);
        con.Open();
        dt = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

        if (dt == null)
        {
            return null;
        }

        String[] excelSheetNames = new String[dt.Rows.Count];
        int i = 0;

        foreach (DataRow row in dt.Rows)
        {
            excelSheetNames[i] = row["TABLE_NAME"].ToString();
            i++;
        }

        return excelSheetNames;
}
15
Tarik

Потому что мне было скучно

 static void Main(string[] args)
 {
            string filename = @"c:\temp\myfile.xlsx";    
            System.Data.OleDb.OleDbConnection myConnection = new System.Data.OleDb.OleDbConnection( 
                        "Provider=Microsoft.ACE.OLEDB.12.0; " +
                         "data source='" + filename + "';" +
                            "Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\" ");
            myConnection.Open();
            DataTable mySheets = myConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });                
            DataSet ds = new DataSet();
            DataTable dt;

            for (int i = 0; i <= mySheets.Rows.Count; i++)
            {
                   dt =   makeDataTableFromSheetName(filename, mySheets.Rows[i]["TABLE_NAME"].ToString());
                   ds.Tables.Add(dt);
            }
 }

private static DataTable makeDataTableFromSheetName(string filename, string sheetName)
{      
    System.Data.OleDb.OleDbConnection myConnection = new System.Data.OleDb.OleDbConnection(
    "Provider=Microsoft.ACE.OLEDB.12.0; " +
    "data source='" + filename + "';" +
    "Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\" ");

    DataTable dtImport = new DataTable();
    System.Data.OleDb.OleDbDataAdapter myImportCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [" + sheetName + "$]", myConnection);
    myImportCommand.Fill(dtImport);
    return dtImport;
}
14
Avitus

Функция, предложенная Avitus, верна, но в ней есть логическая ошибка, которую необходимо переписать в:

DataTable dtImport = new DataTable();
using ( System.Data.OleDb.OleDbConnection myConnection = new System.Data.OleDb.OleDbConnection(
            "Provider=Microsoft.ACE.OLEDB.12.0; " +
             "data source='" + filename + "';" +
                "Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\" ")){


using ( System.Data.OleDb.OleDbDataAdapter myImportCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [" + sheetName + "$]", myConnection))
myImportCommand.Fill(dtImport);
} return dtImport;

это правильно, в противном случае вы должны утилизировать соединение и адаптер данных вручную.

4
user951083

Это может быть не самый лучший и самый быстрый, но это другой способ (Редактирование - добавлено удаление пустых ячеек):

    public static DataSet ReadWorkbook(string excelFileName, bool useFirstRowAsColumnName = false)
    {
        var Excel = new Microsoft.Office.Interop.Excel.Application();
        var workBook = Excel.Workbooks.Open(excelFileName, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);//MLHIDE
        try
        {
            System.Data.DataSet ds = new DataSet(excelFileName);
            foreach (var sheet0 in workBook.Worksheets)
            {
                var sheet = (Microsoft.Office.Interop.Excel.Worksheet)sheet0;
                try
                {
                    var dt = readSheet(sheet, useFirstRowAsColumnName);
                    if (dt != null)
                        ds.Tables.Add(dt);
                }
                finally
                {
                    releaseObject(sheet);
                }
            }
            return ds;
        }
        finally
        {
            workBook.Close(true, null, null);
            Excel.Quit();

            releaseObject(workBook);
            releaseObject(Excel);
        }
    }

    /// <summary>
    /// Returns null for empty sheets or if sheet is not found.
    /// </summary>
    public static DataTable ReadSheet(string excelFileName, string sheetName, bool useFirstRowAsColumnName = false)
    {
        var Excel = new Microsoft.Office.Interop.Excel.Application();
        var workBook = Excel.Workbooks.Open(excelFileName, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);//MLHIDE
        try
        {
            foreach (var sheet0 in workBook.Worksheets)
            {
                var sheet = (Microsoft.Office.Interop.Excel.Worksheet)sheet0;
                try
                {
                    if (sheet.Name.Equals_Wildcard(sheetName))
                    {
                        var dt = readSheet(sheet, useFirstRowAsColumnName);
                        if (dt != null)
                            return dt;
                    }
                }
                finally
                {
                    releaseObject(sheet);
                }
            }
            return null;
        }
        finally
        {
            workBook.Close(true, null, null);
            Excel.Quit();

            releaseObject(workBook);
            releaseObject(Excel);
        }
    }

    /// <summary>
    /// Returns null for empty sheets
    /// </summary>
private static DataTable readSheet(Microsoft.Office.Interop.Excel.Worksheet sheet, bool useFirstRowAsColumnName = false)
        {
            using (Dece.Common.BeginChangeCurrentCultureBlock_EN_us())
            {
                var range = sheet.UsedRange;
                try
                {
                    object[,] values = (object[,])range.Value2;
                    int rowCount = values.GetLength(0);
                    int colCount = values.GetLength(1);
                    int rowCount0 = rowCount;
                    int colCount0 = colCount;
                    #region find row-col count
                    {
                        bool ok = false;
                        for (int row = rowCount; row > 0; row--)
                            if (!ok)
                                for (int col = colCount; col > 0; col--)
                                {
                                    var val = values[row, col];
                                    if ((val != null) && (!System.Convert.ToString(val).IsNullOrEmpty()))
                                    {
                                        rowCount = row;
                                        ok = true;
                                        break;
                                    }
                                }
                            else
                                break;
                    }
                    {
                        bool ok = false;
                        for (int col = colCount; col > 0; col--)
                            if (!ok)
                                for (int row = rowCount; row > 0; row--)
                                {
                                    var val = values[row, col];
                                    if ((val != null) && (!System.Convert.ToString(val).IsNullOrEmpty()))
                                    {
                                        colCount = col;
                                        ok = true;
                                        break;
                                    }
                                }
                            else
                                break;
                    }
                    #endregion
                    if ((rowCount > 0) && (colCount > 0))
                    {  
                        var dt = new DataTable(sheet.Name);
                        dt.BeginLoadData();
                        try
                        {
                            for (int col = 1; col <= colCount; col++)
                                dt.Columns.Add_RenameIfRequired(useFirstRowAsColumnName ? values[1, col].ToString_NullProof() : col.ToString());
                            var arr = new object[colCount];
                            for (int row = useFirstRowAsColumnName ? 1 : 0; row < rowCount; row++)
                            {
                                for (int col = 1; col <= colCount; col++)
                                    arr[col - 1] = values[row + 1, col];
                                dt.Rows.Add(arr);
                            }
                        }
                        finally
                        {
                            dt.EndLoadData();
                        }
                        return dt;                        
                    }
                    else
                        return null;
                }
                finally
                {
                    releaseObject(range);
                }
            }
        }

    private static void releaseObject(object obj)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
            obj = null;
        }
        catch (Exception ex)
        {
            obj = null;
            throw new Exception("Unable to release the Object " + ex.ToString(), ex);//MLHIDE
        }
        finally
        {
            GC.Collect();
        }
    }
0
Koray