简体   繁体   English

如何在C#中在没有OLEDB的情况下将Excel数据的特定列和行导入到datagridview

[英]How to import specific columns and rows of excel data to datagridview WITHOUT OLEDB in C#

I made a simple standalone program for work that auto maps network drives. 我制作了一个简单的独立程序来自动映射网络驱动器。 The program uses a DataGridView to list all the drive letter and paths and the code I wrote reads the entries in the DataGridView and maps the drives based from that - also getting the drive letter and path from a specific excel sheet. 该程序使用DataGridView列出所有驱动器号和路径,而我编写的代码读取DataGridView的条目并根据其映射驱动器-还从特定的excel工作表中获取驱动器号和路径。

That specific excel file keeps track of certain information of a user's computer using VB code. 该特定的excel文件使用VB代码跟踪用户计算机的某些信息。 The 3rd worksheet, named “Drives”, is where the network drives reside in. The drive letter and path are in column C and D. There are no headers except for the name “Network drives” on row 2 before it starts on row 3. Unfortunately, after row 29, entries for outlook pst files start. 第三个工作表名为“ Drives”,是网络驱动器所在的位置。驱动器号和路径位于C和D列中。除了在行2开头的名称“网络驱动器”外,没有任何标题。 。不幸的是,在第29行之后,Outlook pst文件的条目开始了。

With my limited knowledge on C# (I'm new to C#), I somehow managed to create this: 由于对C#的了解有限(我是C#的新手),我设法以某种方式创建了这个代码:

public void FileSelect()
    {
        string filePath = string.Empty;
        string fileExt = string.Empty;
        OpenFileDialog file = new OpenFileDialog(); //open dialog to choose file
        file.Filter = "Discovery Excel|*.xlsm| CSV (Coming Soon)| *.csv";
        file.Title = "Please select a valid data 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(".xlsm") == 0)
            {
                try
                {

                    DataTable dtExcel = new DataTable();
                    dtExcel = ReadExcel(filePath, fileExt); //read file  
                    InfoTB.Visible = false;
                    dataGridView1.Visible = true;
                    FileSelectBT.Visible = false;
                    ManualBT.Visible = false;
                    RunBT.Visible = true;
                    ExitBT.Visible = true;
                    RunBT.Location = new System.Drawing.Point(109, 334);
                    ExitBT.Location = new System.Drawing.Point(190, 334);
                    dataGridView1.DataSource = dtExcel;
                    dataGridView1.AutoResizeColumns();
                    dataGridView1.Columns[0].HeaderText = "Drive Letter";
                    dataGridView1.Columns[1].HeaderText = "Drive Path";
                    for (int i = 1; i < dataGridView1.RowCount - 1; i++)
                    {
                        if (dataGridView1.Rows[i].Cells[0].Value.ToString() == "" || dataGridView1.Rows[i].Cells[1].Value.ToString() == "")
                        {
                            dataGridView1.Rows.RemoveAt(i);
                            i--;
                        }
                    }

                }
                catch (Exception ex)
                {
                    MessageBox.Show("Oops! Something went wrong! We'll make a log of that.\nDon't worry, we'll open the Excel File and switch to manuel mode for you!", "FAIL!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    ManualMode();
                    OpenExcel(filePath);
                    TextWriter txt = new StreamWriter(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "NDrive_Error_Log.txt"); //Saving the info from the results textbox to an actual text file
                    txt.Write(ex.ToString());
                    txt.Close();
                }
            }
            else
            {
                MessageBox.Show("Please choose .xlsm or .CSV file only.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error); //custom messageBox to show error  
            }
        } 
    }


    public DataTable ReadExcel(string fileName, string fileExt)
    {
        string conn = string.Empty;
        DataTable dtexcel = new DataTable();
        conn = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source =" + fileName + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1\";"; //loading the Access engine to load/read the Excel file  
        using (OleDbConnection con = new OleDbConnection(conn))
        {
            try
            {
                OleDbDataAdapter oleAdpt = new OleDbDataAdapter("Select TOP 24 F3,F4 FROM [Drives$]", conn); //read data from sheet 3 which should be the drives 
                oleAdpt.Fill(1, 24, dtexcel); //fill excel data into dataTable  
            }
            catch (InvalidOperationException ex)
            {
                MessageBox.Show("Oops! Something went wrong! We'll make a log of that.\nDon't worry, we'll open the Excel File and switch to manuel mode for you!", "FAIL!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                ManualMode();
                OpenExcel(fileName);
                TextWriter txt = new StreamWriter(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)+ "NDrive_Error_Log.txt"); //Saving the info from the results textbox to an actual text file
                txt.Write(ex.ToString());
                txt.Close();
            }
        }
        return dtexcel;
    }

And this code worked! 并且此代码有效!

Here's photo of what the program looks like when it has some entries 这是程序中有一些条目时的外观照片

Unfortunately, the Microsoft.ACE.OLEDB.12.0 is not reliable when it comes to moving the program from one computer to another. 不幸的是,Microsoft.ACE.OLEDB.12.0在将程序从一台计算机移动到另一台计算机时并不可靠。 I am not able to install ACE on every computer at work, so I must find another method to read the Excel files specifically without the need to use OLEDB. 我无法在工作中的每台计算机上都安装ACE,因此我必须找到另一种方法来专门读取Excel文件,而无需使用OLEDB。

I did look around to find an alternative solution, but the stuff I've found seemed to be focusing on specific starting rows instead of the ending rows. 我确实四处寻找替代解决方案,但是我发现的东西似乎集中在特定的开始行而不是结束行。

Though to be fair, I'm new to C# so I may have overlooked something that would help with my program. 公平地说,我是C#的新手,所以我可能忽略了一些对我的程序有帮助的东西。

That said, is there an alternative to OLEDB for this situation? 也就是说,对于这种情况,是否可以使用OLEDB替代方案?

As stated in the comments by PaulF, Excel Interop is a possible solution, saving the need to use any external libraries. 如PaulF的评论所述,Excel Interop是一种可能的解决方案,从而节省了使用任何外部库的需要。

The following is assuming that your data will always be in C3:D29 and also assumes that the data in the worksheet is valid: 以下假设您的数据将始终位于C3:D29并且还假定工作表中的数据有效:

public DataTable ReadExcel(string fileName)
{ 
    var excel = new Excel.Application();
    var wkb = excel.Workbooks.Open(fileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

    var sheet = wkb.Sheets["Drives"] as Excel.Worksheet;

    var range = sheet.Range[sheet.Cells[3, 3], sheet.Cells[29, 4]];
    var data = range.Value2;

    var dt = new DataTable();
    dt.Columns.Add("Drive");
    dt.Columns.Add("Path");

    for (int i = 1; i <= range.Rows.Count; i++)
    {
        dt.Rows.Add(data[i, 1], data[i, 2]);
    }

    return dt;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM