DATA Step, Macro, Functions and more

How to increase the length of value from dictionary.macros

Accepted Solution Solved
Reply
Contributor
Posts: 28
Accepted Solution

How to increase the length of value from dictionary.macros

 

Dear All,

 

I have a macro generated automatically from the sas environment(measures).

I need to get the macro through sas dictionary.macros.

As the length of the macro is too large, the value column cannot accommodate the contents. I hope the default length is 200(showing in the offset column). I need the 4 rows in to one.

macros.PNG

 

The change in the length of value column is not possible(see the program).

 

Can you please help?

 

Program:

/*below is the amcro which i declared manually(automatically created)*/

%let measures=BUILDINGS_IOTRM CONTENTS_IOTRM TIME_ELEMENT_IOTRM BUILDINGS_IOTRM_AVG CONTENTS_IOTRM_AVG TIME_ELEMENT_IOTRM_AVG PTRM_CNT PTRM PTRM_AVG BUILDINGS_PTRM_CNT BUILDINGS_PTRM BUILDINGS_PTRM_AVG CONTENTS_PTRM_CNT CONTENTS_PTRM CONTENTS_PTRM_AVG STOCK_PTRM_CNT STOCK_PTRM STOCK_PTRM_AVG APPURT_STRUCT_PTRM_CNT APPURT_STRUCT_PTRM APPURT_STRUCT_PTRM_AVG COMBINED_PROP_PTRM_CNT COMBINED_PROP_PTRM COMBINED_PROP_PTRM_AVG TIME_ELEMENT_PTRM_CNT TIME_ELEMENT_PTRM TIME_ELEMENT_PTRM_AVG IOTRM_CNT IOTRM IOTRM_AVG BUILDINGS_IOTRM_CNT CONTENTS_IOTRM_CNT STOCK_IOTRM_CNT STOCK_IOTRM STOCK_IOTRM_AVG APPURT_STRUCT_IOTRM_CNT APPURT_STRUCT_IOTRM APPURT_STRUCT_IOTRM_AVG COMBINED_PROP_IOTRM_CNT COMBINED_PROP_IOTRM COMBINED_PROP_IOTRM_AVG TIME_ELEMENT_IOTRM_CNT;

proc sql;

create table vars as

select name,offset,value as value1 length 10000 from dictionary.macros

where scope eq 'GLOBAL';

 

/* create table macro_variables as*/

/* select catx(' ','%let ',strip(name),'=',strip(value),';') as statement length 700,*/

/* catx(' ','%global', strip(name)) as global_statement length 100*/

/* from vars;*/

quit;

 

Thanks,

Chithra


Accepted Solutions
Solution
‎02-14-2018 02:06 AM
Super User
Super User
Posts: 8,279

Re: How to increase the length of value from dictionary.macros

[ Edited ]

Use the SYMGET() function to retrieve the value of a macro variable.

data vars ;
  length name $32 value $32767 ;
  set sashelp.vmacro ;
  where scope='GLOBAL';
  by name notsorted ;
  if first.name;
  value=symget(name);
  keep name value;
run;

But note that macro variables can be up to 64K bytes and datasetp variables can only be 32K bytes.  You could use RESOLVE() to get the macro variable's length and so be able to create two dataset variables so that you could store macro variable values longer than 32K.

data vars ;
  length name $32 length 8 value1 value2 $32767 ;
  set sashelp.vmacro ;
  where scope='GLOBAL' ;
  by name notsorted;
  if first.name;
  length=input(resolve(cats('%length(%superq(',name,'))')),32.);
  value1=symget(name);
  if length > 32767 then value2 = resolve(cats('%qsubstr(%superq(',name,'),32768)'));
  keep name length value1 value2;
run;

Example result:

365   proc print;
366    where name='TESTVAR';
367   run;

WARNING: Data too long for column "value1"; truncated to 103 characters to fit.
WARNING: Data too long for column "value2"; truncated to 103 characters to fit.
NOTE: There were 1 observations read from the data set WORK.VARS.
      WHERE name='TESTVAR';

Obs  name      length

 58 TESTVAR     35177

Obs                                                 value1

 58 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut bibendum ullamcorper consequat. Nulla ut co

Obs                                                 value2

 58 endum dignissim.  Morbi tincidunt at quam eu placerat. Ut felis turpis, suscipit ac metus id, pellentes

image.png

 

Also note that if you are running inside a macro, so that one or more local symbol tables are currently active, then SYMGET() and RESOLVE() might not be able to fetch the value from the global symbol table.  If you need to retrieve values for macro variables that are hidden by more local macro variables then use this utility macro:

https://github.com/sasutils/macros/blob/master/symget.sas

 

View solution in original post


All Replies
Super User
Super User
Posts: 9,840

Re: How to increase the length of value from dictionary.macros

Why?  Macro isn't the place for data.  Variable lengths can only go up to 2000, and long macro strings get split up into shorter blocks.  Put data in datasets which are unlimted in size.  There are numerous methods for working with lists of variables available in Base SAS, such as:

_all_

_numeric_

_character_

varprefix:

firstvar--lastvar

etc.

Contributor
Posts: 28

Re: How to increase the length of value from dictionary.macros

Thanks for your reply.

 

But here the case is something different right?

The macro which I declared manually in the example was just for reference. This macro (measures) is something which is get via sas webservice which I declared manually here. Through dictionary.macros I can get these values of macros.

Super User
Posts: 5,917

Re: How to increase the length of value from dictionary.macros

I still think there is a why (you need to get it from dictionary.macros).

What is the application (more than it is a web service involved)?

You could however get the macro variable name from the dictionary, but then fetch the actual value from the macro variable itself (which could be up to 32k in size).

Data never sleeps
Contributor
Posts: 28

Re: How to increase the length of value from dictionary.macros

Yes. Thanks. But instead of macro I does the concatenation in the data step

 

I modified the script like below.

 

proc sql;

create table vars as

select name,value from dictionary.macros

where scope eq 'GLOBAL';

quit;

 

proc sort data=vars;

by name;

quit;

 

data want(drop=value rename=(concatenate=value));

length concatenate $ 10000;

do until (last.name);

set vars;

by name;

concatenate = strip(concatenate)||strip(value);

end;

run;

 

Super User
Posts: 6,934

Re: How to increase the length of value from dictionary.macros

You can rebuild the macro variable by copying from dictionary.macros:

 

proc sql;

select value into : measures separated by ''

from dictionary.macros where
name='MEASURES' and scope='GLOBAL';

quit;

 

It's important that the "separated by" is null ... two quotes without a blank between the quotes.  That's one of the few places in the software where it makes a difference.

Contributor
Posts: 28

Re: How to increase the length of value from dictionary.macros

Posted in reply to Astounding

Thanks for your reply.

Instead of macro, I used this in the data step itself.

Solution
‎02-14-2018 02:06 AM
Super User
Super User
Posts: 8,279

Re: How to increase the length of value from dictionary.macros

[ Edited ]

Use the SYMGET() function to retrieve the value of a macro variable.

data vars ;
  length name $32 value $32767 ;
  set sashelp.vmacro ;
  where scope='GLOBAL';
  by name notsorted ;
  if first.name;
  value=symget(name);
  keep name value;
run;

But note that macro variables can be up to 64K bytes and datasetp variables can only be 32K bytes.  You could use RESOLVE() to get the macro variable's length and so be able to create two dataset variables so that you could store macro variable values longer than 32K.

data vars ;
  length name $32 length 8 value1 value2 $32767 ;
  set sashelp.vmacro ;
  where scope='GLOBAL' ;
  by name notsorted;
  if first.name;
  length=input(resolve(cats('%length(%superq(',name,'))')),32.);
  value1=symget(name);
  if length > 32767 then value2 = resolve(cats('%qsubstr(%superq(',name,'),32768)'));
  keep name length value1 value2;
run;

Example result:

365   proc print;
366    where name='TESTVAR';
367   run;

WARNING: Data too long for column "value1"; truncated to 103 characters to fit.
WARNING: Data too long for column "value2"; truncated to 103 characters to fit.
NOTE: There were 1 observations read from the data set WORK.VARS.
      WHERE name='TESTVAR';

Obs  name      length

 58 TESTVAR     35177

Obs                                                 value1

 58 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut bibendum ullamcorper consequat. Nulla ut co

Obs                                                 value2

 58 endum dignissim.  Morbi tincidunt at quam eu placerat. Ut felis turpis, suscipit ac metus id, pellentes

image.png

 

Also note that if you are running inside a macro, so that one or more local symbol tables are currently active, then SYMGET() and RESOLVE() might not be able to fetch the value from the global symbol table.  If you need to retrieve values for macro variables that are hidden by more local macro variables then use this utility macro:

https://github.com/sasutils/macros/blob/master/symget.sas

 

Contributor
Posts: 28

Re: How to increase the length of value from dictionary.macros

Many Thanks for your explanation.

I rewrite as per your writings.

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 8 replies
  • 156 views
  • 0 likes
  • 5 in conversation