c# ईपीप्लस का उपयोग कर डेटाटेबल को एक्सेल-संपादन के लिए एक्सेल लॉक किया गया




excel epplus (5)

मैं देखता हूं, मैंने हाल ही में यहां पोस्ट किया है (अब सही)। ExcelPackage और FileStream ( File.OpenRead ) का उपयोग करने के बाद इसका निपटारा नहीं किया जा सकता है।

public static DataTable GetDataTableFromExcel(string path, bool hasHeader = true)
{
    using (var pck = new OfficeOpenXml.ExcelPackage())
    {
        using (var stream = File.OpenRead(path))
        {
            pck.Load(stream);
        }
        var ws = pck.Workbook.Worksheets.First();  
        DataTable tbl = new DataTable();
        foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column])
        {
            tbl.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column));
        }
        var startRow = hasHeader ? 2 : 1;
        for (int rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++)
        {
            var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column];
            DataRow row = tbl.Rows.Add();
            foreach (var cell in wsRow)
            {
                row[cell.Start.Column - 1] = cell.Text;
            }
        }
        return tbl;
    }
}

मैं ईपीप्लस का उपयोग कर एक्सेल को डेटाटेबल में बदलने के लिए निम्न कोड का उपयोग कर रहा हूं:

public DataTable ExcelToDataTable(string path)
{
    var pck = new OfficeOpenXml.ExcelPackage();
    pck.Load(File.OpenRead(path));
    var ws = pck.Workbook.Worksheets.First();
    DataTable tbl = new DataTable();
    bool hasHeader = true;
    foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column])
    {
        tbl.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column));
    }
    var startRow = hasHeader ? 2 : 1;
    for (var rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++)
    {
        var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column];
        var row = tbl.NewRow();
        foreach (var cell in wsRow)
        {
            row[cell.Start.Column - 1] = cell.Text;
        }
        tbl.Rows.Add(row);
    }
    pck.Dispose();
    return tbl;
}

यह एक्सेल बनाता है, हालांकि, जब मैं इसे खोलने का प्रयास करता हूं, तो यह मुझे संदेश देता है कि इसे किसी अन्य उपयोगकर्ता द्वारा संपादित करने के लिए बंद कर दिया गया है और मैं इसे केवल-पढ़ने के लिए मोड में खोल सकता हूं।

मैंने सोचा था:

pck.Dispose();

इस मुद्दे को हल करेंगे, हालांकि मुझे अभी भी एक ही त्रुटि मिल रही है।

साथ ही, जब मैं फ़ाइल को हटाने का प्रयास करता हूं, तो मुझे संदेश मिलता है: कार्रवाई पूर्ण नहीं की जा सकती क्योंकि फ़ाइल WebDev.WebServer40.EXE में खुली है।

कोई विचार यह कैसे हल करें? अग्रिम में धन्यवाद। :)


मैंने एक विधि बनाई है जो एक्सेल फ़ाइल को ईपीप्लस का उपयोग करके डेटाटेबल में परिवर्तित करता है, और टाइप सुरक्षा को बनाए रखने की कोशिश करता है। साथ ही डुप्लिकेट कॉलम नामों को संभाला जाता है और एक बुलियन के साथ आप शीट के साथ एक पंक्ति में गीलेर विधि को बता सकते हैं। मैंने इसे जटिल आयात प्रक्रिया के लिए बनाया है जिसमें अपलोड करने के बाद कई कदम हैं जिसके लिए डेटाबेस में आने से पहले उपयोगकर्ता इनपुट की आवश्यकता है।

private DataTable ExcelToDataTable(byte[] excelDocumentAsBytes, bool hasHeaderRow)
{
    DataTable dt = new DataTable();
    string errorMessages = "";

    //create a new Excel package in a memorystream
    using (MemoryStream stream = new MemoryStream(excelDocumentAsBytes))
    using (ExcelPackage excelPackage = new ExcelPackage(stream))
    {
        ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets[1];

        //check if the worksheet is completely empty
        if (worksheet.Dimension == null)
        {
            return dt;
        }

        //add the columns to the datatable
        for (int j = worksheet.Dimension.Start.Column; j <= worksheet.Dimension.End.Column; j++)
        {
            string columnName = "Column " + j;
            var excelCell = worksheet.Cells[1, j].Value;

            if (excelCell != null)
            {
                var excelCellDataType = excelCell;

                //if there is a headerrow, set the next cell for the datatype and set the column name
                if (hasHeaderRow == true)
                {
                    excelCellDataType = worksheet.Cells[2, j].Value;

                    columnName = excelCell.ToString();

                    //check if the column name already exists in the datatable, if so make a unique name
                    if (dt.Columns.Contains(columnName) == true)
                    {
                        columnName = columnName + "_" + j;
                    }
                }

                //try to determine the datatype for the column (by looking at the next column if there is a header row)
                if (excelCellDataType is DateTime)
                {
                    dt.Columns.Add(columnName, typeof(DateTime));
                }
                else if (excelCellDataType is Boolean)
                {
                    dt.Columns.Add(columnName, typeof(Boolean));
                }
                else if (excelCellDataType is Double)
                {
                    //determine if the value is a decimal or int by looking for a decimal separator
                    //not the cleanest of solutions but it works since excel always gives a double
                    if (excelCellDataType.ToString().Contains(".") || excelCellDataType.ToString().Contains(","))
                    {
                        dt.Columns.Add(columnName, typeof(Decimal));
                    }
                    else
                    {
                        dt.Columns.Add(columnName, typeof(Int64));
                    }
                }
                else
                {
                    dt.Columns.Add(columnName, typeof(String));
                }
            }
            else
            {
                dt.Columns.Add(columnName, typeof(String));
            }
        }

        //start adding data the datatable here by looping all rows and columns
        for (int i = worksheet.Dimension.Start.Row + Convert.ToInt32(hasHeaderRow); i <= worksheet.Dimension.End.Row; i++)
        {
            //create a new datatable row
            DataRow row = dt.NewRow();

            //loop all columns
            for (int j = worksheet.Dimension.Start.Column; j <= worksheet.Dimension.End.Column; j++)
            {
                var excelCell = worksheet.Cells[i, j].Value;

                //add cell value to the datatable
                if (excelCell != null)
                {
                    try
                    {
                        row[j - 1] = excelCell;
                    }
                    catch
                    {
                        errorMessages += "Row " + (i - 1) + ", Column " + j + ". Invalid " + dt.Columns[j - 1].DataType.ToString().Replace("System.", "") + " value:  " + excelCell.ToString() + "<br>";
                    }
                }
            }

            //add the new row to the datatable
            dt.Rows.Add(row);
        }
    }

    //show error messages if needed
    Label1.Text = errorMessages;

    return dt;
}

वेबफॉर्म बटन डेमो उद्देश्यों के लिए क्लिक करें।

protected void Button1_Click(object sender, EventArgs e)
{
    if (FileUpload1.HasFile)
    {
        DataTable dt = ExcelToDataTable(FileUpload1.FileBytes, CheckBox1.Checked);

        GridView1.DataSource = dt;
        GridView1.DataBind();
    }
}

यह उपरोक्त जेनेरिक में सुधार है। उपयोग करें यदि आपके पास निम्न गुणों के साथ एक वर्ग है, "नाम", "उपनाम", "टेलीफोन", "फ़ैक्स" और आपके पास समान नाम वाली पहली पंक्ति के साथ एक्सेल शीट है, तो यह एक्सेल पंक्तियों को लोड करेगा कक्षा वस्तु और इसे एक सूची में पॉप

public static List<T> GetClassFromExcel<T>(string path, int fromRow, int fromColumn, int toRow = 0, int toColumn = 0)
{
if (toColumn != 0 && toColumn < fromColumn) throw new          Exception("toColumn can not be less than fromColumn");
if (toRow != 0 && toRow < fromRow) throw new Exception("toRow can not be less than fromRow");
List<T> retList = new List<T>();
using (var pck = new ExcelPackage())
{
            using (var stream = File.OpenRead(path))
            {
                pck.Load(stream);
            }
            //Retrieve first Worksheet
            var ws = pck.Workbook.Worksheets.First();
            //If the to column is empty or 0, then make the tocolumn to the count of the properties
            //Of the class object inserted
            toColumn = toColumn == 0 ? typeof(T).GetProperties().Count() : toColumn;

            //Read the first Row for the column names and place into a list so that
            //it can be used as reference to properties
            Dictionary<string, int> columnNames = new Dictionary<string, int>();
            // wsRow = ws.Row(0);
            var colPosition = 0;
            foreach (var cell in ws.Cells[1, 1, 1, toColumn == 0 ? ws.Dimension.Columns : toColumn])
            {
                columnNames.Add(cell.Value.ToString(), colPosition);
                colPosition++;
            }
            //create a instance of T
            T objT = Activator.CreateInstance<T>();
            //Retrieve the type of T
            Type myType = typeof(T);
            //Get all the properties associated with T
            PropertyInfo[] myProp = myType.GetProperties();


            //Loop through the rows of the excel sheet
            for (var rowNum = fromRow; rowNum <= (toRow == 0? ws.Dimension.End.Row : toRow); rowNum++)
            {
                var wsRow = ws.Cells[rowNum, fromColumn, rowNum, ws.Cells.Count()];

                foreach (var propertyInfo in myProp)
                {
                    if (columnNames.ContainsKey(propertyInfo.Name))
                    {
                        int position = 0;
                        columnNames.TryGetValue(propertyInfo.Name, out position);
                        //int position = columnNames.IndexOf(propertyInfo.Name);
                        //To prevent an exception cast the value to the type of the property.
                        propertyInfo.SetValue(objT, Convert.ChangeType(wsRow[rowNum, position + 1].Value, propertyInfo.PropertyType));
                    }
                }

                retList.Add(objT);
            }

        }
        return retList;
    }

यदि आप की जरूरत है तो अब आप एक डाटाबेसिंग स्रोत के रूप में सूची का उपयोग कर सकते हैं ... मुझे आप से एक ... :) डैनियल सी। वेरी

इसे कॉल करने के लिए कॉलम के लिए अपडेट किया गया और पंक्ति में जोड़ा गया और एंड्रियास सुझावों का पालन किया। एंड्रियास के लिए अंगूठे ऊपर


public static List<T> getClassFromExcel<T>(string path, int fromRow, int fromColumn, int toColumn = 0) where T : class
        {
            using (var pck = new OfficeOpenXml.ExcelPackage())
            {
                List<T> retList = new List<T>();

                using (var stream = File.OpenRead(path))
                {
                    pck.Load(stream);
                }
                var ws = pck.Workbook.Worksheets.First();
                toColumn = toColumn == 0 ? typeof(T).GetProperties().Count() : toColumn;

                for (var rowNum = fromRow; rowNum <= ws.Dimension.End.Row; rowNum++)
                {
                    T objT = Activator.CreateInstance<T>();
                    Type myType = typeof(T);
                    PropertyInfo[] myProp = myType.GetProperties();

                    var wsRow = ws.Cells[rowNum, fromColumn, rowNum, toColumn];

                    for (int i = 0; i < myProp.Count(); i++)
                    {
                        myProp[i].SetValue(objT, wsRow[rowNum, fromColumn + i].Text);
                    }
                    retList.Add(objT);
                }
                return retList;
            }
        }

टिम श्मेलर के उत्तर का एक विस्तार संस्करण।

public static DataTable ToDataTable(this ExcelWorksheet ws, bool hasHeaderRow = true)
{
    var tbl = new DataTable();
    foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column])
        tbl.Columns.Add(hasHeaderRow ?
            firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column));
    var startRow = hasHeaderRow ? 2 : 1;
    for (var rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++)
    {
        var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column];
        var row = tbl.NewRow();
        foreach (var cell in wsRow) row[cell.Start.Column - 1] = cell.Text;
        tbl.Rows.Add(row);
    }
    return tbl;
}




epplus