检查一列数据的重复项 vba_从Excel中导出图表到PowerPoint —— VBA技巧与“分解法”思维...

检查一列数据的重复项 vba_从Excel中导出图表到PowerPoint —— VBA技巧与“分解法”思维..._第1张图片

话说我们之所以学习VBA或Python,目的就是为了减少作图作表、复制粘贴等等这些重复无聊的日常操作。而绝大部分这种重复操作,恐怕都是出现在ExcelPowerPoint还有Word这三个最常用的办公工具中。

比如前段时间就有同学在Q群“全民一起VBA 学员交流群”里提出了一个问题:能否使用VBA,将Excel中的统计图表都批量导出到PowerPoint中呢?仔细想想,这个需求在日常工作中还真是比较常见,如果能够自动化完成、免去对一个个图表复制粘贴的操作,确实可以节省大量的时间。所以当时解答完这个问题后,杨老师就一直想写篇文章讲解一下其中涉及到的知识点。只是无奈Python课程录制太紧张,直到现在才腾出手来。

首先,我想同学们希望实现的功能,大概就是下图演示的效果:在一张只有数据的Excel工作表中运行VBA宏(点击按钮),就能让Excel自动把每一列产品数据都单独生成一个折线图,然后再打开或自动创建一个PPT文件,把这些折线图拷贝进去,每张图放进单独一张幻灯片。

检查一列数据的重复项 vba_从Excel中导出图表到PowerPoint —— VBA技巧与“分解法”思维..._第2张图片

这个效果看起来很不赖,但是要怎样用VBA编程实现它呢?相信很多同学面对这种稍微复杂的需求会感到无从下手。其实,只要大家能够领会一个思想,就可以一步步想出解决方案。这个思想就是两个字:分解

检查一列数据的重复项 vba_从Excel中导出图表到PowerPoint —— VBA技巧与“分解法”思维..._第3张图片

下面我们就以这个需求为案例,看看怎样应用分解法来设计程序。首先,分解我们想实现的功能需求。比如对于上面这个演示效果,我们需要实现以下功能:

  1. 在Excel中生成所有统计图表
  2. 打开或新建一个PPT文件
  3. 将所有图表拷贝至该PPT文件中

(大象:还真是三步啊!)

接下来再进一步分析,看看为了实现上面这三个功能,我们需要掌握哪些知识技能:

  1. 在Excel中生成所有统计图表
    1. 能够根据一列数据(比如“产品1”)生成一张统计图表
    2. 能够把 1.1 里面的技能重复循环若干次,从而对所有数据列都生成图表;
  2. 打开或新建一个PPT文件
    1. 能够在VBA中打开一个PPT文件
    2. 能够在VBA中新建一个PPT文件
    3. 能够用一个变量代表打开或新建的PPT文件,以便后面对其进行操作
  3. 将所有图表拷贝至该PPT文件中
    1. 能够逐个找到Excel中每一个图表
    2. 能够把每次找到的图表复制到剪贴板
    3. 能够在PPT文件中新建一张幻灯片
    4. 能够把剪贴板中的图表粘贴到当前幻灯片中

想到这里是不是觉得思路开始清晰了呢?通过上面的分解法,我们不仅明确了编写本程序所需要掌握的知识点,而且顺带着让程序的流程也开始清晰起来。比如1.2里面的“重复循环若干次”,显然就是一个扫描各列的循环语句,而3.1里面“逐个找到并复制”也就是一个扫描所有图表的循环语句。

于是,我们现在就可以依次检查这些知识点,看看哪些是我们已经在《全民一起VBA》课程中学会掌握的、哪些是需要搜索资料补充自学的。

首先,对于 1.1 中要求的“针对一列数据生成统计图表”,我们在《提高篇》第二十七回“工作表随心使用各控件,VBA任意操作统计图”中已经讲解过。

检查一列数据的重复项 vba_从Excel中导出图表到PowerPoint —— VBA技巧与“分解法”思维..._第4张图片

不过考虑到这个功能大家并不总是用到,难免会有遗忘,所以这里我们再一起回忆一下基本的过程:

  1. Excel 工作表对象 Worksheet 有一个集合类型的属性叫做 ChartObjects,代表了这个工作表内的所有图表,里面每一个图表都是一个ChartObject对象。
  2. 调用 Worksheet.ChartObjects 的 Add 方法,就可以在这个工作表中新建一个统计图,用一个ChartObject对象代表。
  3. 调用这个ChartObject对象的 ChartType(图表类型)、SetsourceData(设置数据源)、HasTitle(是否显示标题)、ChartTitle.Text(标题文字)几个方法和属性,就可以生成图表。
  4. 上面一步的关键在于使用 SetSourceData 方法指定数据源。就以我们这次要导出到PPT的工作表为例(见下图),假设我们想为产品 2 (位于D列)创建图表,就需要指定 SetSourceData 中的Range对象包括表格B列(月份)和 D列(产品2数据),行号从3到15。

检查一列数据的重复项 vba_从Excel中导出图表到PowerPoint —— VBA技巧与“分解法”思维..._第5张图片

这就是绘制一个图表的方法。而只要再编写一个循环,依次扫描每一个产品列,然后每找到一列都调用一次这个绘制过程,就可以自动绘制所有图表。这也就是前面分解功能 1.2 的要求。

综上,这段自动绘制所有图表的VBA程序已经呼之欲出。而为了让这个示例代码更清晰好读,我们现在可以把它做成一个函数,具体如下:

检查一列数据的重复项 vba_从Excel中导出图表到PowerPoint —— VBA技巧与“分解法”思维..._第6张图片

至此,功能一 “在Excel中生成所有统计图表”已经实现!所以接下来我们再研究一下第二个功能:怎样在Excel中新建或打开PPT文件。

我们在《全民一起VBA 提高篇》第三十四回“Office软件互相调用、VBA技术处处开花”中讲到过怎样在Excel VBA中创建一个Word对象,从而讲Excel内容导出到Word。显然,同样的模式完全适用于创建PowerPoint对象,只不过对象的名字有所不同。

具体来说,只要调用 CreateObject("PowerPoint.Application"),就可以得到一个 PowerPoint 的Application对象。而我们都知道,无论在Excel VBA还是WordVBA中,Application都是代表该软件本身的最顶级大Boss,可以通过它掌握PowerPoint的一切操作。

比如,PowerPoint的Application对象有一个集合类属性叫做 Presentations,里面容纳了很多个Presentation对象。而所谓的 Presentation(英文“演示”)对象是什么呢?就是一个打开的PPT 文件( .pptx 或 .ppt)!

再进一步,与 Excel VBA 的 WorkBooks 一样,Presentations 集合也有Add方法和Open方法。前者会新建一个空白PPT文件,而后者则是打开一个已经存在的PPT文件。这两种方法都同样返回一个Presentation对象,代表新建或打开的PPT文件 。所以我们只要把这个返回值赋值给一个变量,后面就可以通过该变量控制这个PPT文件了。具体代码如下(假设我们想新建一个PPT文件,并向其中导入Excel图表):

检查一列数据的重复项 vba_从Excel中导出图表到PowerPoint —— VBA技巧与“分解法”思维..._第7张图片

至此,功能2“打开或新建一个PPT文件”也已实现,新建的PPT文件就用变量 ppt_file 来代表。现在万事俱备,只欠“导出”了!

前面提到,Excel 工作表的 ChartObjects 集合容纳了该工作表中所有的图表。所以如果我们在程序中调用刚才编写的“自动生成所有图表”函数,那么自动生成的所有统计图就都被包含在 ChartObjects 中。我们只要用 For Each 循环遍历 ChartObjects,每次就可以得到一个 ChartObject 对象,代表其中一个图表。而 ChartObject 对象都有一个 Copy 方法,执行的功能就是将该图表复制到剪贴板中。所以只要通过下面的代码,我们就能实现前面分解功能 3.1(找到每一个统计图)和 3.2(将统计图复制到剪贴板):

检查一列数据的重复项 vba_从Excel中导出图表到PowerPoint —— VBA技巧与“分解法”思维..._第8张图片

现在终于到了最后两个功能:怎样在刚刚新建的那个PPT文件中增加一张幻灯片(分解功能 3.3 )、然后怎样把剪贴板上的内容(即刚刚复制的统计图)粘贴到这一页幻灯片中(功能3.4)。

在PowerPoint对象体系中,代表一页幻灯片的类叫做Slide。而每个Presentation对象(PPT文件)都有一个Slides集合,容纳了该PPT文件中的每一页幻灯片。与Excel VBA的WorkSheets一样,Slides集合也有Add方法,可以新增一页幻灯片。所以只要调用 Slides.Add ,并且把它的返回值(新幻灯片)赋值给一个变量,就可以通过这个变量操作这一个新建页。

而每一个Slide对象也都有一个Paste方法,功能就是将剪贴板中的内容粘贴到本页幻灯片中。所以我们只要在新建一页幻灯片后,直接调用它的Paste方法,就可以把统计图复制进来!具体代码如下:

检查一列数据的重复项 vba_从Excel中导出图表到PowerPoint —— VBA技巧与“分解法”思维..._第9张图片

大家可能注意到,上面代码中新建幻灯片的 Add 方法比较复杂,提供了两个参数。之所以这样做,是因为默认情况下新建幻灯片会排在所有幻灯片的最前面,后果就是最终幻灯片顺序变成 产品8、产品7、…… 产品1 。而通过上面的两个参数,我们可以要求把新幻灯片的顺序号等于当前已有幻灯片总数slides.count加一;比如当前已经建好了5张幻灯片,那么新建的这一张就排到第6位,换言之,就是让它位于最后。显然,这样做更符合我们希望的展示顺序。

到此,前面分解出来的所有功能都已实现,我们已经可以程序自动生成图表并全部导出到PPT中了!不过还有几个锦上添花的功能和必要的收尾工作需要处理:

首先,为了让幻灯片更漂亮一些,我们可以使用下面的语句把图表标题直接设置为所在幻灯片的页面标题

6f8c2bae3d9f73ca52049c5a5bc2aa54.png

然后,在循环结束、全部导出之后,不要忘记把辛苦得到的PPT文件保存好

cd6b7d497a0a9b52d28dab81e8fdea9c.png

最后,我们在自动生成统计图表时向工作表里新增了一堆统计图,现在不再需要它们,就应该全部删除。这里我们假设工作表中原来没有任何图表,可以简单粗暴的直接用 ChartObjects.Delete 方法删除当前工作表的全部图表对象。

于是最终的主程序代码(不包括前面“自动生成图表”的函数 DrawCharts)如下:

检查一列数据的重复项 vba_从Excel中导出图表到PowerPoint —— VBA技巧与“分解法”思维..._第10张图片

可以看到,这个案例本身并不复杂。但杨老师之所以啰啰嗦嗦写了3000字,就是希望大家不仅了解一个新的技巧(在Excel VBA中创建PPT文件并执行复制粘贴操作),而且希望各位初学者能够体会到怎样构思一个完整的程序怎样解决一个未曾遇到的问题。具体来说,就是怎样对目标功能和知识需求进行“分解”。

要知道,“目标分解”不仅是编写程序的基本思维方式,而且也是整个管理学(目标管理理论)乃至从事数学科学研究的基本工具之一。所以希望初学者能够领会这一思维方式,学会把复杂的功能逐步分解为若干个小问题,再逐个求解

你可能感兴趣的:(检查一列数据的重复项,vba)