VBA/VBScript提取Word(*.doc)文件中包含的图片(照片)

要处理的人事简历表是典型的Word文档,其中一人一份doc,里面包含有个人的照片,如果要把里面的照片复制出来就比较麻烦了,一般手动的做法是选择文件另存为,保存类型选择“网页(*.htm; *.html)”,这样就会另存为网页形式,同时会有个以文件名开头,以.files结尾的文件夹,点击进去就可以看到Word里面嵌入的所有资源,包含所需要的图片资源。

值得注意的是该文件夹里同一张图片正常会有两个副本,其中一张图片文件体积较大,另一张图片文件体积较小,显而易见较小体积的文件是Word自动创建的缩略图,在绝大多数情况下我们可能仅仅需要原始的插入图片,那么选择较大体积的图片文件即可,好在我要处理的人事简历表只有员工的一张照片,那么另存为网页后的文件夹也仅仅只有两张图片,一张原始图片,一张缩略图,这两张图片可以通过大小区分。

继续阅读

VBA/Python/VBScript导出PowerPoint(PPT)幻灯片为JPG图片或者纯文本TXT

最近需要对一堆幻灯片进行整理,为了便于检索,决定做一个全文检索系统,整个系统依旧考虑采用Python技术构建,不得不承认Python的开发效率挺高,我采用Flask+Whoosh一个下午就搭建好搜索平台了。今天把一些细节和大家分享一下,首先是幻灯片不同于Word文档,对于幻灯片的检索我是这样考虑的:对于每一张幻灯片分别保存一张图片和纯文本文字,然后让全文检索引擎检索文本,向最终用户提供纯文本和图片化的幻灯片。这里涉及的技术细节是如何将幻灯片导出为图片格式,当然这里还得请出ActiveX/COM对象VBA技术,对于幻灯片的控制采用的ProgID为PowerPoint.Application

这里同样的采用PyWin32Dispatch或者DispatchEx方法:

from win32com.client import DispatchEx
 
powerpoint = DispatchEx("PowerPoint.Application")
powerpoint.Visible       = True    # 为了便于查阅PPT工作情况,这里设置为可见
powerpoint.DisplayAlerts = False   # 为了使工作不中断,忽略可能的弹出警告

继续阅读

VBA/VBScript批量搜索多个Word或者Excel指定的包含文字

假设我们有多个Word或者Excel文件,现在我们要从这些文件中搜索特定的关键字,比较笨的办法就是一个一个打开,然后“编辑 – 查找”,文件少还好办,如果文件比较多的话,那么打开这么多文件也累得我们够呛。

下面我讲解一个利用VBScript自动批量搜索特定文字的办法,首先还是上面的算法,只不过将人工一个一个打开换成计算机自动打开。实际上这里主要是枚举文件,然后在利用ActiveX控件调用Word.Application或者Excel.Application内部的查找方法来实现相关功能。

对于一份简单的Word文档,基本的查找VBA可以像下面这样实现:

Dim hasFound ' 定义是否找到
Selection.WholeStory
With Selection.Find
    .ClearFormatting
    .MatchWholeWord = False
    .MatchCase = False
    hasFound = .Execute("要查找的文字")
End With

转化为VBScript代码也很容易,多个创建Word.Application并打开Word文件的过程。

继续阅读

VBA/VBScript裁剪拆分Word文档为多个文件(分解为多个独立页面)

标题可能不是很恰当,准确的来说就是将一个有很多页面的Word文档按照指定的页数分解为多个独立的Word文档。本来想通过复制指定页内容然后再新建Word来实现的,后来发现这样做一是很麻烦,二是格式容易错。最后想到了一个比较笨的办法:复制一份原稿,然后除了要保留的页面外,其余的统统删去,然后下个页面再复制一份,以此反复,直到完成全部的拆分。

对于页面的删除,可以通过先选中这个页面内容,然后再执行Selection.Delete方法。这样删除不需要的页面后留下的就是我们需要保留的页面了,这份文档算是完成。

这里有个需要注意的地方,保留Word文档N页中第M页共P页,需要执行两步删除,第一步是删除M页之前的所有页面,第二步是删除M+P页之后的所有页面,然后得到的就是所要的。细节方面就是当执行第一步后,第M页会自动转为第1页(因为前面的都删除了),所以我们接下来执行第二步的时候需要从第1+P页开始,另外如果M=1,说明需要保留从第一页开始,那么第一步可以略去,如果M+P>=总页数,则说明需要保留的包含最后一页,那么第二步就可以略去。

下面提供一份VBScript Class msoWord_SplitPages,其中演示了上面的算法思路,供大家参考:

继续阅读

VB/VBA/VBScript根据出生日期计算年龄函数ComputeAge

有时需要处理一些Excel,这些Excel规定的日期格式是类似2012.02.26这样的形式,当我用到VBA或者VBScript处理这些日期时就很难识别并转换类似的日期格式。一般做法都是通过Split按点对其进行拆分。如果要求计算精确到年的话还好办,直接拿今年的年去减出生年就可以了,比如出生日期是1976.01,那么直接用今年2012 – 1976就得出按年算的年龄,有时可能会要求苛刻一点,比如说要求精确到月,呵呵,再Split,再判断,颇显麻烦,今天终于静下心来搞个统一的函数ComputeAge来处理这些问题,当然要能够识别我目前遇到的形如1972.01、1972.01.02、1972.1.2、72.01、72.01.02、19720102、197201日期格式,计算年龄嘛,我就让这个函数支持精确到日吧(可能用不上)。

单单是计算年龄,可能还不能满足我的胃口,当要统计类似1986年前出生的人的时候,我还要将1986转换一次,感觉麻烦,于是给ComputeAge添加了个比较时间的功能,比较的结果按照标准的-1、0、1进行返回。

比较特别的是这个函数还有个附加的功能就是把形如1972.01、1972.01.02、1972.1.2、72.01、72.01.02、19720102、197201日期格式转换为标准的脚本内置日期变量Date,好啦,说了这么多,函数在这里,用法注释已经写得详细了:

继续阅读

Excel/VBA宏打印奇数偶数页并实现正反打印

大家都知道Word里面有一项设置可以让我们选择打印奇数页还是偶数页,这样我们很容易就实现了Word的正反打印,Excel中貌似找不到这个选项,如果你的打印机支持的话,你可以通过页面设置,工作表选项卡,选项按钮,切换到完成方式,可能会有奇数偶数或者正反打印,当然这一切取决于你的打印机驱动是否支持,如果找不到,那该怎么办呢?难道只能手动打印吗?

其实我们可以利用VBA宏变通一下的,首先获取总页数,奇数页打印也就是从1开始,然后1、3、5、7、9,步长为2,利用VB语言可以描述如下:

1
2
3
4
5
' TotalPages就是总页数
' Step是计算步长,这里i每次加2
For i=1 To TotalPages Step 2
  ' 打印 i 页
Next i

这里很明显将打印1、3、5、7、9这样的奇数页,如果是2、4、6、8、10这样的偶数页该怎么办呢,可以看出步长依旧是2,只是起始从2开始了,那么i初始应该设置为2。

通过PrintOut方法就能进行打印了,这里我们默认打印选中的Sheet,所以使用ActiveWindow.SelectedSheets:

继续阅读

VBScript/VBA批量合并多个Word文件到一个文件

如果手头有一些比较零散的Office Word文件(*.DOC),但是实际需求确实要将这些Word文件合并成一个Word文件,假如说这些零散的文件比较多,那么手工一个一个添加必定会带来麻烦。这时我们就可以使用VBA的相关功能来帮助我们了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Const wdPageBreak = 7 ' 分页符
 
Dim strFileName
strFileName = "要合并的文件.doc"
 
Dim strDestFileName
strDestFileName = "最终合并的文件.doc"
 
Dim wdApp, doc, Selection
Set wdApp = WSH.CreateObject("Word.Application")
wdApp.Visible = False
 
Set doc = wdApp.Documents.Add
 
Set Selection = wdApp.Selection
' 这里strFileName直接是要合并的文件路径
' Selection.InsertFile FileName:=strFileName
Selection.InsertFile strFileName
' 跳转到下一页(插入分页符)
' Selection.InsertBreak Type:=wdPageBreak
Selection.InsertBreak wdPageBreak
 
Set doc = Nothing
doc.SaveAs strDestFileName
doc.Close
 
Set doc = Nothing
wdApp.Visible = True
wdApp.Quit
Set wdApp = Nothing

上面的代码具体演示了如何插入一个文档,那么如何批量插入多个文档呢?你可以试试我前面一篇文章《采用插件机制的批量文件扫描及进程处理工具》所介绍的办法,或者像下面这样:

继续阅读

Word、Excel、PPT、Access等Office VBA编程手册

VBA编程有时确实能帮我们大忙,将我们从繁重枯燥的操作中解放出来,但是相关介绍的文档不是很好找的,如果我们安装有Microsoft Office,那么在安装目录下应该能够找到一份CHM的帮助文档,我将一些关于VBA编程的CHM手册发上来,供大家参考:

  • Word VBA (VbaWord.chm)
  • Excel VBA (Vbaexcelxl10.chm)
  • PowerPoint VBA (VbaPowerPoint.chm)
  • Access VBA (Vbaaccess.chm)

更多的比如Outlook和FrontPage可以点击这里下载获得。

当然,微软还为不愿意下载的我们提供了在线文档,在手边没有手册的情况下可以救救急。
http://msdn.microsoft.com/en-us/library/dd941266(v=office.12).aspx

VBA对Word行、段落和光标位置的移动、选择和操作

Mr.Abao’S Blog上看到的,VBA编程时要参考,特地转一下,另外由于嵌入到VBScript脚本中编程,对一些常量我给出了声明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Const wdCharacter = 1
Const wdExtent = 1
Const wdExtend = 1
Const wdGoToBookmark = -1
Const wdLine = 5
Const wdCell = 12
Const wdTableFormatSimple2 = 2
Const wdAlignParagraphRight = 2
Const wdYellow = 7
Const wdToggle = 9999998
Const wdAlignParagraphCenter = 1
Const wdSentence = 3
Const wdParagraph = 4
Const wdStory = 6
Const wdMove = 0

下面我将Mr.Abao’S Blog的内容转帖(略作修改,主要是注释部分增加了VBScript的脚本写法):在WORD中用VBA宏语言选定一行、一段,删除一行、一段,移动光标至行首、行尾、段首、段尾等。

继续阅读

Word查找替换使用TypeText解决字符串参量过长的错误

在我的这篇《VBScript/VBA批量替换Word指定的内容》文章已经介绍了关于使用VBScript或者VBA查找替换Word的问题,但是在实际操作时,会发现查找和要替换的字符串不能超过一定的数量(大概是500个字符),否则会出现“字符串参量过长”的错误。

其实我们可以通过Selection.TypeText的办法避免这个问题,这个办法只适用于模板的替换,比如设置标记符{%TEMPLATE%},然后替换这个标记符为一段很长的文本。

具体的代码也很简单,我们就以之前那篇文章为例,做下改动,新代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
Const wdReplaceAll  = 2
 
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
 
Set objDoc = objWord.Documents.Open("C:\Scripts\Test.doc")
Set objSelection = objWord.Selection
objWord.Options.ReplaceSelection = True
objSelection.Find.Text = "{%TEMPLATE%}" ' 标记符
objSelection.Find.Forward = True
objSelection.Find.MatchWholeWord = True
objSelection.Find.Execute
objSelection.TypeText "要替换的长文本"

通过TypeText我们就有效的避免了替换长文本时的限制,但是如何查找长文本,目前我还在寻找较好的解决方案。不过解决了长文本的替换就给我们使用查找替换标记符式的Word模板扫清了障碍。