我有Excel文件(.xlsx),其第4行的列名和第5行的数据开头。我不确定在SAS中的Proc Import中使用什么来提取数据。请帮忙。 感谢
答案 0 :(得分:1)
我在SAS 9.2 两次导入中解决了类似的问题,一个用于探索工作表,一个用于提取数据。
这是我在那里所做的概括,但请原谅我发布的内容我没有测试:我的PC上没有安装SAS。 让我们假设你的数据看起来像这样(当保存为制表符分隔文件时):
Some title that does not interust us
Author Dirk Horsten
Date 01-Jan-15
Other Irrelevant thing
Bar Foo Val Remark
A Alfa 1 This is the first line
B Beta 2 This is the second line
C Gamma 3 This is the last line
因此实际数据从单元格C6开始,列标题为“Bar”。让我们假设我们知道找到列“Foo”,“Bar”和“Val”以及可能还有其他一些我们不感兴趣的列,它们是以未知的顺序排列的,而且我们不知道前面有多少数据行。 / p>
现在,我们首次首次导入工作表并查询sasHelp以了解所读内容:;
/** First stroke import, to explore the content of the sheet **/
proc import datafile="&file_name" out=temp_out dbms=excelcs replace;
sheet="&sheet_name";
run;
/** Find out what SAS read in **/
proc sql;
select couint(*) into :nrColstempCos separ by ' '
from sashelp.vcolumn where libName = 'WORK' and memName = 'TEMP_OUT';
select name into :tempCos separated by ' '
from sashelp.vcolumn where libName = 'WORK' and memName = 'TEMP_OUT';
quit;
接下来我们会查找标题和数据,以便我们知道如何正确阅读。; 如果所有列都被解释为字符值,则此方法有效,但遗憾的是,Excel无法强制执行此操作。
data _null_;
set temp_out end=last;
array temp {*} &tempCols.;
retain foo_col bar_col val_col range_bottom 0;
if not (foo_col and bar_col and val_col) then do;
range_left = 0;
range_right = 0;
/* Find out if we finally found the headers */
do col = 1 to &nrCols.;
select (upcase(temp(col));
when ('FOO') do;
foo_col = col;
if not range_left then range_left = col;
rang_right = col;
end;
when ('BAR') do;
bar_col = col;
if not range_left then range_left = col;
rang_right = col;
end;
when ('VALUE') do;
val_col = col;
if not range_left then range_left = col;
rang_right = col;
end;
otherwise;
end;
end;
if (foo_col and bar_col and val_col) then do;
/** remember where the headers were found **/
range_top = _N_ + 1;
call symput ('rangeTop', range_top);
rangeLeft = byte(rank('A') + range_left - 1);
call symput ('rangeLeft', rangeLeft);
rangeRight = byte(rank('A') + range_right - 1);
call symput ('rangeRight', rangeRight);
end;
end;
else do;
/** find out if there is data on this line **/
if (temp(foo_col) ne '' and temp(bar_col) ne '' and temp(val_col) ne '')
then range_bottom = _N_ + 1;
end;
/** remember where the last data was found **/
if last then call symput ('rangeBottom', range_bottom);
run;
为了计算rangeTop和rangeBottom,我们考虑到SAS中的_N_th观察来自excel中的 N +第1行,因为第一个excel行被解释为标题。
要计算rangeLeft和rangeRight,我们必须在我们将要读取的范围内找到左侧columen的相对位置并将其转换为字母
现在我们仅读入相关数据;
/** Second stroke import, to read in the actual data **/
proc import datafile="&file_name" out=&out_ds dbms=excelcs replace;
sheet="&heet_name";
range="&rangeLeft.&rangeTop.&rangeRight.&rangeBottom.";
run;
成功。如果您的计算机上有SAS并且更正了它,请随意测试此代码。
答案 1 :(得分:0)
无论数据前面有多少行,提供数据前面的行都是空白的,以下内容应该有效。
libname xl excel 'C:\somefile.xlsx';
data sheet;
set xl.'Sheet1$'n;
run;
libname xl clear;
这样就可以像设置数据库一样设置Excel工作簿,并且像表格一样直接引用工作表。我应该注意,我的设置是64位SAS 9.4和64位Excel;据我所知,如果你有64位SAS和32位Excel,这种方法可能无法正常工作。