2019-2-9更新
这篇文章的来源是从word抓取数据存入excel里面,所以用上了content control。至于域会不会比content control更合适一些呢?我也不大清楚
2018-11-03更新:
在word里调出开发者模式并插入contentcontrol
显示开发者模式的步骤
- 打开文件>>选项
- 选择自定义功能区
- 在里面把开发工具前面的钩打上
参考:https://jingyan.baidu.com/article/6525d4b1368b1cac7d2e949d.html
另外,contentcontrol是07以后docx版本word文档才支持的功能,所以如果是灰色的,先检查一下你的文件是不是doc扩展名
一些可能遗漏的地方
- 在
dataToWord
里,我把工作表的名称设置成了Data
,而excel中工作表的默认名称是Sheet1,所以这里要设置一下(如果提示超出下界,可能是这个原因) - 如果提示With变量错误,可能是没法找到word文档。word文档应该和excel表(xlsm文件)放在一个目录。word文档的名称应该填入E1单元格(不包括扩展名)
- 如果提示用户定义类型未定义,那应该是引用这里没有把
Microsoft word 15.0 library
这个库加进来
最后,当前这个方法还是有很多moving part,是一个比较初级的解决方案。如果有什么问题欢迎私信或者在文章下方评论,谢谢。
这是我vba系列的第二篇文章。
其他文章:
路人乙小明:[vba] 在word里给表格做自动求和zhuanlan.zhihu.com不可否认的,word,excel,powerpoint就是办公软件的三驾马车,而vba就是这三驾马车中的核心组件。就算vba语法再恶心,vba编辑器再恶心,但是你有种倒是自己做个支持python的office出来呀~~~我做不来,所以我还是乖乖学vba好了。
说回正题,比如现在有这么一篇文档:
这里涉及了对方单位名称,我院职工所在科室,职工的职称,姓名,进修起止时间。在word里面可以将这些需要修改的文本做成contentcontrol
这样下来这篇文档就有10个contentcontrol了。做完以后还可以对文档限制编辑,只能改contentcontrol,这样就可以做一个模板文档让别人去填了。
但是到这里还是不够智能,毕竟还需要手填。尤其是在一些程序文本里,比如一些合同,会反复出现某一段文字,修改起来浪费时间,更容易出错。有没有什么更好的办法呢?
用Excel来驱动这些contentcontrols的修改是一个更好的办法
首先可以将所有的contentcontrols集中起来,这样会更加集中,不容易出现错漏。另外在Excel里要获取数据会容易的多,完全可以从另外的一个地方提取数据,然后转过身就更新docx。所以打通Excel和Word之间的数据流通是实现数据表驱动的文档自动更新的核心步骤。具体怎么做呢?
首先建立一个新的Excel文档,比如test.xlsm (xlsm可以支持宏)。然后先看一下下面这个代码(在Excel里的vba):
Sub dataToWord()
Dim wordApp As Word.Application
Dim wDoc As Word.Document
Dim control As Word.ContentControl
Dim r As Integer
Set wordApp = CreateObject("word.application")
Set wDoc = wordApp.Documents.Open(ThisWorkbook.Path & "/" & Range("E1").Value & ".docx")
wordApp.Visible = True
r = 2
i = 1
For Each control In wDoc.ContentControls
'control.Range.Text = Sheets("Data").Cells(r, 3)
Sheets("Data").Cells(r, 2) = control.Range.Text
Sheets("Data").Cells(r, 1) = i
r = r + 1
i = i + 1
Next
wordApp.Documents.Close
wordApp.Quit
End Sub
对了,一定要记得在引用里面打开word的支持:
前面2个dim是声明word程序和文档方便后续使用
Set wDoc = wordApp.Documents.Open(ThisWorkbook.Path & "/" & Range("E1").Value & ".docx")
这一行是根据E1这一个单元格的内容,打开对应的文档。比如我在当前xlsm同一个目录下新建了一个test.docx,那在E1单元格输入test就可以了。
为了方便演示,我们建立一个test.docx,然后在里面建n个contentcontrols,都是无格式文本,大概长下面这样:
如果现在运行上面这段vba程序(运行以前记得把新建的这个test.docx给关掉,否则容易死机),xlsm就会自动变成下面这样:
所以呢,接下来只需要在excel里面根据抓过来的data开始书写内容了,比如写成下面这样:
接下来把程序里做一点点更改
...
control.Range.Text = Sheets("Data").Cells(r, 3)
'Sheets("Data").Cells(r, 2) = control.Range.Text
'Sheets("Data").Cells(r, 1) = i
...
上面这3行程序,下面两行负责把数据从word向Excel输送,第一行负责把数据从Excel向word输送。修改完以后,接下来点击运行。(老规矩,先关掉test.docx)
至于自动化数据获取的地方,就像我之前说的,Excel和word之间的通路已经打好了,接下来你只需要在Excel里面弄好就ok啦。这个系统里面的数据流向示意图如下:
另外,还可以在Excel里面做一个小按钮,就是画一个小方框:
点指定宏,然后选刚才刚刚做好的那个sub。
接下来你就可以点这个按钮,然后更新docx了。
test.xlsm以及test.docx见:
链接: https:// pan.baidu.com/s/1itBbrQ ixEXU7x5IrUj5prA 密码:1phv
参考资料:
Push Data from Excel to MS Word Content Controls using Excel VBA
Word 2016 VBA: How to set text of the content control