【问题标题】:How to get the range for different sheets in an excel file to use to import in a macro?如何获取excel文件中不同工作表的范围以用于导入宏?
【发布时间】:2017-08-21 19:24:11
【问题描述】:

我正在尝试导入一些具有多张工作表的文件。每张表中的变量名称从不同的行开始。我当前的代码允许我在一个数据集中获取所有工作表名称。我使用它将工作表名称存储在宏列表中,然后在 do 循环中使用 proc import 来导入每个工作表。我面临的问题是每张纸上的数据都从不同的行开始。我想知道是否有一种方法可以获取数据开始的每个工作表中的行号,以便我可以添加代码来指定导入宏中每个工作表的特定范围。

**********GETTING TAB NAMES****************

PROC SQL noprint;
    CONNECT TO pcfiles (path = "[ENTER FILE PATH HERE]");
    CREATE TABLE TABS_NAMES as
    SELECT * from connection to pcfiles (PCFILES::SQLColumns "","","","");                                                             
    DISCONNECT FROM pcfiles;
QUIT;

**********CLEANING TAB NAMES****************

Data Tab_names_1;
set TABS_NAMES;

    Clean_tab_name = dequote(tranwrd(TABLE_NAME,"$",""));
    if prxmatch ('/print/i',Table_name) > 0 then delete;
    keep TABLE_CAT  Clean_tab_name;

run;

Proc sort data = Tab_names_1 out = Tab_names_2 nodupkey;
    by _all_;
run;

**********STORING TAB NAMES**************** 

Proc sql noprint;
    select TABLE_CAT, Clean_tab_name
    into :Path1-:Path999, :Tab_Name1-:Tab_name999
    from Tab_names_2;
    %let max=&sqlobs.;
quit;

***************IMPORTING FILES*********

%MACRO  Import;
    %do i=1 %to &max.;
        Proc import
            datafile = "&&Path&i.."
            out      = Raw_Data_&i..
            dbms     = excelcs
            replace;
            sheet    = "&&Tab_Name&i..";
        run;    
    %end;
%mend;

%Import;

【问题讨论】:

  • 不幸的是,我不知道。 Excel 不是存储数据的好方法,但根据我的经验,这通常超出了程序员的控制范围。您可以指定导入数据的范围,请参阅 SAS 文档以获取使用 RANGE 选项的确切参考。
  • 另外,您是否尝试过 libname 方法而不是 PROC IMPORT?为您的文件分配一个 libname 并使用 PROC COPY 一次导入所有工作表?

标签: sql import macros sas


【解决方案1】:

这是动态获取每个选项卡的第一行的一般(未经测试)想法。 解释在代码中的注释中。这是一个粗略的想法,很可能需要修补。请注意,例如,我假设您的选项卡名称解析为有效的 SAS 表名称

/* assign a libname using the appropriate excel engine (XLS or XLSX)*/
LIBNAME lib XLS "path-to-xls";

/* get the the list of sheets and variables in your excel and output it to 'contents' */
proc contents data=lib._all_ out=contents;
run;

/* get the list of tab names from the contents table and store them in macro variables */
proc sql noprint;
select distinct memname
into :tab1-
from contents
;
quit;


%macro import();
  %let i=1;
  /* iterate accross all your tabs */
  %do %while(%symexist(tab&i.));
    proc sql noprint;
      /* get the column names for the current tab in a comma separated list */
      select name
      into cols separated by ','
      from contents
      where name="&&tab&i."
      ;
      /* store the number of columns for the current tab in another macro variable */
      select count(name)
      into ncols
      from contents
      where name="&&tab&i."
      ;
    quit;
    /* go through each record of your tab until you encounter the first non-empty one and store the record number in a macro variable */
    data _null_;
      retain first 1;
      set lib.&&tab&i.;
      if cmiss(&cols.) = &ncols. then do;
        first=first+1;
        call symput("&&tab&i.",first);
      end;
      else stop;
    run;
    /* you now have the first record of each tab in a macro variable named after the corresponding tab */
    %put &&&&&&tab&i.;

    /* add some code to import your worksheet */

    %let i=%eval(&i+1);
  %end;
  %let n=%eval(&i-1);
%mend;
%import;

【讨论】:

    【解决方案2】:

    不久前我遇到了类似的问题。我需要从包含许多空白行的特定工作表中导入数据,以及第一列中的无用标题。我能想到的最简单的解决方案是从 SAS 调用一个 VB 脚本(使用 SYSTASK)将一张干净的工作表导出到一个临时 csv 文件,然后我可以轻松地导入该文件。

    这是脚本的代码:

    ' deleteEmptyRows.vbs
    '
    ' Script used to delete the first few rows in an Excel sheet prior to
    ' importing using a PROC IMPORT or an EXCEL LIBREF.
    '
    ' Ex.: deleteEmptyRows <source.xls/xlsx> <sheet> <output.csv>
    
    ' Get the full paths.
    Set tmpFSO = CreateObject("Scripting.FileSystemObject")
    sourceFile = tmpFSO.GetAbsolutePathName(Wscript.Arguments.Item(0))
    sheetName = Wscript.Arguments.Item(1)
    outputFile = tmpFSO.GetAbsolutePathName(WScript.Arguments.Item(2))
    
    Dim tmpExcel
    Set tmpExcel = CreateObject("Excel.Application")
    
    Dim tmpBook
    Set tmpBook = oExcel.Workbooks.Open(sourceFile)
    
    Dim tmpSheet
    Set tmpSheet = oBook.Worksheets(sheetName)
    
    ' Delete rows until we reach an unempty one. We use the 2nd column
    ' to get around the header.
    while (tmpSheet.cells(1, 2).value = "")
        tmpSheet.rows(1).delete
    wend
    
    ' Save as CSV, and use local formats
    tmpBook.SaveAs outputFile, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
    
    tmpBook.Saved = True
    tmpExcel.Quit
    

    就我而言,我只有一个文件要处理,所以我确信这可以在您的情况下进行简化,但它应该为您的需要提供一个起点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-25
      • 1970-01-01
      • 1970-01-01
      • 2019-06-30
      • 2021-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多