Troubleshooting Large Macro for Word 2016 - vba

I am trying to create a macro for Word 2016 that will automatically edit a document based on a list of about 250 search terms that I used the "find and replace" function to change. When I record the macro from start to finish and attempt to run, I receive a message saying "Procedure is too long". I have looked through answers on here and understand that you can clean up some code and/or create sub sections within the code to troubleshoot. However, I am not sure what I am doing and the code is very long.
Could someone help me please?
portion of code is included below:
Portion of code

Break your macro into steps. The easiest way is (use a copy of your document for testing, so you can always put the original text back if you make a mistake!):
Record a short macro. It doesn't matter what it does. Name it something like DoAllReplacements.
Record a macro that does your first block of replacements. Name it something like DoReplacement1.
View the macros, and edit the DoReplacement1 macro. Copy all of the text from the end of the comment block to the line just before End Sub.
Put the edit caret (cursor) at the end of the DoReplacement1 End Sub and hit enter twice. Enter the following text:
Sub DoReplacement2()
End Sub
Paste the code from the clipboard between the Sub and End Sub lines you just added. Edit the macro code to do your next block of replacements.
Repeat the above until you have all of your replacements coded, using as many new DoReplacementX routines as needed.
Go back to the very first macro you recorded (DoAllReplacements), and remove all of the code between the Sub DoAllReplacements() and End Sub. Add new calls to the individual DoReplacementX macros you wrote.
Sub DoAllReplacements()
DoReplacement1
DoReplacement2
DoReplacement3
' Etc. until you've added them all
End Sub
Exit the macros code window. Use View Macros, select your DoAllReplacements macro and execute it.

Related

Is it possible to trigger some event when a comment is added or deleted in MS Word using VBA?

In MS Word, when adding a comment to a text selection, I would like to change the background color of this selection if the comment contains some "keyword".
Then obviously, if the comment is deleted or doesn't contain the "keyword", I need to remove this color/highlight to the scope text.
I managed to do it on the global 'run macro' with this code (except the remove part), but ideally this should be dynamic and activates when the focus changes back from the comment to the document or anything else.
Here is a simplified version of my code attempt so far:
'
' ColorComments Macro
'
Dim wdCmt As Comment, cat As String, pg As Paragraph
For Each pg In ActiveDocument.Paragraphs
'Trying to reset the background colors before reapplying the active ones but doesn't work
pg.Shading.BackgroundPatternColorIndex = 0
Next
For Each wdCmt In ActiveDocument.Comments
With wdCmt
If Trim(.Range) = "keyword" Then
'Probably a better way to change the background color of the text that would give me access to more colors?
.Scope.Shading.BackgroundPatternColorIndex = 2
Else
'resetting the comment "Scope" color if it doesn't contain the code
.Scope.Shading.BackgroundPatternColorIndex = 0
End If
End With
Next
End Sub
I guess I should use the pulic events or the WindowsSelectionChange event but I can't find a documentation about it anywhere.
I've little to no experience in VBA so thanks in advance for awy help :)
To make that work effectively you will need to repurpose these two controls from the RibbonUI:
ReviewNewComment
ReviewDeleteComment
Here are a couple of links to articles on repurposing RibbonUI controls
https://gregmaxey.com/word_tip_pages/repurpose_user_interface_controls.html
https://www.experts-exchange.com/articles/21499/Intercepting-Office-Ribbon-Control-Events-with-VBA-using-Repurposing-Commands.html
In prior versions of Word, I don’t recall seeing what version you are trying to use, VBA solutions could access the following event routine:
Sub InsertNewComment()
'
' InsertNewComment Macro
' Insert comment (includes menu)
'
End Sub
And even though this routine still works if you invoke it directly from VBA, this is not what is used from the RibbonUI in today’s versions of Word. I know that because I’ve tried to trap the event using the subroutine but haven’t been successful.
The following VBA routine is invoked by clicking on the Insert Ink Comment on the RibbonUI.
Sub InsertInkComment()
'
' InsertInkComment Macro
' Insert ink comment
'
Selection.Comments.Add Range:=Selection.Range
End Sub
It’s a mystery why this one works and the other does not and that is why I said upfront that you will have to trap and repurpose the RibbonUI, particularly for regular comments.
As for trapping the Delete Comment event, there isn’t a DeleteComment VBA routine that I have found. There are event routines for Deleting All Comments but none for a single comment.

VBA Compile Error: Invalid Outside Procedure

I'm trying to create and run a pretty simple macro in Excel 2016, but I keep getting the following error message "Compile Error: Invalid Outside Procedure.
All the macro is trying to do is when I click a button on one worksheet, the macro moves to another worksheet, and amends a filter on a particular column (and removes the zero's from the column).
I've recorded the macro to do this, but when I assign it to a button and try to run it, the error keeps coming up.
The code shown in the VBA tab is as follows:
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
End Sub
Can someone help as it's driving me nuts!
Thank you
Half code (or incomplete code) is like half-truth, difficult to understand or judge. So, if I understand your question here's the (probable) solution.
1. On the button click method, write the sheet change code (e.g. Sheets("books").Select)
2. Once the intended sheet is selected, select the column you want to apply filter on by simply recording the macro.
3. Then do the rest of the tasks.
These are simple steps. If you still don't succeed then please revert.
It could be just as easy as deleting the first 'End Sub' in your code.
w1n5rx seems to be correct with completing your code to perfom what you're describing.
But maybe other options to try:
Maybe try the active controlx button <--- or however its labeled.
or try
Static Sub Worksheet_SelectionChange(ByVal Target As Range)
End Sub

Why will my macro only work when I run it from the macro dialog box?

I have two macros that I want to work when I push a button. I inserted the code needed in the button sub and made it so that it is not private. Then I opened the macro dialog box and ran the macro and it worked as expected. But, when I try to press the button, it comes up with an error that says "the requested member of the collection does not exist."
The code shouldn't really matter in this case since it is working correctly when I run it manually but here it is:
Sub CommandButton4_Click()
Selection.Tables(1).Select
Selection.Copy
Selection.PasteAndFormat (wdPasteDefault)
ActiveWindow.ActivePane.VerticalPercentScrolled = 24
'Some other Code here
End Sub
When I perform a debug, it says that the problem is in this line: Selection.Tables(1).Select
Then in my other instance I have this code:
Sub CommandButton3_Click()
Selection.SelectRow
Selection.Copy
Selection.InsertRowsBelow 1
Selection.Paste
End Sub
The code error appears to be in this line:
Selection.SelectRow
It says
The SelectRow method or property is not available because some or all of the object does not refer to a table.
I got the code by using the Macro Recorder.
If you have any ideas as to why this is happening, I would appreciate your help.
This code
Selection.Tables(1)
works only when the Selection (the cursor) is inside a table.
When you click the button, the button gets the focus, and the Selection is moved there. If the button is not inside a table, the code will fail.
It does work if you move the button inside the table, but that would probably look silly.
Replace your
Selection.SelectRow
with
'r being which ever row you want to Select
Selection.Table(1).Row(r).Select
You can bind your macro to a key combination. This won't change any focus you've set, and thus should solve your problem.
How to do this differs among different versions of Word, but the recent versions are explained here:
http://wordribbon.tips.net/T008058_Assigning_a_Macro_to_a_Shortcut_Key.html

Running Macros from Toolbar/Running one macro from another

I am trying to develop a macro for a publisher document. This macro will, when run, show a pop-up allowing the user to select one of three types of clients, and add different bullet points to a text box depending on which option was selected. I'm having two different problems which I suspect are coming from the same source. Problem number one is that I can't get the button on my User Form to run a different macro when the button is clicked. Problem two is that I've added my macros to one of the toolbars, and nothing happens when I click on them. In both cases, it's simply not running the macro. What am I doing wrong?
UserForm1
Private Sub CommandButton1_Click()
Application.Run ("ShapeTest")
End Sub
Private Sub UserForm_Initialize()
With ListBox1
.AddItem ("Federal")
.AddItem ("State")
.AddItem ("Local")
End With
End Sub
ThisDocument
Private Sub GenerateStatement()
UserForm1.Show
End Sub
Private Sub ShapeTest()
MsgBox ("Hello!")
Application.ActiveDocument.Pages(1).Shapes(1).TextFrame.TextRange.InsertAfter`enter code here`(Chr(13) & "My Text")
End Sub
Why are you using Application.Run("ShapeTest") rather than simply ShapeTest?
I don't have enough information to be 100% sure, but the following should work: To make ShapeTest callable from the userform you do two things:
1) Move it from ThisDocument to a general code module (first Insert/Module in the editor).
2) Eliminate the word Private in front of Sub ShapeTest()-- you don't want this to be a private sub since you want code outside of the module to be able to use it.
On edit: Alternatively -- you could keep ShapeTest() where it is in ThisDocument, get rid of the Private qualifier and in the userform code refer to ShapeTest as ThisDocument.ShapeTest. I prefer using the first method since I tend to like to keep as much code as possible in general code modules (reserving things like ThisDocument for event handlers) but OTOH my VBA experience is mostly Excel with a smattering of Word and there might be reasons to keep the code in ThisDocument in Publisher. I don't know Publisher, but a problem that I have run into in Word at times is I have sometimes accidentally put code in the Normal template that I wanted to go in the document's project. If something similar is possible in Publisher you should double check where your code is living.

Ending undo transaction in macro in PowerPoint

As described in http://support.microsoft.com/kb/278591 PowerPoint will usually combine all changes that a macro or add-in makes to a single undo step. So if you put the following code into VBA and execute it twice by pressing F5 there
will only be one undo step.
Sub Move()
If ActiveWindow.Selection.Type = ppSelectionShapes Then
ActiveWindow.Selection.ShapeRange.IncrementLeft 10
End If
End Sub
I am looking for a way to change this behavior in a more complex scenario where the user can make multiple changes without directly accessing PowerPoint. Ideally, it should be possible to undo a set of modifications that corresponds to one change from the user's perspective.
What I found out is that ExecuteMso seems to break the undo transaction. So if you execute the following code twice it results in 4 undo steps (first increment, ExecuteMso, second increment, ExecuteMso).
Sub Move()
If ActiveWindow.Selection.Type = ppSelectionShapes Then
ActiveWindow.Selection.ShapeRange.IncrementLeft 10
Application.CommandBars.ExecuteMso "Bold"
End If
End Sub
Anyone knows a real solution for the problem or a better workaround? Although I didn't find it maybe there is a solution for Word or Excel that can be ported to PowerPoint?
If you replace the ExecuteMso line with this one, the entire procedure remains one Undo:
ActiveWindow.Selection.ShapeRange.TextEffect.FontBold = msoTrue
Update
If you are using PowerPoint 2010 or later put this line before each block of code that you want the user to be able to undo a step at a time:
Application.StartNewUndoEntry