Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Storing formatted text in a variable and pasting it back.

588 views
Skip to first unread message

marzolian

unread,
Apr 3, 2007, 9:34:33 PM4/3/07
to
I sometimes need to use a macro to temporarily move footnotes from
their actual location. Here's the current version:

http://techlanguage.com/tips/MoveFootnotesToEnd.txt

The routine "MoveFootnotesToEnd" copies each footnote text into a
string array, sets a bookmark at the location of the footnote, and
deletes the footnote. It then moves to the very end of the document
and creates a table. Finally, it pastes each footnote into the table.

A second macro restores each footnote to its original position.

My problem is, this version strips all the formatting from each
footnote.

To fix it, my first thought was, instead storing the text in a string,
I could use some other variable type. In the assignment step, these
statements do put the proper value into the variable:

ReDim FootnoteText(Q) As Variant

Set FootnoteText(i) = Fnote.Range.FormattedText

However, I can't get VB to paste or type the formatted text into the
table cell. This statement was used to test the location:

Selection.Tables(1).Cell(i + 1, Q).Range.Text = "xxx"

xxx shows up in the correct table cell. But this step produces
nothing:

Selection.Tables(1).Cell(i + 1, Q).Range.FormattedText =
FootnoteText(i).FormattedText

The VB editor tells me that FootnoteText(i) = "" (empty string) when
it comes to this step.

Any suggestions? Thanks.

Steven Marzuola
mar-z...@ya-hoo.com.invalid
(delete dashes and invalid)

Jean-Guy Marcil

unread,
Apr 3, 2007, 10:51:57 PM4/3/07
to
marzolian was telling us:
marzolian nous racontait que :

Could we see the full relevant code instead of excerpts?

--

Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
jmarci...@CAPSsympatico.caTHISTOO
Word MVP site: http://www.word.mvps.org


marzolian

unread,
Apr 4, 2007, 2:46:12 AM4/4/07
to
> > mar-zo-l...@ya-hoo.com.invalid

> > (delete dashes and invalid)
>
> Could we see the full relevant code instead of excerpts?

This is the old version, that works, but strips all formatting:

http://techlanguage.com/tips/MoveFootnotesToEnd.txt

I'm working on a version that preserves the formatting, but it doesn't
work:

http://www.techlanguage.com/tips/NewMoveFootnotes.txt

Steven

Jean-Guy Marcil

unread,
Apr 4, 2007, 3:36:13 PM4/4/07
to
marzolian was telling us:
marzolian nous racontait que :

> On Apr 3, 9:51 pm, "Jean-Guy Marcil" <DontEvenTry@NoSpam> wrote:
>> marzolian was telling us:
>> marzolian nous racontait que :
>>

> This is the old version, that works, but strips all formatting:
>
> http://techlanguage.com/tips/MoveFootnotesToEnd.txt
>
> I'm working on a version that preserves the formatting, but it doesn't
> work:
>
> http://www.techlanguage.com/tips/NewMoveFootnotes.txt
>

There are lots of problems with your code.

1) You should not use End, it is not necessary in VBA, Just use "Exit Sub"
2) Only use the Selection object when you absolutely need to, in this case
it is absolutely unnecessary!
3) Use objects when manipulating different area of a document, like a table
and footnotes in this case
4) You tried something like:
Selection.FormattedText = FootnoteText(i).FormattedText
FootnoteText(i) is a variant Array, you can not append Word VBA
property to it. The compiler will try to interpret it and will try to read
"FootnoteText(i)" as some range and fails.
5) Selection.TypeText Text:=FootnoteMark(i) is unclear as to what it is
supposed to do. FootnoteMark(i) is not an actual printable character.
6) The way your statements are put together, Selection.TypeText
Text:="MoveFootnotesToEnd" inserts the text in the first cell of the table.
Is that intentional?

Here is a revised version that corrects all those problems. It will get you
started...

'_______________________________________
Sub MoveFootnotesToEnd()

Dim i As Long
Dim Q As Long

Dim tbleFootNotes As Table
Dim rgeTbl As Range
Dim rgeRef As Range

If ActiveDocument.Footnotes.Count = 0 Then
Exit Sub
Else
Q = ActiveDocument.Footnotes.Count
End If

'Set up the table right away
Set rgeTbl = ActiveDocument.Range

With rgeTbl
.InsertParagraphAfter
.Collapse wdCollapseEnd
.Style = ActiveDocument.Styles(wdStyleFootnoteText)
.InsertAfter "MoveFootnotesToEnd"
.InsertParagraphAfter
.Collapse wdCollapseEnd
End With

Set tbleFootNotes = rgeTbl.Tables.Add(Range:=rgeTbl, NumRows:=Q, _
NumColumns:=2, DefaultTableBehavior:=wdWord9TableBehavior, _
AutoFitBehavior:=wdAutoFitFixed)

'Transfer and delete footnotes
i = 1

Do While ActiveDocument.Footnotes.Count > 0
With tbleFootNotes
.Cell(i, 1).Range.Text = "Footnote # " & i
.Cell(i, 2).Range.FormattedText =
ActiveDocument.Footnotes(1).Range.FormattedText
End With
Set rgeRef = ActiveDocument.Footnotes(1).Reference
ActiveDocument.Footnotes(1).Delete
ActiveDocument.Bookmarks.Add Range:=rgeRef, Name:="xxFootnote" & i
i = i + 1
Loop

End Sub
'_______________________________________

marzolian

unread,
Apr 5, 2007, 12:32:47 AM4/5/07
to


Jean-Guy,

I knew there were problems, it was very quick and dirty. This step is
intentional.

Selection.TypeText Text:="MoveFootnotesToEnd"

I use the presence of this text in the reverse function, the one that
restores the footnotes to their original locations in the text. Also,
to find the table that includes these footnotes. That function will
have to be revised as well.

However, before I could implement any solution for now, I needed to
get started on my project (It's a translation of about 14,000
words). But as soon as it's finished, I'll try out your solution.
Thanks!

Steven

Jean-Guy Marcil

unread,
Apr 5, 2007, 11:54:27 AM4/5/07
to
marzolian was telling us:
marzolian nous racontait que :

>


> I knew there were problems, it was very quick and dirty. This step is
> intentional.
>
> Selection.TypeText Text:="MoveFootnotesToEnd"
>
> I use the presence of this text in the reverse function, the one that
> restores the footnotes to their original locations in the text. Also,
> to find the table that includes these footnotes. That function will
> have to be revised as well.
>

What I meant was that I have no problem with inserting this in the document
(I did insert it in my code, but just before the table). But the problem in
your code is that you insert a table with a number of rows equal to the
number of footnotes. Then, you insert this text in the first row. When I ran
your code as you posted it in the link you provided, the code ended up
missing a row...

So either you create a table with a number of rows equal to the number of
footnotes plus one, or the reverse function locates the table by locating
this text and then grabbing the following table.

Bresson@discussions.microsoft.com Tom Bresson

unread,
Apr 20, 2007, 10:18:02 AM4/20/07
to
"Jean-Guy Marcil" wrote:


Hello,

I am having a problem with something very similar to the title of the thread.

I have a document template that I need to hold a few generic incomplete
sections of (While retaining the formatting of the text), so that they can be
duplicated and filled in as my VBA code runs.

Essentially, I want to have a sub that takes a range of text and inserts it
in an array or collection object, preserving formatting. Then I need another
sub to be able to retrieve the "Formatted Text" Object and put the text into
Word.

I am relatively new to the Office VBA types and functions, and I am learning
as I go, but this has stumped me for more than a few hours.

Here is my code thus far:


<code>
'The effective use of this class will be document specific.
'In theory, this should be the only file that needs changed to modify from
document to document
'when the other document is fairly similar to this one.


Private tagFirstLevel, tagSecondLevel, tagThirdLevel, tagEndTag As String

Private collectionOfFormattedText As Collection


Sub initialize()

tagFirstLevel = "<Functional Area>"
tagSecondLevel = "<TEST DESCRIPTION CATEGORY>"
tagThirdLevel = "<Individual Test Description>"
tagEndTag = "<End_of_Test>"

Set collectionOfFormattedText = New Collection

End Sub

Sub findFirstSection()
End Sub

Sub processFolder()
End Sub


Sub processTestSet()
End Sub


Sub processTest()
End Sub


Sub processTestRun()
End Sub

Sub setSelectionRange(ByVal startingString As String, ByVal endingString As
String)

Dim selectionStart As Integer
Dim selectionEnd As Integer

Selection.Find.ClearFormatting
With Selection.Find
.Text = startingString
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
If .Found Then
selectionStart = Selection.Start
End If
End With

Selection.Find.ClearFormatting
With Selection.Find
.Text = endingString
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
If .Found Then
selectionEnd = Selection.Start
End If
End With

Selection.Start = selectionStart
Selection.End = selectionEnd

End Sub

Sub insertSelectionIntoFormattedTextCollection()
Dim temp As Variant
Set temp = Selection.FormattedText

'This was to test if the text came out of the Variant ok,
'AND IT DOES!
'Selection.Range.FormattedText = temp

collectionOfFormattedText.Add (temp)

End Sub

Sub insertFormattedTextIntoSelection(indexOfFormattedText As Integer)

Selection.FormattedText =
collectionOfFormattedText.Item(indexOfFormattedText)

End Sub

Sub test()

Call DocParser.initialize

Call setSelectionRange(tagFirstLevel, tagSecondLevel)
Call insertSelectionIntoFormattedTextCollection

Call setSelectionRange(tagSecondLevel, tagThirdLevel)
Call insertSelectionIntoFormattedTextCollection

Call setSelectionRange(tagThirdLevel, tagEndTag)
Call insertSelectionIntoFormattedTextCollection

Call insertFormattedTextIntoSelection(1)
Call insertFormattedTextIntoSelection(2)
Call insertFormattedTextIntoSelection(3)
Call insertFormattedTextIntoSelection(3)
Call insertFormattedTextIntoSelection(3)

End Sub
</code>

Any help at all would be very much appreciated!

Thank you all,

-Tom

Jean-Guy Marcil

unread,
Apr 20, 2007, 4:00:56 PM4/20/07
to
Tom Bresson was telling us:
Tom Bresson nous racontait que :

Here, only tagEndTag is a String, all other are Variant.

> Private collectionOfFormattedText As Collection
>
>
> Sub initialize()
>
> tagFirstLevel = "<Functional Area>"
> tagSecondLevel = "<TEST DESCRIPTION CATEGORY>"
> tagThirdLevel = "<Individual Test Description>"
> tagEndTag = "<End_of_Test>"
>
> Set collectionOfFormattedText = New Collection
>
> End Sub
>
> Sub findFirstSection()
> End Sub
>
> Sub processFolder()
> End Sub
>
>
> Sub processTestSet()
> End Sub
>
>
> Sub processTest()
> End Sub
>
>
> Sub processTestRun()
> End Sub
>
> Sub setSelectionRange(ByVal startingString As String, ByVal
> endingString As String)
>
> Dim selectionStart As Integer
> Dim selectionEnd As Integer

Range (or Selection) Start and End properties are defined in VBA as Long,
not Integer.
So, here, the compiler as to do unnecessary type conversion.

By the way, Integer is no longer the base numeric unit, Long is.
Even if you use Integer, the compiler converts them to Long because the
smallest memory unit is a equivalent to a Long.

It would probably be better to use a Range object instead of defining a
Selection object.

> Sub insertSelectionIntoFormattedTextCollection()
> Dim temp As Variant
> Set temp = Selection.FormattedText
>
> 'This was to test if the text came out of the Variant ok,
> 'AND IT DOES!
> 'Selection.Range.FormattedText = temp

It does, but not formatted, right?

> collectionOfFormattedText.Add (temp)
>
>
> End Sub
>
> Sub insertFormattedTextIntoSelection(indexOfFormattedText As Integer)

Use a Long instead of an Integer

> Selection.FormattedText =
> collectionOfFormattedText.Item(indexOfFormattedText)

Selection.FormattedText expects a Range object, you are feeding it a
Variant, as is it will not work.
You could use:
Selection.TypeText collectionOfFormattedText.Item(indexOfFormattedText)
But this will not return formatted text, which it does not matter anyway
because the Collection does not contain formatted text.


> End Sub
>
> Sub test()
>
> Call DocParser.initialize
>
> Call setSelectionRange(tagFirstLevel, tagSecondLevel)
> Call insertSelectionIntoFormattedTextCollection
>
> Call setSelectionRange(tagSecondLevel, tagThirdLevel)
> Call insertSelectionIntoFormattedTextCollection
>
> Call setSelectionRange(tagThirdLevel, tagEndTag)
> Call insertSelectionIntoFormattedTextCollection
>
> Call insertFormattedTextIntoSelection(1)
> Call insertFormattedTextIntoSelection(2)
> Call insertFormattedTextIntoSelection(3)
> Call insertFormattedTextIntoSelection(3)
> Call insertFormattedTextIntoSelection(3)

As is, by the time you get to the first Call
insertFormattedTextIntoSelection, yourt selection is ocated at teh lst item
that was found when setSelectionRange was called.
So, in effect, yu are inserting text over the lst found items...

THis is why I suggested using range objects instead.

> End Sub
> </code>

I am afraid that as long as you are going to work with any type of
variables, you will not succeed as variables cannot hold formatting
information, unless there is some type of RichText variable that I am not
aware of.

What you could do is create an invisible document (starting with Word XP, I
believe) and store the ranges there when you find them, then when you are
done, get them back.

Or, if you are selecting ranges of text and then, in the same code run,
copying those range elsewhere in the document, you do not need a collection
or a secondary document, copy those bits of text as you find them.

Tom Bresson

unread,
Apr 24, 2007, 4:04:02 PM4/24/07
to
Thank you for the help Jean-Guy Marcil,

I found creating, using and removing autotext entries programically seems to
allow me to be able to easily insert formatted text into a document. It
essentially boils down to:

Select a range, create a known autotext entry (which can preserve
formatting) in the Normal template, use the autotext entry, then delete the
autotext entry when done.

There is plenty of documentation of autotext entries on the MSDN site. I am
very surprised that Microsoft did not include a variable type to store
formatted text. I would think that would be very desired behavior for a
language that should be able to help automate documents.

I hope this helps anyone who happens to stumble upon this thread, via
Google, like I did.

Thanks again!

-Tom

0 new messages