First quick stab at revising what I did earlier. I don't think it's
very efficient, but I'm looking for a better solution. The
additional code takes into account the following holidays, in order:
Memorial Day, July 4th, Labor Day, Columbus Day, Veterans Day,
Thanksgiving Day and the Friday after Thanksgiving Day, Christmas
Eve, Christmas Day, New Year's Eve, and New Year's Day '08:
Sub AddDate()
Dim strFirstDate As String
Dim strSecondDate As Date
Dim IntervalType As String
Dim Number As Integer
Dim bkRange As Range
Dim AvoidDate As Date
strFirstDate = InputBox("Enter Beginning Date in Full Date Format,
i.e., 'November 1, 2007'")
IntervalType = "d"
Number = 2
strSecondDate = DateAdd(IntervalType, Number, strFirstDate)
Do While DatePart("w", strSecondDate, vbMonday) > 5
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Loop
Do While strSecondDate = #5/28/2007#
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Loop
Do While strSecondDate = #7/4/2007#
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Loop
Do While strSecondDate = #9/3/2007#
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Loop
Do While strSecondDate = #10/15/2007#
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Loop
Do While strSecondDate = #11/12/2007#
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Loop
Do While strSecondDate = #11/22/2007#
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Loop
Do While strSecondDate = #11/23/2007#
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Loop
Do While strSecondDate = #12/24/2007#
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Loop
Do While strSecondDate = #12/25/2007#
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Loop
Do While strSecondDate = #12/31/2007#
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Loop
Do While strSecondDate = #1/1/2008#
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Loop
Set bkRange = ActiveDocument.Bookmarks("bkSecondDate").Range
bkRange.Text = strSecondDate
End Sub
As mentioned in my first message, the disadvantage to this approach
is that you must revise each holiday annually, both to adjust the
holidays that change dates from year to year and to adjust the year
for each holiday. On the other hand, if you don't have access to an
external database of holidays and store this macro in the template
for your document so that it is easily accessible, this method won't
require that much work each year.
I'll try to revise this code to make it more efficient, but I had
been thinking about this problem in connection with another
document I've been working on so it gave me the motivation to
tackle it this afternoon.
:
This method should work for adding two days but skipping the
weekend days. A bookmark and a macro should do the trick. Create
your letter template. My simple template says "We would like the
courtesy of a reply by []" where the brackets are replaced by an
inserted bookmark. For the purposes of this question, I called the
bookmark, "bkSecondDate" which represents the two days in the
future. The following code should automatically insert the
advanced date when run:
Sub AddDate()
Dim strFirstDate As String
Dim strSecondDate As Date
Dim IntervalType As String
Dim Number As Integer
Dim bkRange As Range
strFirstDate = InputBox("Enter Beginning Date in Full Date Format,
i.e., 'November 1, 2007'")
IntervalType = "d"
Number = 2
strSecondDate = DateAdd(IntervalType, Number, strFirstDate)
While DatePart("w", strSecondDate, vbMonday) > 5
strSecondDate = DateAdd(IntervalType, 1, strSecondDate)
Wend
Set bkRange = ActiveDocument.Bookmarks("bkSecondDate").Range
bkRange.Text = strSecondDate
End Sub
This code can be embedded in the template as a macro and fired to
run when a new document based on the template is created by using
the AutoNew command.
Apparently without reference to an external database, to avoid
holidays, you would need to create additional coding that compares
the date returned with a set of dates to avoid, in this case annual
holidays. This coding would have to be revised annually in order
to include those holidays that change from year to year, such as
Easter and Thanksgiving. I haven't yet generated this code, but
if I have time to come up with something, I'll post back.
Hope this is helpful.
:
OK, so how about a serious vba solution ...
--
macropod
[MVP - Microsoft Word]
-------------------------
That explains pretty clearly why you don't want to use this
method for any serious purpose.
Hi Peter/Graham,
Modifying one of my date calculation fields at:
http://www.wopr.com/cgi-bin/w3t/showthreaded.pl?Number=249902
to cope with weekends would be fairly trivial. For example,
adding: {SET jd{=jd+(MOD(jd,7)>4)*(4-MOD(jd,7))}}
or
{SET jd{=jd+(MOD(jd,7)>4)*(7-MOD(jd,7))}}
after the existing 'SET' jd field would adjust the calculated
dates to the previous Friday or next Monday, respectively.
Dealing with public holidays could be problematic if they fall
on Mondays or Fridays, but only because they'd have to be coded
for on a case-by-case basis. VBA probably wouldn't be any
easier in this regard.
Cheers
--
macropod
[MVP - Microsoft Word]
-------------------------
message There's no really simple way to do any of what you want using
fields.
For the simple case (i.e. forgetting about the weekends and
holidays thing) you can try using a DATABASE field, but you
need a Jet database to do it e.g. in Word 2002/2003
{ DATABASE \d "c:\i\i.mdb" \s "SELECT
dateadd('d',2,datevalue('{ DATE \@"YYYY-MM-DD" }'))"
\@"M/D/YYYY" }
or even
{ DATABASE \d "c:\i\i.mdb" \s "SELECT dateadd('d',2,'{ DATE
\@"YYYY-MM-DD" }')" \@"M/D/YYYY" }
where /all/ the {} are the special field braces you can insert
using ctrl-F9.
For earlier versions of Word you need a bit more to prevent
Word trying to open Access (which you may not have).
You may also encounter a number of security-related barriers to
this approach.
The .mdb needs to be a valid Jet database, but it can be empty,
i.e. have no visible queries or tables. There are various ways
to create one:
a. If you have Access, it should be easy to create an empty
.mdb. b. Depending on what software is on your system you may
be able to right-click in Windows Explorer and use the "New"
option to create a new "Micrrosoft Office Access Application"
c. create one in a copy of Access on another system and copy it
to your system.
d. in Word, use Tools|"Letters and Mailings"|"Mail Merge" to
start the Mail Merge Wizard, follow the task panes, and in
"Select Recipients", select "Type a new list", then click
Create. Add a record, then save the resulting .mdb
Whether it's advisable to use this approach is a different
question. The main drawback of is its reliance on an external
file (and related database access software) and the increased
potential for maintenance problems.
To deal with weekends you could use a more complicated
expression, e.g. something like
{ DATABASE \d "c:\i\i.mdb" \s "SELECT
dateadd('d',choose(weekday(datevalue('{ DATE
\@"YYYY-MM-DD" }'),1),2,2,2,2,4,4,3),datevalue('{ DATE
\@"YYYY-MM-DD" }'))" \@"M/D/YYYY" }
or, paring it down a bit, perhaps
{ SET d "{ DATE \@"YYYY-MM-DD" }" }{ DATABASE \d "c:\i\i.mdb"
\s "SELECT dateadd('d',choose(weekday('{ d
}'),2,2,2,2,4,4,3),'{ d }')" \@"M/D/YYYY" }
NB in recent versions of Word, the result of a DATABASE field
sometimes includes a paragraph mark, which has rendered it
useless for including individual text values. If the result is
a date or a number, a date/numeric format switch seems to deal
with that problem.
As for the holidays, even assuming you are only interested in
one country's holidays, you would only be able to build
additional query criteria in if the list of holidays was
atypically small and predictable (partly because the query
text length is constrained, probably to 255 characters).
Typically, you will simply have to maintain a calendar of some
kind. If you also keep that in a database (somewhere, depends
on what sort of system we're talking about) then you have to
decide how far ahead your calendar is going to go, and
precisely how you are going to represent holidays, weekends
and so on. If you are only ever going to have a "two business
days ahead" requirement, you might as well have a database
with two columns containing the precise result you want:
currentdate,dateplus2