如何将excel数据导入sas

时间:2014-11-06 00:57:30

标签: sas

我有Excel文件(.xlsx),其第4行的列名和第5行的数据开头。我不确定在SAS中的Proc Import中使用什么来提取数据。请帮忙。 感谢

2 个答案:

答案 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,这种方法可能无法正常工作。