I am trying to establish a libname by piecing together three different macros.
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?
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:
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.
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:
Hope this helps point you in the right direction.
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).
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.
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
For this to work, your SAS needs to run on a Windows computer having the S: drive mounted. Have you verified that?
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:
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:
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.
Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.
If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website.
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.