echart怎样修改内容_随机修改代数题、帮助孩子多复习 —— 一个 Word VBA 小案例...

f527e2e19ca84b1e6860050951af4ffc.png

大家好!时值端午,虽然假期只有三天,但也可以让大家在紧张的工作中稍微透一口气。不过对于已经在电脑前度过一个学期的孩子们来说,小长假恐怕也放松不得,因为马上就要进入疫情后的第一次期末考试了。

孩子考试,家长当然也不会轻松。这不,昨天一位朋友就跟我说:老师在群里发了一套初一代数的例题模板(Word文件),让家长自己在此基础上,随便修改每道题的数字系数和加减号,以便同学反复练习整式化简的技巧。

94b8b69fb9c359ac201d566f252c5706.png

听到这里,杨老师马上明白了他的意思:能不能想个办法,自动修改上面这个 word 文件中每一道题的数字系数和加减号,然后对它们随机修改,从而生成无穷无尽的练习题,比如下面这页:

7c74f16c3e2c0f99beab98ddedd1415a.png

因为这个问题非常适合使用 Word VBA 解决,所以今天我们就聊一聊这个实用的小程序 —— 怎样用 Word VBA 随机“改题”。

从朋友的叙述可知,这个任务包括两个要求:(1)随机改变加减号,也就是正负号(2)随机改变多项式的数字系数。相对而言,加减号的实现思路比较简单,所以咱们就从它开始。

还是我们在《全民一起VBA 基础篇》中反复强调的那个思维:如果不知道怎样写程序,就看看我们人类自己处理这个问题时,会遵循怎样的步骤。

比如对于修改加减号的操作,如果是我们自己手动解决,那么相必会是这样的流程:

  1. 让眼睛定位到第一行

  2. 从左向右读取每一个字符

  3. 如果发现该字符是一个加号或者减号,就停下来执行步骤 4,否则回到第2步继续读取下一个字符

  4. 如果发现是加减号并停下来,那么马上抛一个硬币,如果硬币正面朝上,就把它写成加号、如果背面朝上就写成减号,不管它以前是加号还是减号

  5. 如上反复,直到读完一行所有字符,就回到第1步再读取下一行。

如果各位对上述流程没有异议,那么我们就可以用一模一样的方式写出一个VBA程序。只不过对于其中“定位某一行”、“读取一个字符”、“抛硬币”三个环节,需要用到一点Word对象用法知识和随机数技巧:

技巧1:读取Word文档的每一段

前面的第1步“读取每一行”,在Word中对应的是“读取每一个段落”。我们在《全民一起VBA 提高篇》里学过:当前打开的Word文档(docx文件)在VBA中表示为 ActiveDocumen 对象,而Document类的对象都有一个集合性质的属性 Paragraphs,代表该文档中的所有段落。

所以,我们可以使用 For each p in ActiveDocument.Paragraphs 的方式,依次扫描当前文档中的每一段。每次循环时,循环变量 p 都是一个 Paragraph(段落)对象,代表当前扫描到的那个段落。框架代码如下:

ee4072365cbf804d919cbd882d0b8d8c.png

技巧2:读取一段中的每个字符并修改

Paragraph(段落)对象有一个Range属性,代表该段落的所有内容,包括其中每一个字符以及它们的格式等等。其中 Range.Characters属性代表的就是该段落中的所有字符,Range.Characters(i) 就是其中第 i 个字符,而 Range.Characters.Count 则代表这一段字符的总数量。

所以,使用下面的循环就可以读取每一个段落中的每一个字符,并且将它们都改成 “*”:

26777ae7fbece60d8e1defc9b93bb8ee.png

技巧3:“抛硬币”决定加减号

学过《提高篇》的同学一定都记得“随机数”这个概念,显然,抛硬币就是最经典的随机变量问题。我们知道,VBA中可以使用 rnd() 函数生成一个0到1之间的随机小数,所以只要调用 rnd() 生成一个随机数,然后判断它是否大于0.5 —— 如果大于则返回“+”、否则返回“-”即可。

这里为了简化代码,杨老师使用了一个《全民一起VBA》中没有介绍过的函数 IIF 来表示随机返回加减号的过程:

7380034cd5e5ddb853c777cf81c3350c.png

IIF函数其实就是一个简化版的if语句,与Excel表格公式中的IF函数非常相似:假如第一个参数 Rnd()>0.5 为True,那么就返回第二个参数“+”,否则返回第三个参数“-”。因此上面语句执行后,s 就是一个随机的加号或减号。

攻克了上述三个技巧,稍加组合,VBA代码就已经呼之欲出了:

373b5330f21429180ffcc2b558c94f70.png

上面的代码基本就是前面三个技巧的组合使用,具体参见代码中的注释即可。运行之后,果然所有加减号都被随机处理,下面就是杨老师运行后的截图示例:

4c86822fd9adac07f2dc6e97a0177adc.png

ukd

dbba0efa68a74bfd77331864a35c795f.gif

解决了加减号,接下来就可以解决数字的随机化。整体思路当然也与加减号一样,可以逐个扫描每一段落的每一个字符,如果发现是数字字符,就把它换成一个随机数字字符。

但是别急,咱们先观察一下原来的内容,会发现其中有三个场合会出现数字:(1)题目序号(2)多项式系数比如第一题中的23、15、8 等 (3)指数,比如第一题中a的3次方、c的2次方等。而在这三种场合中,只有(2)多项式系数是需要随机修改的、其他应该保持不变。

60ccedf5033c1cd8aa209ddbba30c19f.png

那么怎样排除掉(1)和(2)两种情况呢?其实也不难。对于(1)题目序号,因为源文档使用的是Word“项目编号”功能,不会被认作段落中的内容字符,因而p.Range.Characters里面根本扫描不到它,所以我们完全可以忽略不管。

而对于出现在(2)“指数”中的数字,则与多项式中的数字系数一样,实实在在是 Range.Characters 中的一员,所以必须要找出来并排除掉。

正规的排除方法,应当是判断一个数字是否出现在加减号、括号、空格等分隔符之后、同时又位于本项的第一个字母之前,所以使用正则表达式更为合理,不过这样做比较复杂。事实上,本例的Word文档中有一个捷径可以利用:所有作为指数的数字,其字体格式都是“上标”。

dc1e65832c7256642302844ff4ebad9e.png

而在Word中,如果我们想知道某一段(用对象 p 代表)的第i个字符的字体,那么只要用 r=p.Range 得到 p 中所有内容范围,接下来可以使用下面的代码实现:

04d428d286b425ca12225f4b448e0303.png

而在Word的Font对象中,又有一个 SuperScript 属性和 SubScript属性,分别代表这个内容的字体格式是否为上标或下标。假如 Font.SuperScript 是 -1 ,则说明是上标格式,0 则说明不是上标。

所以把上面这个判断也加到前面处理加减号的循环中,我们的程序就大功告成了:

b9b7bb0ced33ca846b81aadc92a8c044.png

程序运行,稍等片刻,所有习题果然连参数带正负号都被随机修改。这一次朋友再也不担心孩子没题可做了 —— 无论你小子做题多么快,老爸只要一按按钮,你就得从头再来200道!

17160c958250371e820f10fffa572797.png

当然,因为我们走了一个“捷径”,所以还是会产生一些遗留问题不便处理。比如随机数字只有1-9,没有考虑0;而且有时候还会出现下面这种“不专业”的随机系数:

1259569bfcc8982742d153855afb222a.png

对于这些问题,根本的解决方案是按照数学规范中对“系数”的定义去分析文本,比如“位于一个项的第一个字母之前、若干位连续数字、1可以省略 …… ”,大家有兴趣可以尝试改进。而今天这篇文章只是抛砖引玉,毕竟十几行代码就已经基本解决了随意改题的需求,虽有瑕疵但也足堪使用。反正大过节的,咱就不较真了吧 7e3654efbf77285610ccb43111d3c461.png

祝大家节日快乐!

ukd

00ccf4026cbfc9bd45e6ddac9bf0efa6.gif

更多精彩阅读

b5c81bcc7b1c6f44e5540d1d8d268ff9.gif

接下来,我们会怎么走 —— 关于新的课程和教学方式

不变的,是初心 —— 写在又一门课程收尾之际

为什么又是游戏?—— 摘一段二十多年前的青涩文章

44ed446b19aee320e16b4bd0812cbb90.png

扫码听课

杨老师课程全集

全民一起玩Python

全民一起VBA

欢迎加入、一起进步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值