Script de traitement par lots: Valider la saisie de la date

J’ai un fichier de commandes que j’utilise pour créer de nouveaux dossiers de projet pour les clients, qui guide l’utilisateur dans le processus de création et ajoute les fichiers et dossiers appropriés à un emplacement central. Je dois append une section de saisie afin de pouvoir insérer une date (pas toujours la date actuelle) et elle est incluse dans la dénomination des fichiers.

Le problème que j’ai, et j’ai chassé haut et bas et ne trouve pas ma réponse, est que je dois prouver la saisie de la date. Je souhaite que l’utilisateur saisisse la date au format MM-DD-YYYY , y compris les tirets. Il doit ensuite le formater en YYYY-MM-DD . Il doit être suffisamment intelligent pour obliger l’utilisateur à utiliser le format requirejs de MM-DD-YYYY ; doit être des nombres et des tirets, aucune barre oblique, la bonne quantité de caractères, etc.

Je n’ai pas été en mesure de trouver quoi que ce soit proche de moi, même à distance, alors je demande aux génies géniaux de l’aide à cet égard, car cela me pousse au mur. Voici mon code de script. J’ai besoin de cette entrée pour aller directement après le type de travail est sélectionné. "Please insert date (MM-DD-YYYY format): "

 @echo off setlocal EnableDelayedExpansion set version=7.95 set projectpath="P:" set workbookpath="\\server2\Documents\Blanks (DO NOT EDIT)\dryingworkbook_v3r75.xls" set questions="\\server2\Documents\Blanks (DO NOT EDIT)\Abatement and Mold Questions.txt" set notes="\\server2\Documents\Blanks (DO NOT EDIT)\Job Notes.docx" set info="\\server2\Documents\Blanks (DO NOT EDIT)\Job Information.docx" set bizname=1 ECHO =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ECHO = Welcome to SERVPRO Project Creation Wizard v%version% = ECHO =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ECHO. :sof ECHO. ECHO Is this new project for a Residential or Commercial job? :loopJobType SET /P jobtype=Enter [r] for Residential or [c] for Commercial: ECHO. IF "%jobtype%" == "r" GOTO :loopResidential IF "%jobtype%" == "R" GOTO :loopResidential IF "%jobtype%" == "c" GOTO :loopCommercial IF "%jobtype%" == "C" GOTO :loopCommercial GOTO :loopJobType :loopResidential ECHO You have chosen to create a new Residential job project. ECHO. set type=1 GOTO :loopFirstName :loopCommercial ECHO You have chosen to create a new Commercial job project. ECHO. set type=2 SET /p bizname=Please enter the business name: ECHO. IF "%bizname%"=="" GOTO :loopCommercial :loopFirstName SET /P FirstName=Please enter the insured's first name: IF "%FirstName%"=="" GOTO :loopFirstName call :format FirstName :loopLastName ECHO. SET /P LastName= Please enter the insured's last name: IF "%LastName%"=="" GOTO :loopLastName call :format LastName SET FullName=%LastName%, %FirstName% SET FullBizName=%bizname% (%FullName%) goto :ConfirmProject :format set Name=!%1! set Head=%Name:~0,1% set Tail=%Name:~1% for %%a in (ABCDEFGHIJKLMNOPQRSTU VWXYZ) do set Head=!Head:%%a=%%a! for %%a in (abcdefghijklmnopqrstu vwxyz) do set Tail=!Tail:%%a=%%a! set %1=%Head%%Tail% GOTO :eof :ConfirmProject ECHO. IF "%type%" == "1" SET /P yesno=Are you sure you want to add "%FullName%" to the Project directory? [y/n] IF "%type%" == "2" SET /P yesno=Are you sure you want to add "%FullBizName%" to the Project directory? [y/n] IF "%yesno%" == "y" GOTO :CreateProject IF "%yesno%" == "Y" GOTO :CreateProject IF "%yesno%" == "n" GOTO :sof IF "%yesno%" == "N" GOTO :sof GOTO :ConfirmProject :CreateProject IF "%type%" == "1" SET ProjectName=%FullName% IF "%type%" == "2" SET ProjectName=%FullBizName% :: Create a folder containing a new project. mkdir "%projectpath%\%ProjectName%" ECHO. ECHO. ECHO Creating a Project directory for "%ProjectName%" ... :: Create a folder within said project that will contain job documents. ECHO Creating a Documents directory for "%ProjectName%" ... mkdir "%projectpath%\%ProjectName%\Documents" :: (Taken out of use 7-15-13) ECHO Adding a Job Information file for "%ProjectName%" ... :: (Taken out of use 7-15-13) copy /-Y %info% "%projectpath%\%ProjectName%\Documents\Job Information - %ProjectName%.docx" ECHO Documents directory creation for "%ProjectName%" finished ... :: Create a folder within said project that will contain drying workbook(s). ECHO Creating a Drying Workbook directory for "%ProjectName%" ... mkdir "%projectpath%\%ProjectName%\Drying Workbooks" :: Copy a new blank workbook to the project workbook directory and give it the proper name. ECHO Adding a Drying Workbook for "%ProjectName%" ... copy /-Y %workbookpath% "%projectpath%\%ProjectName%\Drying Workbooks\DRY 1_%ProjectName%.xls" ECHO Adding an Abatement and Mold Questions file for "%ProjectName%" ... copy /-Y %questions% "%projectpath%\%ProjectName%\Drying Workbooks\Abatement and Mold Questions.txt" ECHO Drying Workbook directory creation for "%ProjectName%" finished ... :: Create a folder within said project that will contain original photos. ECHO Creating a Photos directory for "%ProjectName%" ... mkdir "%projectpath%\%ProjectName%\"Photos :: Create a folder within said project photo folder that will contain resized photos. mkdir "%projectpath%\%ProjectName%\Photos\Resized" mkdir "%projectpath%\%ProjectName%\Photos\Upload" ECHO Photos directory creation for "%ProjectName%" finished ... :: Add in Job Notes file. ECHO Adding a Job Notes files for "%ProjectName%" ... copy /-Y %notes% "%projectpath%\%ProjectName%\Job Notes - %ProjectName%.docx" :: Log the creation of the project. FOR /F "TOKENS=1* DELIMS= " %%A IN ('DATE/T') DO SET CDATE=%%B For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set date=%%a%%b%%c) echo off > "%projectpath%\Logs\%ProjectName% - [Project Created %date% by %computername%].txt" ECHO Logging "%ProjectName%" creation date and time... ECHO Project directory creation for "%ProjectName%" finished ... GOTO :OpenProject :OpenProject :: Ask if the project should be opened now. If so open and close script, else close script. set /p reply=Do you want to open the "%ProjectName%" project now? [y/n] if "%reply%" == "y" %SystemRoot%\explorer.exe "%projectpath%\%ProjectName%" IF "%yesno%" == "Y" %SystemRoot%\explorer.exe "%projectpath%\%ProjectName%" GOTO :eof IF "%yesno%" == "n" GOTO :No IF "%yesno%" == "N" GOTO :No exit :No ECHO. ECHO. ECHO You have successfully created a new project for %ProjectName%. ECHO. ECHO Press any key to exit . . . PAUSE>NUL :eof 

    Le fichier Batch ci-dessous vérifie que la date insérée a le bon format et qu’elle représente une date valide, c’est-à-dire le bon nombre de jours dans chaque mois, même en février les années bissextiles!

     @echo off setlocal EnableDelayedExpansion set i=0 for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do ( set /A i+=1 set dpm[!i!]=%%a ) set /P "inDate=Please insert date (MM-DD-YYYY format): " if "%inDate:~2,1%%inDate:~5,1%" neq "--" goto invalidDate for /F "tokens=1-3 delims=-" %%a in ("%inDate%") do set "MM=%%a" & set "DD=%%b" & set "YYYY=%%c" ver > NUL set /A month=1%MM%-100, day=1%DD%-100, year=1%YYYY%-10000, leap=year%%4 2>NUL if errorlevel 1 goto invalidDate if not defined dpm[%month%] goto invalidDate if %leap% equ 0 set dpm[2]=29 if %day% gtr !dpm[%month%]! goto invalidDate if %day% lss 1 goto invalidDate echo Date correct: %YYYY%-%MM%-%DD% goto :EOF :invalidDate echo Bad date 

    Vous pouvez vérifier si votre chaîne est valide facilement avec la commande findstr.

     set /p date= Please insert date (MM-DD-YYYY format): echo %date%| findstr /r "^[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]$">nul if errorlevel 1 ( echo invalid date ) pause 

    (^ signifie le début de la ligne, tandis que $ représente la fin de la ligne.)

    Maintenant, pour reformater MM-JJ-AAAA en AAAA-MM-JJ, vous pouvez diviser votre chaîne et la réassembler. Comme il s’agit d’un format fixe, ce n’est pas trop difficile non plus:

     set yyyy=%date:~6,4% set mm=%date:~0,2% set dd=%date:~3,2% set newDate=%yyyy%-%mm%-%dd% echo %newDate% 

    Le premier numéro de chaque commande ressemble à la position où la chaîne sera coupée. Le deuxième nombre ressemble à la longueur de la sous-chaîne.

    J’ai fait une fonction: getdate qui teste la date l’essaie; Il testera si les séparateurs sont corrects, la plage de valeurs pour le mois et le jour et si les valeurs sont NUM.

     @ECHO OFF setlocal enabledelayedexpansion :GetDate set /p $D=Enter a date (MM-DD-YYYY) : set $separate=%$d:~2,1% %$d:~5,1% for %%a in (%$separate%) do (if "%%a" neq "-" (echo Wrong Separator : %%a pause goto:Getdate)) set $D=%$D:-= % set $c=1 for %%a in (%$d%) do (call:test !$c! %%a set /a $c+=1) if !$c!==4 set $DateOK=%$month%-%$day%-%$Year% echo This DATE IS OK %$dateOK% exit /b :test if %1 equ 1 (echo %2 | findstr [0-9][0-9] if errorlevel 1 (echo Unvalid value for Month [NOT NUM]: %2 pause goto:getdate) if %2 GTR 12 (echo Unvalid value for Month [VALUR RANGE +]: %2 pause goto:getdate) if %2 LSS 1 (echo Unvalid value for Month [VALUR RANGE -]: %2 pause goto:getdate) set $month=%2) if %1==2 (echo %2 | findstr [0-9][0-9] if errorlevel 1 (echo Unvalid value for Day [NOT NUM]: %2 pause goto:getdate) if %2 GTR 31 (echo Unvalid value for Day [VALUR RANGE +] : %2 pause goto:getdate) if %2 LSS 01 (echo Unvalid value for Day [VALUE RANGE -]: %2 pause goto:getdate) set $day=%2) if %1==3 (echo %2 | findstr [0-9][0-9][0-9][0-9] if errorlevel 1 (echo Unvalid value for Year [NOT NUM] : %2 pause goto:getdate) set $Year=%2) 
     @ECHO OFF SETLOCAL enabledelayedexpansion CALL :getverdate ECHO DATE %indate% is OK. GOTO :EOF :: :: Get and verify date in format mm-dd-yyyy; reformat as yyyy-mmm-dd :: :regetdate ECHO "%indate%" is not in format "MM-DD-YYYY" or is invalid :getverdate SET /p indate="Please insert date (MM-DD-YYYY format): " IF NOT "%indate:~2,1%%indate:~5,1%"=="--" GOTO regetdate SET checkdate=9%indate:-=% IF NOT "%checkdate:~8%"=="%checkdate:~8,1%" GOTO regetdate FOR %%a IN (0 1 2 3 4 5 6 7 8 9) DO SET checkdate=!checkdate:%%a=! IF DEFINED checkdate GOTO regetdate IF %indate:~3,2%==00 GOTO regetdate FOR %%i IN (01:31 02:29 03:31 04:30 05:31 06:30 07:31 08:31 09:30 10:31 11:30 12:31) DO ( FOR /f "tokens=1,2delims=:" %%j IN ("%%i") DO IF %%j==%indate:~0,2% if "%%k" geq "%indate:~3,2%" GOTO goodday ) GOTO regetdate :goodday IF "%indate:~-4%" geq "1980" IF "%indate:~-4%" leq "2099" GOTO goodyear GOTO regetdate :goodyear SET /a checkdate=%indate:~-4% %% 4 IF "%indate:~0,2%%indate:~3,2%"=="0229" IF %checkdate% neq 0 GOTO regetdate SET indate=%indate:~-4%-%indate:~0,2%-%indate:~3,2% GOTO :eof 

    Voici une autre routine “get and validate date”.

    Notez que dans votre code, vous ne devez jamais définir une variable appelée date . %date% renverra la date actuelle – c’est une “variable magique” contrôlée par CMD. Parmi ces variables, citons %time% , %random% et %errorlevel% . La définition de l’un de ces parameters remplace la valeur établie par le système.

    Vous pouvez présenter à l’utilisateur trois invites – année, mois, jour.

     set /py="Please enter year (YYYY): " set /pm="Please enter month (MM): " set /pd="Please enter day (DD): " set date=%y%-%m%-%d% 

    Si vous souhaitez vérifier la longueur de l’entrée, procédez comme suit:

     if [%y:~4%] NEQ [] echo year entered incorrectly & goto :getDate 

    Vous pouvez supposer que %y% est supérieur à quatre caractères – c’est-à-dire si% y: ~ 4% n’est pas nul – qu’il a été saisi de manière incorrecte (voir Astuces Dos sur la manipulation de chaînes ). Le même principe s’applique pour le jour et le mois, sauf qu’ils doivent comporter deux caractères.
    Évidemment, pour cet exemple, vous devez append le libellé :getDate avant l’entrée utilisateur.

    Vous pouvez utiliser la sous-routine ReadFormattedLine pour toutes les entrées formatées. Par exemple, la commande ci-dessous lit 3 numéros dans un format de date; la routine accepte simplement les chiffres, insère les tirets et continue automatiquement après avoir lu le dernier chiffre. Si l’utilisateur supprime des caractères, les traits d’union sont également supprimés automatiquement.

     call :ReadFormattedLine myDate="##-##-####" /M "Please insert date (MM-DD-YYYY format): " 

    Ce sous-programme est écrit en pur Batch, il ne nécessite donc aucun programme supplémentaire et permet plusieurs opérations de saisie formatées, comme lire des mots de passe, convertir des lettres en majuscules, etc.