BookmarkSubscribeRSS Feed
raivester
Quartz | Level 8

I am trying to establish a libname by piecing together three different macros.

 

I have:

GLOBAL PII_PREFIX S:\projects\ABCD\Data2\PII\Final\PPSI\PT\

GLOBAL PII_SUFFIX \internal SAF\PII Only

 

And I loop though CYC_YEAR values of 2020 and 2021.

 

One of the full filepaths I want to establish is: S:\projects\ABCD\Data2\PII\Final\PPSI\PT\2020\internal SAF\PII Only

 

I try to establish this libname when I call in the following macro from my main program (only showing a piece of the macro . . . obviously):

 

 

%macro check_program;

  %do cyc_year = &syr. %to &eyr.;

    libname lib_&cyc_year. "&PII_PREFIX.&cyc_year.&PII_SUFFIX.";

    ...

%mend;

 

 

However, when my program runs, I get the following error: 

ERROR: Create of library LIB_2020 failed.
ERROR: Error in the LIBNAME statement.
ERROR: Libref LIB_2020 is not assigned.

 

I feel like there is some syntax error here, but I honestly have no clue . . . help?

 

 

9 REPLIES 9
ballardw
Super User

I don't see a problem with the libname statement shown.

Add this code before where you run the macro, or a simpler version that ONLY generates the libname calls:

options mprint;

That will show the libname syntax as generated in more detail.

 

Are you sure that the folder already exists? You may want the system option DLCREATEDIR set if you are attempting to  use Libname statements to create libraries if the folder has not been made prior to running the macro.

Cynthia_sas
SAS Super FREQ

Hi:

  Well, there are a few issues that I see. The first one is that you should have %GLOBAL as the declaration statement and you need %LET to assign a value to the variable. As an example, this worked for me. I just used %PUT statements inside the macro program as proof that the values were being built correctly. I did not have any need to issue multiple LIBNAME statements:

Cynthia_sas_0-1679079413303.png

Hope this helps point you in the right direction.

Cynthia

Tom
Super User Tom
Super User

Why would adding %GLOBAL statement in the macro make any difference in how the posted code works?

 

If the macro variables did not already exist when the macro ran then that would just create them with empty values.

If they already existed in the GLOBAL scope then the %GLOBAL statement does nothing.

And if they already existed in the LOCAL scope of some macro that called the macro in question then the %GLOBAL statement will cause an error.

 

Adding a %GLOBAL statement to a macro definition is only of value for macro variables that you want the macro to create and assign values to that will remain available after the macro finishes running.  It serve no real purpose for macro variables that the macro is just going to reference (other than perhaps some documentation to other users about what the source of those macro variable should be).

Cynthia_sas
SAS Super FREQ
You're right. Adding the %GLOBAL doesn't make a difference. However, the posted syntax was wrong, so that was my only purpose.
Cynthia
Tom
Super User Tom
Super User

The posted code was fine. 

 

Were you confused by the inclusion of the lines from the LOG of the output of a %PUT dump of the symbol tables?

2218  %put _global_;
GLOBAL ABC Value of ABC
...
yabwon
Onyx | Level 15

I changed Drive letter to R, because I don't have S, and tested your code:

1    %let PII_PREFIX = R:\projects\ABCD\Data2\PII\Final\PPSI\PT\;
2    %let PII_SUFFIX=\internal SAF\PII Only;
3
4    %let syr=2020;
5    %let eyr=2021;
6
7    %macro check_program();
8
9      %do cyc_year = &syr. %to &eyr.;
10
11       libname lib_&cyc_year. "&PII_PREFIX.&cyc_year.&PII_SUFFIX.";
12
13       /* ...some code... */
14
15     %end;
16
17     /* ...some code... */
18
19   %mend check_program;
20
21
22   %check_program()
NOTE: Libref LIB_2020 was successfully assigned as follows:
      Engine:        V9
      Physical Name: R:\projects\ABCD\Data2\PII\Final\PPSI\PT\2020\internal SAF\PII Only
NOTE: Libref LIB_2021 was successfully assigned as follows:
      Engine:        V9
      Physical Name: R:\projects\ABCD\Data2\PII\Final\PPSI\PT\2021\internal SAF\PII Only

What you showed us looks good, at least as long as all macro variables are declared correctly.

 

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



SASKiwi
PROC Star

Do you have a really, really good reason for storing your SAS data in yearly folders?! Personally I avoid such complexity like the plague because I see no value in doing it. In your case you wouldn't need a macro loop at all if ALL data years were in:

S:\projects\ABCD\Data2\PII\Final\PPSI\PT\internal SAF\PII Only

 

Quentin
Super User

I thought this was a weird error message.  Even the grammar seems weird: "create of library failed" instead of "creation of library failed."  

 

But I was curious enough to google and found this related post, with a likely answer:

https://communities.sas.com/t5/New-SAS-User/DLCreatedir-not-working/td-p/573583

 

I'm guessing you are using the system option DLCREATEDIR which allows the libname statement to create a directory if it doesn't already exist.  But apparently it's documented that DLCREATEDIR can only create one directory, it can't create multiple directories.  

 

I was able to get the error message.  I have a directory Q:\Junk, but don't have Q:\Junk\NotThere or Q:\Junk\NotThere\NotThere.  I can get your error message with:

4    options dlcreatedir ;
5    libname foo "Q:\junk\NotThere\NotThere" ;
ERROR: Create of library FOO failed.
ERROR: Error in the LIBNAME statement.

In your case, I am guessing that this directory exists:

S:\projects\ABCD\Data2\PII\Final\PPSI\PT

But if you try to execute:

libname foo "S:\projects\ABCD\Data2\PII\Final\PPSI\PT\2020\internal SAF\PII Only";

It will error if the subdirectories \2020 and \internal SAF don't exist.

 

If you have XCMD enabled, you could use MKDIR to create the sub-directories.  Or as a hack, you could have your macro run three separate libname statements in order to create the three directories, i.e. essentially generate.:

libname foo "S:\projects\ABCD\Data2\PII\Final\PPSI\PT\2020\";
libname foo "S:\projects\ABCD\Data2\PII\Final\PPSI\PT\2020\internal SAF";
libname foo "S:\projects\ABCD\Data2\PII\Final\PPSI\PT\2020\internal SAF\PII Only";

As an aside, this is an example of the common situation where debugging a macro is often easier if you start by forgetting about the macro language and just test the SAS code you are trying to generate.  When you try to debug a macro, you're debugging in two languages.  If you test the SAS code and it doesn't work, you only have to debug one language.

 

BASUG is hosting free webinars Next up: Mark Keintz presenting History Carried Forward, Future Carried Back: Mixing Time Series of Differing Frequencies on May 8. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 9 replies
  • 764 views
  • 2 likes
  • 8 in conversation