搜索
aardio官方社区 门户 查看主题

探讨高效查找读写EXCEL的函数

发布者: xwlzx | 发布时间: 2013-5-1 21:00| 查看数: 4864| 评论数: 12|帖子模式

1、利用VBA的Find函数,其效率比循环读取每一单元格值进行比较要高很多。代码如下。
  1. //仅在同一列用单关键词查找,仅返回行号
  2. findrow=function(sheetobj,key){
  3.     var tab={}
  4.     var rng=sheetobj.cells.find(key,,,1/*_xlWhole*/)
  5.     if(rng==null){
  6.        return false;
  7.            }
  8.           var colid=string.pack(rng.Column+64);
  9.         var mark=rng.row;                                     //退出循环查找的标志
  10.         var i=0
  11.         while(rng){
  12.             i+=1
  13.                   tab[i]=rng.row
  14.             rng=sheetobj.range(colid++":"++colid).FindNext(rng)
  15.                   if(rng.row==mark){
  16.                           break ;
  17.                   }
  18.     }
  19.     if(#tab>1){
  20.         var name=""
  21.         for(i=1;#tab;1){
  22.                 name++=(tab[i]++"行")
  23.         
  24.         }
  25.         import win.clip;
  26.         win.clip.write(name);
  27.             win.msgbox("源表有同名关键词,所在行是:"++name,"提醒:已复制到剪贴板")
  28.     }
  29.     return tab;
  30. }
复制代码
  1. //仅在同一列用双关键词查找,仅返回行号
  2. findmulti=function(sheetobj,key1,key2){
  3.         /*var语句声明的变量作用域限于函数内部*/
  4.         var tab={}
  5.         var rng2=sheetobj.cells.find(key2,,,1/*_xlWhole*/)      //注意:rng2必须放在rng1前,否则会清空while中的rng1
  6.         if(rng2==null){
  7.        return false;
  8.            }
  9.         var colid=rng2.column
  10.     var rng1=sheetobj.cells.find(key1,,,1/*_xlWhole*/)
  11.     if(rng1==null){
  12.        return false;
  13.            }
  14.     var markrow=rng1.row;                                   //退出循环查找的标志
  15.     var markcol=rng1.Column;                                //退出循环查找的标志
  16.     var col=string.pack(markcol+64);
  17.     var i=0
  18.     while(rng1){
  19.             if(sheetobj.cells(rng1.row,colid).value2==key2){
  20.                 i+=1
  21.                     tab[i]=rng1.row
  22.             }
  23.             //rng1=sheetobj.cells.FindNext(rng1)
  24.             rng1=sheetobj.range(col++":"++col).FindNext(rng1)
  25.                   if(rng1.row==markrow){
  26.                           break ;
  27.                   }
  28.     }
  29.     if(#tab>1){
  30.         var name=""
  31.         for(i=1;#tab;1){
  32.                 name++=(tab[i]++"行")
  33.         
  34.         }
  35.         import win.clip;
  36.         win.clip.write(name);
  37.             win.msgbox("源表有同名关键词,所在行是:"++name,"提醒:已复制到剪贴板")
  38.     }
  39.            return tab;
  40. }
复制代码
2、利用循环读取单元格值进行比较,效率比较低下,但不失为一种思路。代码如下。
  1. findmulti=function(sheetobj,key1,key2){
  2.         /*var语句声明的变量作用域限于函数内部*/
  3.         var tab={}
  4.     var rng1=sheetobj.cells.find(key1)
  5.     var rng2=sheetobj.cells.find(key2)
  6.     if(rng1==null or rng2==null){
  7.        return false;
  8.            }
  9.     var maxcol1=string.pack(rng1.column+64)//转成列号
  10.     var usedrow=sheetobj.Range(maxcol1++"65536").End(-4162/*_xlUp*/).Row    //已使用的有效行数
  11.     var j=0
  12.            for(i=1;usedrow;1){
  13.               if(sheetobj.cells(i,rng1.column).value2==key1){
  14.                         if(sheetobj.cells(i,rng2.column).value2==key2){
  15.                            j+=1
  16.                                  tab[j]=i
  17.                                  break ;
  18.                         }
  19.               }
  20.           
  21.            }
  22.            return tab;
  23. }
复制代码
3、读行区域到数组
  1. readarray=function(sheetobj,row,startcol,endcol){
  2.         /*var语句声明的变量作用域限于函数内部*/
  3.         tab={}
  4.         for(i=1;endcol-startcol+1;1){
  5.                 tab[i]=sheetobj.cells(row,startcol+i-1).value2
  6.         }
  7.         return tab;
  8. }
复制代码
4、写数组到行区域
  1. writearray=function(sheetobj,row,startcol,tab){
  2.         /*var语句声明的变量作用域限于函数内部*/
  3.         for(i=1;#tab;1){
  4.                 sheetobj.cells(row,startcol+i-1).value2=tab[i]
  5.         }
  6. }
复制代码
注:读写单元格区域最好不要用sheetobj.range("单元格区域").value2;原因是:如果"单元格区域"中有空值单元格,就会造成读写失败。

评分

参与人数 2专家分 +100 银币 +2 收起 理由
xuefu3858 + 2 赞一个!
qqmmcc + 100 赞一个!

查看全部评分

最新评论

nvt303 发表于 2013-5-2 09:34:34

学习!

学习!
hgbuser 发表于 2013-5-2 10:40:38

这个思路不错,收藏

这个思路不错,收藏
aifuqiang 发表于 2013-11-5 20:47:57

太慢了,如果不往exl里面写数据,单是从数据库查询,得30s,如果按照这种方式插入的话,下来得5分钟,只是1800条数据,如果60多W的数据的话,就得一天一夜不

太慢了,如果不往exl里面写数据,单是从数据库查询,得30s,如果按照这种方式插入的话,下来得5分钟,只是1800条数据,如果60多W的数据的话,就得一天一夜不止
求更高速方法
AAuFuns 发表于 2013-11-5 22:58:32

[quote][size=2][url=forum.php?mod=redirect&goto=findpost&pid=62673&ptid=10200][c

aifuqiang 发表于 2013-11-5 20:47
太慢了,如果不往exl里面写数据,单是从数据库查询,得30s,如果按照这种方式插入的话,下来得5分钟,只是1 ...

60多W的数据;
用数据库了,不要用Excel 。
aifuqiang 发表于 2013-11-6 11:46:55

[quote][size=2][url=forum.php?mod=redirect&goto=findpost&pid=62677&ptid=10200][c

AAuFuns 发表于 2013-11-5 22:58
60多W的数据;
用数据库了,不要用Excel 。

客户经常需要提数据,将oracle数据库的数据提取他们想要的,然后导出在exl里面
AAuFuns 发表于 2013-11-7 10:08:51

[quote][size=2][url=forum.php?mod=redirect&goto=findpost&pid=62695&ptid=10200][c

aifuqiang 发表于 2013-11-6 11:46
客户经常需要提数据,将oracle数据库的数据提取他们想要的,然后导出在exl里面

用ADO 后台连接数据库,Excel 只做前台显示一部分数据。
不必一股脑都倒入Excel 。
aifuqiang 发表于 2013-11-8 11:16:59

[quote][size=2][url=forum.php?mod=redirect&goto=findpost&pid=62750&ptid=10200][c

AAuFuns 发表于 2013-11-7 10:08
用ADO 后台连接数据库,Excel 只做前台显示一部分数据。
不必一股脑都倒入Excel 。

最后使用sql操作exl   效果比较理想     
xwlzx 发表于 2014-1-29 14:28:20

[code][lang=aardio,false]readarray=function(sheetobj,row,startcol,endcol){ /*v

  1. readarray=function(sheetobj,row,startcol,endcol){
  2.         /*var语句声明的变量作用域限于函数内部*/
  3.         tab={}
  4.         for(i=1;endcol-startcol+1;1){
  5.                 tab[i]=(not sheetobj.cells(row,startcol+i-1).value2)?"":(sheetobj.cells(row,startcol+i-1).value2)
  6.         }
  7.         return tab;
  8. }
复制代码


避免读取EXCEL空值导致出错,改进:
  1. tab[i]=sheetobj.cells(row,startcol+i-1).value2
复制代码


  1. tab[i]=(not sheetobj.cells(row,startcol+i-1).value2)?"":(sheetobj.cells(row,startcol+i-1).value2)
复制代码
ybzjl 发表于 2014-2-17 06:42:54

感兴趣操作Excel的话题,好好学习一下。

感兴趣操作Excel的话题,好好学习一下。
lvhoo 发表于 2016-6-9 09:09:35

如果要读取excel中,sheet(1)中区域A1:K50的内容, 怎么实现呢? 一个单元格一个单元格的循环读取,效率太低。 按上面的整行读取,其实也是一

如果要读取excel中,sheet(1)中区域A1:K50的内容,
怎么实现呢?
一个单元格一个单元格的循环读取,效率太低。
按上面的整行读取,其实也是一个一个单元格的读取。
有没有可以整个区域读取的方法?如何实现
alajia 发表于 2016-10-19 17:03:42
本帖最后由 alajia 于 2016-10-19 17:04 编辑

结合整个单元格区域和单个单元格的读写,能有效提高效率。
以楼上“读取excel中,sheet(1)中区域A1:K50的内容”为例:
  1. var tab = sheet.range("A1:K50").value2;        //读单元格区域

  2. //校验是否有读取失败
  3. for(i=1;50;1){
  4.         for(j=1;11;1){
  5.                 if( tab[i][j] == null ){       
  6.                         if(sheet.Cells(i,j).value2){
  7.                                 tab[i][j] = sheet.Cells(i,j).value2;        //重新读取单个单元格内值
  8.                         }
  9.                         else {
  10.                                 tab[i][j] == "";        //防止写单元格区域错误       
  11.                         }
  12.                 }                       
  13.         }
  14. }

  15. //数值处理......

  16. sheet.range("A1:K50").value2 = tab;        //写单元格区域
复制代码


如果空值单元格不多,可以提升效率
taochunsong 发表于 2016-10-22 01:28:23
学习····

手机版|未经许可严禁引用或转载本站文章|站长邮箱|aardio.com|aardio官方社区 ( 皖ICP备09012014号 )

GMT+8, 2017-11-23 21:04 , Processed in 0.093750 second(s), 21 queries , WinCache On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表