I found a macro presented at SAS Global Forum to help zip/unzip compressed files. I am downloading a zip file daily, extracting the files to a folder, then performing further processing in SAS. The zip file contains the same set of files every time - I need to unzip the files and then overwrite the previous day's files. I'm trying to run my program in batch mode, and keep getting the window that asks me to confirm whether or not I want to replace the files. I need to suppress this window and have the files overwrite automatically. I don't know enough about VBScript to understand where to insert an overwrite option. What modification do I need to make?
%macro SASZip_Lite(zip=, sfdr=, fstyl=%str(*.sas*dat), tfdr=);
/****************************************************************
The code posted below is provided "AS IS" with NO WARRANTIES.
ZIP: directory and file name of zip archive
SFDR: directory of source files (to be zipped)
FSTYL: File type of source files; value: *.* as "zip a folder"
TFDR: Target directory for unzipped files (for unzip)
*****************************************************************/
%local zip sfdr fstyl tfdr vbadir p q mode;
/* Set up a temporary working folder for VBScript */
%let vbsdir=c:\MyZi$Dir;
options noxwait;
/* To initiate a clean working space */
%if %sysfunc(fileexist("&vbsdir"))=1 %then %sysexec rd /s/q "&vbsdir";
%if %index(%upcase(&zip), .ZIP)=0 %then %let zip=&zip..zip;
%let mode=;
/* Compress (zip) files */
%if %length(&sfdr)>0 and (%length(&zip)>0) %then %do;
/* Extract directory name of the zip file, if no such folder, generate one */
%let q=%sysfunc(tranwrd(&zip, %scan(&zip, -1, %str(\)), %str( )));
%let q=%substr(&q, 1, %length(&q)-1);
%if %sysfunc(fileexist("&q"))=0 %then %sysexec md "&q";
/* Copy all requested files from a validated source folder to a temporary folder,
and keep their original time stamps */
%if %length(&sfdr)>0 and %sysfunc(fileexist("&sfdr"))=1 %then %do;
%let mode=z;
%sysexec md "&vbsdir";
%if %qupcase(&fstyl)^=%str(*.*) %then %do;
%sysexec md "&vbsdir.\temp_zip";
%sysexec copy "&sfdr.\&fstyl" "&vbsdir.\temp_zip";
%end;
%end;
%end;
%else %if %length(&tfdr)>0 and %length(&zip)>0 and %sysfunc(fileexist("&zip"))>0
%then %do; /* Unzip files */
%let mode=u;
%sysexec md "&vbsdir";
%end;
%if &mode=z or &mode=u %then %do;
/* Generate VBScript based on different modes */
data _null_;
FILE "&vbsdir.\xpzip.vbs";
put 'Set ZipArgs = WScript.Arguments';
put 'InputFile = ZipArgs(0)';
put 'TgtFile = ZipArgs(1)';
put 'Set objShell = CreateObject("Shell.Application")';
put 'Set source = objShell.NameSpace(InputFile).Items';
put 'soucnt = objShell.NameSpace(InputFile).Items.Count';
%if &mode=z %then %do;
put 'CreateObject("Scripting.FileSystemObject").CreateTextFile(TgtFile,
True).Write "PK" & Chr(5) & Chr(6) & String(18, Chr(0))';
put 'objShell.NameSpace(TgtFile).CopyHere(source)';
put 'Do Until objShell.NameSpace(TgtFile).Items.Count = soucnt';
put 'wScript.Sleep 3000';
put 'Loop';
%end;
%else put 'objShell.NameSpace(TgtFile).CopyHere(source)'; ;
put 'wScript.Sleep 3000';
run;
/* Run VBScript file for data archiving */
%if &mode=z %then %do;
%if %qupcase(&fstyl)=%str(*.*) %then %sysexec CScript "&vbsdir.\xpzip.vbs"
"&sfdr" "&zip";
%else %sysexec CScript "&vbsdir.\xpzip.vbs" "&vbsdir.\temp_zip" "&zip";
%end;
%else %sysexec CScript "&vbsdir.\xpzip.vbs" "&zip" "&tfdr";
%end;
/* Clean up */
%if %sysfunc(fileexist("&vbsdir"))=1 %then %sysexec rd /s/q "&vbsdir";
%mend SASZip_Lite;
@Reeza - definitely open to another way if there is one. ZIP contains CSV files. Running SAS 9.4 on Windows 10.
I have another process later on that extracts the names from the CSV files using the filename statement - not sure if that is dependent upon the files being unzipped already, or not. This is the code that needs to follow the unzipping of the file:
filename csvfiles pipe "dir ""&directory\*.csv"" /b";
data csvlist;
length csvname $100;
infile csvfiles length=reclen;
input csvname $varying100. reclen;
run;
data _null_;
set csvlist end=end;
count+1;
call symputx('path'||put(count,4.-l),cats("&directory\",csvname));
call symputx('sasname'||put(count,4.-l),scan(csvname,1,'.'));
if end then call symputx('max',count);
run;
This is probably what you want then:
Note that the code is at the bottom of the blog post. For a text file, you can read it directly from the zip file, the documentation has an example, the third one.
@viola wrote:
@Reeza - definitely open to another way if there is one. ZIP contains CSV files. Running SAS 9.4 on Windows 10.
I have another process later on that extracts the names from the CSV files using the filename statement - not sure if that is dependent upon the files being unzipped already, or not. This is the code that needs to follow the unzipping of the file:
filename csvfiles pipe "dir ""&directory\*.csv"" /b"; data csvlist; length csvname $100; infile csvfiles length=reclen; input csvname $varying100. reclen; run; data _null_; set csvlist end=end; count+1; call symputx('path'||put(count,4.-l),cats("&directory\",csvname)); call symputx('sasname'||put(count,4.-l),scan(csvname,1,'.')); if end then call symputx('max',count); run;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.