2016-07-29 64 views
0

我是C#中的新手,我在c#Windows应用程序中遇到了一个问题。 我在c#中创建了一个Windows应用程序,它成功地完成了所有任务,但是当我第一次尝试打开我的c#windows应用程序时,它需要大约1分30秒,因为第一次在应用程序中加载了一个excel文件试图打开应用程序。如何减少在第一次打开应用程序时将Excel文件数据加载到C#应用程序的时间

该excel文件用于“AutoCompleteStringCollection”。

请参阅下面的代码,并建议我的解决方案,我可以如何减少我的应用程序的开放时间。

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); 
        } 
       } 

      } 
     } 

注:当我选择较少的数据包含然后Excel应用程序打开时间也减少意味着它的问题了,选择大型数据包含Excel文件。

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

+0

在应用程序启动后,您可以尝试使用不同的线程从Excel加载数据。 – Elangovan

+0

跨越程序和Excel过程之间的鸿沟所需的过程使得此代码非常昂贵。请务必阅读只*一次*,[读取数组](http://stackoverflow.com/questions/910400/reading-from-excel-range-into-multidimensional-array-c-sharp),而不是一个单元格一次。并强烈考虑使用OpenXML API,因此您不必等到Excel启动。 –

+0

由此,您只需添加一个项目的线性列表,那么为什么不使用简单的文本文件或XML配置文件而不是Excel? – cjb110

回答

0

我建议你不要使用Excel本身来将Excel工作表加载到你的应用程序中。造成这种情况的原因很多:

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

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

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

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

下面是您可以用来打开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); 
       } 
      } 
     } 
    } 
} 
+0

感谢您的建议,但不知道如何使用以及我的代码中使用了哪种版本的NPOI库,请告诉我相关信息。 –

+0

@TusharPatil,我刚刚添加了一个代码示例和从哪里获取库的链接 –

1

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

var array = range.Value;

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

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

请注意,这提供了在阵列是基于1(不从0开始),即需要做: 对(INT I = 1;我< = range.Rows.Count;我++){ 对(INT J = 1;Ĵ< = range.Columns.Count; J ++){ // 处理阵列[I,J]这里 } }

0

更一般的问题的答案:“我已经得到一个沉重的/长期的过程阻塞我的程序“,就是使用多线程。最简单的方法是使用内置的BackgroundWorker类:MSDN page

基本上在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是该过程完成后要执行的操作。

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

+0

非常感谢您提供的代码(BackgroundWorker)对我的应用程序来说非常合适。再次感谢“cjb100”。 –

+0

@TusharPatil酷,记得标记答案! – cjb110

相关问题