Convert Bulletpoints into Listitems in Word - vba

In my word-doc there are Automatically imported lists like lookin like that:
- Listitem one
- Listitem two
- Listitem three
- ...
They are only pagraphs starting with a dash '-'. So im trying to convert them into lists:
Selection.WholeStory
Selection.MoveLeft Unit:=wdCharacter, count:=1
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Style = ActiveDocument.Styles("Aufzählungszeichen")
With Selection.Find
.Text = "^p- "
.Replacement.Text = "^p "
.Forward = True
.Wrap = wdFindStop
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
However this results in lists that are only styled like a list but don't behave like real lists in word. How can i replace the paragraphs (starting ^p-) with real list items through a macro?

Word actually has a built-in feature that can convert text lists into bullet lists. It's disappeared from the UI in recent years, but is still available in the list of "Commands not in the Ribbon" and in the object model. It's called AutoFormat. These can be added to the Ribbon or the QAT, or used with code.
For example select the list then
Selection.Range.AutoFormat
or, to use the UI functionality (which will show and interactive dialog allowing finer control):
Application.CommandBars.ExecuteMso("AutoFormat")
There are also options settings for controlling what AutoFormat does
Application.CommandBars.ExecuteMso("AutoFormatOptions")
It's also possible to apply a style using Find/Replace, but it's important that the style is linked to a list. Create a new style if you don't have one already, then...
Go to the Multilevel list control on the Ribbon and choose Define new list style. Assign a name, click Format, choose Numbering and define the list properties (assign a bullet symbol from Number style for this level). Click the More button and from Link level to style choose the style name that should be used.
Now, when you run the Find/Replace code in the question, using the style name (not the list style name) it should apply the list as well as the style formatting.
If you run into issues with defining the style pair, best to ask in an end-user venue such as Super User.

You're on the right track with applying a style. If the style applied is a member of a list numbering style, the text will behave as a list. The trick is to apply one of the styles that are a member of the list style, since you can't apply the list style directly.
To clarify this difference, here is Shauna Kelly's article about creating numbering lists: How to create numbered headings or outline numbering in Word
In her article, "Headings" is the list style used to organize the sub-styles. If you created a list style using this article, you would apply Heading 1, Heading 2, etc. as a style.

Related

VBA-Word bug: Undo list get error if use UndoRecord to record "Replace All" while there is a "Apply Quick Style" in the undo list. How to avoid?

On Word window, do something like typing, format font, paragraph... to ensure the undo list is not empty, and then change style of some text by clicking any Style on Ribbon. An entry named "Apply Quick Style" appear in the undo list. Then run macro like:
Sub SampleMacro()
Dim myUndoRecord As UndoRecord
Set myUndoRecord = Application.UndoRecord
myUndoRecord.StartCustomRecord ("VBA - Format Text")
'I do a lot of step here, but for this example, just simple like below
Selection.Characters(1).Bold = True 'just for example
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "Find Text"
.Replacement.Text = "Replace Text"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
'Word undo list get error after below step
Selection.Find.Execute Replace:=wdReplaceAll
'no crash, no error message, but the entry "Apply Quick Style"
'become to "Replace All", and Word can't go back before that entry
myUndoRecord.EndCustomRecord
End Sub
After this line of code:
Selection.Find.Execute Replace:=wdReplaceAll
The entry named "Apply Quick Style" in the undo list will become to "Replace All" and I can't undo (by press Ctrl-Z, or click arrow button on Quick Access Toolbar) to go back any step before that entry "Replace All". It's allway appear in undo list and Word will not go back anymore.
How to avoid this bug?
I'm using Word 2016 pro 64 bit
Additional information: using copy paste by press Ctrl+C, Ctrl+V (from other document to current document) instead of "Apply Quick Style" also get error, the entry "Paste" in undo list also rename to "Replace all". The different is still able to go back before that entry. Maybe there is another way will get error if use UndoRecord to record "Replace all".
Update 10/01
A working work around
The problem is specific to wdReplaceAll. If that specific wdConstant is omitted or replaced then "Apply Quick Style" will not be renamed and the undo stack remains accessible.
Lucky for us, Find.Execute returns a Boolean value (True for success). That means, we can loop with wdFindOne to replace all matches and use .Execute = False as the exit condition.
Add the word Do above your With block and replace the line with .Execute.
Do
With Selection.Find
[....]
End With
Loop While Selection.Find.Execute(Replace:=wdReplaceOne)
A word of caution: some circumstances will create an infinite loop (such as replacing "A" with "A"). As such, you should consider using a second exit condition or replacing wdFindContinue with wdFindAsk or wdFindStop.
Update 9/30
(Edit 10/01) Oops!! The Apply Quick Style entry was not renamed (good) but I wrongly assumed the undo stack could be reached when the same limitation exists (bad). Also, testing today, I learned there is a third condition: .Execute must not find any matches (worse). Suffice it to say, this is an exemplary demonstration of how not to test a solution, I hope everyone learned thier lesson!
When I create a new document and follow your steps, I can consistently reproduce the issue you describe. Thank you for making that easy!
As much as I am able to replicate the problem, I am also able prevent it by meeting two conditions.
Ensure Replace All is listed in the Undo Stack above Apply Quick Style.
Replace All is applied to the entire document (the problem persists if Replace All is applied to a Selection within the document)
This method worked regardless if it was done manually with 'Ctrl + H' or if it was part of a macro. Replacing a character with the same character was sufficient.
A screenshot showing the execution point after the problematic line:
The Undo Stack contains an intentionally placed Replace All to preserve Apply Quick Style.
This article is for Excel but it's relevant for Word.
https://excel.tips.net/T002060_Preserving_the_Undo_List.html
In short, you're on your own.
You have two options: revert to a previously saved version; or, write a macro that mimics Undo and ensure this macro is running before you start the one that messes with the Undo list

Cross reference to custom reference type

I'm trying to add a cross reference into a SEQ field.
My document contains "point headings" which means that between two heading elements, the user can add an extension (between 1.1 and 1.2 may be 1.1A, 1.1B, ...)
Here is how the point heading code looks like:
{STYLEREF "HEADING 2" \N}{SEQ "HEADING 2 POINT" \* ALPHABETIC \S 2}
Which results with: 1.1A
I want to be able to do a cross reference into the point heading.
While I can set the reference type into 'Heading' I can't find out how to reference it to a custom element.
Searching through the web did not reveal any solution but some clues that it might be possible:
This website which explains cross-reference formatting, contains an image with custom type (My New Caption).
Microsoft DOC's description for ReferenceType is: The type of item for which a cross-reference is to be inserted. Can be any WdReferenceType or WdCaptionLabelID constant or a user defined caption label.
My client is used to work with the cross reference dialog box hence I prefer this approach, but VBA script will also be appreciated.
Thanks!
Update:
I'll try to describe my constraints and environment.
Headings 1-9 are used inside Multi-Level list item, hence they have custom styling.
They cannot be changed.
For a specific task, which is described and answered here, I've created what I call 'Point Headings'.
'Point Headings' are basically an extension that the user can add in between the Multi-Level numbering with a VBA macro.
Let's say that I have two Heading 2 items (1.1, 1.2), the user can add 1.1A, followed by 1.1B and so on.
The user can add point headings from level 2 up to level 5.
Their style is 'Heading 2 Point', 'Heading 3 Point' and so on, and each one is based on its relevant Heading.
As described above, eventually in the document, the word field has the following structure: {STYLEREF "HEADING 2" \N}{SEQ "HEADING 2 POINT" \* ALPHABETIC \S 2}.
My goal is to be able to cross reference into these items, but they do not appear in the Heading type, well because they are not of style Heading.
I wish to be able to create a custom reference type, which will show these items.
After some research, here is my answer. Hopefully it will help some future viewers.
Private Sub createPointHeader(pointLevel As Integer, Optional appendixPrefix As String = "")
Dim sQuote As String, referencedStyle As String, captionName As String
sQuote = Chr(34)
referencedStyle = appendixPrefix & "Heading " & pointLevel
captionName = referencedStyle & " Point"
With Selection
.Fields.Add .Range, wdFieldEmpty, "StyleRef " & sQuote & referencedStyle & sQuote & " \n", False
.Collapse wdCollapseEnd
CaptionLabels.Add (captionName)
.InsertCaption Label:=captionName, ExcludeLabel:=True
' Select the created field
.MoveLeft Count:=1, Extend:=True
' Replace the syntax from Arabic to Alphabetic
.Fields.ToggleShowCodes
With .find
.Text = "ARABIC"
.Forward = False
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchKashida = False
.MatchDiacritics = False
.MatchAlefHamza = False
.MatchControl = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
If .Found = True Then
Selection.Range.Text = "ALPHABETIC \s " & pointLevel
End If
End With
.Fields.ToggleShowCodes
.Fields.Update
.MoveRight Count:=1
.InsertAfter vbTab
.Collapse wdCollapseEnd
' Apply style after .InsertCaption, because it changes the style to Caption
.Style = ActiveDocument.Styles(referencedStyle & " Point")
End With
End Sub
Few remarks
I have two styles to base upon: Heading (2-5), and Appendix Heading (2-5). This is the reason for the optional appendixPrefix as a sub variable.
CaptionLabels.Add as I've checked can get the same value. No need to check in advance if it already exists.
Selection.InsertCaption automatically changes the style into Caption. This is why I apply the style change at the end.
The result
Here is how Point Heading 2 looks like:
{STYLEREF "HEADING 2" \N"}{SEQ HEADING_2_POINT \* ALPHABETIC \S 2}
Snapshot of the document with the point headings
And finally, as requested, cross reference to the Point headings from the Cross reference box
The question asks how to create a cross reference to a custom reference type. I suspect this answer may actually respond to what the original asker might have been getting at.
The idea is to use custom caption labels. A custom caption label appears (ideally) in the Insert/Cross Reference dialog.
A custom caption label is created when you say Insert/Caption and then ask to add a new custom label.
If you have added a custom caption label yourself in a given document, then it automatically appears as a choice when you say Insert/Cross Reference ...
However a difficulty arises when you are given a document where someone else has already added the cross reference type and you want to edit it (by adding additional cross references to the given type of caption). The secret here is to add the custom caption label yourself (even though it already exists), by creating a new temporary caption with the custom label type. You can then go ahead and delete the temporary caption, but you will from then on be able to add cross references to that caption type.
I use this when I want to make reference to 'Code Snippets' or 'Boxes' or 'Algorithms'.
I'm taking the chance of responding as an answer rather than as a comment as the reply is longish but hopefully should get you going in the right direction.
I think you have been led down the wrong path by the point pages article you have referenced.
I'm assuming that we can't modify the styles 'Heading 1' to 'Heading 9'. If you can then you will be able to adapt the suggestion below to use with only 'Heading 1' to 'Heading 9' styles.
You will need to create some new styles. I've used the following styles
Name Based on Style Outline level
Heading Point 1 Heading 1 1
Heading Point 2 Heading 2 2
Heading Point 2 Ext Heading 2 3
Heading Point 3 Heading 3 4
Heading Point 3 Ext Heading 3 5
Heading Point 4 Heading 4 6
Heading Point 4 Ext Heading 4 7
Heading Point 5 Heading 5 8
Heading Point 5 Ext Heading 5 9
Please note that getting the outline level correct is important for Heading numbering.
Next create a new Multilevel list. Call the list 'PointNumbering' (Because if you do this you can identify the list by the name in VBA should you need this facility). Link the styles 'Heading Point 1' to 'Heading Point 5 Ext' to levels 1 to 9 of the numbering sequence (e.g. Outline level 1 matches level 1 in the numbering sequence etc).
Turn off the legal style numbering for each level otherwise we won't be able to use Alphabetic numbering. Set the numbering scheme as indicated below.
Level Number style format levels* Final Appearance
1 1,2,3, 1 1
2 1,2,3 1.2 1.1
3 A,B,C 1.23 1.1A
4 1,2,3 1.2.4 1.1.1
5 A,B,C 1.2.45 1.1.1A
6 1,2,3 1.2.4.6 1.1.1.1
7 A,B,C 1.2.4.67 1.1.1.1A
8 1,2,3 1.2.4.6.8 1.1.1.1.1
9 A,B,C 1.2.3.6.89 1.1.1.1.1A
The actual levels are picked from a drop down list and appear as '1' in the number format box. This makes getting the numbering wrong quite easy so take care. The last number in each level is obtained by selecting the number format in the 'Number style for this level' box.
Once you have set up your styles and ensured that they are linked to the above numbering scheme you need to adjust the styles used for the headings in you current document.
Do a search and replace to do the following style replacements
Current Style New Style
Heading 1 Heading Point 1
Heading 2 Heading Point 2
Heading 3 Heading Point 3
Heading 4 Heading Point 4
Heading 5 Heading Point 5
Then for each of your extension headings where you are currently creating the numbering using style ref and seq field delete the fields and apply the relevant Ext Heading.
Thus for A,B,C numbering after 'Heading Point 2', apply the 'Heading Point 2 Ext' style.
This should now mean that all Heading Point styles can be accessed through the cross reference dialog.
If you document headings at 'Heading 6' Level 6 and below the after 'Heading Point 5 Ext you can use the Heading styles (Heading 6 to Heading 9) as normal. However, each time you use a Heading 6 you will need to manually reset the number. I think this is an easier task than asking users to insert multiple styleref and seq fields because you just select then right click on the heading number and then tick buttons to enable 'Advanced value (skip number)' which allows you to reset any level within your current Heading Number.
If you subsequently need to create a TOC field for your document you will now have to use the \t switch and provide a list of styles and the level number to use for the style in the TOC. e.g. {toc \t "Heading Point 1,1,Heading Point 2,2,Heading Point 2 Ext,2,Heading Point 3,3,Heading Point 3 Ext,3.....etc}.
I have created and tested all of the above in a Word document.

Find non-printable characters using MS word VBA

I have written a macro which searches in a word document for a certain wind-card defined text string and then find which paragraph this found match belongs to. Everything works fine, but now I have the following challenge: I need to find non-printable characters, specifically I need to find the Ms word index references, which are show in a word like {XE “text to index”}.
I found a dilemma, that whilst when I call the Ms Word find dialogue box (CNTRL+F) and then define the wildcard search pattern ‘XE “*”’ then ms Word finds these. However when I pass the same pattern for VBA find function, then it does not find them, so I observe some difference between behavior of manually called Find function and the one from VBA.
Any idea how to find these non-printable characters using VBA?
Just for info, this is how I call find function
With range1.Find
.Text = searchString
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
‘some code goes here
End With
KazJaw, thank you for a link, very informative.
But, I must say, it did not help in my case. Still the problem which I had is that MS Word Search would produce different results depending on whether it was called manually (CNTRL+F) or from VBA (range.find). The difference is, once again, that manually-called search function finds non-printable index-related characters (provided they are show) but the VBA-called function does not do it.
At certain moment I though that it was fixed, by inserting the line to programmatically show non-printable characters ( ActiveWindow.ActivePane.View.ShowAll = True). It was important that it was programmatically, as an opposite to running macro on the document, where it was manually enabled. But even in this case the behaviour was very unstable: it would only work say 1 time out of 10 on exactly the same document. At that moment I must say I thought I was getting crazy because of this instability, but my colleague confirmed that he independently has stumbled across the same issue.
Therefore we concluded that using range.find function to search for non-printable characters does not produce a stable result in MS Word.
In our case we reached our goal by searching for indexes (fields objects) directly as an opposite of searching for them as for patterns of non-printable characters
For Each aField In range1.Fields
If aField.Type = 4 Then
aField.Select
pageOfFoundIndexEntry = Selection.Information(wdActiveEndPageNumber)
textOfFoundIndexEntry = Mid(aField.Code, 4)
...

Macro to delete all repeated instances of text in word doc

I'm looking for a simple way to delete repeated text in a Word 2007 document. If there are some shortcuts with the Find/Replace commands, I'm not seeing it. Otherwise, can someone recommend how I might write a macro that works like the following:
1- Select a block of text (could be mulitple paragraphs, have bullet points, etc).
2- Run the macro or do the command.
3- The macro or command deletes all instances of the selected text block.
Any insight here?
Selection.Text returns the current selection's text.
In principle, the syntax for your Replace command is:
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = Selection.Text
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
You replace by an empty string, thus delete every instance of the text to find.
But: You have to decide of course how to handle the formatting of the selected text, maybe have to analyze your selected block first because replacing might not work with control chars neglected by Selection.Text ... This is just the start, you need to specify what you want and then ask again, yourself or us. Meanwhile Record macro and the word vba reference are your friends.
For alpha number text (with out newlines), you can use Find/Replace however as soon as you get in the realm of bullets, new paragraphs, etc. it will no longer do exact matching. If you often need to do that, I would suggest using a program like LaTeX to write your documents. LaTeX would allow you do this style of exact matching of large blocks of text. If you're on a Windows machine, a great LaTeX package would be proTeXt which can be found at http://www.tug.org/protext/
I had exactly the same problem, huge mailing list and I just needed the emails. I solved it by copying the text in excel, filtering sentence by sentence (or bullets) the paragraph i wanted to remove and deleting all rows. Mine was more than 270 pages, worked just fine (as long as the text is not too long, it was a lot faster than replaceing sentence by sentence in word.) Or if it is an option, just filter with a text filter - begins with "to:" , then you are done in 10 secs. Hope it helps.
Just Press Ctrl+H to select and replace text, Type the text you want to remove and Press Replace All leaving replace with field BLANK

How do I apply a style to multiple selections in Word using VBA?

I created a macro that will apply a particular style to whatever is selected in the document. However, when in draft view, when the user clicks in the style area pane to select a paragraph and then Ctrl + clicks on an additional paragraph, this additional selection is not applied when this macro is run:
Sub BodyTextApply()
Selection.Style = ActiveDocument.Styles("Body Text,bt")
End Sub
What do I need to add to this? Note: The workflow cannot change so that the user selects that actual text in the document; they are set on using the style area pane...
The workflow is as follows:
alt text http://img6.imageshack.us/img6/1994/91231840.png
The (undesired) output is as follows:
alt text http://img34.imageshack.us/img34/1239/outputt.png
Looks like your style "Body Text,bt" is a pure paragraph style. That means it will only be applied to a complete paragraph.
However, in your screenshot there is only part of the second paragraph selected. Make sure the complete paragraph is selected or, if the style should only be applied to part of the paragraph, make your style "Body Text,bt" a linked (paragraph and character) style.
Programmatic access to discontiguous selections is very limited, and such selections can only be created using the Word UI. The MSDN article Limited programmatic access to Word discontiguous selections gives some more details.
If applying the style only to part of the paragraph (by making it a linked style) is not what you want you probably have to come up with a hack like this:
Sub BodyTextApply()
Dim oRange As Range
' create a temporary character style
ActiveDocument.Styles.Add "_TEMP_STYLE_", wdStyleTypeCharacter
' apply the temporary style to the discontiguous selection
Selection.Style = ActiveDocument.Styles("_TEMP_STYLE_")
Set oRange = ActiveDocument.Range
With oRange.Find
.ClearAllFuzzyOptions
.ClearFormatting
.ClearHitHighlight
.Style = ActiveDocument.Styles("_TEMP_STYLE_")
.Text = ""
.Wrap = wdFindStop
' search for all occurences of the temporary style and format the
' complete paraphraph with the desired style
Do While .Execute
oRange.Paragraphs(1).Style = ActiveDocument.Styles("Body Text,bt")
Loop
End With
' cleanup
ActiveDocument.Styles("_TEMP_STYLE_").Delete
End Sub
You probably want to add some error handling as well to make sure that the temporary style used is finally removed from the document.