我在 SAS 9.2 两次导入中解决了类似的问题,一次用于探索工作表,一次用于提取数据。
这是我在那里所做的概括,但请原谅我发布我没有测试的源:我的电脑上没有安装 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
因此,实际数据从具有列标题“Bar”的单元格 C6 开始。让我们也假设我们知道以未知的顺序找到列“Foo”、“Bar”和“Val”以及可能我们不感兴趣的其他一些列,并且我们不知道有多少数据行。
现在,我们第一次天真地导入工作表并查询 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_ 个观察值来自 excel 中的第 N+1 行,因为第一个 excel 行被解释为标题。
要计算 rangeLeft 和 rangeRight,我们必须在我们将读取的范围内找到左侧列的相对位置并将其转换为字母
现在我们只读取相关数据;
/** 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 并更正它,请随意测试此代码。