如何编写用于在 sas 中导入多个 excel 文件(xlsx)的宏并将其附加
How to write macro for importing multiple excel files(xlsx) in sas and append it
我有大约 50 个 excel 文件(xlsx 格式)要导入到 sas,然后需要附加它以供分析。所有 excel 文件头都相同,即所有文件的变量名都相同。我需要宏来一次导入和附加所有文件,而不是一个一个地导入所有文件,然后再附加它。非常感谢您的帮助。
excel 文件的另一个问题是变量名和数据点之间有一个空白列。我已经编写了一个代码,使用数据步骤将其删除,但我们在导入时也在宏中编写了它。
Data XXX.yyy;
Set XXX.yyy;
if missing(coalesceC(of ASC Brand Cdesc1 Cust_ DGM Desc Family Grp1 High_Level_Product_Desc
Issf Name Prod_Desc Product__Code RVP SA_Desc Terr_ UOM Yr
)) and missing(coalesce(of Acc Int_Margin M_Cost Mth Net_Sales Sls__ Uts )) then delete;
运行;
听起来好像您现有的代码已经完成了您需要它做的事情。我怀疑尝试在一个数据步骤中导入所有 50 个文件是否会带来很大的性能提升(这可以通过 dde,但相当繁琐)。
如果您现有的代码设置为只处理一个硬编码文件,我建议使用它来编写一个简单的宏,将一个 excel 文件作为输入,导入该文件,然后附加它到主数据集。然后你可以调用宏50次。
例如您可以像这样编写宏,合并代码的所有相关位,并用宏变量替换对特定文件的所有引用:
%macro import_and_append(excel_file,base_dataset);
proc import datafile = "&excel_file" dbms = excel out = t_import;
run;
proc append base = &base_dataset data = t_import;
run;
proc datasets lib = work nolist nowarn;
delete t_import;
run;
quit;
%mend;
然后你可以像这样调用宏:
%import_and_append(c:\excel_file_01.xls,work.master_dataset)
另一种方法是使用 Excel LIBNAME 引擎。您为每个文件声明一个库,然后在 1 个数据步骤中读取所有工作表。
在这个例子中,我在 C:\temp 中有 2 个工作簿(Book1.xlsx 和 Book2.xlsx)。所有数据都在 Sheet1 中。 3 个变量 -- X、Y 和 Z。根据您的目的进行修改。
data files;
format file .;
input file $;
datalines;
Book1.xlsx
Book2.xlsx
;
run;
%macro read_excel(dir,outdata,files);
data _null_;
set &files end=last;
call execute("libname t" || strip(put(_n_,8.)) || " excel '&dir\" || strip(file) || "';");
if last then
call symput("n",_n_);
run;
data &outdata;
set
%do i=1 %to &n;
t&i.."Sheet1$"n
%end;
;
a = sum(x,y,z);
if missing(a) then delete;
run;
%do i=1 %to &n;
libname t&i clear;
%end;
%mend;
%read_excel(c:\temp,data_from_excel,files);
我有大约 50 个 excel 文件(xlsx 格式)要导入到 sas,然后需要附加它以供分析。所有 excel 文件头都相同,即所有文件的变量名都相同。我需要宏来一次导入和附加所有文件,而不是一个一个地导入所有文件,然后再附加它。非常感谢您的帮助。
excel 文件的另一个问题是变量名和数据点之间有一个空白列。我已经编写了一个代码,使用数据步骤将其删除,但我们在导入时也在宏中编写了它。
Data XXX.yyy;
Set XXX.yyy;
if missing(coalesceC(of ASC Brand Cdesc1 Cust_ DGM Desc Family Grp1 High_Level_Product_Desc
Issf Name Prod_Desc Product__Code RVP SA_Desc Terr_ UOM Yr
)) and missing(coalesce(of Acc Int_Margin M_Cost Mth Net_Sales Sls__ Uts )) then delete;
运行;
听起来好像您现有的代码已经完成了您需要它做的事情。我怀疑尝试在一个数据步骤中导入所有 50 个文件是否会带来很大的性能提升(这可以通过 dde,但相当繁琐)。
如果您现有的代码设置为只处理一个硬编码文件,我建议使用它来编写一个简单的宏,将一个 excel 文件作为输入,导入该文件,然后附加它到主数据集。然后你可以调用宏50次。
例如您可以像这样编写宏,合并代码的所有相关位,并用宏变量替换对特定文件的所有引用:
%macro import_and_append(excel_file,base_dataset);
proc import datafile = "&excel_file" dbms = excel out = t_import;
run;
proc append base = &base_dataset data = t_import;
run;
proc datasets lib = work nolist nowarn;
delete t_import;
run;
quit;
%mend;
然后你可以像这样调用宏:
%import_and_append(c:\excel_file_01.xls,work.master_dataset)
另一种方法是使用 Excel LIBNAME 引擎。您为每个文件声明一个库,然后在 1 个数据步骤中读取所有工作表。
在这个例子中,我在 C:\temp 中有 2 个工作簿(Book1.xlsx 和 Book2.xlsx)。所有数据都在 Sheet1 中。 3 个变量 -- X、Y 和 Z。根据您的目的进行修改。
data files;
format file .;
input file $;
datalines;
Book1.xlsx
Book2.xlsx
;
run;
%macro read_excel(dir,outdata,files);
data _null_;
set &files end=last;
call execute("libname t" || strip(put(_n_,8.)) || " excel '&dir\" || strip(file) || "';");
if last then
call symput("n",_n_);
run;
data &outdata;
set
%do i=1 %to &n;
t&i.."Sheet1$"n
%end;
;
a = sum(x,y,z);
if missing(a) then delete;
run;
%do i=1 %to &n;
libname t&i clear;
%end;
%mend;
%read_excel(c:\temp,data_from_excel,files);