Word VBA中的光标操作
一、 光标对象及其位置属性在WordVBA中光标对象的名称为Selection。一个Selection实际上由两个位置指示器组成其中一个指示器称为Start一个指示器称为End分别代表光标的起始位置和结束位置。当Start与End相等时光标显示为一条竖线不相等时光标显示为一个选择区域。二、 光标的移动光标的移动主要有两大类方法一种为Move系方法一种为GoTo系方法。1、Move系方法包括Move、MoveDown、MoveEnd、MoveEndUntil、MoveEndWhile、MoveLeft、MoveRight、MoveStart、MoveStartUntil、MoveStartWhile、MoveUntil、MoveUp、MoveWhile、HomeKey、EndKey、StartOf、EndOf等这些方法的共同特点是返回一个整型值表示实际移动的数量参数中一般都包含一个unit移动单位和一个count移动数量其中unit参数可取值为WdUnits枚举类型。部分方法还有一个Extend参数默认值为wdMove表示Start位置指示器和End位置指示器捆绑在一起移动形成光标移动效果当它取值为wdExtend时向后移动只有Start位置指示器移动向前移动只有End位置指示器移动形成选择一个区域的效果。此外StartOf、EndOf与HomeKey、EndKey比较前面两个方法的unit参数可用的类型更多例如wdSection就只能用于做前者的参数而不能用于做后者的参数office2010其它版本是否如此未测试。2、Goto系方法包括GoTo、GoToNext、GoToPrevious等。这组方法与Move方法最大的差别是它的返回值为代表当前选择区域的Range。要知道这组方法执行后实际移动了多少数量的字符只能通过记录执行前后的光标位置来计算。它的参数有四个。what参数取值为WdGoToItem常量之一which参数为WdGoToDirection常量之一count参数为项的数目与Move系方法不同的是count不能为负数最后一个参数为name如果what参数值为wdGoToBookmark、wdGoToComment、wdGoToField或wdGoToObject那么这个参数可以指定一个名称。由于WdGoToItem常量没有提供类似wdGotoCharacter的常数无法通过这组方法指定移动多少字符。下面的代码演示先记录光标位置在进行一些操作后恢复光标位置SubSelectionPositionDemo()Dimposition,countAsLongpositionSelection.Start记录光标距离文档最后一个字符的位置注意光标不能在最后一个回车符之后所以要调整一个字符countposition-ActiveDocument.Characters.count1这里可以添加操作文档的代码如果这些操作改变了文章内容的长度需要调整及时count恢复光标位置先将光标移动至文档末尾再移动count个字符Selection.EndOf wdStory Selection.Move wdCharacter,countDebug.Printposition:Selection.Startstart:Selection.StartEndSub当然用书签记录光标位置后再恢复是更灵活的无需关注文档内容的修改导致的原来光标所在位置的移动但是如果操作文档时删除了原来光标所在位置的内容导致书签被删除或者以任何方式删除了书签就无法恢复光标原来所在位置SubRestoreCursorPosition() 利用临时书签在完成一些操作后恢复光标位置DimdocAsDocument,tmpBookmark$,textAtCursor$SetdocActiveDocument 创建书签名称避免覆盖文档中已有书签tmpBookmarktmpSelection.startWhiledoc.Bookmarks.Exists(tmpBookmark)tmpBookmark_tmpBookmarkWend 在光标所在位置添加书签doc.Bookmarks.Add tmpBookmark,Selection.Range 读取光标位置前一个字符需防止光标位于文档开头时Selection.start - 1引发错误IfSelection.start0ThentextAtCursordoc.Range(Selection.start-1,Selection.End).text 光标前一个字符是空白字符提示空白字符Select CaseAsc(textAtCursor)chr(9):制表符^tchr(10):系统换行符vbLfWord中不用chr(11):手动换行符^l chr(12):分节符^bchr(13):段落标记vbCr^pchr(14):分栏符^nchr(32):空格。 分页符^m为chr(12) chr(13)Case9,10,11,12,13,14,32: Enter 段落回车 ^ptextAtCursor空白字符EndSelectElse 为演示操作前后光标处文本时不输出空白将textAtCursor设为光标位 于文档开头的标志字符串实际上设为空字符串更合理textAtCursor^文档开头EndIf 这里可以添加操作文档的代码这里以在文档开头添加一段文字为例Selection.StartOf wdStory Selection.TypeText在文档开头插入一个段落新增加一些文字vbCrLfIfdoc.Bookmarks.Exists(tmpBookmark)Then 将光标移动到临时书签所在位置即恢复了光标位置Selection.GoTowdGoToBookmark,,,tmpBookmark 删除临时书签doc.Bookmarks(tmpBookmark).Delete 验证操作前后书签位置Debug.Print操作前光标处字符:textAtCursorIftextAtCursor^文档开头ThentextAtCursordoc.Range(Selection.start-1,Selection.End).textSelect CaseAsc(textAtCursor)Case9,10,11,12,13,14,32: Enter 段落回车 ^ptextAtCursor空白字符EndSelectEndIfDebug.Print操作后光标处字符:textAtCursorElseDebug.Print你在操作文档时删除了书签EndIfEndSub用GoTo系方法遍历文档时如需判断当前所遍历到的对象是否是文档最后一个遍历对象可以通过执行GoTo系方法前后光标位置是否发生变化进行。如果文档中不存在遍历对象第一次执行GoTo系方法后光标的初始位置是0。以wdGoToHeading作为参数遍历文档时的示例代码如下Subtest()DimposAsLongWithSelection .HomeKey wdStory光标回到文档开头此时Selection.Start为0Dopos.Start先记录光标位置.GoTowdGoToHeading,wdGoToNext,1向后移动到下一个标题以标题为对象遍历文档MsgBoxposposvbCrLf.Start.Start 如果光标位置没有发生变化则已遍历完文档中所有的标题If.StartposThenIf.Start0ThenMsgBox文档中没有标题ElseMsgBox已到达文档中最后一个标题EndIfExitDoEndIfLoopEndWithEndSub三、输入内容主要包括以下Insert系列方法InsertAfter、InsertBefore、InsertBreak、InsertCaption、InsertCells、InsertColumns、InsertColumnsRight、InsertCrossReference、InsertDateTime、InsertFile、InsertFormula、InsertNewPage、InsertParagraph、InsertParagraphAfter、InsertParagraphBefore、InsertRows、InsertRowsAbove、InsertRowsBelow、InsertStyleSeparator、InsertSymbol、InsertXML。还有一个直接输入字符串的方法TypeText输入的字符串由参数Text指定。四、由Selection获取其他对象1、获取Range对象直接使用Selection对象的Range属性。2、获取BookMark、Field、Paragraph、Character、Section、Cell、Row、Word、Table等对象这些对象在Selection对象中均有相应的集合属性使用Selection对象的相应集合属性加上索引即可取得。所有索引均从1开始计数。例如Selection.Paragraphs(1)可以取得光标区域第一个段落Selection.Fields(1)可以取得选择区的第一个域。这些对象均可以通过ForEach语句进行遍历。五、操作页眉页脚直接用Selection.HeaderFooter操作页眉页脚容易出错需要先确保Selection已经在页眉页脚区域中。可以通过Selection.Sections(1).Headers(wdHeaderFooterPrimary).Range.Select将光标移动到当前光标所在页的页眉中。但是这一操作会导致视图变换为草稿视图。可以通过以下操作将视图恢复为页面视图 恢复视图为页面视图IfActiveWindow.View.SplitSpecialwdPaneNoneThenActiveWindow.Panes(2).CloseEndIfActiveWindow.ActivePane.View.TypewdPrintView六、判断光标是否已经到达文档内容结束处可以通过Selection对象的位置指示器与文档内容结束位置的比较来判断光标是否已到达文档内容的结束位置。文档结束位置可以使用ActiveDocument.Content.End - 1取得。如下代码片段光标放在文档主体内容的最后一个回车符处时将提示“True”否则将提示“False”。需要注意的是如果文档最后一页有脚注或尾注或光标位于最后一页页脚的最后一个回车符位置下面的代码也将提示“False”。MsgBox Selection.start(ActiveDocument.Content.End-1)要排除脚注或尾注的影响判断光标是否在文档主体内容的结尾可先记录光标当前位置再将光标移动到文档末尾再通过比较光标位置是否发生了变化来进行判断参考如下代码Subtest()Dimpos,countAsLongWithSelectionpos.Start .EndOf wdStoryIf.StartposThenMsgBox光标在主体内容的末尾。Else恢复光标位置countpos-ActiveDocument.Characters.count1.Move wdCharacter,count MsgBox光标没有在主体内容的末尾。EndIfEndWithEndSub上面的代码移动了光标如果不移动光标可以使用以下代码Subtest()DimmainTextRangeAsRangeSetmainTextRangeActiveDocument.content mainTextRange.Collapse wdCollapseEndMsgBox selection.End selection.End vbCrLf mainTextRange.End mainTextRange.EndIfselection.EndmainTextRange.EndThenMsgBox光标在主体内容的末尾。ElseMsgBox光标没有在主体内容的末尾。EndIfEndSub如果用GoTo系方法按存在集合属性的对象进行遍历当然对这种对象更推荐使用For Each语句进行遍历这里只是做个演示例如Section、Paragraph等则可以利用集合对象的Last属性取得其最后对象与光标所在对象进行比较以判断是否到达了文档中最后一个该类型对象。对于Section等不支持直接比较是否相等的对象可以取其Range进行比较示例代码如下Subtest()DimrngLastAsRange 取得文档最后一节的RangeSetrngLastActiveDocument.Sections.Last.RangeDo 按Section遍历文档Selection.GoToNext wdGoToSectionIfSelection.Sections(1).RangerngLastThenDebug.Print这里可以在遍历时进行操作。ElseDebug.Print已经遍历到最后一节。ExitDoEndIfLoopEndSub七、查找和替换一在全文中查找替换VBA中进行全文查找和替换可以通过Selection.Find对象的Execute方法实现。以下示例在选择范围内向前搜索“Microsoft”。 如果找到了该单词则自动将其选中。WithSelection.Find .ForwardTrue.ClearFormatting .MatchWholeWordTrue.MatchCaseFalse.WrapwdFindContinue .Execute FindText:MicrosoftEndWith下面的示例查找选择范围内所有的“hi”并且将其替换为“hello”。WithSelection.Find .ForwardTrue.ClearFormatting .MatchWholeWordTrue.MatchCaseFalse.WrapwdFindContinue .Execute FindText:hi,_ ReplaceWith:hello,Replace:wdReplaceAllEndWith二在指定范围内查找和替换如果要在指定范围内进行查找则应使用Range.Find对象的Execute方法实现这一方法在找到匹配对象后并不将匹配对象选择但是Range对象的范围则变更为匹配内容所占据的范围。下面的示例代码会将一段文字中顺序错误的带圈数字序号替换成正确序号并将序号设置成上标形式Sub乱序带圈序号替换为有序序号()DimtmpRangeAsRange,searchRangeAsRange,i%,commentRef$ 指定的查找范围这里设置成整个文档也可用Selection.Range设定为选择区SetsearchRangeActiveDocument.Range i0 开始循环查找匹配内容Do 设定本次循环的查找范围SettmpRangesearchRange 设置tmpRange.Find对象的相关属性并进行查找WithtmpRange.Find .Text[①-⑩] 查找带圈数字序号.MatchWildcardsTrue.ForwardTrue.Wrap1 wdFindContinue.Execute 执行查找定位匹配项的位置IftmpRange.Find.foundThenii1 将阿拉伯数字转换为带圈数字序号仍然使用带圈数字序号 commentRef ChrW(i AscW(①) - 1) 更正为正确的带圈数字序号。但是正确的unicode编码在正文中却显示为错误的序号原因未知 tmpRange.Text commentRef 将匹配的内容设置为正确的数字序号并设置为上标tmpRange.Texti tmpRange.Font.Superscript-1 有必要的话调整查找范围。如果仍然使用带圈数字序号就需要这么做以防查找陷入死循环 换成阿拉伯数字就无需这么做 searchRange.SetRange start:tmpRange.End, End:searchRange.EndEndIfEndWithLoopWhiletmpRange.Find.found 直到找不到匹配内容时停止循环EndSub上述代码执行示例转换前转换后八、Information方法VBA中Range对象及其子类对象如Selection、Character、Word等都有Information方法该方法有一个Type参数这个参数的取值为wdInformation枚举类型该枚举类型指定我们需要获取的信息可用枚举值及其含义如下名称值DescriptionwdActiveEndAdjustedPageNumber1返回包含指定的所选内容或区域的活动结尾的页面数。 如果设置一个起始页码或进行其他手动调整则返回经调整的页码与 wdActiveEndPageNumber 不同。wdActiveEndPageNumber3返回包含指定的选定内容或范围从文档的开头开始计数的活动端的页面数。 与 wdActiveEndAdjustedPageNumber)不同 忽略对页码的任何手动调整。wdActiveEndSectionNumber2返回节号在该节中包含了指定的所选内容或区域的活动结尾。wdAtEndOfRowMarker31如果指定的所选内容或区域位于表格的行结尾标记处则该参数返回 True 。wdCapsLock21如果 Caps Lock 有效则该参数返回 True 。wdEndOfRangeColumnNumber17返回表格列号在该表格列中包含指定的所选内容或区域的结尾。wdEndOfRangeRowNumber14返回表格行号在该表格行中包含指定的所选内容或区域的结尾。wdFirstCharacterColumnNumber9返回指定的所选内容或区域中第一个字符的位置。 如果所选内容或区域是折叠的则返回紧靠所选内容或区域右侧的字符编号该编号与状态栏中列后面的字符列数相同。wdFirstCharacterLineNumber10返回指定的所选内容或区域中第一个字符在当前页面处于第几行。 如果所选内容或区域是折叠的则返回紧靠所选内容或区域右侧的字符编号该编号与状态栏中行后面的字符行数相同。wdFrameIsSelected11如果所选内容或区域是一个完整的图文框或文本框则该参数返回 True 。wdHeaderFooterType33返回一个值该值指示包含了指定所选内容或区域的页眉或页脚的类型。 有关其他信息请参阅注解部分中的表。wdHorizontalPositionRelativeToPage5返回指定选定内容或区域的水平位置;这是从所选内容或范围的左边缘到页面左边缘的距离以磅 (1 磅 20 twips72 磅 1 英寸) 。 如果所选内容或范围不在屏幕区域内则返回 -1。wdHorizontalPositionRelativeToTextBoundary7返回指定所选内容或区域相对于周围最近的正文边界左边缘的水平位置以磅为单位1 磅 20 缇72 磅 1 英寸。 如果所选内容或范围不在屏幕区域内则返回 -1。wdInBibliography42如果指定的选定内容或区域位于书目则返回 True 。wdInCitation43如果指定的选定内容或区域位于引文则返回 True 。wdInClipboard38有关该常量的信息请参阅包含在 Microsoft Office Macintosh Edition 中的语言参考帮助。wdInCommentPane26如果指定的所选内容或区域位于批注窗格则该参数返回 True 。wdInContentControl46如果指定的选定内容或区域中的内容控件则返回 True 。wdInCoverPage41如果指定的选定内容或区域位于封面则返回 True 。wdInEndnote36如果指定的选定内容或区域位于或尾注窗格中页面视图的尾注区内在普通视图中则返回 True 。wdInFieldCode44如果指定的选定内容或区域位于域代码则返回 True 。wdInFieldResult45如果指定的选定内容或区域位于域结果则返回 True 。wdInFootnote35如果指定的选定内容或区域位于或脚注窗格中页面视图的脚注区内在普通视图中则返回 True 。wdInFootnoteEndnotePane25如果指定的选定内容或区域位于脚注或尾注窗格在普通视图和页面视图的脚注或尾注区内则返回 True 。 有关详细信息请参阅 wdInFootnote 和 wdInEndnote 在前面的段落中所描述。wdInHeaderFooter28如果所选内容或区域的页眉或页脚窗格中或在页眉或页脚中打印版式视图中则返回 True 。wdInMasterDocument34如果所选内容或区域位于主控文档 (即包含至少一个子文档的文档)则返回 True 。wdInWordMail37如果所选内容或区域的页眉或页脚窗格中或在页眉或页脚中打印版式视图中则返回 True 。wdMaximumNumberOfColumns18返回所选内容或区域中任何行的最大表格列数。wdMaximumNumberOfRows15返回指定的所选内容或区域中表格的最大行数。wdNumberOfPagesInDocument4返回与所选内容或区域相关联的文档的页数。wdNumLock22如果 Num Lock 有效则该参数返回 True 。wdOverType23如果启用改写模式则该参数返回 True 。 可使用 Overtype 属性改变改写模式的状态。wdReferenceOfType32返回一个值该值表明所选内容相对于脚注、尾注或批注引用的位置如注解部分中的表所示。wdRevisionMarking24如果打开修订功能则该参数返回 True 。wdSelectionMode20返回一个值该值表明当前的选定模式如下表所示。wdStartOfRangeColumnNumber16返回表格列号在该表格列中包含所选内容或区域的起点。wdStartOfRangeRowNumber13返回表格行号在该表格行中包含所选内容或区域的起点。wdVerticalPositionRelativeToPage6返回所选内容或区域的垂直位置即所选内容的上边缘与页面的上边缘之间的距离以磅为单位1 磅 20 缇72 磅 1 英寸。 如果所选内容在文档窗口中不可见则返回 -1。wdVerticalPositionRelativeToTextBoundary8返回所选内容或区域相对于周围最近的正文边界的上边缘的垂直位置以磅为单位1 磅 20 缇72 磅 1 英寸。 该参数可用于在图文框或表格中确定插入点位置。 如果所选内容不可见则返回 -1。wdWithInTable12如果所选内容位于表格中则该参数返回 True 。wdZoomPercentage19按 百分比 属性返回当前设置的缩放百分比。以下代码演示了获取光标所在节的起始页码和终止页码Sub获取光标所在节的起始页码和终止页码()WithSelection在立即窗口打印节标题默认为节的第一个段落Debug.PrintReplace(.Sections(1).Range.Paragraphs(1).Range.Text,Chr(13),)光标移动到节开头位置.StartOf wdSection打印出光标所在页码信息Debug.Print开始页码——.Information(wdActiveEndPageNumber)光标移动到节结束位置.EndOf wdSection打印出光标所在页码信息Debug.Print结束页码——.Information(wdActiveEndPageNumber)EndWithEndSub上面的宏执行完成后光标位置发生了移动如需要恢复到原始位置可参考本文第一段演示代码下面的宏则可以在不移动光标的前提下获取光标所在节的起始页码和终止页码Sub不移动光标获取光标所在节的起始页码和终止页码()WithSelection.Sections(1).RangeDebug.Print当前光标处于第.Information(wdActiveEndSectionNumber)节_开始页码——.Characters(1).Information(wdActiveEndPageNumber)_;结束页码——.Characters.Last.Information(wdActiveEndPageNumber)EndWithEndSub九、判断文档中是否存在选择区域要判断文档中是否存在被选择的字符除了比较Selection.Start与Selection.End是否相等外还可以测试逻辑表达式Selection.Type wdSelectionIP or Selection.TypewdNoSelection表达式为真时文档中没有选择字符即此时按下CtrlC剪贴板为空白否则文档中选择了字符。