PDA

View Full Version : Solved: date/time, page in footers via VBA



TheAntiGates
05-25-2005, 01:48 PM
I want to set up dynamic fields { DATE }, { PAGE }, { NUMPAGES } in a one-time processing (per document). I tend to see recommendations to go with BeforePrint; but I instead want to manually set a footer, with dynamic date, time, and "page X of Y" fields. With BeforePrint I would haved used Now() but in this case I need to insert a field such as { DATE \@ "d/d/yyyy" }

First, I begin with the next line, as I want the same footer on each page. Is this how?
For i = ActiveDocument.Sections.Count To 1 Step -1

ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range.Text = "printed on { DATE } "
fails as it is not acknowledged as a field. How in VBA would I generate a field - i.e. the Ctrl-F9 braces? And "&D" is for Excel only, right?

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbawd11/html/womthInsertDateTime1_HV05211111.asp suggests
ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range.InsertDateT ime DateTimeFormat:="MMMM dd,yyyy hh:mm"
This seems to destroy existing footer content, rather than append. Brilliant, Microsoft.
(webmaster: I can't rid the space after letter T above. It's not in my source.)

I stumbled onto WdBuiltInProperty values which is handy for page count but not dates. However, this is back off track because I want self-updating fields, and this wouldn't qualify.

TIA for you good peoples' time and effort on this.

The fumei Dog Boy clause: All simply helpful help is appreciated. For any immature time-wasting remarks and puerile rants that one is a retard if they don't 'use a template!' or 'learn the object model!' or 'the problem is that you don't like Microsoft' or such, doubly thank you for just clicking "next post" instead, and taking your little pill. ty,tyvm

MOS MASTER
05-25-2005, 02:02 PM
The fumei Dog Boy clause: All simply helpful help is appreciated. For any immature time-wasting remarks and puerile rants that one is a retard if they don't 'use a template!' or 'learn the object model!' or 'the problem is that you don't like Microsoft' or such, doubly thank you for just clicking "next post" instead, and taking your little pill. ty,tyvm
Have I missed some interesting conversation here! :rofl:

To your question, try:
Sub InsertDateField()
Dim oRange As Word.Range
Dim i As Integer
For i = ActiveDocument.Sections.Count To 1 Step -1
Set oRange = ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range
oRange.Collapse Direction:=wdCollapseEnd
oRange.Fields.Add Range:=oRange, _
Type:=wdFieldEmpty, _
Text:="DATE \@ ""d/d/yyyy"" ", _
PreserveFormatting:=True
Next

Set oRange = Nothing
End Sub


Many other ways to do this but this will probably work.

By the way I do find the requested date format a little odd but this is what you requested..(easily changed...).

Enjoy! :whistle:

TheAntiGates
05-25-2005, 02:39 PM
As to d/d/yy above, that's what you type before saying "dohhh!" when intending m/d/yy. Thanks.

BTW I've lately tried but had problems with
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldDate
One issue right off is getting selection at the correct point to insert within descriptive surrounding text. If instead I go
Set foo = ActiveDocument.Fields.Add(Range:=Selection.Range, Type:=wdFieldDate)
ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range.Text = "printed on " & foo.Result.Text & " by..."
it does not really provide a field object - it's just text (simply reflecting the date/time the macro was run). I couldn't outduel the compiler into accepting any other form of foo.

But back to your solution: I'll want to combine descriptive text there, as just shown. I confess that I'm pretty clueless with word ranges, so I'm going to be hunting for oRange.add or such to concatenate. (The macro recorder sent me in the lame direction of using Selection and I think you've got me back on track.)

All in all, what you've shown looks like what I'm after.

MOS MASTER
05-25-2005, 02:43 PM
Hi,

You're Welcome.

To the selection story. You're right better not use it.
I'm using the Range object which is much faster and doesn't give you that irritating screen flicker!

So go ahead and try the code out and I'm dying to see how you expand on that.

So Enjoy and I'll see yah....if you have more questions. :whistle:

TheAntiGates
05-25-2005, 02:59 PM
Okay, .Add appends. That's what I need. But I'm still stumbling with it:

I added a line
oRange.Fields.Add Range:=oRange, Text:=" succeeding text ", PreserveFormatting:=True

and this gave "Bookmark not defined" I'm guessing that I don't want .Fields for simple text appending? (.Fields refers to a control field like Date?)

and I'm having trouble with m/d/yy assuming minute. I wanted a single digit 5 for may. (Don't tell me the answer is capital M.)

MOS MASTER
05-25-2005, 03:33 PM
Okay, .Add appends. That's what I need. But I'm still stumbling with it:

No it doesn't The range is Collapsed by the code and therefore it's appended just like : oRange.InsertAfter Text:="Hi"



I added a line
oRange.Fields.Add Range:=oRange, Text:=" succeeding text ", PreserveFormatting:=True

and this gave "Bookmark not defined" I'm guessing that I don't want .Fields for simple text appending? (.Fields refers to a control field like Date?)
Shure it does...it's for adding fields and you're not adding a field in the posted code so you'l get an error.

For text appending after the range see a few lines up...InsertAfter method!


and I'm having trouble with m/d/yy assuming minute. I wanted a single digit 5 for may. (Don't tell me the answer is capital M.)

Wel I'm going to tel you it does need a capital M! :rofl:

This works fine over here: { DATE \@ "M/D/YYYY" \* MERGEFORMAT }

Enjoy! :whistle:

fumei
05-26-2005, 06:37 AM
As requested (oh and that is Dog MAN to you sonny) I will continue on to the next thread.

BTW: if anyone needs a solution (it is fairly easy), you can PM me.

MOS MASTER
05-26-2005, 09:42 AM
I wish I had a clue of what's going on here.....:doh:

TheAntiGates
05-26-2005, 11:14 AM
Okay, MOS, those were all excellent points. I do note that Fields.Add indeed does append to an existing range in some circumstances and prepends in others, and I'm open to understanding what that's about. I can give you an example where it appends if you need. (Yet .InsertAfter also prepends. Try code below! ???)

This is a stab at what I'm going after. I happily admit to worse errors than the prepending. (E.g. "PAGES" doesn't exist. Yet DATE and PAGE are not help topic items, so if you can steer me to their help, I'd be grateful.) It's lengthy too; the problem there would seem to be that building a text String would not contain Field objects, so this has to be done by building onto a Range. (And one more thing - the lovely Word/VBA help doesn't fully explain some property defaults. Can I lose the Range and PreserveFormatting spacetakers?!)
Sub pStdFooterCreate() 'build standard footer on each page of document
Dim rngFooter As Range, i As Integer
For i = ActiveDocument.Sections.Count To 1 Step -1
Set rngFooter = ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range
rngFooter.Collapse Direction:=wdCollapseEnd
ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range.Text = "Page "
rngFooter.Fields.Add Range:=rngFooter, Text:=" PAGE \@ ""0"" ", PreserveFormatting:=True
rngFooter.InsertAfter " of "
rngFooter.Fields.Add Range:=rngFooter, Text:=" PAGES \@ ""0"" ", PreserveFormatting:=True
rngFooter.InsertAfter "; printed "
rngFooter.Fields.Add Range:=rngFooter, Text:=" DATE \@ ""M/d/yyyy hh:mm"" ", PreserveFormatting:=True
rngFooter.InsertAfter _
CARR_RET & "(was by " & ActiveDocument.BuiltInDocumentProperties(wdPropertyLastAuthor) _
& " in " & ActiveDocument.FullName & " on " & Date & ")"
Next
End Sub
BTW, Collapse and wdCollapseEnd are odd animals. I'll be perusing help on them after posting this! :think:

Thank you for your patience and kind assistance. You're the board's Ogilvy!

TheAntiGates
05-26-2005, 11:20 AM
Already I believe I'm seeing that .Collapse is at the front and center of the prepending issue. Could you please explain the tactical or practical reason to use it?

MOS MASTER
05-26-2005, 11:37 AM
Hi, :yes

Thank you what is a: "Ogilvy"?

I'm building something right now so I'll answer your question when I'm done coding.

Later...:whistle:

TheAntiGates
05-26-2005, 12:36 PM
No problem whatsoever. You're very generous with your time and I'm grateful. Besides, I'm only slipping time into this pursuit here and there myself while busy making money.

Tom Ogilvy cannot be described in earthly terms. He is the legendary superhuman expert of the hardcore usenet Excel groups. His throughput level - at virtually 100% accuracy - is simply beyond belief.

Kind of like it you seem to do here, huh? :clap:

fumei
05-26-2005, 12:41 PM
:funnyashe

MOS MASTER
05-26-2005, 01:01 PM
Hi,

Ah..ok he's a person.. let's call him Tom the Great..Thanks for the kuddos..but I don't think I can walk in the shadow of one that can't be discribed in earthly terms. :yes

To you're question:
Now I see your latest post I think we have to change some things. My code was based on the assumption that you only had one field to append to some text.

If you need to and you do I see...append more text and fields in one line you have to set the range (To the footer range) again to make it collapse in the right way!

If it was only text the collapse method would be suffient...but where mixing fields with text so we have make sure you append to the correct range (end)

This will make the code a litter bigger so I have a suggestion for the Page X of Y part in your code.

You can use a Autotext entry for this one and this will save time in execution.

I'll use it in my code Word has a buildin autotext called: "Page X of Y" that I will use.

If you don't want this Autotext you can just add more set/with blocks to accomodate for the appended fields..

This is the revised code: (ps made: CARR_RET a string could be a variable of yours but I dunno...)


Sub pStdFooterCreate() 'build standard footer on each page of document
Dim rngFooter As Word.Range, i As Integer

For i = ActiveDocument.Sections.Count To 1 Step -1

Set rngFooter = ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range
With rngFooter
.Text = "Page "
.Collapse Direction:=wdCollapseEnd

ActiveDocument.AttachedTemplate.AutoTextEntries _
("Page X of Y").Insert Where:=rngFooter
End With

Set rngFooter = ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range
With rngFooter
.Collapse Direction:=wdCollapseEnd
.Text = "; printed "
End With

Set rngFooter = ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range
With rngFooter
.Collapse Direction:=wdCollapseEnd
.Fields.Add Range:=rngFooter, Type:=wdFieldEmpty, _
Text:=" DATE \@ ""M/d/yyyy hh:mm"" ", PreserveFormatting:=True
End With

Set rngFooter = ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range
With rngFooter
.Collapse Direction:=wdCollapseEnd
.Text = " CARR_RET " & _
"(was by " & ActiveDocument.BuiltInDocumentProperties(wdPropertyLastAuthor) _
& " in " & ActiveDocument.FullName & " on " & Date & ")"
End With

rngFooter.Fields.Update
Next
Set rngFooter = Nothing
End Sub


A Tip:
If you build the desired look of your Footer in a Word document and then Save it as a AutoText entry you could Trow away about all of the code and have only one Insert Statement left. (Consider it...it will save time!)

Enjoy! :whistle:

TheAntiGates
05-26-2005, 02:08 PM
That's some tricky stuff there. I instantly attempted to combine the four operations into a single Set and With Block, deleting the 3 trios of {End With,Set,With}, but as you surely know, that creates a mess.

I'll have to play with this some to appreciate its nuances, but AFAICT this is precisely what I'm looking for. Microsoft fanboys' :cloud9: love for All Things Microsoft aside, this is pretty nontrivial. Maybe I should stick to Excel and Access for VBA, and leave Word's to the experts and painters!

And sorry - my fault - I did neglect to show the lines
Dim CARR_RET As String * 2 '(carriage return)
CARR_RET = Chr(10) ' & Chr(13) unnecessary
So CARR_RET is for making a two-line footer. (So remove the quotes in your code)
(It might be better named LINEFEED - it's evolved as I experimented with LF and CR)

MOS MASTER
05-26-2005, 02:17 PM
Hi, :yes

You're welcome.

I'll leave my code and post the revised one so others can use it. (Otherwise I also have to change my comments in the other thread)


Sub pStdFooterCreate() 'build standard footer on each page of document
Dim CARR_RET As String * 2 '(carriage return)
CARR_RET = Chr(10) ' & Chr(13) unnecessary
Dim rngFooter As Word.Range, i As Integer

For i = ActiveDocument.Sections.Count To 1 Step -1

Set rngFooter = ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range
With rngFooter
.Text = "Page "
.Collapse Direction:=wdCollapseEnd

ActiveDocument.AttachedTemplate.AutoTextEntries _
("Page X of Y").Insert Where:=rngFooter
End With

Set rngFooter = ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range
With rngFooter
.Collapse Direction:=wdCollapseEnd
.Text = "; printed "
End With

Set rngFooter = ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range
With rngFooter
.Collapse Direction:=wdCollapseEnd
.Fields.Add Range:=rngFooter, Type:=wdFieldEmpty, _
Text:=" DATE \@ ""M/d/yyyy hh:mm"" ", PreserveFormatting:=True
End With

Set rngFooter = ActiveDocument.Sections(i).Footers(wdHeaderFooterPrimary).Range
With rngFooter
.Collapse Direction:=wdCollapseEnd
.Text = CARR_RET & _
"(was by " & ActiveDocument.BuiltInDocumentProperties(wdPropertyLastAuthor) _
& " in " & ActiveDocument.FullName & " on " & Date & ")"
End With

rngFooter.Fields.Update
Next
Set rngFooter = Nothing
End Sub


So have fun playing with this tricky bit of Word coding and please don't forget to mark your thread solved...

Tada..:whistle: