ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: figfig

[原创] 在vba里使用PERL

[复制链接]

TA的精华主题

TA的得分主题

发表于 2010-5-6 12:49 | 显示全部楼层
本帖已被收录到知识树中,索引项:脚本语言应用
原帖由 figfig 于 2010-5-6 09:26 发表
Sub perl()

Set x = CreateObject("scriptcontrol")
x.Language = "perlscript"
x.eval "$_ = qq(yabba dabba doo);if(~/(abba)/) {$a=$1;}"


MsgBox x.eval("$a")
End Sub


最好把$_解释一下,没学过PERL的新手会看不懂“~/(abba)/”这里省略的内容的。

不过真得谢谢了,还真没想过把VBA和PERL绑在一起,呵呵

TA的精华主题

TA的得分主题

 楼主| 发表于 2010-5-6 12:52 | 显示全部楼层
到现在为止,我们在本学时中一直是在介绍整个数组和列表方面的内容。但是在许多情
况下,需要获得数组中的各个元素,需要搜索数组,改变元素的值,或者将元素添加给数组
或从数组中删除各个元素。
若要获得整个数组的内容,最简单的方法是使用双引号中的数组:
print "@array";
这个例子用于输出@ a r r a y的元素,每个元素之间用空格隔开。数组中的各个元素可以按
索引来访问,如下面这个代码所示。数组元素的索引从数字0开始,每增加一个元素,索引便
递增1。数组的每个元素都有一个索引值,如下所示:
第4学时基本构件的堆栈:列表与数组使用41
下载
数组中元素的数量只受系统内存的限制。若要访问一个元素,可以使用句法$ a r r a y [ i n d e x ],
其中a r r a y是数组的名字, i n d e x是你想要的元素的索引。在引用各个元素之前,数组不一定存
在。数组会魔术般地自动弹出来。下面是访问数组元素的一些例子:
请注意,如果要指@ t r e e s中的某个元素,该代码可以使用一个$。你可能会问:“$标记通
常是保留供标量使用的,这里是怎么回事呢?”在$ t r e e s [ 3 ]中的$是指@ t r e e s中的一个标量值。
标量也可以用美元符号来表示,因为它们也是单数。你应该注意这里的一个模式。
在本学时的开头,我们讲过标量和数组可以拥有相同的变量名,但是它们互不相关。P e r l
能够说明$ t r e e s与@ t r e e s [ 0 ]之间的差别,因为$ t r e e s [ 0 ]中有一个方括号。P e r l知道你指的是
@ t r e e s的第一个元素,而根本不是指$ t r e e s。
还可以将数组划分成分组,称为片。若要使用数组的一个片,可以使用@标号,以指明
你说的是一组元素,也可以使用方括号,以指明你说的是数组的各个元素,如下所示:
Sub perl()

Set x = CreateObject("scriptcontrol")
x.Language = "perlscript"
x.eval "@a=qw (apples oranges bananas);@b=@a[0,1]"


Debug.Print x.eval("@b[0]"), x.eval("@b[1]")



End Sub

TA的精华主题

TA的得分主题

 楼主| 发表于 2010-5-6 13:03 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
有时需要寻找数组的结尾,例如,要查看@ t r e e s数组中究竟有多少树状结构,或者从
@ t r e e s数组中砍下一些树枝来。P e r l提供了两个机制,可以用来查找数组的结尾。第一个方法
是个特殊变量,其形式是$ # a r r a y n a m e。它能够返回数组的最后一个有效索引的号码。请看下
面这个例子:
这个例子包含8个元素,但是你必须记住,数组是从0开始编号的。因此,上面这个例子
输出的号码是7。如果修改$ # t r e e s的值,就会改变数组的长度。如果要缩小数组,请在你设定
的某个索引处截断数组;如果要扩大数组,那么就给它增加更多的元素。新增加的元素的值
将全部设置为u n d e f。
寻找数组大小的另一种方法是在期望存在标量的位置上使用数组变量:
$ s i z e = @ a r r a y ;
这将把@ a r r a y中的元素数量放入$ s i z e中。它利用了P e r l的一个概念,称为上下文(环境),
这将在下一节中介绍。
也可以为数组设定负索引。负索引号从数组的结尾开始计数,然后反向
递增。例如,$ a r r a y [ - 1 ]是@ a r r a y的最后一个元素, $ a r r a y [ - 2 ]是倒数第二个元
素,依次类推。
Sub perl()

Set x = CreateObject("scriptcontrol")
x.Language = "perlscript"
x.eval "@a=qw (apples oranges bananascc);"


Debug.Print x.eval("@a[-2]")



End Sub

TA的精华主题

TA的得分主题

 楼主| 发表于 2010-5-6 13:10 | 显示全部楼层
当你创建一个数组时,常常想让它们用不同于创建时的顺序来显示。例如,如果你的P e r l
程序从文件中读取一个客户列表,那么用字母顺序来输出该客户列表是可行的。若要给数据
排序, P e r l提供了s o r t函数。S o r t函数将一个列表作为它的参数,并且大体上按照字母顺序对
列表进行排序,然后该函数返回一个排定顺序的新列表。原始数组保持不变,如下面这个例
子所示:
这个例子用于输出Bush Carter Clinton Ford Nixon Reagan。应该预先注意的是,它的默认
排序次序是A S C I I顺序。这意味着以大写字母开头的所有单词均排在以小写字母开头的单词的
前面。用A S C I I顺序对数字进行排序的方式与你期望的不一样,它们不按值来排序。例如, 11
排在1 0 0的前面。在这种情况下,必须按非默认顺序来进行排序。
使用s o r t函数,你可以使用代码块(或者子例程名)作为第二个参数,按照你想要的任何
顺序进行排序。在代码块(或者子例程)中,两个变量$ a和$ b被设置为列表的两个元素。代
码块的任务是:如果$ b小于、等于或大于$ a,则分别返回- 1、0或1。下面是进行数字排序的
硬办法,假设@ n u m b e r s是包含了许多数字值的话:
上面这个例子当然按照数字顺序给@ n u m b e r s进行排序。但是,该代码从事这样一个普
通的排序任务看起来太复杂了。由于你可能认为这个方法太麻烦,所以P e r l有一个捷径可供
使用,你可以使用飞船运算符< = >。飞船运算符因为从侧面看它像一个飞行的碟子而得名。
如果它左边的操作数小于右边的操作数,那么它返回- 1,如果左边的操作数大于右边的操作
数,则返回0:
这个代码看上去比较清楚,并且更加直观。飞船运算符只应该用来比较数字值。
若要比较字母字符串,请使用c m p运算符,它的运行方式与飞船运算符完全相同。只需要
编写一个更加复杂的排序例程,就可以将更加复杂的排序参数放在一起。如果你需要了解更
多的情况,本学时第7节中的P e r l常见问题给出了一些比较复杂的例子。
本学时要介绍的最后一个函数是个非常容易使用的函数,即r e v e r s e。当在标量上下文中
被赋予一个标量值时, r e v e r s e函数能够对字符串的字符进行倒序操作,返回倒序后的字符串。
例如,在标量上下之中调用r e v e r s e ( " P e r l ")将返回l r e p。当在列表上下文中被赋予一个列表时,
r e v e r s e函数能够返回倒序后的列表元素,如下面的例子所示:
这个代码段用于输出ham and eggs green like not do I。若要继续进行这个试验,充分展示
该函数堆栈的功能,可以给混合列表添加更多的奇怪内容:
48使用第一部分Perl 基础
下载
print join(' ', reverse so@rtl i n e s ) ;
该代码首先运行s o r t函数,产生一个莫名其妙的列表( I,a n d,d o,e g g s,g r e e n,h a m,
l i k e,n o t)。该列表被倒序后再被传递给j o i n函数,以便将这些元素连接起来,并且加上一个
空格。结果是not like ham green egg do and I,真不敢恭维这样的句子。

Sub perl()

Set x = CreateObject("scriptcontrol")
x.Language = "perlscript"
x.eval "@a=qw (apples oranges bananas,cc,dd);$b=join('', sort @a)"


Debug.Print x.eval("$b")



End Sub

TA的精华主题

TA的得分主题

 楼主| 发表于 2010-5-6 13:14 | 显示全部楼层

回复 31楼 wudixin96 的帖子

  1. ,用户输入的重量存放在$ 中,并用替换运算符和匹配运算符进行操作。
  2. 第6学时模式匹配使用71
  3. 下载
  4. 不过该程序清单存在一个问题,那就是$ 并不是用来存放“重量”的最佳变量名。对于初学
  5. 者来说,$ 并不十分直观,在不经意中, $ 也许被改变了。
  6. 一般来说,将数据长期存放在$ 中是非常危险的,最终你会感到非常恼
  7. 火。P e r l的许多运算符都使用$ 作为默认参数,其中有些运算符也会修改$ 。
  8. $ _是P e r l的通用变量,如果试图将一个值长时间存放在$ _中(尤其是当你学
  9. 习了第8学时的内容后),最终将会导致某些错误。
  10. 在程序清单6 - 2中使用变量$ w e i g h t就比较好。如果要对非$ 的变量使用匹配运算符和替换
  11. 运算符,则必须将它们与该变量连接起来。为此可以使用连接运算符= ~,如下所示:
  12. = ~运算符并不进行赋值,它只是取出右边的运算符,并使它对左边的变量进行操作。整
  13. 个表达式拥有的值与使用$ 时所拥有的值是相同的,正如你在下面这个例子中看到的那样:
复制代码

TA的精华主题

TA的得分主题

发表于 2010-5-6 13:22 | 显示全部楼层
站队学习,请老师举几个perl代替sed、awk的例子。

TA的精华主题

TA的得分主题

 楼主| 发表于 2010-5-6 13:25 | 显示全部楼层
  1. P e r l中的一个常见操作是搜索数组,寻找某些模式。例如,如果将一个文件读入一个数组,
  2. 然后你想要知道哪一行包含某个单词。P e r l有一个特殊的函数,可以用来进行这项操作,这个
  3. 函数称为g r e p。g r e p函数的句法如下:
  4. g r e p函数迭代运行通过l i s t中的每个元素,然后执行e x p r e s s i o n或b l o c k。在e x p r e s s i o n或
  5. b l o c k中,$ 被设置为要计算的列表中的每个元素。如果该表达式返回真, g r e p就返回该元素。
  6. 请看下面这个例子:
  7. 在上面这个例子中, @ d o g s的每个元素被依次赋予$ 。然后根据$ 对表达式/ h o u n d /进行
  8. 测试。返回真的每个元素被g r e p返回,并存放在@ h o u n d s中。
  9. 第6学时模式匹配使用73
  10. 下载
  11. 这里你必须记住两点。首先,在表达式中, $ 是对列表中的实际值的引用。如果修改$ ,
  12. 就会改变列表中的原始元素:
  13. 当运行这个代码后, @ h o u n d s将包含g r e y h o u n d s和b l o o d h o u n d s(请注意它们结尾处的字
  14. 母s )。通过修改$ _,原始数组@ d o g s也被修改了,同时,它现在包含了g r e y h o u n d s、
  15. b l o o d h o u n d s、t e r r i e r、m u t t和c h i h u a h u a。
  16. 需要记住的另一点( P e r l程序员有时忘记了这一点)是: g r e p不一定必须与模式匹配或替
  17. 换运算符一道使用,它可以与任何运算符一道使用。下面这个例子用于检索长度超过8个字符
  18. 的犬名:
  19. g r e p函数与U N I X的一个命令同名,该命令用于搜索文件中的模式。
  20. U N I X的g r e p命令在U N I X中的用处是如此之大(因此在P e r l中用处也很大),
  21. 以至于它已经变成了一个动词,即“ to grep”(进行模式搜索)。如果我们
  22. 说to grep through a book ,那么这句话的意思是翻阅每一页,寻找某个模
  23. 式。
  24. 一个相关函数m a p的句法与g r e p基本相同,不过它的表达式(或语句块)返回的值是从
  25. m a p返回的,而不是$ 的值。可以使用m a p函数,根据第一个数组来产生第二个数组。下面是
  26. 该函数的一个例子:
  27. @ words= map {split ' ',$_} @ input;
  28. 在这个例子中,数组@ i n p u t的每个元素(作为$ 传递给语句块)均用空格隔开。这意味
  29. 着@ i n p u t的每个元素均产生一个单词列表。该列表存放在@ w o r d s中。@ i n p u t的每个相邻行均
  30. 被分隔开来,并在@ w o r d s中进行累加。
复制代码
Sub perl()

Set x = CreateObject("scriptcontrol")
x.Language = "perlscript"
x.eval "@dogs=qw (apples oranges bananas cc dd ccc);@b=grep /cc/,@dogs;"


Debug.Print x.eval("@b[0]"), x.eval("@b[1]")



End Sub

TA的精华主题

TA的得分主题

 楼主| 发表于 2010-5-6 13:38 | 显示全部楼层
只有当P e r l已经遇到子例程的定义时,才能使用上面不带括号的第二种参数形式。
在子例程中,被传递的参数可以通过P e r l的特殊变量@ 来访问。下面这个代码段显示了
为函数传递参数(3个字符串直接量)和输出参数的情况:
若要像下面这个例子中那样,访问传递过来的各个参数,可以使用数组@ 上的下标,就
像你对任何其他数组操作时那样。请记住, $ [ 0 ](@ 的一个下标)与标量变量$ 毫不相干:
对$ [ 3 ]这样的变量名进行操作并不是一种“明确的”编程风格。拥有多个参数的函数常
常为这些参数赋予一个名字,这样,就能够清楚地知道它们能够做些什么。为理解这些话的
含义,请看下面这个例子:
Sub perl()

Set x = CreateObject("scriptcontrol")
x.Language = "perlscript"
x.eval "sub kk{($a,$b)=@_;$a+$b }"


Debug.Print x.eval("&kk(2,3)"), x.eval("$a")



End Sub

[ 本帖最后由 figfig 于 2010-5-6 13:39 编辑 ]

TA的精华主题

TA的得分主题

 楼主| 发表于 2010-5-6 13:50 | 显示全部楼层
s y s t e m函数有一个很小的不足,它没有提供特别好的方法,来捕获命令的输出,并将它
送往P e r l进行分析。如果要以迂回方式进行这项操作,你可以使用下面这个代码:
在上面这个代码段中, s y s t e m运行的命令让它的输出转到一个称为o u t f i l e的文件中。然后
该文件被打开并读入一个数组。这时数据@ d a t a包含了d i r命令的输入。
Sub perl()

Set x = CreateObject("scriptcontrol")
x.Language = "perlscript"
x.eval "system('dir>file');open(kk,'file');@aa=<kk>;$bb=join(',',@aa) "


Debug.Print x.eval("$bb")



End Sub

TA的精华主题

TA的得分主题

 楼主| 发表于 2010-5-6 14:55 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
八、列出数组的索引和值
    上面已经提到,keys()函数返回关联数组下标的列表,如:


%fruit = ("apples", 9,
          "bananas", 23,
          "cherries", 11);
@fruitsubs = keys(%fruits);

    这里,@fruitsubs被赋给apples、bananas、cherries构成的列表,再次提请注意,此列表没有次序,若想按字母顺序排列,可使用sort()函数。
    @fruitindexes = sort keys(%fruits);
    这样结果为("apples","bananas","cherries")。类似的,内嵌函数values()返回关联数组值的列表,如:


%fruit = ("apples", 9,
           "bananas", 23,
           "cherries", 11);
@fruitvalues = values(%fruits);

    这里,@fruitvalues可能的结果为(9,23.11),次序可能不同。

Sub perl()

Set x = CreateObject("scriptcontrol")
x.Language = "perlscript"
x.eval "%fruits = (apples, 9,bananas, 23,cherries, 11);@aa = values(%fruits); @bb = keys(%fruits);"


Debug.Print x.eval("@aa[1]"), x.eval("@bb[1]")



End Sub
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-12-22 17:53 , Processed in 0.045796 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

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