I read in a book something like this: for each OS
in (Win 9X 2000 XP ...) echo "MS-DOS batch files is
much more smart than OS 6.22 or below" BUT that seems
to be not correctly.
Anyhow, I can't get this one to work:
for each littleMonth in (4 6 9 11)
Benny Pedersen, ?
'Find the date of yesterday,
dim day, month, year
day = 14
month = 5
year = 2002
if day = 1 then
if month = 1 then
year = year -1
month = 12
day = 31
else
for each littleMonth in (4 6 9 11)
if month = littleMonth then
day = 30
else
if month = 2 then
if year = 2004 then
day = 29
else
day = 28
if year = 2008 then
wscript.echo "Fatal error!"
end if
end if
else
day = 31
end if
end if
next
end if
else
day = day -1
end if
wscript.echo "D M Y: " &day &" " &month &" " &year
for each variable in (day month year)
variable = nothing
next
'PS. So, that meens that I have just readed a
'100 pages book about nonsense objects. Hmmm.
> 'PS. So, that meens that I have just readed a
> '100 pages book about nonsense objects. Hmmm.
This is not batch related. However, you asked here, so it should be answered
here. (Standard reply accepted by some.) In the future, I will ignore
further VBScript discussion regarding this thread/topic.
Benny,
Your using the VBScript "For Each" operative (loop) incorrectly. The (group)
must be an object or array. Your trying to use a list as in a batch
FOR/IN/DO loop. Note, you should avoid using Month, Day, and Year for your
variable names. Although no error occurs when using them in this language,
these are intrinsic functions of VBScript and will eventually cause you
headaches when attempting to debug some problem code later.
'Corrections inserted to your original code follows...
'Find the date of yesterday,
dim day, month, year
day = 14
month = 5
year = 2002
Dim SmallArray(3)
SmallArray(0) = 4
SmallArray(1) = 6
SmallArray(2) = 9
SmallArray(3) = 11
if day = 1 then
if month = 1 then
year = year -1
month = 12
day = 31
else
for each littleMonth in SmallArray
if month = littleMonth then
day = 30
else
if month = 2 then
if year = 2004 then
day = 29
else
day = 28
if year = 2008 then
wscript.echo "Fatal error!"
end if
end if
else
day = 31
end if
end if
next
end if
else
day = day -1
end if
'Note, clearing your variables is not required.
set SmallArray = nothing
set month = nothing
set day = nothing
set year = nothing
wscript.echo "D M Y: " &day &" " &month &" " &year
'=========================
Better yet, you should look up the Select Case statement... Executes one of
several groups of statements, depending on the value of an expression.
mymonth = 1 '<=== Play with this value and try it out.
Select Case mymonth
Case 4, 6, 9, 11
msgbox "30 days"
Case 2
msgbox "Feb has 28, and sometimes 29, days."
Case Else
msgbox "31 days"
End Select
'=========================
Or best of all, check out the DateAdd Function... Returns a date to which a
specified time interval has been added.
MsgBox "Yesterday was " & DateAdd("d", -1, Date)
BTW, a book's content is only as good as its author. Good luck in your
WSH/VBS quest.
--
Todd Vargo (body of message must contain my name to reply by email)
Once debugged, it will in any case fail in 2012.
The following approach, taken from HUNT.PAS, may be better :
const Ult : array [1..12] of byte = (31,28,31,30,31,30,31,31,30,31,30,31) ;
for JW := Fnq downto 1 do begin Dec(Day) ;
if Day=0 then begin Dec(Month) ;
if Month=0 then begin Month := 12 ; Dec(Year) end ;
if (Month=2) and
((Year and 3) = 0) and ((Year mod 100 > 0) or (Year mod 400 = 0))
then Day := 29 else Day := Ult[Month] ;
end {Day 0};
end {for} ;
Note, though, that the Julian Calendar suffices for DOS, since DOS goes
wrong after 2099.
The approach is slower than going via a daycount; but it is fast enough
on my slowest machine, in a context where usually Fnq<366.
--
© John Stockton, Surrey, UK. j...@merlyn.demon.co.uk Turnpike v4.00 MIME. ©
Web <URL:http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms
PAS EXE etc : <URL:http://www.merlyn.demon.co.uk/programs/> - see 00index.txt
Dates - miscdate.htm moredate.htm js-dates.htm pas-time.htm critdate.htm etc.
This is wrong. The "For Each...Next" Statement iterates
through the elements of an Array or an Object. It's not
used to run through lists.
In any event, it's more interesting to compute the number
of days in any month directly by a logic+arithmetic mix.
This avoids tiresome lists of days in the various months.
Start from noticing that, if you look at the year beginning
in March (as the Romans did), then the numbers of days
form two cycles, one a interval 2 and one at interval 5, thus:
Mar 31
Apr 30
May 31
Jun 30
Jul 31
Aug 31
Sep 30
Oct 31
Nov 30
Dec 31
Jan 31
Feb 30 adjust(-1 or -2)
You can write a VBS function to match this double cycle, and make
the February adjustment to calculate the days in any month, all in a
one-line formula. If the month is m (where Jan=1) and the year
is y (four digit), then to calculate the number of days (d) in the
month m, you can use the 5+2 pattern to deduce this formula
(in VBS notation):
d=30+((6*m+59)\5)mod(2)+(m=2)*(m+((y mod 4)=(0)))
Applies from March 1900 to January 2100 inclusive. Note
that VBS logic equivalences (a=b) evalute to -1IfTrue and
to 0 IfFalse. In VBS notation, mod = remainder on integer
division, and \ = integer quotient.
--
(pp) William Allen
Thanks all for the suggested and useful syntax!
Below is my results.
Notice that line numb 112 was needed: if not D = 30 then D = 31
Benny Pedersen,
BTW: Such useful replys motivates me to pay a reward:
If you computer freeze (U can't do anything), then
you maybe have got a CPU coller which is to small,
(get a bigger one). Anyhow, if your computer also
freeze when the weather isn't warm, then you can
turn off the hardware acceleration in properties,
graphic menu, (just right clich "This Computer" icon
and select properties). Now you can write text files
or whatever but you havn't any OpenGL if playing
"Counter Strike". So, turn off the AGP Turbo in BIOS
instead of turning off the hardware acceleration in
properties and the performance and the graphic would
be better than the local Net-Café, and the computer
don't freeze anymore. BTW. Also turn off the Vertical
Syncron.
--End of reward.
@echo off
goto %1 Begin --------------------------------------------------------
' A Standard Template for DOS-Batch/VBS/WSH programming.
May 16, 2002 by Benny Pedersen, http://2dos.homepage.dk/
:Begin --------------------------------------------------------
::for %%c in (%ComSpec% goto:End) do %%c /cstart.exe/min %0 :CreateVBS
:CreateVBS Arg2
%ComSpec% /c%0 Write echo > %temp%.\~.VBS
:RunScript
start.exe /wait wscript.exe %temp%.\~.VBS //t:10
::start/max /wait cscript.exe %temp%.\~.VBS //nologo Arg0 >> CON
:Done
for %%c in (:::set :::pause :::cls erase:%temp%.\~.VBS) do %%c
::Notepad %temp%.\~.VBS
:End
for %%c in (:::exit rem:OR: ctty goto::) do %%c nul
Local library
%2 if not fso.folderexists("named") then
%2 etc...
______________________________________________________________________
:Write
%2:' Date of yesterday
%2:
goto 3'th_solution
: 3'th_solution (`dateAdd instead of `case or `if)
%2: msgBox "Yesterday was" &vbCrLf & dateAdd("d", -1, date)
goto --(end of write script)--
: 2'th_solution (`case instead of `dateAdd or `if)
%2: dim D, M, Y
%2: D = day(now)
%2: M = month(now)
%2: Y = year(now)
%2:
%2: if D = 1 then
%2: select case M
%2: case 1 Y = Y -1
%2: M = 12
%2: D = 31
%2: case 3 M = 2
%2: D = 28 -((Y mod 4)=(0))
%2: case 5,7,10,12 M = M -1
%2: D = 30
%2: case else M = M -1
%2: D = 31
%2: end select
%2: else
%2: D = D -1
%2: end if
%2:
%2: wscript.echo "Yesterday, Day Month Year: " &D &" " &M &" " &Y
goto --(end of write script)--
: 1'th_solution (`if instead of `dateAdd or `case)
%2: dim D, M, Y
%2: D = day(now)
%2: M = month(now)
%2: Y = year(now)
%2:
%2: if D = 1 then
%2: if M = 1 then
%2: Y = Y -1
%2: M = 12
%2: D = 31
%2: else
%2: M = M -1
%2: if M = 2 then
%2: D = 28 -((Y mod 4)=(0))
%2: else
%2: dim Array(3)
%2: Array(0) = 4
%2: Array(1) = 6
%2: Array(2) = 9
%2: Array(3) = 11
%2: for each LittleMonth in Array
%2: if M = LittleMonth then
%2: D = 30
%2: else
%2: if not D = 30 then D = 31
%2: end if
%2: next
%2: end if
%2: end if
%2: else
%2: D = D -1
%2: end if
%2:
%2: wscript.echo "Yesterday, Day Month Year: " &D &" " &M &" " &Y
: --(end of write script)--
I assume you are aware that WSH (see Note 1) already includes
the DateAdd function? This function makes calculating the date
tokens for any number of days forward or back quite trivial. The
following demo shows a series of Subroutine calls (see Note 2)
showing one possible Batch syntax for doing so:
====Begin cut-and-paste (omit this line)
@ECHO OFF
IF (GOTO:)==(%1) %1%2 (Subroutine handler)
:: Set D=day MO=month Y=year for +/-Days difference
CALL %0 GOTO: _DAYDIF 0 D MO Y
ECHO. Current Date : Day=%D% Month=%MO% Year=%Y%
CALL %0 GOTO: _DAYDIF -1 D MO Y
ECHO. Current Date -1 days: Day=%D% Month=%MO% Year=%Y%
CALL %0 GOTO: _DAYDIF +7 D MO Y
ECHO. Current Date +7 days: Day=%D% Month=%MO% Year=%Y%
CALL %0 GOTO: _DAYDIF -30 D MO Y
ECHO. Current Date -30 days: Day=%D% Month=%MO% Year=%Y%
FOR %%V IN (D MO Y) DO SET %%V=
GOTO EOF (=Subroutine code follows=)
:_DAYDIF (Usage: CALL %0 GOTO: _DAYDIF +/-Days DayVar MonthVar YearVar)
%COMSPEC% /c %0 GOTO: 1_DAYDIF ECHO. %3 %4 %5 %6>%TEMP%.\_S.VBS
cscript//nologo %TEMP%.\_S.VBS>%TEMP%.\_T.BAT
FOR %%C IN (CALL DEL) DO %%C %TEMP%.\_T.BAT
DEL %TEMP%.\_S.VBS
GOTO EOF (=Subroutine code follows=)
:1_DAYDIF
%3Set fso=CreateObject("Scripting.FileSystemObject")
%3s=DateAdd("d",%4,now)
%3wscript.echo "SET %5="& right(100+day(s),2)
%3wscript.echo "SET %6="& right(100+month(s),2)
%3wscript.echo "SET %7="& year(s)
:EOF (End-of-file)
====End cut-and-paste (omit this line)
Win9x GUI study/demo only. Cut-and-paste as Batch script (file with .BAT
extension). Lines that don't begin with 2 spaces have wrapped by mistake.
If editing or mixing with your own code, see Subroutine Guidelines below.
For details of VBS script embedding method, see Note 3.
--
(pp) William Allen
Note 1:
WSH (Windows Script Host) is available as a free downloadable
add-on for the tiny proportion of Windows machines (mostly older
Windows 95 ones) which don't already have it installed in one
version or another. Current version (around 5.6-ish) will install
on Windows 95 machines as well as Windows 98 and ME. There
is _extremely_ extensive free documentation included for WSH
in the form of HTML help files, which include masses of syntax
examples in VBScript and JScript.
Windows Script Host main page for information and downloads:
http://msdn.microsoft.com/scripting/
By default, WSH installs CSCRIPT.EXE which is a Batch file
interface allowing all WSH functionality to be run from a normal
DOS-style Batch file. This interface provides Windows machines
with an enormous extension to the traditional Batch functionality.
Note 2:
====Batch Subroutines: Guidelines for use
Batch Subroutines are code chunks for inclusion in a main Batch script.
Your main Batch Script itself should BEGIN with our two standard lines:
@ECHO OFF
IF (GOTO:)==(%1) %1%2 (Subroutine Handler)
The "Subroutine Handler" intercepts and routes all Subroutine recalls.
Your main Batch script should keep our Subroutine section at the END
GOTO EOF (=Subroutine Section below=)
... all the lines of code for Subroutine(s) are here ...
:EOF (End-of-file)
The "GOTO EOF" in the Subroutine Section header isolates it properly
from any of your own code if you add it above this Subroutine Section.
Typical Subroutine invocations (with Subroutine PARameters) are:
CALL %0 GOTO: _SUBR Par1 Par2
OR (where a child shell call is required):
%COMSPEC% /c %0 GOTO: _SUBR Par1 Par2
This restarts the main script (%0 holds its recall name). The GOTO: (as
the %1 parameter) is caught by Subroutine Handler at 2nd line of main
script. The Handler uses the Subroutine's ID (%2=_SUBR above) to jump
to right Subroutine (which "sees" Par1 as %3 and Par2 as %4). When the
Subroutine ends, control returns to main script at line after the call.
====Editing/mixing our code with your own code in a Batch file:
KEEP the "Subroutine Handler" line as the second line of your own version
(after the initial @ECHO OFF). The Handler line is needed to route calls
to Subroutines, but won't otherwise affect any of your code. KEEP all
Subroutine code (and the EOF label) at the end of your reworked version.
The "Subroutine code" is all the text including and following the line(s):
GOTO EOF (=Subroutine section below=)
The "GOTO EOF" in this line prevents execution of the following Subroutine
code unless it's specifically invoked by a Subroutine call.
Follow these guidelines and it is easier to combine any of our posted
Subroutines with your own scripts, and maintain the resultant code mix.
Note 3:
Embedding non-batch scripts in Batch files
http://groups.google.com/groups?selm=a7kpl5$ltm4i$1...@ID-55970.news.dfncis.de
Date: Sun, 24 Mar 2002
Hi William
No, if it was not included in my post, then I'm not aware of it
but I try to learn it. Unfortunately, I have some other things
to do the next two days (out of city).
Benny Pedersen,
PS. About my previous post, here's a "modification":
:Write
set cmdline= % %
%2:' CountDays.vbs
%2: % %
%2: function countDays(theDate)
%2: CountDays = datediff("d", date, cdate(theDate))
%2: end function
%2:
%2: dim Days
%2: Days = countDays("24-12-" & year(date))
PROMPT $ if Days $G 0 then'%cmdline%%cmdline%%cmdline% ignore:
FOR %%o in (n ff) do %2:o%%o
%2: msgbox "Xmas: " & Days & " day(s)"
PROMPT $ elseif Days $L 0 then'%cmdline%%cmdline%%cmdline% ignore:
FOR %%o in (n ff) do %2:o%%o
%2: msgbox "Over"
%2: else
%2: msgbox "%cmdline%T" &vbCrLf &"%cmdline% o" &vbCrLf &vbCrLf &_
%2: "%cmdline%D" &vbCrLf &"%cmdline% a" &vbCrLf &"%cmdline% y"
%2: end if
There was a redundancy in the previous code, since there is
no need to create an instance of the FileSystemObject. The
DateAdd and string handling functions are available without
further Object creation. This version removes that line.
====Begin cut-and-paste (omit this line @ECHO OFF
IF (GOTO:)==(%1) %1%2 (Subroutine handler)
:: Set D=day MO=month Y=year for +/-Days difference
CALL %0 GOTO: _DAYDIF 0 D MO Y
ECHO. Current Date : Day=%D% Month=%MO% Year=%Y%
CALL %0 GOTO: _DAYDIF -1 D MO Y
ECHO. Current Date -1 days: Day=%D% Month=%MO% Year=%Y%
CALL %0 GOTO: _DAYDIF +7 D MO Y
ECHO. Current Date +7 days: Day=%D% Month=%MO% Year=%Y%
CALL %0 GOTO: _DAYDIF -30 D MO Y
ECHO. Current Date -30 days: Day=%D% Month=%MO% Year=%Y%
CALL %0 GOTO: _DAYDIF +10000 D MO Y
ECHO. Current Date +10000 days: Day=%D% Month=%MO% Year=%Y%
FOR %%V IN (D MO Y) DO SET %%V=
GOTO EOF (=Subroutine code follows=)
:_DAYDIF (Usage: CALL %0 GOTO: _DAYDIF +/-Days DayVar MonthVar YearVar)
%COMSPEC% /c %0 GOTO: 1_DAYDIF ECHO. %3 %4 %5 %6>%TEMP%.\_S.VBS
cscript//nologo %TEMP%.\_S.VBS>%TEMP%.\_T.BAT
FOR %%C IN (CALL DEL) DO %%C %TEMP%.\_T.BAT
DEL %TEMP%.\_S.VBS
GOTO EOF (=Subroutine code follows=)
:1_DAYDIF
You may use William's Standard Goto Technique, or constructing
you own Standard Templates, as I did:
http://2dos.homepage.dk/batutil/NEWS7.HTM#mavad
Benny Pedersen,
Related information:
@ echo off
echo.
echo. ========================================================
echo.
echo. After you have executed this batch, then you are able to
echo right click and choose the following:
echo.
echo. 1. New
echo. 2. MS-DOS-batchfile or a VBScript
echo.
echo. ========================================================
echo.
echo. Tips:
echo.
echo. To rename a file, select the file and press [F2].
echo.
echo. ========================================================
echo.
echo.
pause
cls
echo: REGEDIT4 > %temp%.\~tmp.reg
echo: >> %temp%.\~tmp.reg
echo: [HKEY_CLASSES_ROOT\.bat\ShellNew] >> %temp%.\~tmp.reg
echo: "FileName"="New.bat" >> %temp%.\~tmp.reg
echo: >> %temp%.\~tmp.reg
echo: [HKEY_CLASSES_ROOT\.vbs\ShellNew] >> %temp%.\~tmp.reg
echo: "FileName"="New.vbs" >> %temp%.\~tmp.reg
echo: >> %temp%.\~tmp.reg
echo:@echo off> %windir%\ShellNew\New.bat
echo:>> %windir%\ShellNew\New.bat
echo:' New.vbs> %windir%\ShellNew\New.vbs
echo:>> %windir%\ShellNew\New.vbs
GOTO _________________________________________________________________
rem If you remove the above line: GOTO, (or prefix it with REM), then
rem you may config Windows so you can also right click for an Editor:
echo: [HKEY_CLASSES_ROOT\batfile\shell\Edit\command]>>%temp%.\~tmp.reg
echo:@="C:\\WINDOWS\\COMMAND\\PFE32.EXE /g2 \"%%1\"">>%temp%.\~tmp.reg
echo:
echo: [HKEY_CLASSES_ROOT\vbsfile\shell\Edit\command]>>%temp%.\~tmp.reg
echo:@="C:\\WINDOWS\\COMMAND\\PFE32.EXE /g2 \"%%1\"">>%temp%.\~tmp.reg
echo:
rem The above /g switch (for PFE32) would place the cursor
rem in front of line number 2 as "goto jump" /g2.
rem
rem Download PFE Editor: http://2dos.homepage.dk/batutil/download.htm
rem or use Notepad or whatever.
:_____________________________________________________________________
start.exe /wait %temp%.\~tmp.reg
erase %temp%.\~tmp.reg