如何在第一次打开应用程序时减less时间将Excel文件数据加载到C#应用程序中

我是新来的C#,我有我的C#Windows应用程序中的一个问题。 我创build一个Windows应用程序在C#中,它成功地工作的所有任务,但是当我试图打开我的C#Windows应用程序第一次需要大约1分30秒,因为一个Excel文件是在第一次尝试时加载应用程序打开应用程序。

这个excel文件用于“AutoCompleteStringCollection”。

请参阅下面的代码,并build议我的解决scheme,我可以减less时间到我的应用程序开放时间。

private void Form1_Load(object sender, EventArgs e) { InitializeTextSearchListView(); textBox1.AutoCompleteMode = AutoCompleteMode.Suggest; textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource; AutoCompleteStringCollection DataCollection = new AutoCompleteStringCollection(); addItems(DataCollection,listView1); textBox1.AutoCompleteCustomSource = DataCollection; } 

  public void addItems(AutoCompleteStringCollection col, ListView ListView1) { Excel.Application xlApp; Excel.Workbook xlWorkBook; Excel.Worksheet xlWorkSheet; Excel.Range range; object missing = System.Reflection.Missing.Value; string str; int rCnt = 0; int cCnt = 0; xlApp = new Excel.Application(); xlWorkBook = xlApp.Workbooks.Open("C:\\SAM Files\\Static Ticker Data.xlsx", 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0); xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1); range = xlWorkSheet.UsedRange; for (rCnt = 1; rCnt <= range.Rows.Count; rCnt++) { for (cCnt = 1; cCnt <= range.Columns.Count; cCnt++) { if (!(((range.Cells[rCnt, cCnt] as Excel.Range).Value2) == null)) { if ((range.Cells[rCnt, cCnt] as Excel.Range).Value2.GetType().ToString() == "System.Double") { double d1 = (Double)(range.Cells[rCnt, cCnt] as Excel.Range).Value2; str = Convert.ToString(d1); col.Add(str); } else { str = (string)(range.Cells[rCnt, cCnt] as Excel.Range).Value2; col.Add(str); } } } } 

注意:当我select较less的数据包含excel的时候,那么应用程序的开放时间也就减less了,对于select大数据包含excel文件来说它的问题。

所以请告诉我如何减less打开我的应用程序的时间。

在Excel中范围内的各个单元格单步执行非常缓慢。 它通常要快得多(对于读写操作)来把整个范围作为一个对象数组来处理。 假设你的数据是在一个简单的表结构(和UsedRange不跨越表,单元格等不同的组合),那么我会build议尝试:

var array = range.Value;

这将创build一个匹配您的表的对象数组。

从Range对象中取出行和列的尺寸,应该快速地遍历结果数组,而不是单步执行Excel范围中的单元格。

请注意,这里提供的数组是基于1的(不是基于0的),也就是说你需要这样做:for(int i = 1; i <= range.Rows.Count; i ++){for(int j = 1; j <= range.Columns.Count; j ++){//在这里处理数组[i,j]}}

我build议你不要使用Excel本身将Excel工作表加载到你的应用程序中。 这件事情是由很多原因导致的:

  1. 您需要在运行应用程序的每台计算机上安装Excel。
  2. 这很慢。
  3. 可能会遇到各种各样的安全问题。

从我在代码中看到的只需要从Excel工作表读取值。 在这种情况下,一个好的select是NPOI图书馆。 这是一个开源的库,你可以在这里find: https : //npoi.codeplex.com/ 。

如果您需要更多的Excelfunction,例如将数据写入Excel工作表,并重新计算Excel工作表,那么可以考虑SpreadSheet Gear库,您可以在这里find: http : //www.spreadsheetgear.com/ 。 这不是开源的,但它的效果很好。

我现在使用的NPOI库版本是NPOI 2.2.1,可以从https://npoi.codeplex.com/releases下载&#x3002;

以下代码可用于打开Excel工作表并遍历数据。

 using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { HSSFWorkbook hssfwb; using (var file = new FileStream(args[0], FileMode.Open, FileAccess.Read)) { hssfwb = new HSSFWorkbook(file); } ISheet sheet = hssfwb.GetSheet("Arkusz1"); for (int row = 0; row <= sheet.LastRowNum; row++) { if (sheet.GetRow(row) != null) //null is when the row only contains empty cells { Console.WriteLine(sheet.GetRow(row).GetCell(0).StringCellValue); } } } } } 

对于你的问题“我有一个沉重的/长的进程阻塞我的程序”的更一般的答案是使用multithreading。 最简单的方法是使用内置的BackgroundWorker类: MSDN页面

基本上在Form1_Load你需要类似于:

 textBox1.AutoCompleteMode = AutoCompleteMode.Suggest; textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource; AutoCompleteStringCollection DataCollection = new AutoCompleteStringCollection(); BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += (s, ev) => { addItems(DataCollection,listView1); }; worker.RunWorkerCompleted += (s, ev) => { textBox1.AutoCompleteCustomSource = DataCollection; }; worker.RunWorkerAsync(); 

所以在DoWork方法中是繁重的/长时间运行的过程,那么在RunWorkerCompleted就是当这个过程完成之后该怎么做。

这不是没有缺陷,尤其是用户界面,因为通常只有一个线程可以更新用户界面,所以你必须编组线程。 而且你还有第二个问题要回答:在这项工作正在进行中,程序能用多久? 我需要显示用户在后台工作吗? 等等