PDA

View Full Version : Keep character formatting when applying character style



rruckus
10-29-2012, 11:54 AM
Using VBA, I need to apply a specific character style to a selection of text and I need to be able to keep the existing Bold, Italic, Underline, Strikethrough, Sub/Superscript. Does anyone know how to do this? Is there a fast script out there that anyone can share that can achieve this result?

fumei
10-29-2012, 01:02 PM
Yes. Make those formats part of the "specific" character style...otherwise it is not very specific, is it?

No VBA required.

Frosty
10-29-2012, 01:04 PM
What have you tried so far? Why do you want to preserve character formatting while applying a character style?

The way to do it is fairly easy... you check to see if the selection of text already has the formats you care about, apply the character style, and the restore those settings.

However, there are a host of issues with this (not the least of which is what you want to do when *some* of the selection is bold (or any of the formats you care about) and some is not.

But, primarily... can you answer why you would want to do this in the first place? Because asking this question suggests, to me, that you're not asking the right question.

rruckus
10-29-2012, 01:22 PM
You are right that I'm trying to use a character style in a way that is not how they are designed to be used. But the reality is that I have weeks of effort into this project and I can't change it now without effecting a whole bunch of existing templates, documents and downstream processes. So I need to be able to fix this in the way described.

Here is what happens:

1. The user makes a selection and hits my VBA button to mark their selection of text as a special meaningful selection of text (could be any user selection within a single or across many paragraphs).

2. My VBA then formats this text with the style. I used a character style to achieve this, let's call it "Special".

Selection.Style = ActiveDocument.Styles("Special")

3. This applies the style BUT now all of the users Bold, Italic, etc., are all removed! I need to keep them. Looking back, I probably should have used a different Word feature (maybe Highlight) but it is now too late to change it.

I wrote a function that goes char by char, remembers the formatting, and restores it. This works but it is so slow and it is not practical because some users will be selecting multiple pages.

Is there any other way to fix this issue within my contraints?

Frosty
10-29-2012, 01:32 PM
Sorry... so you have documents already in production which utilize your "Special" character style? Or this is something you are adding to the functionality? Or you promised other developers that it would be formatted with a character style, and they have written code based on that?

Because I don't understand why you can't mark your text with a bookmark-- does it have to be apparent to the end-user?

And if you've already written a function which does this, but discarded it because the function is slow... then maybe you should post that function?

Otherwise, you ask a generic question-- we have to ask you a whole bunch of questions back on why you're doing that in that way.

If you post a function which works, but is slow... that is a different process to solving your problem.

No one is going to give you the answer of "you shouldn't have done it that way" and leave it at that. But by the same token, if you feel you've programmatically painted yourself into a corner, you may not know all of your options. There may be an easier fix to what you want to have done.

That said... going character by character will be slow. However, you can use the .Find object to search for formatting, mark that formatting with some special characters during a ReplaceAll, apply your character style, and then replace your "marked text" with formatted text.

I've used this methodology before when writing document conversion routines. But it can still be slow, depending on how many find operations you need to run.

In general, any time you're working with a lot of different areas of the document-- you should always investigate the use of a .Find process, rather than iterating through individual characters.

So-- give the .Find process a whirl and post that code, or post your original code that you've discarded because of slowness... OR give a little more info and maybe there's a solution you haven't yet thought of...

rruckus
10-29-2012, 01:44 PM
Yes I have documents in production with this special style.

Other developers also expect that the text is formatted with this style for downstream processing of the documents.

I can't use bookmarks because it is too late (as mentioned above) AND because users need to SEE the style (they also need to be able to UNMARK the special text too!).

Here is the function that works but is too slow:

Public Sub ApplySpecialFormat(oRng As Word.Range)
Dim oCurDoc As Word.Document
Set oCurDoc = ActiveDocument
Dim oNewDoc As Word.Document
Set oNewDoc = Application.Documents.Add(Template:=oCurDoc.AttachedTemplate.FullName, Visible:=False)
oNewDoc.Range.Delete
oNewDoc.Range.Text = "ii"
oNewDoc.Range.Style = "Special"
Dim oNewDocRng As Word.Range
Set oNewDocRng = oNewDoc.Range
oRng.Copy
oNewDocRng.SetRange 1, 1
oNewDocRng.PasteAndFormat wdFormatSurroundingFormattingWithEmphasis
oRng.Style = "Special"
Dim i As Integer
i = 2
Dim r As Word.Range
Dim tr As Word.Range
For Each r In oRng.Characters
oNewDocRng.SetRange i, i
If oNewDocRng.Font.Bold Then r.Font.Bold = True
If oNewDocRng.Font.Italic Then r.Font.Italic = True
If oNewDocRng.Font.Underline Then r.Font.Underline = True
If oNewDocRng.Font.StrikeThrough Then r.Font.StrikeThrough = True
If oNewDocRng.Font.Superscript Then r.Font.Superscript = True
If oNewDocRng.Font.Subscript Then r.Font.Subscript = True
i = i + 1
Next
oNewDoc.Close False
End Sub


Yes, I agree the .Find would be faster, but I'm not sure what to find and replace.

Thanks for your help!

Frosty
10-29-2012, 02:10 PM
Well, this is going to be complicated (unless someone else has some ideas)... I'll get you started. This is sort of a proof of concept.... it only preserves bold formatting, at the moment.

But you're also going to need to follow a Last In First Out methodology, since multiple formats will get multiple "format codes" -- I'm not sure how much optimization you will get, as I suspect there is a cost-benefit analysis to the size of the selection and using the .Find approach vs. some variant of what you're doing.

Why don't you play with something like this, and then post your modifications to the code and what issues you have.

Private Const UNIQUECODE = "xyzzy"
Sub MarkBold_ApplyStyle_ReplaceBold()

'mark the text
With Selection.Range.Duplicate.Find
.Format = True
.Font.Bold = True
.Replacement.text = UNIQUECODE & "B" & UNIQUECODE & "^&" & UNIQUECODE & "BE" & UNIQUECODE
.Wrap = wdFindStop
.Execute Replace:=wdReplaceAll
End With

'apply the style
Selection.Style = "Special"

'replace the formatting, using a wildcard search
With Selection.Range.Duplicate.Find
.text = UNIQUECODE & "B" & UNIQUECODE & "*" & UNIQUECODE & "BE" & UNIQUECODE
.Replacement.Font.Bold = True
.MatchWildcards = True
.Execute Replace:=wdReplaceAll
End With

'now remove the special codes
With Selection.Range.Duplicate.Find
.text = UNIQUECODE & "B" & UNIQUECODE
.Replacement.text = ""
.Execute Replace:=wdReplaceAll

.text = UNIQUECODE & "BE" & UNIQUECODE
.Replacement.text = ""
.Execute Replace:=wdReplaceAll
End With

End Sub

rruckus
10-29-2012, 02:52 PM
Thanks Frosty, this does work for me and I'll try to get this working with the multiple inline formatting that I want to keep.