我是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文件的问题。
所以请告诉我如何缩短打开我的应用程序的时间。
答案 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工作表加载到您的应用程序中。这有很多原因:
从我在您的代码中看到的内容,您只需要从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,所以你必须编组线程。而且你还有次要问题要回答:这项工作正在进行中程序可以使用多远?我是否需要向用户显示其在后台工作?等