在数据分析工作中,我们做一个项目,通常要需要很多数据。数据分析之初,我们把数据存储在外部文件当中,如excel、spss,因此就需要将数据导入到sas,通常我们会用proc import。同样,分析工作结束后,会生成相应的数据集,我们需要把它们导出到外部文件以更方便地使用,通常我们用proc export。
如果一个文件夹只有一个或几个文件,或着一个逻辑库只有一个或几个数据集,一次一次使用proc import和proc export也不是很麻烦的工作。但要是有大量的excel文件或sas数据集,一个个导入和导出就显得有点繁琐了。
那么有没有什么办法将excel文件批量导入和导出呢?其实,百度搜索可以得到很多可行的办法,但大多程序复杂。因此,我在参考了几种方法以及sashelp之后,写了如下两个宏程序,用来批量导入和到处excel文件,下面就分享给大家。如果有兴趣可参考下列代码试试写写其他格式的文件导入和导出的批量化。
一:excel文件的导出(宏%excel_export)
- %macro excel_export(libname,outfile,method,filename,type);
- %let libname=%upcase(&libname);
- proc sql noprint;
- select memname,count(memname) into:memlist separated by "\" ,
- :nummem
- from dictionary.tables where libname="&libname";
- quit;
- %do i=1 %to &nummem;
- %let memname&i=%scan(&memlist,&i,\);
- %if &method=onefile %then %do;
- proc export data=&libname..&&memname&i
- outfile="&outfile\&filename..&type"
- dbms=excel;
- run;
- %end;
- %if &method=lmuitifile %then %do;
- proc export data=&libname..&&memname&i
- outfile="&outfile\&&memname&i...&type"
- dbms=excel;
- run;
- %end;
- %end;
- %mend;
宏参数 | 解释 |
libname | 指定逻辑库 |
outfile | 指定输出到目标文件夹 |
method | 指定导出的方法(onefile:所有数据集导出到一个excel文件里,不同数据集不同的sheet。multifile:不同数据集导出到不同的excel文件) |
filename | 指定excel文件名,如果是onefile,则只需一个文件名,multifile就需要多个文件名,具体见宏程序 |
type | 指定文件格式,excel文件有两种格式:.xls和.xlsx |
二:excel文件的导入(宏%excel_import)
- %macro excel_import(location);
- %let location=%bquote(&location);
- %let rc=%sysfunc(filename(myfile,&location));
- %let did=%sysfunc(dopen(&myfile));
- %let memname=;
- %let nummem=%sysfunc(dnum(&did));
- %if &nummem>0 %then %do;
- %do i=1 %to &nummem;
- %let memname&i=%sysfunc(dread(&did,&i));
- %let table&i=%scan(&&memname&i.,1,%str(.));
- %end;
- %end;
- %do i=1 %to &nummem;
- proc import out=&&table&i.
- datafile="&location\&&memname&i"
- dbms=excel replace;
- getnames=yes;
- run;
- %end;
- %mend;
该宏程序参数只有一个location(指定目标文件夹的路径),虽然只有几行,但这个宏所用的函数比较少见,是文件操作函数。
下面我分别对这两个宏的思路做一个简单的解释:
宏%excel_export的思路是:
使用proc sql中的tables字典自动识别出目标逻辑库的数据名列表,再用do循环,依次创建宏变量,存储单个数据名,依次添加进proc export的data选项。
如果只想得到一个excel文件,而把逻辑库中的每个数据集存储为不同的sheet,则用method=onefile,这种情况下,filename只需指定你想要的文件名就行。如果想要不同的数据集导出到不同的excel文件,则用method=multifile,但宏参数filename就需要用宏变量&&memname&i来指定,结果会用每个数据集名给excel文件命名。
宏%excel_import虽然参数少,但代码较为难懂,这里用到了文件操作函数:dopen、dnum、dread、dclose
首先第一个%let语句用了%bquote将路径保护起来,目的是防止路径中有特殊字符,第二个%let中的filename函数给路径命名为myfile。
dopen函数:打开目标文件夹,这里会给did赋一个值,如果大于0表示该文件夹是可以打开的。但通常情况下我们自己所创建的文件夹都是可以打开的,所以不考虑等于0的情况,随后did将作为后面几个函数的参数。
dnum函数:计算目标文件夹中有多少个文件
dread函数:返回这些文件的名称,注意,dread还有另一个参数,是用来指定返回哪个文件的文件名。
dclose函数:在得到所需要的结果后,需要用dclose将文件夹关闭。
得到所有文件的文件名后,我们就可以创建宏变量了。由于文件名包含扩展名(如class.xls),因此&&memname&i这一组宏变量只能用在datafile=选项里,不能作为out=选项的数据集名。因此我们还需要对&&memname&i进行截取,截取出(.)前的单词作为数据集名,这组宏变量即为&&table&i。注意,%scan中的第三个参数为%str(.),这样表示的原因是(.)在sas中也属于特殊字符,它有自己的用途,为了掩蔽它在sas中自己的作用,需用到掩蔽函数%str(这一些系列的函数有很多,上述的%bquote也属于掩蔽函数)。有了文件名和数据集名,我们就可以import了。
getnames=yes,虽然并不是所有的文件都适用,但为了批量输出实现自动化,建议大家使用该宏时还是尽量将excel文件的变量名改成符合sas变量名的命名规则的吧。
其实,这个宏程序稍作修改也可以实现导入一个excel文件里有很多sheet的情况,具体怎么修改,大家不妨自己动手试试看。