【问题标题】:SAS nested macro, how to use varible outside macroSAS嵌套宏,如何在宏外使用变量
【发布时间】:2016-04-04 20:49:55
【问题描述】:

希望能解释清楚。我正在使用 SAS 8.2(这是我公司使用的)并尝试获取在 create_var 宏中创建的名为 &op_var_name 的变量名称。每次 run_loops 宏运行时都会改变。例如,它将基于 ds_split_list 数据集创建 list_detail1、list_detail2 和 list_detail3。我需要稍后在代码中使用这些变量,我似乎无法让它工作。我尝试在 run_loops 和 create_var 宏中添加 %global &op_var_name。日志在 run_loop 部分显示带有数据的变量,但随后在代码中引用该变量时日志显示为空白。

%macro create_var(ds_in=, item_to_list=, op_var_name=);

data &op_var_name;
set &ds_in end=eof;
length gen_list $30000.;
retain gen_list;
if not eof then do;
   gen_list=trim(left(gen_list))||"'"||trim(left(&item_to_list))||"'"||  ",";
end;
if eof then do;
   gen_list=trim(left(gen_list))||"'"||trim(left(&item_to_list))||"'";
   call symput("gen_name",trim(left(gen_list)));
   output;
end;
run;


%put &op_var_name=&gen_name ;


%mend create_var;

data _null_;
 set ds_split_list;
 call symput ('nobs', _n_);
 call symput ('ds_feed'||left(_n_),memname);
 call symput ('item_to_list', 'lotlabel');
 call symput ('op_var_name'||left(_n_), 'list_detail'||left(_n_));
run;


%macro run_loops;
  /* &nobs and all the "&&var&i" variables defined above */
     %do i = 1 %to &nobs;
        %create_var(ds_in=&&ds_feed&i, item_to_list=&&item_to_list, op_var_name=&&op_var_name&i);
     %end;
%mend run_loops;

%run_loops;


/* Later in the code is where I reference the variable created above. */

%get_oper(list=&list_detail1);

谢谢!

编辑:我最终使用了 Tom 回复中的这个选项。

或者您可以在子宏中创建变量时将其设为全局变量。

%global &op_var_name;
%let &op_var_name=&gen_name ; 

【问题讨论】:

    标签: variables macros nested sas


    【解决方案1】:

    您似乎有错字和逻辑错误。错字是你的内部宏有一个%PUT 语句而不是%LET 语句。因此,唯一生成的宏变量是名为GEN_NAME 的宏变量,而不是以分析变量命名的宏变量。所以改成这一行。

    %let &op_var_name=&gen_name ;
    

    您遇到的逻辑问题是您对新宏变量的初始引用位于内部宏内部,因此默认情况下它变为本地并在宏结束时消失。您可以简单地在调用宏之前先定义宏变量。

    %let &&op_var_name&i=;
    %create_var(ds_in=&&ds_feed&i, item_to_list=&&item_to_list, op_var_name=&&op_var_name&i);
    

    或者您可以在子宏中创建变量时将其设为全局变量。

    %global &op_var_name;
    %let &op_var_name=&gen_name ; 
    

    您甚至可以使用CALL SYMPUTX() 来执行此操作并消除额外的 GEN_NAME 宏变量。

    call symputx("&op_var_name",gen_list,'global');
    

    除了宏变量之外,您真的需要所有这些单独的数据集吗?为什么不直接从输入数据集创建宏变量而不创建另一个数据集?

    proc sql noprint ;
      select "'"||trim(left(&item_to_list))||"'"
        into :&op_var_name separated by ','
        from &ds_in
      ;
    quit;
    

    【讨论】:

    • 我更新了我的帖子,但忘了说我使用的是 SAS 8.2。这会抛出 symputx 选项。 %let 选项也不起作用,除非我没有做错什么。我的问题是在 %create_var 宏之前有 %let,我也应该设置什么?我喜欢的 sql 选项,但需要对我未发布的代码进行更多更改。
    • 即使在 8.2 中,您也应该能够声明具有全局范围的宏变量。在宏的开头添加:%GLOBAL op_var_name ;
    • 添加%GLOBAL 示例回答。
    • @Tony 您可能需要硬着头皮升级您的 SAS 版本。 SAS 8.2 于 15 年前发布。 blogs.sas.com/content/iml/2013/08/02/…
    • @Tom 我希望公司能够升级新版本有很多东西我不必在 8.2 中解决。谢谢你帮助汤姆!
    【解决方案2】:

    宏变量范围。如果要在宏之外使用,请声明为全局。调用 symputx 有第三个参数指定作用域。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多