我的宏没法进入循环了,是罗技鼠标宏怎么循环回事

查看: 11357|回复: 11
[已解决]【求教】vba死循环,怎么正确的让宏停止
【求教】vba死循环,怎么正确的让宏停止请老师帮助下。我自己假想的,另外开一个excel程序,来终止原来的excel死循环,不知道可以不。或者老师有更好的方法,请您赐教
醉风发布于
编程过程发现死循环可以长按【Esc】键中断,但如果明知会造成死循环还不去设法避免,那这设计也就是失败的。
Ctrl+Break
按Ctrl+Break
Ctrl + Pause breek
都保存不了表格呀,还有什么方法呢???????
不要有死循环好了,别人写的话先禁止宏,看死循环在哪里,注释掉
&&&本楼为最佳答案&&&
编程过程发现死循环可以长按【Esc】键中断,但如果明知会造成死循环还不去设法避免,那这设计也就是失败的。
以下是引用醉风在 12:37:00的发言:编程过程发现死循环可以长按【Esc】键中断,但如果明知会造成死循环还不去设法避免,那这设计也就是失败的。其实也不是死循环,但表格就是停不下来,很奇怪。现在没有出现这个情况了,下次出现用你的方法试验下。谢谢了,就你这个方法创新了
Powered by> 博客详情
宏的主要作用就是简化代码编写,简化一些需要重复编码的地方,以得到看起来更优雅的代码。但宏要用得好并不容易,用的不好很容易引发灾难性的后果。本文会介绍宏比较偏门但又很实用的技巧。
首先就是最常用的技巧(
#define MACROCAT( x, y ) MACROCAT1 ( x, y )
#define MACROCAT1( x, y ) x##y
#define TOSTRING( s ) #s
MACROCAT把x和y展开后连結,而TOSTRING把s转化为字符串,比如可以printf(TOSTRING(%s), TOSTRING(abcdefg));
然后,因为宏不能递归,但可以做递归模拟,我们可以这样玩。比如要生成n位的二进制数并且从小到大构成的字符串(用到前面的宏):
#define BIN_0(arg) TOSTRING ( arg )
#define BIN_1(arg) BIN_0(MACROCAT(arg, 0)) &,& BIN_0(MACROCAT(arg, 1))
#define BIN_2(arg) BIN_1(MACROCAT(arg, 0)) &,& BIN_1(MACROCAT(arg, 1))
#define BIN_3(arg) BIN_2(MACROCAT(arg, 0)) &,& BIN_2(MACROCAT(arg, 1))
#define BIN_4(arg) BIN_3(MACROCAT(arg, 0)) &,& BIN_3(MACROCAT(arg, 1))
int main()
puts(BIN_4());
这里要注意的是,比如BIN_2(),实际上展开的结果是
&0& &0& &,& &0& &1& &,& &1& &0& &,& &1& &1&
不过c/c++规定这样连写的字符串,编译时就会合并成一个,于是就能用puts直接完整输出结果了
如果你想得到更多的位,很简单,只要你不介意,上面的宏复制并改改数字就可以了
不过,这样一改要改若干个数字,比较麻烦,能不能让它工作得更好?比如只要改宏名?
这个时候,就要用更富有技巧性的一招了:让每个宏多一个参数n,然后前面的BIN_x使用MACROCAT把它与数字连结起来,不就可以了么?
想法不错,不过问题是宏本身没有做减法的能力,能做的仅仅是替换。减1应该怎么实现呢?
其实不难,见以下定义:
#define DECVAL_1 0
#define DECVAL_2 1
#define DECVAL_3 2
#define DECVAL_4 3
#define DECVAL_5 4
#define DECVAL_6 5
#define DECVAL_7 6
#define DECVAL_8 7
#define DECVAL_9 8
#define DECVAL( n ) DECVAL_##n
好了,有了这个利器,我们就可以对原宏改造了,先拿0号和1号宏开刀:
#define BIN_0(n, arg) TOSTRING ( arg )
#define BIN_1(n, arg) MACROCAT(BIN_, DECVAL(n)) (DECVAL(n), MACROCAT(arg, 0))
&,& MACROCAT(BIN_, DECVAL(n)) (DECVAL(n), MACROCAT(arg, 1))
看得懂替换了一些什么吗?这样,后面的2,3,4,5号,只要复制一下1号的定义,改一改宏名就解决问题了
这里生成的二进制结果是带前导0的,如何改写能使生成的结果不带前导0?
使用此法可以“递归”式生成很多类似代码,同时这个技巧也非常的实用,但递归构造并不容易,需要编写的人仔细想清楚,否则很容易出错,特别要注意宏展开的时机,一般不直接使用MACROCAT1宏,因为那个很可能不是你想要的结果
之后,到C99标准出台后(也就是说,下文内容与bc3/tc/vc6不兼容),宏里面多了一个狠角色:可变参数个数宏
比如可以 #define PRINTF(…) fprintf(stdout, VA_ARGS)
其中__VA_ARGS__代表了‘…’部分的全部参数,这样可以轻松的重定义库函数里不定参数的函数的输出行为,比如printf重定向到文件(虽然也可以用freopen实现,但只想说明宏也可以这样搞)
好了,下文将区分编译器来介绍,一共分为两派,vc派和gcc派(包括clang/objc),因为两者对以下代码的处理并不一致,需要使用略为不同的宏来实现,目前我也只遇到这两派。
现在的目的是这样,因为__VA_ARGS__包含了若干参数,我怎么才能知道里面参数有多少个呢?
比如写一个宏NUM_PARAMS(),里面写NUM_PARAMS(abc,a,d,e)的话,替换后得到的结果要是4,能办到吗?
广告时间:
广告过后,回来精彩的节目
首先先介绍gcc派的解决方案:
#define PP_NARG(...) PP_NARG_(VA_ARGS, PP_RSEQ_N())
#define PP_NARG_(...) PP_ARG_N(VA_ARGS)
#define PP_ARG_N(
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10,
_11,_12,_13,_14,_15,_16, N, ...) N
#define PP_RSEQ_N()
16,15,14,13,12,11,10,
9,8,7,6,5,4,3,2,1,0
非常漂亮巧妙又简洁的方案,我想不用我多解释了吧?
不过,请注意,这是gcc的方案,以上代码放在vc8/vc9/vc2010等都会得不到正确的结果的,这个和vc的宏处理方式有关
接下来就是给出vc的解决方案(以下均以vc2008和vc2010为准)
#define BRACKET_L() (
#define BRACKET_R() )
#define PP_NARG(...)
PP_NARG_ ( VA_ARGS, PP_RSEQ_N() )
#define PP_NARG_(...)
PP_ARG_N BRACKET_L() VA_ARGS BRACKET_R()
#define PP_ARG_N(
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10,
_11,_12,_13,_14,_15,_16, N,...) N
#define PP_RSEQ_N()
16,15,14,13,12,11,10,
9,8,7,6,5,4,3,2,1,0
这里很特别的一点是对部分小括号做了替换。
问题在于PP_NARG_到PP_ARG_N做参数传递的时候,如果已有显式的括号,那么不对里面的宏做展开计算参数个数,仅直接按显式的逗号个数判断出参数个数,从而导致__VA_ARGS__被当成一个参数传入。而把括号用宏替换掉后,则不出现直接的括号,就先对宏做展开,而展开后,再展开新构造出来的宏,这样才能让参数匹配上。
不过gcc里面不能这么干,gcc会把宏名展开出来后,如果发现后面的符号并不是显式的括号,则把前面的宏符号化,不再展开。这两种不同的特性让我现在还不知道怎么编写宏能让两派都能兼容,正确展开出我想要的东西。
解释了两个编译器的不同点以后,后面不再解释相同的问题,而会同时给出两份代码。
另一个类似的问题,就是既然有不定个数的参数,如果我希望对每个参数都做一些处理,那如何做呢?
举例,实现一个宏#define SPREAD(…),要把参数里的东西连结成一个字符串
之前的例子里,已经实现了把不定参数展开的手段,现在我们来尝试递归下降式展开(gcc版本):
#define SPREAD0( arg ) #arg
#define SPREAD1(arg, …) SPREAD0(arg)
#define SPREAD2(arg, …) SPREAD0(arg) SPREAD1(VA_ARGS,)
#define SPREAD3(arg, …) SPREAD0(arg) SPREAD2(VA_ARGS,)
#define SPREAD4(arg, …) SPREAD0(arg) SPREAD3(VA_ARGS,)
#define SPREAD5(arg, …) SPREAD0(arg) SPREAD4(VA_ARGS,)
#define SPREAD6(arg, …) SPREAD0(arg) SPREAD5(VA_ARGS,)
#define SPREAD7(arg, …) SPREAD0(arg) SPREAD6(VA_ARGS,)
#define SPREAD8(arg, …) SPREAD0(arg) SPREAD7(VA_ARGS,)
#define SPREAD9(arg, …) SPREAD0(arg) SPREAD8(VA_ARGS,)
#define SPREAD(…) SPREAD9(VA_ARGS)
在这里,每进入一层,就从__VA_ARGS__拆解一个最前面的参数出来,把剩下的参数给下一层
这里有一个细节是__VA_ARGS__后面有一个逗号,意思就是补一个空参数,避免后面参数不足
然后就可以用puts(SPREAD(1, 2, 3, 4));来测试了
当然,还要使用前文的方式处理一下(gcc版):
#define SPREAD0( arg ) #arg
#define SPREAD1(n, arg, …) SPREAD0(arg)
#define SPREAD2(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) ( DECVAL(n), VA_ARGS, )
#define SPREAD3(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) ( DECVAL(n), VA_ARGS, )
#define SPREAD4(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) ( DECVAL(n), VA_ARGS, )
#define SPREAD5(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) ( DECVAL(n), VA_ARGS, )
#define SPREAD6(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) ( DECVAL(n), VA_ARGS, )
#define SPREAD7(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) ( DECVAL(n), VA_ARGS, )
#define SPREAD8(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) ( DECVAL(n), VA_ARGS, )
#define SPREAD9(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) ( DECVAL(n), VA_ARGS, )
#define SPREAD(…) SPREAD9 ( 9, VA_ARGS )
#pragma warning(disable:4003) // 去除警告
#define SPREAD0( arg ) #arg
#define SPREAD1(n, arg, …) SPREAD0(arg)
#define SPREAD2(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) BRACKET_L() DECVAL(n), VA_ARGS, BRACKET_R()
#define SPREAD3(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) BRACKET_L() DECVAL(n), VA_ARGS, BRACKET_R()
#define SPREAD4(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) BRACKET_L() DECVAL(n), VA_ARGS, BRACKET_R()
#define SPREAD5(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) BRACKET_L() DECVAL(n), VA_ARGS, BRACKET_R()
#define SPREAD6(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) BRACKET_L() DECVAL(n), VA_ARGS, BRACKET_R()
#define SPREAD7(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) BRACKET_L() DECVAL(n), VA_ARGS, BRACKET_R()
#define SPREAD8(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) BRACKET_L() DECVAL(n), VA_ARGS, BRACKET_R()
#define SPREAD9(n, arg, …) SPREAD0(arg) MACROCAT(SPREAD, DECVAL(n)) BRACKET_L() DECVAL(n), VA_ARGS, BRACKET_R()
#define SPREAD(…) SPREAD9 BRACKET_L() 9, VA_ARGS, BRACKET_R()
以上只是模糊方式展开,因为参数个数不知道,后面会遇到宏参数为空的情况,于是vc编译器给出了警告
如果把之前说的过技巧,就是分析出不定参数个数的宏,与这个结合,将产生更大的威力,我们可以实现精确展开,就是在SPREAD宏的定义里,有9的地方使用宏PP_NARG(VA_ARGS)替换一下,于是__VA_ARGS__后面的逗号可以去掉,也可以简化一些代码了,也能避免展开后有你所不希望的多余字符出现。
测试考题1:
定义一宏#define printf,让它能把printf(str, a, b, c);替换成std::cout&&a&&b&&c&&std::
参数个数不确定,不用考虑str的内容,但假设不多于10个参数
宏的威力还不止至此,当宏与C++模板编程结合的时候,真正的可怕就来临了。。。
测试考题2:
在C++0x之前,模板还没有不定参数,于是需要多个参数的时候,不得不手工解决,或者聪明的人,使用模板来生成多参模板代码。尝试一下这么做,看看和之前的问题难度加大在哪里。比如生成一个名为sum的模板函数,能接受1 – 10个参数,返回这些参数的相加的结果
文章附带:
第一考题参考答案:
#define BINARY_E0(n, arg) TOSTRING ( arg )
#define BINARY_E1(n, arg) MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 0) )
&,& MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 1) )
#define BINARY_E2(n, arg) MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 0) )
&,& MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 1) )
#define BINARY_E3(n, arg) MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 0) )
&,& MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 1) )
#define BINARY_E4(n, arg) MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 0) )
&,& MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 1) )
#define BINARY_E5(n, arg) MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 0) )
&,& MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 1) )
#define BINARY_E6(n, arg) MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 0) )
&,& MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 1) )
#define BINARY_E7(n, arg) MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 0) )
&,& MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 1) )
#define BINARY_E8(n, arg) MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 0) )
&,& MACROCAT(BINARY_E, DECVAL(n)) ( DECVAL(n), MACROCAT(arg, 1) )
#define BINARY_ENUM(n) MACROCAT(BINARY_E, n) ( n, )
#define BIN_0(n, arg) TOSTRING ( arg )
#define BIN_1(n, arg) MACROCAT(BIN_, DECVAL(n)) (DECVAL(n), arg)
&,& MACROCAT(BINARY_E, DECVAL(n)) (DECVAL(n), MACROCAT(arg, 1))
#define BIN_2(n, arg) MACROCAT(BIN_, DECVAL(n)) (DECVAL(n), arg)
&,& MACROCAT(BINARY_E, DECVAL(n)) (DECVAL(n), MACROCAT(arg, 1))
#define BIN_3(n, arg) MACROCAT(BIN_, DECVAL(n)) (DECVAL(n), arg)
&,& MACROCAT(BINARY_E, DECVAL(n)) (DECVAL(n), MACROCAT(arg, 1))
#define BIN_4(n, arg) MACROCAT(BIN_, DECVAL(n)) (DECVAL(n), arg)
&,& MACROCAT(BINARY_E, DECVAL(n)) (DECVAL(n), MACROCAT(arg, 1))
#define BIN_5(n, arg) MACROCAT(BIN_, DECVAL(n)) (DECVAL(n), arg)
&,& MACROCAT(BINARY_E, DECVAL(n)) (DECVAL(n), MACROCAT(arg, 1))
#define BIN_6(n, arg) MACROCAT(BIN_, DECVAL(n)) (DECVAL(n), arg)
&,& MACROCAT(BINARY_E, DECVAL(n)) (DECVAL(n), MACROCAT(arg, 1))
#define BIN_7(n, arg) MACROCAT(BIN_, DECVAL(n)) (DECVAL(n), arg)
&,& MACROCAT(BINARY_E, DECVAL(n)) (DECVAL(n), MACROCAT(arg, 1))
#define BIN_8(n, arg) MACROCAT(BIN_, DECVAL(n)) (DECVAL(n), arg)
&,& MACROCAT(BINARY_E, DECVAL(n)) (DECVAL(n), MACROCAT(arg, 1))
#define BIN_ENUM(n) &0& MACROCAT(BIN_, n) ( n, )
测试代码:puts(BIN_ENUM(8));
测试考题不提供答案。
语法高亮测试
再一次尝试MMX优化AlphaBlend
闲的X痛就写了个C/C++源文件删除注释代码的程序
C语言循环的小艺术
委托模式的C++初步实现的烂代码一份。。。摊手
另一种用位运算枚举所有组合的算法
[原创] 88行代码实现俄罗斯方块游戏(含讲解)
另类的谢宾斯基(Sierpinski)分形三角形输出程序
支付宝支付
微信扫码支付
打赏金额: ¥
已支付成功
打赏金额: ¥查看: 5741|回复: 4
新人求助!如何循环执行一段宏命令
阅读权限10
在线时间 小时
因为工作需要,每天需要把许多工作表的信息汇总到一个工作薄里,虽然是西拼八凑总算凑出一个宏,可是每次运行都要点快捷键简直太麻烦,怎样才能让宏循环执行呢?Sub 粘表()
& & Selection.Copy
& & Windows(&排采四队日报.xls&).Activate
& & Sheets(&Sheet3&).Select
& & ActiveCell.Select
& & Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
& && &&&:=False, Transpose:=False
& & ActiveCell.Offset(1, 0).Select
& & Windows(&排采四队数据总表.xls&).Activate
& & ActiveSheet.Next.Select
End Sub复制代码还有因为这个ActiveSheet.Next.Select每次到最后一张工作表都会跳出错误,改怎么解决好,求指点
阅读权限95
在线时间 小时
使用For Each ws&&in worksheets循环好一些,建议上传附件。
阅读权限10
在线时间 小时
求各位老师解惑!刚刚在网上找了一段循环语句硬套了进去,还是没有解决问题以及到最后一张工作表出错的情况,原始文件太大,只择了前几张表,附上刚刚写的循环语句Sub sheet3粘表()
& &Dim i As Integer
& &For i = 1 To Sheets.Count
& & Selection.Copy
& & Windows(&忻州分公司
排采四队日报表.xls&).Activate
& & Sheets(&Sheet3&).Select
& & ActiveCell.Select
& & Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
& && &&&:=False, Transpose:=False
& & ActiveCell.Offset(1, 0).Select
& & Windows(&忻州分公司
排采四队数据总表.xls&).Activate
& & ActiveSheet.Next.Select
& & Next i
End Sub复制代码
11:26 上传
点击文件名下载附件
307.91 KB, 下载次数: 19
阅读权限30
在线时间 小时
看你录的宏&&只是跨表张贴数据
你用selection 看不出要求& &不如你直接说清楚要求好些& &
阅读权限10
在线时间 小时
宏就是直接录的然后改了下,见笑了,我的意思是能把附件里“数据总表”里每个工作表当天日期的数据区域依次条件粘贴到“日报表”的sheet3里面,不知道有没有更好的办法
最新热点 /1
ExcelHome每周都有线上直播公开课,
国内一流讲师真身分享,高手贴身答疑,
赶不上直播还能看录像,
关键居然是免费的!
厚木哥们都已经这么努力了,
你还好意思说学不好Office。
玩命加载中,请稍候
玩命加载中,请稍候
Powered by
本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任! & & 本站特聘法律顾问:徐怀玉律师 李志群律师大家都在搜:
扫描二维码安装房天下APP
手机浏览器访问房天下
> > 问题详情
C语言进入死循环了怎么退出啊???
浏览次数:0
正确的做法是Ctrl+Break,然后修改程序。重新运行后它问你是否重新编译,按是“Y”。
不知道下面这条知识能否帮助到您
最近许多人开始讨论,眼下买房值不值得?对于这个问题没有人能给出准确的答案,但是小编经过梳理发现,这8种房子卖了铁定赔死!下面咱们来一起看看。
买房注意了!这6种房子买了铁定赔死!!
手机动态登录
请输入用户名/邮箱/手机号码!
请输入密码!
没有房天下通行证,
ask:3,asku:1,askr:113,askz:18,askd:19,RedisW:0askR:1,askD:157 mz:nohit,askU:0,askT:0askA:160
Copyright &
北京拓世宏业科技发展有限公司
Beijing Tuo Shi Hong Ye Science&Technology Development Co.,Ltd 版权所有
违法信息举报邮箱:

我要回帖

更多关于 魔兽世界无限循环宏 的文章

 

随机推荐