Consider the following table in Word 2013
A BBB
A CCC
D E F
A, B and C are merged cells.
A and B are empty. C has text A inside.
Now the following code
Set rng = ActiveDocument.Range(0, 0)
With rng.Find
.Forward = True
.Wrap = wdFindStop
.Execute "A"
End With
Crashes word on Execute "A".
If I change text to Execute "B" it doesn't find anything but doesn't crash word. Issue is present only in word 2013.
We tried searching manually and Selection.Find cell by cell, but both of those are rather slow.
Is there a quick way to circumvent this error?
EDIT: this is minimum fail example that I constructed. In our application we use a lot of Range.Find, sometimes with wrap and almost never starting from Document.Start
EDIT2: further investigation shows that Error isn't present if you open Document in compatibility mode (Word 97-2003 format).
And you can't just activate a .Find object off the Tables(index).Selection object rather than the range object?
If you are just activating the .Selection object off of the ActiveDocument instead of the Table object then, yeah that could take forever. But coming directly off the table index will speed it up significantly.
ActiveDocument.Tables(1).Select
With Selection.Find
.Forward = True
.Wrap = wdFindStop
.Execute FindText:="A"
End With
Related
I've been tasked with writing VBA code to automate Word. I have no idea about VBA.
What is needed:
There is a standard Word document based on a template, which has a section for writing issues. Each section has a heading, and below the heading there is a table with a couple of rows.
Sections view
The overall document layout with the different sections.
Issue view
A standard issue, with a Heading for the issue title, then a table to be filled, and then a description.
How do I write a macro that will:
Review ALL the issues in the document to see if the issue has a list of "Affected Hosts" in the table below the heading that contains more than 10 hosts
If this is not the case, ignore and move on to the next one.
If this is the case, that list should be replaced with some generic text such as "See Appendix G", and then add to that Appendix G the issue title and below it the list of all those hosts.
Where I am at:
I looked for examples of code snippets, looked at the documentation, etc. This is all I have:
Sub TidyAffectedSystems()
'
' TidyAffectedSystems Macro
'
'
' Loop over all issues by finding the appropriate style (IssueHeading)
With ActiveDocument.Range
With .Find
.ClearFormatting
.Forward = True
.Format = True
.Style = "Issue Heading" ' Heading style to find
.Wrap = wdFindStop
.Execute
End With
Do While .Find.Found
MsgBox .Text
' If it is the last one, then finish looping over
If .End = ActiveDocument.Range.End Then Exit Do
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
End Sub
This code tries to find the headings based on the style ("Issue Heading"), and then print that heading. I'm doing this to make sure that at least I am finding the right sections, but that's it.
I don't know how to for example select the table below the current found item to then see if that table has more than 10 hosts and all that, and of course no idea how to then replace, take it to an Appendix and repeat.
BACKGROUND: My daughter works as a Special Needs instructor for a very large school district (with overwhelmed IT especially at the start of the new school year) and has an untouchable/unreachable database that creates a pdf report. She and many of her ~50 Special Needs Instructor co-workers want summary reports that hold only data applicable to their respective needs (1 page) instead of multiple pages (2-6 pages). She alone has over 75 reports of this type.
THUS FAR: On a PC running Windows 10 with Office 365, I've manually converted a pdf file to MS Word and modified a stack overflow obtained VBA macro to delete everything after "Delete Hereafter".
THE NEEDS: From a list of file names in an Office document, open the PDFs as DOCm files and save, then modify each DOCm file and save.
THE SOUGHT-AFTER MODIFICATION: Each report has two tables with text between. The second table always begins with the same header: "Second Table Title". For the second table, she wants to delete rows 2 through a row which always contains "Text Needed" less 1, a variable number of rows.
Your assistance would be appreciated not only by her, but by her co-workers as well. I am a novice user who has benefitted from Stack Overflow answers many times, but need a bit more help to solve this problem.
For example:
Sub TableCleaner()
Application.ScreenUpdating = False
Dim i As Long, r As Long
With ActiveDocument.Tables(2)
With .Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchCase = True
.Forward = True
.Wrap = wdFindStop
.Text = "Text Needed"
.Replacement.Text = ""
.Execute
End With
If .Find.Found = True Then i = .Cells(1).RowIndex - 1
End With
For r = i To 2 Step -1
.Rows(r).Delete
Next
End With
Application.ScreenUpdating = True
End Sub
I'm trying to do a search and replace on a document that finds all 'small' page breaks ('^m' in Word/VBA), and replaces them with a 'full' page break. These small page breaks all have a paragraph mark after them. When that is removed, they become a full page break.
How do I search and replace for all instances of "^m" and remove one character immediately to the right of any selection found?
In old versions of word, you could tick a box for 'split apart page break and paragraph marks', but no longer. The documents I'm working with are being fed through software that doesn't know how to read small page breaks, hence the need to remove the paragraph marker immediately after any that are found.
I've noticed this can be accomplished by replacing the '^m' with '^m ', which removes the paragraph marker after the page break and inserts a space instead, but then I can't seem to figure out how to remove the space immediately afterward (AND maintain the full sized page break).
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "^m"
.Replacement.Text = "^m "
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.MoveRight
Selection.TypeBackspace
Selection.TypeBackspace
SendKeys ("{BACKSPACE}")
This code does, somehow, find 'small' page breaks, replace them with 'full' page breaks, and remove a space afterwards. However, when there's multiple page breaks in the document it introduces various issues, including random character deletion (not surprising considering the code).
Any help would be appreciated! I've managed to use VBA to do a lot of amazing things so far, but this (admittedly very basic) task has me stumped, as I don't fully understand how to use the selection/replacement code.
I have a document that is roughly 200 pages and is essentially a list of test procedures for a specific software. Now this document has certain parts to it the pertain to different versions of the software and these parts are mixed in so their not nicely formatted in a specific order. What I would like to do is Be able to hide the parts of the document that are not needed when testing a different version. I know MS word has a font option to hide text but I would like to be able to setup up a button/hypertext link/macro that will easily hide the unneeded sections. Is this possible and how would I do it? I've started experimenting with VBA script to design my own macro but have only found a way to hide one part per shortcut hit. Is there a way to do this so all parts are effected simultaneously?
EDIT:
The document is organized like this
Version 1
Test Option button
/
Version 2
Test Option button
Check that Sample button is disabled
/
Version 1
Test Save button
/
Version 3
Test Save to USB button
/
So as you can see it's completely unorganized the code I currently have for one macro really doesn't work because instead of selecting between the two point I specify it selects the whole document.
Sub TextSelectTest()
'
' TextSelectTest Macro
' Base Test
'
With Selection.Find
.Text = "Version1"
.Forward = False
.MatchWildcards = False
.Wrap = wdFindStop
.Execute
End With
Selection.Extend
With Selection.Find
.Text = "/"
.Forward = True
.Execute
.Text = ""
End With
Selection.Extend
With Selection.Font
.Hidden = True
End With
End Sub
I don't think hiding font is most professional solution as the result is visible only for printing. But that could be the easiest in this situation especially you suggested it.
First step: set sections in your documents. It's quite easy and should be done ones in Word app. You will need to insert as many section separation marks as many parts of the document you need to manage. We will need to know which section should be/shouldn't be part of each Manual but I'll back to that later.
Second steps: Than you will need the following subroutine which will 'hide' all sections and than show appropriate ones:
Sub HideUnhide_Document_Section(secIndex As Variant)
Dim Doc As Document
Set Doc = ActiveDocument
Dim secDoc As Variant
'to hide all section first, by iteration
For Each secDoc In Doc.Sections
secDoc.Range.Font.Hidden = True
Next secDoc
'alternatively we could hide whole content without iteration:
'secDoc.Content.Font.Hidden = True
'to un-hide chosen sections
For Each secDoc In secIndex
Doc.Sections(secDoc).Range.Font.Hidden = False
Next secDoc
End Sub
And to manage your hiding process I would propose the following code:
Sub Call_Hide()
Dim arrVersion1 As Variant
'put all sections for appropriate version
arrVersion1 = Array(1, 3)
'to unhide
HideUnhide_Document_Section arrVersion1
End Sub
You could either prepare similar separate subroutine for each version or parametrize that one. It that second situation it will have to have separate arrays (arrVarsionX) for each Version of your manuals.
I am trying to delete empty lines occurring in a word document between two placeholders.
I am not sure how to find the position of the placeholders within the entire document.
I am not sure how to search between the placeholders and replace multiple carriage returns with a single carriage return.
I tried to convert the code here but couldn't get it working.
If your placeholders are always the same, you can accomplish the whole thing from Word's Find and Replace dialog. No code necessary.
For example, to replace multiple carriage returns:
Ctrl+H
turn "Use Wildcards" on
Find: (Placeholder1)^13{2,}(Placeholder2) \include the parentheses
Replace: \1 ^13 \2
If you're trying to incorporate this into a bigger block of code:
With Selection.Find
.Text = "(Placeholder1)^13{2,}(Placeholder2)"
.Replacement.Text="\1" & " ^13 " & "\2"
.Forward = True
.Wrap = wdFindContinue
.MatchWildcards = True
.Execute
End With
Let me know if that works for you.