代码有时会运行完成,但并不总是给出相同的输入

时间:2015-08-21 12:29:21

标签: c# excel

以下程序在第1列中包含带有产品ID(以MT或MU开头)的Excel文件。然后,它会通过采购订单(PO)按供应商的文件夹中包含那些产品ID,这些产品ID按年份包含子文件夹。用户输入文件夹路径并指定要搜索的年份。然后,程序会在用户指定的原始电子表格中的产品ID旁边的列中返回最新的供应商,价格和日期。该计划需要大约3到4个小时来运行10,000个产品ID和一年的PO(数百个PO)。有时它会结束(有一个消息框显示完成后完成),有时它没有给出相同的确切输入。没有错误,但CPU使用率突然从大约40%上升到1%任何人都知道为什么?

    string filepath = "";
    string folderpath = "";

    private void button1_Click(object sender, EventArgs e)
    {
        //New Excel App
        Excel._Application oApp = new Excel.Application();
        oApp.Visible = true;


        //Opens Worksheet to be updated
        Excel.Workbook oWorkbook = oApp.Workbooks.Open(filepath);
        Excel.Worksheet oWorksheet = oWorkbook.Worksheets["Sheet1"];

        //Takes all MT/MU numbers from first column of worksheet needing updating and puts them into a string
        Excel.Range firstColumn = oWorksheet.UsedRange.Columns[1];
        System.Array myvalues = (System.Array)firstColumn.Cells.Value;
        string[] strArray = myvalues.OfType<object>().Select(o => o.ToString()).ToArray();

        //Specify what year to begin and end looking at POs
        int beginYear = Convert.ToInt32(textBox2.Text);
        beginYear = int.Parse(textBox2.Text);
        int endYear = Convert.ToInt32(textBox3.Text);
        endYear = int.Parse(textBox3.Text);
        int count = 0;
        List<string> yearList = new List<string>();
        while (count <= endYear-beginYear )
        {
            int addYear = beginYear + count;
            string addYearString = addYear.ToString();
            yearList.Add(addYearString);
            count++;

        }
        string[] years = yearList.ToArray();


       foreach (string year in years)
        {
            //Creates array of all excel files existing in path (including subdirectories) in folder chosen by user
            IEnumerable<string> files =
            from f in Directory.GetFiles(folderpath, "*.xls", SearchOption.AllDirectories)
            where Path.GetDirectoryName(f).Contains(year)
            select f;

            foreach (string file in files)
            {
                //Opens file
                Excel._Application oApp2 = new Excel.Application();
                oApp2.Visible = false;
                Excel.Workbook PO = oApp2.Workbooks.Open(file);
                Excel.Worksheet oWorksheet2 = PO.Worksheets["Sheet1"];

                foreach (string item in strArray)
                {
                    Excel.Range currentFind = null;
                    string newestDateSoFar = "01/01/1900";
                    DateTime newestDateTimeSoFar = Convert.ToDateTime(newestDateSoFar);

                    object misValue = System.Reflection.Missing.Value;

                    Excel.Range xlRange = oWorksheet2.get_Range("C1");

                    //Looks through column for MT/MU number
                    currentFind = xlRange.EntireColumn.Find(item,
                    misValue, Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlPart,
                    Excel.XlSearchOrder.xlByColumns, Excel.XlSearchDirection.xlNext,
                    true, misValue, misValue);

                    //If there is a match in the PO
                    if (currentFind != null)
                    {

                        //Get Date on PO
                        string currentDate = null;
                        DateTime currentDateTime = Convert.ToDateTime(currentDate);
                        if (oWorksheet2.Cells[6, 6].Value != null)
                        {
                            currentDate = oWorksheet2.Cells[6, 6].Value.ToString();
                            currentDateTime = Convert.ToDateTime(currentDate);
                        }

                        Excel.Range xlRange2 = oWorksheet.get_Range("A1");

                        //Looks through column of worksheet needing updating for MT/MU number, so can compare date
                        Excel.Range needsUpdatingFind = xlRange2.EntireColumn.Find(item,
                        misValue, Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlPart,
                        Excel.XlSearchOrder.xlByColumns, Excel.XlSearchDirection.xlNext,
                        true, misValue, misValue);

                        int dateColumn = Convert.ToInt32(textBox4.Text);
                        dateColumn = int.Parse(textBox4.Text);
                        if (needsUpdatingFind.get_Offset(0, dateColumn-1).Value != null)
                        {
                            newestDateSoFar = needsUpdatingFind.Offset[0, dateColumn-1].Value.ToString();
                            newestDateTimeSoFar = Convert.ToDateTime(newestDateSoFar);
                        }



                        //If Date on PO is most recent, get information that needs updating         
                        if (currentDateTime > newestDateTimeSoFar || needsUpdatingFind.get_Offset(0, dateColumn - 1).Value == null)
                        {

                            //Gets assosciated price and sets it in worksheet that needs updating
                            string price = null;
                            int priceColumn = Convert.ToInt32(textBox6.Text);
                            priceColumn = int.Parse(textBox6.Text);
                            if (currentFind.get_Offset(0, 2).Value != null)
                            {
                                price = currentFind.get_Offset(0, 2).Value.ToString();
                                needsUpdatingFind.Offset[0, priceColumn-1].Value = price;
                            }
                            else if (currentFind.get_Offset(-1, 2).Value != null)
                            {
                                price = currentFind.get_Offset(-1, 2).Value.ToString();
                                needsUpdatingFind.Offset[0, priceColumn-1].Value = price;
                            }
                            else if (currentFind.get_Offset(-2, 2).Value != null)
                            {
                                price = currentFind.get_Offset(-2, 2).Value.ToString();
                                needsUpdatingFind.Offset[0, priceColumn-1].Value = price;
                            }
                            else if (currentFind.get_Offset(-3, 2).Value != null)
                            {
                                price = currentFind.get_Offset(-3, 2).Value.ToString();
                                needsUpdatingFind.Offset[0, priceColumn-1].Value = price;
                            }
                            else if (currentFind.get_Offset(-4, 2).Value != null)
                            {
                                price = currentFind.get_Offset(-4, 2).Value.ToString();
                                needsUpdatingFind.Offset[0, priceColumn-1].Value = price;
                            }
                            else if (currentFind.get_Offset(-5, 2).Value != null)
                            {
                                price = currentFind.get_Offset(-5, 2).Value.ToString();
                                needsUpdatingFind.Offset[0, priceColumn-1].Value = price;
                            }

                            //Gets assosciated supplier and sets it in worksheet that needs updating
                            int supplierColumn = Convert.ToInt32(textBox5.Text);
                            supplierColumn = int.Parse(textBox5.Text);
                            string supplier = oWorksheet2.Cells[6, 2].Value.ToString();
                            needsUpdatingFind.Offset[0, supplierColumn-1].Value = supplier;

                            //Gets assosciated PO date and sets it in worksheet that needs updating

                            needsUpdatingFind.Offset[0, dateColumn-1].Value = currentDateTime.ToString();

                            //Resets current find
                            currentFind = null;
                            needsUpdatingFind = null;

                        }
                        while (Marshal.ReleaseComObject(xlRange2) != 0) { }


                        xlRange2 = null;


                        GC.Collect();
                        GC.WaitForPendingFinalizers();
                    }


                    while (Marshal.ReleaseComObject(xlRange) != 0) { }


                    xlRange = null;

                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                }
                //Closes PO
                object missing = System.Reflection.Missing.Value;
                PO.Close(false, missing, missing);

                //Quits Excel
                oApp2.Quit();

                //Manual disposal because of COM
                while (Marshal.ReleaseComObject(oApp2) != 0) { }
                while (Marshal.ReleaseComObject(PO) != 0) { }
                while (Marshal.ReleaseComObject(oWorksheet2) != 0) { }


                oApp2 = null;
                PO = null;
                oWorksheet2 = null;


                GC.Collect();
                GC.WaitForPendingFinalizers();
            }

        }



        MessageBox.Show("Done");
    }

    private void button2_Click(object sender, EventArgs e)
    {

        OpenFileDialog openFileDialog1 = new OpenFileDialog();
        if (openFileDialog1.ShowDialog() == DialogResult.OK)
        {
            filepath = openFileDialog1.FileName;
            textBox1.Text = filepath;
        }
    }

    private void button3_Click(object sender, EventArgs e)
    {
        FolderBrowserDialog openFileDialog2 = new FolderBrowserDialog();
        if (openFileDialog2.ShowDialog() == DialogResult.OK)
        {
            folderpath = openFileDialog2.SelectedPath;
            textBox7.Text = folderpath;
        }
    }
}
}

1 个答案:

答案 0 :(得分:0)

您应该使用test/luaDataSet将数据放入内存,然后让C#/ Linq完成工作。它听起来并不像是在谈论大量数据,所以似乎Interop是缓慢的根本原因。这是一个示例/比较:Open Excel, Parse Data?。在该帖子中,请注意ADO.Net和Interop之间的比较。选择的答案比替代的,有效的答案要快得多。看来你遇到了同样的问题。