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

时间:2016-07-29 07:47:51

标签: c# excel vba

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

此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文件的问题。

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

3 个答案:

答案 0 :(得分:1)

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

var array = range.Value;

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

从Range对象中获取行和列的尺寸,单步执行生成的数组要快得多,而不是单步执行Excel范围中的单元格。

请注意,此提供的数组是基于1的(不是基于0的),即您需要执行以下操作:     for(int i = 1; i&lt; = range.Rows.Count; i ++)     {         for(int j = 1; j&lt; = range.Columns.Count; j ++)         {             //在这里处理数组[i,j]         }     }

答案 1 :(得分:0)

我建议您不要使用Excel本身将Excel工作表加载到您的应用程序中。这有很多原因:

  1. 您需要在运行该应用程序的每台计算机上安装Excel。
  2. 很慢。
  3. 可能会遇到各种安全问题。
  4. 从我在您的代码中看到的内容,您只需要从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);
                    }
                }
            }
        }
    }
    

答案 2 :(得分: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,因为通常只有一个线程可以更新UI,所以你必须编组线程。而且你还有次要问题要回答:这项工作正在进行中程序可以使用多远?我是否需要向用户显示其在后台工作?等