MS Word Macro for batch conversion Word to UTF-8

xujiajin

管理员
Staff member
It can be scripted within Word using Word's own macro language (Visual Basic For Applications).

Here's a very quick script I threw together to do just that, built from a couple of prerecorded macros and a few hints from web searches. It finds anything matching *.doc in the target directory (here, C:\, but you could change it to whatever you wanted by adjusting the path variable), and saves them as the same thing with an extra ".txt". If you edit this text into the macros of a dummy document or template, and select the run option for the SaveAllDocsAsUtf8 macro, it will generate the files you need.

(begin bit to copy into the macro file)

Sub SaveAllDocsAsUtf8() Dim path As String Dim file As String Dim newfile As String

path = "C:\" file = Dir(path & "*.doc")

Do While file <> "" newfile = path & file & ".txt" 'MsgBox newfile Documents.Open FileName:=path & file, ConfirmConversions:= _

False, ReadOnly:=False, AddToRecentFiles:=False, PasswordDocument:="", _

PasswordTemplate:="", Revert:=False, WritePasswordDocument:="", _

WritePasswordTemplate:="", Format:=wdOpenFormatAuto, XMLTransform:=""

ActiveDocument.SaveAs FileName:=newfile, FileFormat:= _

wdFormatText, LockComments:=False, Password:="", AddToRecentFiles:=True, _

WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _

SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _

False, Encoding:=65001, InsertLineBreaks:=False, AllowSubstitutions:= _

False, LineEnding:=wdCRLF

ActiveDocument.Close

file = Dir Loop

End Sub

由兰卡斯特大学的Andrew Hardie提供。
 
上面的VBA的一些代码行的末尾没有回车而无法运行,下面是校正且测试有效了的代码

如果把上面的VBA代码直接拷贝到Office的VBA编辑器是无法运行的,例如:
Sub SaveAllDocsAsUtf8() Dim path As String Dim file As String Dim newfile As String
应该改为
Sub SaveAllDocsAsUtf8()
Dim path As String
Dim file As String
Dim newfile As String

才是正确有效能运行的。

此外,像下面的代码是属于强行换行,是不能接一个空白行的,必须下一行就是下一行而不是空白行……
ActiveDocument.SaveAs FileName:=newfile, FileFormat:= _

wdFormatText, LockComments:=False, Password:="", AddToRecentFiles:=True, _


WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _


SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _


False, Encoding:=65001, InsertLineBreaks:=False, AllowSubstitutions:= _


False, LineEnding:=wdCRLF

而应该改为下面的效果,才能运行无误……
ActiveDocument.SaveAs FileName:=newfile, FileFormat:= _
wdFormatText, LockComments:=False, Password:="", AddToRecentFiles:=True, _
WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _

SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _

False, Encoding:=65001, InsertLineBreaks:=False, AllowSubstitutions:= _

False, LineEnding:=wdCRLF


Sub SaveAllDocsAsUtf8()
Dim path As String
Dim file As String
Dim newfile As String
path = "C:\"
file = Dir(path & "*.doc")
Do While file <> ""
newfile = path & file & ".txt"
'MsgBox newfile
Documents.Open FileName:=path & file, ConfirmConversions:= _
False, ReadOnly:=False, AddToRecentFiles:=False, PasswordDocument:="", _
PasswordTemplate:="", Revert:=False, WritePasswordDocument:="", _
WritePasswordTemplate:="", Format:=wdOpenFormatAuto, XMLTransform:=""
ActiveDocument.SaveAs FileName:=newfile, FileFormat:= _
wdFormatText, LockComments:=False, Password:="", AddToRecentFiles:=True, _
WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _
False, Encoding:=65001, InsertLineBreaks:=False, AllowSubstitutions:= _
False, LineEnding:=wdCRLF
ActiveDocument.Close
file = Dir
Loop
End Sub

【以上代码的运行机制,就是首先设置搜索某个路径上的所有的doc文件,然后逐一打开另存为,直到最后一个doc文件都已经被转换处理】
【行末的空格加下划线,这表示强行换行,表示下一行代码是上一行代码的连续而不是新的一行代码】
ActiveDocument.SaveAsActiveDocument是Word VBA中的现成的对象模型的预置对象,SaveAs是一个函数,在不需要返回值的情况下,可以写成无括号的命令行的参数传递的形式】
ReadOnly:=False,或AddToRecentFiles:=False,或Encoding:=65001,这些东西叫做“VBA预置参数名称及其对应的预置常量或预置常量名称”,有了预置参数名称与预置常量名称之后,你就可以省略一些可有可无的参数及其取值而不影响运行哟】
【注意】VBA是一种“弱类型的编程语言”,所以一般情况下是不用定义变量类型的,所以,下面的三行是冗余且可被删除而不影响整个程序的……
Dim path As String
Dim file As String
Dim newfile As String
 
Andrew Hardie的VBA代码其实有挺多赘肉,我精简下

Andrew Hardie的VBA代码其实有挺多赘肉,原因是他是几乎照搬的录制的宏的预置参数名称与预置常量名称而没有剔除,而从日常需求而言,完全可以剔除而不影响整个程序的运行品质。
所以,我精简下且清晰下,就如下:


Sub Doc转UTF8()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.doc")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=65001
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub

以上代码我采用了中文变量名,更加清晰。

整个代码的最难之处在于对dir()的正确理解和运用。dir()第一次调用的时候需要写明“完整的路径名称(支持模糊匹配)”,但第二次调用的时候就直接写dir了,等于是dir(),反复调用dir()就形成了对某个文件路径的穷举,直到返回值为空,就可以停止调用或跳出循环了。

VBA编程的学习难度是普通编程语言(Java呀,C呀,C++呀,C#呀,VB呀,D语言呀,Delphi/Pascal呀)的1%左右,而开发效率是它们的10倍左右,也就是说同样的文本处理程序你用VBA来做,代码数量大大减少且代码写作时间大大缩短。

跟其他带有通用性质的脚本编程语言(Lua呀,Perl呀,Python呀)相比,以Andrew Hardie本次提供的VBA代码为范例也能看出:VBA的开发效率也是“快到无敌”,因为像Perl呀Python呀的,它们也必须调用Win32模块及其COM(component object model)才能操作Office的Word文件,且代码跟上面的VBA代码几乎一致,却必然有类似“import ...”或“include ...”或“CreateObject(...)”或“require(...)”或“system.using ...”的代码来呼叫Office的组件对象模型的一系列方法与常量与事件。因此,我们也可以说,针对Office文件的字符串处理而言,用什么Perl或Python或Java或C#,它们都能做,做起来都一个样,其实都是VBA编程而已!
 
DOC转四大文字编码的VBA一览

Sub Doc转ANSI()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.doc")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=936
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub


Sub Doc转Unicode()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.doc")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=1200
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub


Sub Doc转Unicode_big_endian()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.doc")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=1201
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub


Sub Doc转UTF8()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.doc")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=65001
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub
 
HTM转四大文字编码的VBA一览

Sub Htm转ANSI()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.htm")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=936
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub


Sub Htm转Unicode()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.htm")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=1200
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub


Sub Htm转Unicode_big_endian()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.htm")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=1201
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub


Sub Htm转UTF8()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.htm")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=65001
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub
 
XML转四大文字编码的VBA一览

Sub XML转ANSI()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.xml")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=936
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub


Sub XML转Unicode()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.xml")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=1200
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub


Sub XML转Unicode_big_endian()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.xml")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=1201
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub


Sub XML转UTF8()
特定路径 = "C:\"
当前文件名 = Dir(特定路径 & "*.xml")
Do While 当前文件名 <> ""
新文件名称 = 特定路径 & 当前文件名 & ".txt"
Documents.Open FileName:=特定路径 & 当前文件名
ActiveDocument.SaveAs FileName:=新文件名称, FileFormat:=wdFormatText, Encoding:=65001
ActiveDocument.Close
当前文件名 = Dir
Loop
End Sub
 
回复: MS Word Macro for batch conversion Word to UTF-8

谢谢李亮1975重庆。
 
【概论】VBA程序的5种类型与反思

基于2009年年初至今的4年的Office VBA开发实战,我感觉VBA程序有5种类型(教科书或教程都没有这样的类型概括哟):
【1】纯Sub型;
【2】基于Sub的菜单型;
【3】基于Sub的窗体型;
【4】基于Sub的域代码型;
【5】基于Sub的自动运行型;

Sub是subroutine或subprocedure的缩写,就是子程序或子模块,特点是可以接收参数却没有返回值,适合直接执行而不必返回执行结果的数值的情况。典型的一个Sub如下:

Sub hello()
msgbox "你好!"
End Sub

以上3行代码,第一行是“程序头”,第二行是“程序体”,第三行是“程序尾”,而蓝色的hello叫做“程序名”,而程序名之后的()是两个圆括号,表示这两个圆括号之间可以填入参数来更加灵活地执行。

从最小的运行单位来说,VBA程序就是Sub或Function两种类型,前者是无返回值的运行模块,后者是可以有返回值的运行模块。Sub及其配套的End Sub之间的这样的一个程序代码片段是可以直接执行的,具有完全的独立性;而Function及其配套的End Function之间的这样的一个程序代码片段是不可以直接执行的,只能被其他的Function或Sub调用而仅仅具有半独立性。

一个完整独立的VBA程序,可以是:
【1】纯Sub型,也就是由若干个sub或function所组成,它们相互调用,而你点“宏列表”中的某个sub而执行某个既定的宏代码,“宏代码”也就是sub或function了;此外,你也可以通过录制宏而设置某个组合键或热键来触发式执行某个宏或sub;
【2】基于Sub的菜单型,也就是自己在Office中设置出自定义的菜单或子菜单或菜单项目,并且跟对应的sub进行链接,就形成了基于某个Word文件或Normal.dot模版文件的菜单性质的程序状态了;
【3】基于Sub的窗体型,也就是你在VBA编辑器中,插入一个用户窗体,添加按钮呀文本框呀之类的控件,然后双击控件而写出其后台的VBA代码,同时你也可以设置窗体是打开当前文件就立即运行的,你也可以随时用VBA代码设置窗体的可见性visible为false而隐藏它,或者设置visible为true而显现该窗体;
【4】基于Sub的域代码型,也就是你插入一个域或者MacroButton域,尤其是你插入了一个“MacroButton域”的时候你可以添加一些普通的文字作为双击而触发执行的“触发器”;
【5】基于Sub的自动运行型,也就是Sub Document_New(),或Sub Document_Open(),或Sub Document_Close()这3个特殊名称的Sub就是在当前文件或某个Word文件被新建或打开或关闭的时候能自动执行的宏代码。

有了我提供的对VBA程序类型的概括性认识,你就不会误以为VBA程序是没有窗体或没有菜单的,你就会深深地爱上这种如此简单且颇为颇为强大的编程语言,她摆脱了C++和Java和C#的必须自己写出各种类和对象的做法,她摆脱了Perl和Python很容易牵涉到CGI编程和Linux操作系统的学习难堪或学习复杂性,她摆脱了C语言只方便直接对纯txt文件进行操作的难堪局面,她也摆脱了Windows API对数据类型的严格限制而调用易出错的烦恼,她也摆脱了你必须学点互联网原理的先决条件,她也摆脱了必须学习较完整的XML DOM知识的烦恼,她也摆脱了你必须对Linux或Unix有所了解的烦恼,……

 
Back
顶部