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