zoukankan      html  css  js  c++  java
  • 从读取Excel文件引申出的问题(上)

    事件起因源于偶然在百度知道看到一个提问,说是他的Excel文件中共有几十万行的数据,希望可以将表中重复内容删除,并将内容分离为每个Excel文件5000行数据。然后就有了这个测试,也许是因为思维发散的缘故,不知道,怎么的,就转到了处理从Excel文件中读取图片上来,事情的发展出乎我的意料,看来不够专注,不过这也让我有了意外的收获。

    经过分析得出,不管是采用OleDbConnection还是采用Application对象,都是一样的需要加载Excel文件(纯粹废话),首先来了一段OleDbConnection读取的代码。

    代码
    string connection =string.Format("Provider=Microsoft.Jet.OLEDB.4.0;DataSource={0};Extended Properties=Excel 8.0;", FilePath);
    OleDbConnection conn
    =new OleDbConnection(connection);
    conn.Open();
    DataTable=conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, newobject[] {
    null,null, null, "Table" });

    上面的代码读取了在某个excel文件中存在所有工作簿,实际上是获取了excel文件的架构,即Sheet,这样可达到动态读取excel文件中所有内容的目的。

    再看如何填充

    代码
    for(int i =0; i < dt.Rows.Count; i++)
    {
    Stringtext
    =string.Format("selec*from {0}", dt.Rows[i]["TABLE_NAME"]);
    OleDbDataAdaptermyCommand
    =new OleDbDataAdapter(text,connection);
    DataSetmyDataSet
    =new DataSet();
    myCommand.Fill(myDataSet);
    }

    上面的代码是把所有工作簿都填充为一个DataSet,这里仅作演示,因为我知道我的excel文件只有一个工作簿,当然实际中我们会分开的填充的。填充完毕后,我打开数据集一看,我被震精了,数据集中只有字符串内容,而并没有图片。这相当让我崩溃。

    再换一个角度,用com对象来读取,思路和上面的一致,加载Excel文件,读取字符串数据。

    代码
    Excel.Application excel =new Excel.Application();
    Excel.Workbook workbook
    = excel.Workbooks.Add(filePath);
    excel.UserControl
    =true;
    excel.Visible
    =false;
    for (int i =0; i < workbook.Worksheets.Count; i++)
    {
    System.Text.StringBuilder sb
    =new System.Text.StringBuilder();
    Excel.Worksheet sheet
    = workbook.Worksheets.get_Item(i +1) as Excel.Worksheet;
    for (int row =2; row <= sheet.UsedRange.Rows.Count; row++)
    {
    //取单元格值;
    for (int col =1; col <= sheet.UsedRange.Columns.Count; col++)
    {
    Microsoft.Office.Interop.Excel.Range range
    = sheet.Cells[row, col] as Excel.Range;
    sb.Append(
    ","+ col.ToString() +":"+ range.Text);
    }
    sb.Append(System.Environment.NewLine);
    Console.WriteLine(sb.ToString());
    //取存图片;
    if (sheet.Shapes.Count >0)
    {
    Bitmap picture;
    IDataObject data
    =null;
    foreach (Excel.Shape item in sheet.Shapes)
    {
    item.Copy();
    data
    = Clipboard.GetDataObject();
    if (null!= data)
    {
    picture
    = (Bitmap) data.GetData(DataFormats.Bitmap);
    picture.Save(
    string.Format(@"D:\temp\aa\{0}.jpg", row));
    }
    }
    }
    }
    }
    workbook.Close(
    false, null, null);
    excel.Quit();

    上面的代码是达到了读取数据和图片的要求,可实在是太慢,特别是对图片的读取上,这对内存一来一往的Copy和Paste,着实让我无法忍受,明明想要的东西就在眼前,这还要跑两次内存读取,相当的无语。

    再次调试,显示IL后发现,我决定使用Shape.CopyPicture()方法,因为我发现Copy和CopyPicture方法实际上调用的是不同的实现,Copy是不管你是什么东西,一概Copy到内存中,CopyPicture则是可以按照一定的外观和格式Copy过去,当然,原理上说,应该是Copy速度更快一些。

    曾经冒出过一个 极其可笑兼常用的方式,直接把IComObject对象转换为托管对象,如下:

    IDataObject data=null;
    Bitmapimg
    =(Bitmap)data

    这里直接失败,别说运行,编译都不通过。

    再又冒出了一个把对象序列化流的想法,希望流的速度快些,结果发现Shape对象不支持序列化,意思是这条路也走不通了,最后看来,目前只能使用内存复制粘贴的方式来执行了。好吧,我还不相信没有别的办法了,等下回我再来收拾你。

  • 相关阅读:
    你是否听说过 HashMap 在多线程环境下操作可能会导致程序死循环?
    深入浅出分析 PriorityQueue
    深入浅出分析 ArrayDeque
    深入浅出的分析 Set集合
    深入浅出的分析 Properties
    深入浅出分析 HashMap
    深入浅出的分析 Hashtable
    深入浅出的分析 WeakHashMap
    深入浅出的分析IdentityHashMap
    python 执行js PyExecJS
  • 原文地址:https://www.cnblogs.com/viter/p/1642221.html
Copyright © 2011-2022 走看看