问题描述
需要读取一excel文件内容进行处理,此文件共约700条数据,(每条数据约12项)。每隔三分钟会有一第三方程序向此文件写入一条数据。此第三方程序不可进行二次开发,且具有最高权限,就是说此第三方程序写入数据时,其它程序不得对excel文件进行占用。请问此问题如何解决。我的思路是尽量快速读取excel文件数据然后关闭excel文件。把读取的数据生成dataset在计算机内存中处理而不在打开excel文件时一边读数一边处理。那么哪位高人可以给我一个读取快速excel文件数据并生成dataset的例子?愿给500分!注意,使用读取数据库的方法读取excel文件并生成dataset方法不可取,因为一:使用此方法必须建立数据库连接,这个过程需要耗费时间,且如果网络有问题的话时间会更长。二直接读取excel文件,按照标准的读取excel文件的range方法不可取,时间太长!
解决方案
解决方案二:
那你还不如读之前把excel复制一份,想读多久都没关系或者开文件时候开启读写共享
解决方案三:
第三方程序是怎么写excel的,你每次读取完了,就把excel初始化下,使得它清空,不就可以了。
解决方案四:
二楼:1第三方程序每隔三分钟就操作一下excel,这意味着我每隔三分钟就要拷贝一下文件,首先二十四小时对文件要拷贝许多次,而且并不只有这一个excel,实际我一次要操作大约二十个excel文件。此方法还对硬盘频繁操作,损伤寿命(机器除非断电,否则终年不停机)2我说了,打开文件方法不可取,因为一是用此方法读取数据太慢(一个不明显,二十个*700*12是龟速),且我记得在visualstudio中需要调用excel实例才能打开此文件,这个打开文件的动作似乎是独占的,如何读写共享呢?如果真可以共享,那么我读取数据时,第三方程序此时写入一条数据,然后关闭文件,由于数据有变化,那么excel文件关闭时必然弹出保存对话框,这就需要人工确认。而实际这是无人操作,无法进行保存确认的。三楼:我的程序不能对excel文件进行任何改变内容的操作。实际上这个文件是由那个第三方程序自动生成,自动写入数据。我的程序只能趁它不操作此文件时读取一下数据,其它什么都不能干!我主要是想解决当我对此文件独占使用时,恰好第三方程序也对其使用而引发的冲突问题,而此时要求第三方程序必须具有最高权限,不能影响它对excel文件的使用,且无法更改第三方程序代码。我目前的思路只能是尽快的对此文件数据读出来,然后关闭文件供第三方程序使用。当然这仍然无法保证百分百可以解决冲突问题,但可以使冲突可能性尽量降低到最小。
解决方案五:
首先参考GetinstanceofExcelapplicationwithC#byHandlehttp://stackoverflow.com/questions/1118735/get-instance-of-excel-application-with-c-sharp-by-handleusingExcel=Microsoft.Office.Interop.Excel;publicExcel.ApplicationStartExcel(){Excel.Applicationinstance=null;try{instance=(Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");}catch(System.Runtime.InteropServices.COMExceptionex){instance=newExcel.ApplicationClass();}returninstance;}
可以直接从系统中获取已存在的excel实例,应该可以解决文件被独占访问的问题。第二步,判断文件是否已打开varxls=StartExcel();foreach(Excel.Workbookwbinxls.Workbooks){if(wb.Path==path)//文件是否打开判断}
第三步,利用二维数组映射数据,快速读取object[,]arr=(object[,])sh.UsedRange.Value;
测试:文件包含一张表7个字段,2542行数据关闭状态用时<300ms打开状态用时<50msusingSystem;usingSystem.Diagnostics;usingSystem.Runtime.InteropServices;usingSystem.Text;usingExcel=Microsoft.Office.Interop.Excel;//获取系统中已存在的ExcelApplication实例publicExcel.ApplicationGetInstance(){Excel.Applicationinstance=null;try{instance=(Excel.Application)Marshal.GetActiveObject("Excel.Application");}catch(System.Runtime.InteropServices.COMExceptionex){Console.WriteLine(ex.Message);instance=newExcel.Application();}returninstance;}privatevoidmeOnClick(objectsender,RoutedEventArgse){Stopwatchsw=newStopwatch();//启动一个计时器sw.Start();Excel.Applicationxls=GetInstance();//获取Excel实例Excel.Workbookwb=null;Excel.Worksheetsh;boolopenByMe=false;//用于标识是否是自己的程序打开的文件//程序目录中放了一个测试用的xlsx//表中有7个字段2542行数据stringpath=System.IO.Path.GetFullPath("test.xlsx");foreach(Excel.Workbookiteminxls.Workbooks){//通过路径判断文件是否已被打开if(item.FullName==path){wb=item;break;}}if(wb==null)//判断文件是否已打开{try{wb=xls.Workbooks.Open(path,ReadOnly:true);//已只读方式打开文件openByMe=true;//是自己的程序打开的}catch(Exceptionex){Console.WriteLine(ex.Message);}}if(wb==null)return;sh=(Excel.Worksheet)wb.Sheets["systems"];//获取目标Worksheetobject[,]arr=(object[,])sh.UsedRange.Value;//以最快的方式获取数据if(openByMe)//判断标识{wb.Close(SaveChanges:false);//关闭文件xls.Quit();//退出Excelsh=null;wb=null;xls=null;}Console.WriteLine("{0}",sw.Elapsed.TotalMilliseconds);if(arr==null)//判断是否获取了数据return;varsb=newStringBuilder();//将数组数据植入StringBuilderfor(inti=arr.GetLowerBound(0);i<=arr.GetUpperBound(0);i++){for(intj=arr.GetLowerBound(1);j<=arr.GetUpperBound(1);j++){if(j==arr.GetLowerBound(1)){sb.AppendFormat("{0}",arr[i,j]);//首个字段直接写值}else{sb.AppendFormat("t{0}",arr[i,j]);//非首字段写t+值}}sb.AppendLine();//写入回车}//获取一个cache.csv文件路径,该文件位于当前应用程序目录stringpath=System.IO.Path.GetFullPath("cache.csv");System.IO.File.WriteAllText(path,sb.ToString(),Encoding.Default);//写入数据sw.Stop();Console.WriteLine("{0}",sw.Elapsed.TotalMilliseconds);}
解决方案六:
上面的代码有个问题,path复用,前面的string要去掉。