在c#中每隔500毫秒从excel文件中读取数据
我有一个包含一些logging,并logging在一秒钟内刷新的Excel文件。 我想要将所有logging存储在SQL Server数据库中。 所以我的意图是每500毫秒后将数据从这个文件读入我的数据库。 我已经成功读取数据并存储在我的数据库中。 但几分钟后,excel挂起,处于不响应的状态。
Excel._Application excel = (Excel._Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"); clsDBOLiveData objDBOLiveData = new clsDBOLiveData(); clsDatabase objDatabase = new clsDatabase(); private static System.Timers.Timer aTimerLive_1; private static System.Timers.Timer aTimerHist_1; private static System.Timers.Timer aTimerLive_2; private static System.Timers.Timer aTimerHist_2; //Here I declare all variables. public TradeData() { SetTimer1_Data(); SetTimer2_Data(); SetTimerHist_1_Data(); SetTimerHist_2_Data(); } private void SetTimerLiveMCX_1_Data() { aTimerLive_1 = new System.Timers.Timer(500); aTimerLive_1.Elapsed += OnTimedEvent_1; aTimerLive_1.AutoReset = true; aTimerLive_1.Enabled = true; } private void OnTimedEvent_1(Object source, ElapsedEventArgs e) { try { Excel.Workbook workbook = excel.Workbooks[1]; Excel.Worksheet workSheet = workbook.Worksheets.get_Item(1); Excel.Range range = workSheet.UsedRange; for (int j = 3; j < range.Rows.Count; j = j + 5) { if ((range.Cells[j, 2] as Excel.Range).Value2 == null || Convert.ToString((range.Cells[j, 2] as Excel.Range).Value2)=="") continue; clsDBOLiveData objDBOLiveData = new clsDBOLiveData(); objDBOLiveData.SYMBOL_NAME = (string)(range.Cells[j, 8] as Excel.Range).Value2; objDBOLiveData.BAR_TIME= (double)(range.Cells[j, 2] as Excel.Range).Value2; objDBOLiveData.HIGH= (decimal)(range.Cells[j, 3] as Excel.Range).Value2; objDBOLiveData.LAST = (decimal)(range.Cells[j, 4] as Excel.Range).Value2; objDBOLiveData.LOW = (decimal)(range.Cells[j, 5] as Excel.Range).Value2; objDBOLiveData.OPEN = (decimal)(range.Cells[j, 6] as Excel.Range).Value2; objDBOLiveData.VOLUME = (decimal)(range.Cells[j, 7] as Excel.Range).Value2; objDBOLiveData.STATUS = (string)(range.Cells[j, 9] as Excel.Range).Value2; string strErrorMgs = ""; if (!objDatabase.SaveData_1(objDBOLiveData, ref strErrorMgs)){} } } catch(Exception ex) { } }
哦,天哪,这里有几件事。
首先,正如其他读者所提到的那样。 当您使用Excel COM对象时,您必须释放它们。
以下是我如何devise你的代码的样式:
Excel.Workbook workbook = null; Excel.Worksheet workSheet = null; Excel.Range range = null; try { workbook = excel.Workbooks[1]; workSheet = workbook.Worksheets.get_Item(1); range = workSheet.UsedRange; . . . } catch(Exception ex) { } finally { if (range != null) Marshal.FinalReleaseComObject(range); if (worksheet != null) Marshal.FinalReleaseComObject(worksheet); if (workbook != null) Marshal.FinalReleaseComObject(workbook); // Garbage collection GC.Collect(GC.MaxGeneration, GCCollectionMode.Default, false); }
其次,我真的不相信在同一行中包含Excel.Range
和Value2
任何行:
objDBOLiveData.SYMBOL_NAME = (string)(range.Cells[j, 8] as Excel.Range).Value2;
做一个谷歌search“Excel COM双点”为(很多)的解释,为什么这是一个坏主意。
就个人而言,如果您的所有数据都在一个工作表中,我build议您在整个工作表中读入一个object[,]
数组,然后遍历那里的值。
object[,] cellValues = (object[,])range.Value2;
你也可以把这个variables转换成一个Array
如果这样可以让你的代码变得更容易:
System.Array arr = (System.Array)cellValues; int numOfRows = arr.GetUpperBound(0); int numOfColumns = arr.GetUpperBound(1);
一次读取所有的单元格数据效率更高,COM对象留在的可能性更小。
最后一件事:小心UsedRange
。
Excel.Range range = workSheet.UsedRange;
我们已经举了一些例子,这些例子已经返回了巨大的范围(例如16000列,实际上只有7列数据),这些数据又反过来使我们的代码崩溃,因为它试图遍历巨大的(空白)单元格范围。
阅读下面的StackOverflow文章来描述唯一安全的方法来查找电子表格中的哪些单元格确实包含数据:
UsedRange的替代方法
唷。
处理对象.. Excel对象很重