I'm new to VBA and I really would appreciate the help. First I should mention that I use OFFICE 2016.
I used Macro recording to create a macro that copies the selected equation then it inserts a table (one row,two columns)and adjust it to remove borders. After that the macro pastes the copied equation in the first cell and moves to the next cell and insert an empty equation (which the user then inserts the desired number of the equation in it).
It works fine except until it reaches the step where it should paste the copied equation. Every time I run the macro I get
Run-time error: 6335
and the macro breaks and when I debug it, this is the line that breaks the procedure:
Selection.PasteAndFormat (wdFormatOriginalFormatting)
after debugging when I hit the continue/run button, it completes the job as required.
Below is the macro I use. Thanks in advance.
Sub MacroEQNUMBER()
'
' MacroEQNUMBER Macro
'
'
Dim rng As Range
If Selection.Range = "" Then
Selection.HomeKey Unit:=wdLine
Selection.EndKey Unit:=wdLine, Extend:=wdExtend
End If
Set rng = Selection.Range
rng.Cut
ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=1, NumColumns:= _
2, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
wdAutoFitFixed
With Selection.Tables(1)
If .Style <> "Table Grid" Then
.Style = "Table Grid"
End If
.ApplyStyleHeadingRows = True
.ApplyStyleLastRow = False
.ApplyStyleFirstColumn = True
.ApplyStyleLastColumn = False
.ApplyStyleRowBands = True
.ApplyStyleColumnBands = False
.Borders.Enable = False
End With
Selection.Tables(1).Cell(1, 1).Range.Select
Selection.TypeText Text:="["
Selection.OMaths.Add Range:=Selection.Range
Selection.MoveRight Unit:=wdCharacter, Count:=2
Selection.MoveLeft Unit:=wdCharacter, Count:=1
Selection.TypeText Text:="]"
Selection.MoveLeft Unit:=wdCharacter, Count:=2
Selection.Tables(1).Columns(1).Cells.Width = 80
Selection.Tables(1).Columns(2).Cells.Width = 350
Selection.Tables(1).Cell(1, 2).Range.Select
Selection.PasteAndFormat (wdFormatOriginalFormatting)
Selection.TypeBackspace
Selection.HomeKey Unit:=wdLine
Selection.MoveLeft Unit:=wdCharacter, Count:=4
End Sub
I get the feeling the problem comes from pasting the equation. Since you're using Selection it's quite possible you're putting the Selection in a table cell structure. Word used to allow this, which would "break" the document. In more recent versions it's simply not allowed, which will result in an error...
Rather than try to put bandaids on your recorded code, I've done my best to interpret what is meant (thank you for the excellent description) and convert it to "object code". The SELECTION object isn't ideal because you can never be sure where it is, nor what is meant. Better is to use the underlying object model, usually RANGE objects.
To begin, the Selection is assigned to a Range - now, no matter where the visible selection is in the document, the Range will never change.
Next, I assign the new table to a Table object. From that, I can get the Range of the first cell and work with it (insert text).
I apparently do need a Selection for inserting the OMath, so I position between the square brackets, select and insert that. Finally, the columns are formatted, the cut equation pasted and the selection positioned at the beginning of the first cell (I think that's what you wanted, but I'm not sure about this last).
Sub MacroEQNUMBER()
'
' MacroEQNUMBER Macro
'
'
Dim rng As Range
Dim tbl As word.Table
Dim cel As word.Cell
Dim rngCell As word.Range
If Selection.Range = "" Then
Selection.HomeKey Unit:=wdLine
Selection.EndKey Unit:=wdLine, Extend:=wdExtend
End If
Set rng = Selection.Range
rng.Cut
Set tbl = ActiveDocument.Tables.Add(Range:=Selection.Range, NumRows:=1, NumColumns:= _
2, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
wdAutoFitFixed)
With tbl
If .Style <> "Table Grid" Then
.Style = "Table Grid"
End If
.ApplyStyleHeadingRows = True
.ApplyStyleLastRow = False
.ApplyStyleFirstColumn = True
.ApplyStyleLastColumn = False
.ApplyStyleRowBands = True
.ApplyStyleColumnBands = False
.Borders.Enable = False
End With
Set cel = tbl.Cell(1, 1)
Set rngCell = cel.Range
rngCell.Text = "[]"
rngCell.Collapse wdCollapseStart
rngCell.MoveStart wdCharacter, 1
rngCell.Select
rngCell.OMaths.Add Range:=rngCell
tbl.Columns(1).Cells.width = 80
tbl.Columns(2).Cells.width = 350
Set rngCell = tbl.Cell(1, 2).Range
rngCell.PasteAndFormat wdFormatOriginalFormatting
rngCell.Characters(rngCell.Characters.Count - 1).Delete
tbl.Cell(1, 1).Select
Selection.Collapse wdCollapseStart
End Sub
Related
I have a Word document using font size 8 in which I manually have created some index objects using the shortcut Shift-Alt-X. It might look like this, showing formatting symbols:
some·words·in·bold{·XE·"bold"},·some·in·italic{·XE·"italic"}
Actually, the "XE" is set with font size 11 (my normal standard), but I can't reproduce that here. So I have written a macro which intends to normalize the index object when called from just after the ”}”-sign. It extends the range backwards to include the ”{”-sign and resets the selection to standard values:
Private Sub NormalizeEntry()
Dim rng As Range
Set rng = Selection.Range
With rng
.MoveStartUntil Cset:="{", Count:=-100
.MoveStart Unit:=wdCharacter, Count:=-1
.Select
.Font.Size = 8
.Font.ColorIndex = wdBlack
.Font.Bold = False
.Font.Italic = False
.Select
End With
End Sub
The macro works fine if I apply it after a standard sequence of words enclosed in brackets like
Behold, {here are some words enclosed in brackets} and more words...
("brackets" written with a colored font, which I also can't reproduce here), but it fails when used after an XE-entry. The entry gets selectet all right, but the font is not changed. What am I missing here?
As John advises, you should set the font attributes of the underlying Style to 8pt. As for the bold & italic formatting:
Bold should be applied via the Strong character Style; and
Italic should be applied via the Emphasis character Style.
To revert anything with the wrong format to that of the underlying paragraph Style, simply select the offending content and press Ctrl-Space.
Here's a way of achieving the same thing for all fields via a macro:
Sub FieldReset()
Application.ScreenUpdating = False
Dim Fld As Field, Rng As Range
For Each Fld In ActiveDocument.Fields
With Fld
Set Rng = .Code
With Rng
With .Duplicate
Do While .Fields.Count = 0
.Start = .Start - 1
Loop
Rng.Start = .Start + 1
End With
Do While .Fields.Count = 0
.End = .End + 1
Loop
.Start = .Start - 1
.Font.Reset
End With
End With
Next
Application.ScreenUpdating = True
End Sub
Thank you, Macropod, for your input. However your solution is not what I am looking for, I want to format the field upon insertion.
By experimenting I found a useful solution: Don’t use ActiveDocument.Indexes.MarkEntry, but construct the XE-field yourself using rng.Fields.Add. Here is my result:
Sub TextToNormal(rng As Range)
With rng.Font
.Bold = False
.Italic = False
.Underline = wdUnderlineNone
.StrikeThrough = False
.DoubleStrikeThrough = False
.Color = wdColorAutomatic
.Engrave = False
.Superscript = False
.Subscript = False
End With
End Sub
Function SkipSurroundingSpaces(rng As Range) As Range
With rng
.MoveStartWhile Cset:=" ", Count:=wdForward
.MoveEndWhile Cset:=" ", Count:=wdBackward
.Select
End With
End Function
Sub TestSkipSurroundingSpaces()
Dim rng As Range
Set rng = Selection.Range
SkipSurroundingSpaces rng
End Sub
Sub InsertXEfield()
Dim Xref As String
Dim rng As Range
Set rng = Selection.Range
With rng
SkipSurroundingSpaces rng
Xref = .Text
.Collapse wdCollapseEnd
.Fields.Add Range:=rng, Type:=wdFieldEmpty, _
PreserveFormatting:=False
.Select
.MoveEnd Unit:=wdCharacter, Count:=4
Debug.Print .Start, .End
TextToNormal rng
.MoveStart Unit:=wdCharacter, Count:=2
Debug.Print .Start, .End
.Collapse wdCollapseStart
.InsertAfter "XE """ & Xref & """"
.MoveStart Unit:=wdCharacter, Count:=4
.MoveEnd Unit:=wdCharacter, Count:=-1
.Italic = True
.Bold = True
.Font.ColorIndex = wdViolet
End With
End Sub
Comments:
When selecting a word the range could include a trailing space. This is removed by a call to SkipSurroundingSpaces. Next the selected word is read (actually I take Xref from a form’s inputbox, where it can be changed to something more appropriate, say changing “exoplanets” to “exoplanet”). The range is collapsed to its end and an empty field is inserted. This field might have inherrited formatting from the entry, so it is set back to normal by calling TextToNormal. Then the range is moved into the field (passing by “{·”) and the XE-text is inserted. Finally the range is reduced to include the inserted word only and this word can now be formatted to your heart’s content or as instructed by information from a user form.
(Code and comments updated 2022-06-08)
I'm trying to find and tag all blank DOCPROPERTY fields in a selection of text.
The macro will tag some of the required fields with the text, but not others.
The macro then fails with run-time error 5941.
I have a feeling it has something to do with how the loop is counting and cycling through blank fields.
Sub RemoveFieldCodes()
'Moves to start of doc and selects text block
Selection.HomeKey Unit:=wdStory
Selection.HomeKey Unit:=wdStory
Selection.MoveDown Unit:=wdLine, Count:=2
Selection.MoveDown Unit:=wdParagraph, Count:=6, Extend:=wdExtend
'Finds blank fields and appends text to end
Dim i As Long
With Selection
For i = Selection.Fields.Count To 1 Step -1
If .Fields(i).Type = wdFieldDocProperty And .Result = "" Then
.Fields(i).Select
Selection.EndKey Unit:=wdLine
Selection.TypeText Text:="BLANK"
End If
Next i
End With
You should work backwards through the collection; otherwise consecutive blanks are liable to be missed. Try:
Sub Demo()
Application.ScreenUpdating = False
Dim i As Long, Rng As Range
With ActiveDocument
For i = .Fields.Count To 1 Step -1
With .Fields(i)
If .Type = wdFieldDocProperty Then
If .Result = " " Then
Set Rng = .Result
.Delete
Rng.Text = "BLANK"
End If
End If
End With
Next
End With
Application.ScreenUpdating = True
End Sub
It's not clear why you're using 'Selection.EndKey Unit:=wdLine' so, if:
Rng.Text = "BLANK"
isn't sufficient, try replacing that with:
With Rng
.End = .Paragraphs(1).Range.End - 1
.Text = "BLANK"
End With
I need to copy a word always begining with exact string "p1" and copy that word to a table in another document. Then copy a sentence always between exact strings and copy that sentence to the same table.
let me explain with an example. Here are few paragraphs of text I need to copy from:
variable labels p1consid 'SDQ: Considerate (Parent1)'.
variable labels p1restles 'SDQ: Restless (Parent1)'.
variable labels p1somatic 'SDQ: Headache, stomach-ache (Parent1)'.
So, "p1consid" should go to a column 1 of a table, and "SDQ: Considerate (Parent1)" to a column 2 of the same table.
COLUMN 1
p1consid
p1restles
p1somatic
COLUMN 2
SDQ: Considerate (Parent1)
SDQ: Restless (Parent1)
SDQ: Headache, stomach-ache (Parent1)
Thank you!
There's a bunch of assumptions in this code but try this for a start.
It assumes the source documents formatting is as you described and that a 2-column table exists in the destination document. The table is the first table, there are no header rows and it is a single row table.
Sub CopyStrings()
Dim docSrc As word.Document, docDst As word.Document
Dim rng As word.Range, tbl As word.Table, tRng As word.Range
Set docSrc = Documents.Open("Your Source Doc")
Set docDst = Documents.Open("Your Destination Doc")
Set rng = docSrc.Content
Set tbl = docDst.Content.Tables(1)
With rng.Find
.ClearFormatting
.Format = False
.Forward = True
.Text = "p1"
.Wrap = wdFindStop
.Execute
Do While .found
rng.MoveEnd word.WdUnits.wdWord, Count:=1
Set tRng = tbl.rows(1).Cells(1).Range
tRng.MoveEnd word.WdUnits.wdCharacter, Count:=-1
tRng.Collapse word.WdCollapseDirection.wdCollapseEnd
tRng.Text = rng.Text & vbCr
rng.Collapse word.WdCollapseDirection.wdCollapseEnd
rng.MoveStart word.WdUnits.wdWord, Count:=1
rng.MoveStart word.WdUnits.wdCharacter, Count:=1
rng.MoveEnd word.WdUnits.wdParagraph, Count:=1
Set tRng = tbl.rows(1).Cells(2).Range
tRng.MoveEnd word.WdUnits.wdCharacter, Count:=-1
tRng.Collapse word.WdCollapseDirection.wdCollapseEnd
tRng.Text = rng.Text
rng.Collapse word.WdCollapseDirection.wdCollapseEnd
.Execute
Loop
End With
End Sub
I wanted to develop a program such a way that when up or down arrow moved, highlight the entire line of text. So when I go up or down with arrow keys it highlight the line where my cursor is.
So I developed this code.
Application.ScreenUpdating = False
Dim currentPosition As Range
Set currentPosition = Selection.Range 'pick up current cursor position
Selection.WholeStory
Selection.Range.HighlightColorIndex = wdNoHighlight
currentPosition.Select 'return cursor to original position
Selection.Range.HighlightColorIndex = wdYellow
Selection.HomeKey Unit:=wdLine
Selection.EndKey Unit:=wdLine, Extend:=wdExtend
Selection.Range.HighlightColorIndex = wdYellow
'Unselect the line
Application.Selection.EndOf
Application.ScreenUpdating = True
Then I tried to assign this macro to both Up arrow key and Down arrow key. Then I realised that we can't assign one macro for 2 key combinations. So I created 2 macros like this. (Content is same. Only name is different.).
And assigned SelectLineUp to Up arrow key and assigned SelectLineDown to down arrow key.
Sub SelectLineUp()
Application.ScreenUpdating = False
Dim currentPosition As Range
Set currentPosition = Selection.Range 'pick up current cursor position
Selection.WholeStory
Selection.Range.HighlightColorIndex = wdNoHighlight
currentPosition.Select 'return cursor to original position
Selection.Range.HighlightColorIndex = wdYellow
Selection.HomeKey Unit:=wdLine
Selection.EndKey Unit:=wdLine, Extend:=wdExtend
Selection.Range.HighlightColorIndex = wdYellow
'Unselect the line
Application.Selection.EndOf
Application.ScreenUpdating = True
End Sub
And this is for down arrow
Sub SelectLineDown()
Application.ScreenUpdating = False
Dim currentPosition As Range
Set currentPosition = Selection.Range 'pick up current cursor position
Selection.WholeStory
Selection.Range.HighlightColorIndex = wdNoHighlight
currentPosition.Select 'return cursor to original position
Selection.Range.HighlightColorIndex = wdYellow
Selection.HomeKey Unit:=wdLine
Selection.EndKey Unit:=wdLine, Extend:=wdExtend
Selection.Range.HighlightColorIndex = wdYellow
'Unselect the line
Application.Selection.EndOf
Application.ScreenUpdating = True
End Sub
Now the problem is when I press down arrow in the keybord it works as I intended. But when I press Up arrow, it still goes down dirrenction in the document. Highly appreciate if you can tell me what I have done wrong.
The following works for me. I used some additional methods for changing the Selection (or Range) locations, such as MoveEnd, MoveStart and Collapse. Note the change for the highlight setting of the entire document, so that you don't have to change the Selection.
If you use F8 to step through the code, and switch between the VBA Editor and document windows, you can see how these methods work. The details can be found in the VBA Help.
Sub SelectLineUp()
Application.ScreenUpdating = False
ActiveDocument.content.HighlightColorIndex = wdNoHighlight
Selection.MoveEnd wdLine, -1
Selection.EndKey Unit:=wdLine, Extend:=wdExtend
Selection.Range.HighlightColorIndex = wdYellow
'Unselect the line
Application.Selection.StartOf
Application.ScreenUpdating = True
End Sub
Sub SelectLineDown()
Application.ScreenUpdating = False
ActiveDocument.content.HighlightColorIndex = wdNoHighlight
Selection.MoveStart wdLine, 1
Selection.HomeKey Unit:=wdLine
Selection.EndKey Unit:=wdLine, Extend:=wdExtend
Selection.Range.HighlightColorIndex = wdYellow
'Unselect the line
Application.Selection.Collapse wdCollapseStart
Application.ScreenUpdating = True
End Sub
Try this out. This works for me, while keeping the code very DRY.
Option Explicit
Private Declare Function GetKeyState Lib "user32.dll" (ByVal nKey As Long) As Integer
Public Sub KeyUpOrDown()
Dim keyUp As Boolean
keyUp = CBool(GetKeyState(vbKeyUp) And &H80) ' Was "keyup" pressed
If (keyUp) Then
Selection.MoveUp Unit:=wdLine
Call HighlightLine
Else
Selection.MoveDown Unit:=wdLine
Call HighlightLine
End If
End Sub
Private Sub HighlightLine()
Application.ScreenUpdating = False
Dim currPosition As Range
Set currPosition = Selection.Range
ActiveDocument.Content.HighlightColorIndex = wdNoHighlight
Selection.Expand Unit:=wdLine
Selection.Range.HighlightColorIndex = wdYellow
currPosition.Select
End Sub
Both trigger keys can be bounded to the public subroutine "KeyUpOrDown".
I like the way this works, because it has a native feel. As you hinted in your code, the selection point does not get collapsed to one side but it maintains it's original position while switching line.
Another big one is the simulated key press event using the external "user32.dll" library.
I hope you'd find it useful.
Thank you.
A little performance improvement in the accepted answer. Un highlighting whole document takes too much time if you have 400 pages book. Also the code doesn't return you to same cursor position.
I have modified the code a little bit to solve both issues:
Add this to declaration section.
Dim currSelection As Range
bind these macros to up and down keys
Sub UpKey()
Application.ScreenUpdating = False
'get current position
Dim currPosition As Range
Set currPosition = Selection.Range
'remove highlight from previous line
If Not currSelection Is Nothing Then
currSelection.HighlightColorIndex = wdNoHighlight
End If
'move and highlight new line
Selection.MoveUp Unit:=wdLine
Selection.HomeKey Unit:=wdLine
Selection.EndKey Unit:=wdLine, Extend:=wdExtend
Set currSelection = Selection.Range
Selection.Range.HighlightColorIndex = wdYellow
'get back to old spot and move the line
currPosition.Select
Selection.MoveUp Unit:=wdLine
Application.ScreenUpdating = True
End Sub
Sub DownKey()
Application.ScreenUpdating = False
Dim currPosition As Range
Set currPosition = Selection.Range
If Not currSelection Is Nothing Then
currSelection.HighlightColorIndex = wdNoHighlight
End If
Selection.MoveDown Unit:=wdLine
Selection.HomeKey Unit:=wdLine
Selection.EndKey Unit:=wdLine, Extend:=wdExtend
Set currSelection = Selection.Range
Selection.Range.HighlightColorIndex = wdYellow
currPosition.Select
Selection.MoveDown Unit:=wdLine
Application.ScreenUpdating = True
End Sub
Note: If for some reason a row stays highlighted then take cursor to the row and move up or down once.
I have a Word document with a table of 3 columns and an unknown number of rows and
I need a macro that can search for the string "Sum" in column 1.
If an exact match is found the macro must set the typography of the two remaining cells in the row to two different typographies from Word and also delete the string "Sum" in cell 1.
The table can contain many instances of the string "sum" but they wil alwaye be in the first column.
The code I have tried, and I apologize for my lack of coding skills, but I have only been doing this for at week, works fine until the first instance of "sum" and then just quits.
I am using this code:
Sub FindSum()
Dim oTbl As Table
Dim oRow As Row
Set myRange = ActiveDocument.Content
For Each oTbl In ActiveDocument.Tables
For Each oRow In oTbl.Rows
Selection.Find.Execute FindText:="Sum", ReplaceWith:=""
If Selection.Find.Found = True Then
Selection.MoveRight Unit:=wdCell
Selection.Style = ActiveDocument.Styles("Titel")
Selection.MoveRight Unit:=wdCell
Selection.Style = ActiveDocument.Styles("Citat")
End If
Next
Next
End Sub
I hope you can help me.
this appears to work
ignores "Sum" outside of tables
tested with two tables
Option Explicit
Sub FindSum()
Dim oTbl As Table
Dim stT As Long, enT As Long
Dim stS As Long, enS As Long
With Selection.Find ' the settings remain until changed
.Text = "Sum"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
End With
For Each oTbl In ActiveDocument.Tables
oTbl.Columns(1).Select ' not sure if this is required
Do While Selection.Find.Execute
stT = oTbl.Range.Start ' table range
enT = oTbl.Range.End
stS = Selection.Range.Start ' found text range
enS = Selection.Range.End
If stS < stT Or enS > enT Then Exit Do ' text found inside table ???
Selection.Collapse wdCollapseStart
Selection.Find.Execute Replace:=wdReplaceOne
Selection.MoveRight Unit:=wdCell
Selection.Style = wdStyleTitle ' original code was invalid
Selection.MoveRight Unit:=wdCell
Selection.Style = wdStyleHeading3
Loop
Selection.Collapse wdCollapseEnd
Next
End Sub