Run-time error '5852' when iterating over revisions - vba

I am easily annoyed by word tracking format changes (even in text that is newly inserted in a revision), so I am using a macro to accept all format changes, once they summed up:
Sub AcceptAllFormatChanges()
Dim xRev As Revision
Dim count As Integer
count = 0
For Each xRev In ActiveDocument.Revisions
If Not xRev Is Nothing Then
If xRev.Type = wdRevisionProperty Then
count = count + 1
xRev.Accept
End If
End If
Next xRev
MsgBox ("Accepted " & count & " format changes")
End Sub
This works fine most of the time, but on some documents, it gives me a run-time error '5852' - Requested object is not available on the "If xRev.Type" line. I am looking for a way to check the object that is yielded by ActiveDocument.Revisions without it throwing a run-time error. Checking for Nothing is not enough. The issue also occures when removing the xRev.Accept or when looping backwards through the revisions.
Update: I tracked down the issue to a Word Bug today. If the macro strikes, I am also unable to iterate through changes in the document using the Next Change button on the review panel. Additionally, if I open the revision panel, the number of revisions jumps back and forth between two numbers. This helped me track down those ghost revisions to a few insertions which included fields (references to other sections). I am able to correct those by deleting/reinserting, so at least now I know how to fix my documents to make the macro work again. Unfortunately, I cannot reproduce the bug in order to actually file a bug report.
The VBA question though remains open: Is there a way for the macro to skip those ghost revisions without throwing a run-time error?

Use the WdRevisionType enumeration instead of cryptic numbers in the code for checking the Type property. Also you may try to check for Nothing before getting the Type property value. The following code works like a charm for me:
Public Sub AcceptSelection()
Dim rev As Revision
For Each rev In Selection.Range.Revisions
rev.Accept
Next rev
End Sub
And the last resort is to replace the for each loop with a reverse for loop.

Related

Find a Specific Cell entry in a Column in VBA

I'm working on creating a userform for reviewing an excel sheet. I need to search a specific column to see if the user has already reviewed the row. If they have, the cell will be filled with "Reviewed", if it hasn't been reviewed yet it will have "Not Reviewed" in it.
Each department has their own Column logging whether the Row has been reviewed or not. I.e. Dept1 may have reviewed the row, while Dept2 has not yet.
I've tried something like
With Sheets("ECR")
UnReviewedRow = .Range(DepartmentReviewColumn:DepartmentReviewColumn).Find(what:="Not Reviewed", after:=.Cells(DepartmentReviewColumn, 3)).Row
End With
But I'm getting an error, not quite sure where it's coming from though. The hardcoded "3" is because I know that all entries begin at row three, everything above is headers.
I've found a few different similar questions, but they all assume that the column being searched will be the same every time. My issue is that I don't want to code this for each department, I'd like to be a bit more elegant than that.
Something like this:
With Sheets("ECR")
UnReviewedRow = .Range(DepartmentReviewColumn & ":" & DepartmentReviewColumn).Find(What:="Not Reviewed", After:=.Cells(3, DepartmentReviewColumn)).Row
End With
Modifications made:
Range() now takes a properly built string argument;
Cells() now has a row number as its first argument, and a column expressed as a string as its second argument.
Note that this code will fail with Object variable or With block variable not set if the search string is not found. You can handle this situation by initializing UnReviewedRow to e.g. 0 (zero) and putting On Error Resume Next above the Find call, and On Error Resume <either 0 or your original error handler's label> below the Find call. Then, check if UnReviewedRow = 0 and act appropriately.
Always put Option Explicit at the top of modules and classes, and compile your code (Debug / Compile VBAProject). When posting, include the text of all errors encountered.

VBA in Word 2013 with TableOfContents Object issue

I'm trying to update my Table of Contents in one of my macros after I edit a bunch of stuff. I'm running into an odd issue though. Below is the snippet I was running.
Note: user_document is declared globally as a Document object. It is accessible in this function.
Private Sub RunBuild_Click()
Dim TOC As TableOfContents
With user_document
For Each TOC In .TableOfContents 'ERROR OCCURS HERE
TOC.Update
Next
End With
user_document.Save
End Sub
When I run this, I get an object doesn't support this property or method error. I can't seem to figure out why I can't access the TableOfContents object in this document through a loop. The For Each block is supposed to enumerate the collection of objects so I can loop them, but it's acting like this concept doesn't exist. I've seen other posts for updating all Table of Contents that use this exact type of loop and have no issues.
If I use the line
user_document.TableOfContents(1).Update
The command runs perfectly fine. However, this doesn't allow me to catch the situation that no TOC exists or when multiple exists, it will only update the first instance.
Any ideas? I'm stumped. I keep rewriting the loop and trying different ways to access the object but they all throw the same error.
I've figured it out.
The TOC object I declared is of type "TableOfContents", but the Document Object contains a TablesOfContents object with individual TableOfContents objects inside.
The following code correctly loops through the structure.
Private Sub RunBuild_Click()
Dim TOC As TableOfContents
With user_document
For Each TOC In .TablesOfContents
TOC.Update
Next
End With
user_document.Save
End Sub
This also explains why i had trouble without getting a more meaningful error - I was accessing valid objects incorrectly instead of invalid objects correctly. Since word wasn't fussing about the object being invalid, I didn't even think to check the object for singular/plural naming.
Edit1: My Bad. Your code should work if you write it like this:
Dim TOC as TableOfContents ' without s on Table
With user_document
For Each TOC In .TablesOfContents ' with s on Table
TOC.Update
Next
End With
But below should work as well just fine.
Dim i As Long
With user_document
For i = .TablesOfContents.Count To 1 Step -1
.TablesOfContents(i).Update
Next
End With
This is assuming user_document is a document object properly set.

VBA Excel + using match function

I'm having some kind of problem in a piece of code.
I need to find values in a excel book and then copy it to another. The thing is that i need to copy it concept by concept in the right place. The problem is that the file doesnt come every week in the same order.
So i need to find the concept and then copy the next cell that is the value of that concept.
First of all i use need to locate the correct line so i can start copying (this part is easy and its done).
Secondly, having the correct line, i need to find the concept, which in this example im going to use the "619".
After having find the location of this value i store the value in "c_audiovisual".
On Error GoTo ErrhandlerCAV
lRowC_AV = Application.WorksheetFunction.Match(619, Range("A" & line & ":FI" & line), 0) + 1
'On Error GoTo ErrhandlerCAV
Continue:
If errorCAV = 1 Then
c_audiovisual = 0
errorCAV = 0
Else
c_audiovisual = ActiveSheet.Cells(line+ m2, lRowC_AV).Value
End If
I've made a escape in case that this concept isn't present in that line (which sometimes occurs).
Sometimes this piece of code works, and other it doesn't.
When i'm on debug mode (pressing F8) it works. And when i use small files to look for the values it works. On bigger files sometimes don't.
Any ideas?
I faced similar issues. I fixed it with using ThisWorkbook.Sheets("MySheet").Range(...) inside the Match function. Or try ActiveWorkbook as applicable. Let me know if this worked. Curious to know.
Btw I noticed column and row number both are "line". Is that a mistake?

Get the number of pages in a Word document

I am making lots of changes to a Word document using automation, and then running a VBA macro which - among other things - checks that the document is no more than a certain number of pages.
I'm using ActiveDocument.Information(wdNumberOfPagesInDocument) to get the number of pages, but this method is returning an incorrect result. I think this is because Word has not yet updated the pagination of the document to reflect the changes that I've made.
ActiveDocument.ComputeStatistics(wdStatisticPages) also suffers from the same issue.
I've tried sticking in a call to ActiveDocument.Repaginate, but that makes no difference.
I did have some luck with adding a paragraph to the end of the document and then deleting it again - but that hack seems to no longer work (I've recently moved from Word 2003 to Word 2010).
Is there any way I can force Word to actually repaginate, and/or wait until the repagination is complete?
I just spent a good 2 hours trying to solve this, and I have yet to see this answer on any forum so I thought I would share it.
https://msdn.microsoft.com/en-us/vba/word-vba/articles/pages-object-word?f=255&MSPPError=-2147217396
That gave me my solution combined with combing through the articles to find that most of the solutions people reference are not supported in the newest versions of Word. I don't know what version it changed in, but my assumption is that 2013 and newer can use this code to count pages:
ActiveDocument.ActiveWindow.Panes(1).Pages.Count.
I believe the way this works is ActiveDocument selects the file, ActiveWindow confirms that the file to be used is in the current window (in case the file is open in multiple windows from the view tab), Panes determines that if there is multiple windows/split panes/any other nonsense you want the "first" one to be evaluated, pages.count designates the pages object to be evaluated by counting the number of items in the collection.
Anyone more knowledgeable feel free to correct me, but this is the first method that gave me the correct page count on any document I tried!
Also I apologize but I cant figure out how to format that line into a code block. If the mods want to edit my comment to do that be my guest.
Try (maybe after ActiveDocument.Repaginate)
ActiveDocument.BuiltinDocumentProperties(wdPropertyPages)
It is causing my Word 2010 to spend half-second with "Counting words" status in status bar, while ActiveDocument.ComputeStatistics(wdStatisticPages) returns the result immediately.
Source: https://support.microsoft.com/en-us/kb/185509
After you've made all your changes, you can use OnTime to force a slight delay before reading the page statistics.
Application.OnTime When:=Now + TimeValue("00:00:02"), _
Name:="UpdateStats"
I would also update all the fields before this OnTime statement:
ActiveDocument.Range.Fields.Update
I found a possible workaround below, if not a real answer to the topic question.
Yesterday, the first ComputeStatistics line below was returning the correct total of 31 pages, but today it returns only 1.
The solution is to get rid of the Content object and the correct number of pages is returned.
Dim docMultiple As Document
Set docMultiple = ActiveDocument
lPageCount = docMultiple.Content.ComputeStatistics(wdStatisticPages) ' Returns 1
lPageCount = docMultiple.ComputeStatistics(wdStatisticPages) ' Returns correct count, 31
ActiveDocument.Range.Information(wdNumberOfPagesInDocument)
This works every time for me. It returns total physical pages in the word.
I used this from within Excel
it worked reliably on about 20 documents
none were longer than 20 pages but some were quite complex
with images and page breaks etc.
Sub GetlastPageFromInsideExcel()
Set wD = CreateObject("Word.Application")
Set myDoc = wD.Documents.Open("C:\Temp\mydocument.docx")
myDoc.Characters.Last.Select ' move to end of document
wD.Selection.Collapse ' collapse selection at end
lastPage = wD.Selection.Information(wdActiveEndPageNumber)
mydoc.close
wd.quit
Set wD = Nothing
End Sub
One problem I had in getting "ComputeStatistics" to return a correct page count was that I often work in "Web Layout" view in Word. Whenever you start Word it reverts to the last view mode used. If Word was left in "Web Layout" mode "ComputeStatistics" returned a page count of "1" page for all files processed by the script. Once I specifically set "Print Layout" view I got the correct page counts.
For example:
$MSWord.activewindow.view.type = 3 # 3 is 'wdPrintView', 6 is 'wdWebView'
$Pages = $mydoc.ComputeStatistics(2) # 2 is 'wdStatisticPages'
You can use Pages-Object and its properties such as Count. It works perfect;)
Dim objPages As Pages
Set objPage = ActiveDocument.ActiveWindow.Panes(1).Pages
QuantityOfPages = ActiveDocument.ActiveWindow.Panes(1).Pages.Count
Dim wordapp As Object
Set wordapp = CreateObject("Word.Application")
Dim doc As Object
Set doc = wordapp.Documents.Open(oFile.Path)
Dim pagesCount As Integer
pagesCount = doc.Content.Information(4) 'wdNumberOfPagesInDocument
doc.Close False
Set doc = Nothing

Error on ActiveSelection.Tasks

Does anyone know what this means
Set oProjTasks = ActiveSelection.Tasks
I have a macro that generates status reports from MS project and exports them directly into MS Word. It is a slick tool when it works.
When I run it now it throws "runtime error '424': object required" at this point.
How do I fix this?
The code that you are displaying is a set statement, that is setting the object ProjTasks equal to the task that is selected in the message box. The ActiveSelection property returns a selection object that represents the active selection.
It could be that you are experiencing an issue where there are no items selected, in which case it will throw a trappable error code 424. There is a code snippet that you can modify from the MSDN that will work to prevent this type of error from occuring.
Here is the link to the MSDN article... just remember to not use this code verbatim, but modify it to work with your macro.
http://msdn.microsoft.com/en-us/library/aa169315%28v=office.11%29.aspx
You could try just wrapping the error check around the set statement. I've written a small macro on a non-empty project file:
Sub Testing()
On Error GoTo ActiveSelectionErrHandler:
Set oProjTasks = ActiveSelection.Tasks
If oProjTasks Is Nothing Then
MsgBox "No tasks in current project"
End If
ActiveSelectionErrHandler:
Set oProjTasks = ThisProject.Tasks 'or something like that
Resume Next
End Sub
This handles the error but as Steve has already expressed more work is required to integrate the code.
You will have to follow the code to make changes to handle oProjTasks being empty where it is expected to have some values. Otherwise you will see more errors perhaps where the oProjTasks is found to be empty.
Another alternative solution could be to launch the macro after selecting a project as the code you have quoted will work fine if something is selected.