How to assign a library to the same path as your SAS Enterprise Guide project

19

SAS Enterprise Guide sets values for several useful SAS macro variables when it connects to a SAS session, including one macro variable, &_CLIENTPROJECTPATH, that contains the name and path of the current SAS Enterprise Guide project file.

(To learn about this and other macro variables that SAS Enterprise Guide assigns, look in Help->SAS Enterprise Guide help, and search the Index for "macro variables".)

If your SAS program knows the path of your project file, then you can use that information to make your project more "portable", and reference data resources using paths that are relative to the project location, instead of having to hard-code absolute paths into your program.

For example, I've been working with some data from DonorsChoose.org, and I've captured that work in a project file. After saving the project, I can easily get the name of the project file by checking the value of &_CLIENTPROJECTPATH:

15    %put &_clientprojectpath;
'C:\DataSources\DonorsChoose\DonorsChoose.egp'

If you can get the full path of the project file, then you can build that information into a SAS program so that as you move the project file and its "assets" (such as data), you don't need to make changes to the project to accommodate a new project folder "home". Here is the bit of code that takes the project file location and distills a path from it, and then uses it to assign a path-based SAS library.
/* a bit of code to detect the local project path                          */
/* NOTE: &_CLIENTPROJECTPATH is set only if you saved the project already! */
%let localProjectPath =
%sysfunc(substr(%sysfunc(dequote(&_CLIENTPROJECTPATH)), 1,
%sysfunc(findc(%sysfunc(dequote(&_CLIENTPROJECTPATH)), %str(/), -255 )))); 

libname DC "&localProjectPath";

Here's the output:
21  libname DC "&localProjectPath";
NOTE: Libref DC was successfully assigned as follows:
Engine:        V9
Physical Name: C:\DataSources\DonorsChoose

This allows me to keep the project together with the data that it consumes and creates. And I can easily share the project and data with a colleague, who can store it in a different folder on his/her machine, and it should work just the same without any changes.

Share

About Author

Chris Hemedinger

Director, SAS User Engagement

+Chris Hemedinger is the Director of SAS User Engagement, which includes our SAS Communities and SAS User Groups. Since 1993, Chris has worked for SAS as an author, a software developer, an R&D manager and a consultant. Inexplicably, Chris is still coasting on the limited fame he earned as an author of SAS For Dummies

19 Comments

  1. Andrew Howell on

    Hi Chris,

    This works fine if EG & SAS are on the same PC (or at least map the same way to the same folder).

    What are suggestions when EG & the underlying SAS are on different platforms and/or don't map to same folder?

    For example:
    - EG on the PC connecting to SAS on Unix
    - EG project on a PC's mapped "Z:" drive connecting to SAS on a WIndows server where the equivalent folder is "D:"?

    Cheers.

  2. Tricia Aanderud on

    Yeah. I guess the problem is that the .egp is a PC format and it just will not translate to Unix in the desired way.

    But awesome tip Chris!!

  3. Actually, it can work IF you save the project to the server file system. For example, File->Save As, choose SASApp (your server), Files, and navigate to a file folder on the remote SAS server.

    In that case _CLIENTPROJECTPATH is set to the path and name on the remote server, even if it's Unix. For example:

    23 %put &_clientprojectpath;
    '/r/server.unx.sas.com/vol/vol910/u91/sascrh/projects/SampleCars.egp'

  4. Pingback: Special automatic macro variables available in SAS Enterprise Guide - The SAS Dummy

  5. What do I do wrong? Part of the log:
    15 %let localProjectPath =
    16 %sysfunc(substr(%sysfunc(dequote(&_CLIENTPROJECTPATH)), 1,
    WARNING: Argument 3 to function SUBSTR referenced by the %SYSFUNC or %QSYSFUNC macro function
    is out of range.
    17 %sysfunc(findc(%sysfunc(dequote(&_CLIENTPROJECTPATH)), %str(/), -25 ))));
    18
    19 libname DC "&localProjectPath";
    NOTE: Libref DC was successfully assigned as follows:
    Engine: V9
    Physical Name: C:\Windows\system32\

  6. Now I ran it with SASApp but still the wrong path:

    WARNING: Argument 3 to function SUBSTR referenced by the %SYSFUNC or %QSYSFUNC macro function is out
    of range.
    17 %sysfunc(findc(%sysfunc(dequote(&_CLIENTPROJECTPATH)), %str(/), -255 ))));
    18
    19 libname DC "&localProjectPath";
    NOTE: Libref DC was successfully assigned as follows:
    Engine: V9
    Physical Name: E:\SAS\Config\Lev1\SASApp\

    • Chris Hemedinger
      Chris Hemedinger on

      The CLIENTPROJECTPATH macro yields the folder name for the EGP file on your local machine. That means if your SAS workspace is remote, then you won't be able to use that path in your programs this way.

      See this list of other macro variables that might be helpful for your SAS programs.

      • Hi, I had the same problem as Hend. For me, the solution was to change '%str(/)' in '%str(\)'.

        This solved the warning and pointed localProjecPath to the right location.

        With '%str(/)' same problem

        NOTE: Libref DC was successfully assigned as follows: Engine: V9 Physical Name: C:\Windows\system32\

        With '%str($$' problem solved
        NOTE: Libref DC was successfully assigned as follows: Engine: V9 Physical Name: \\NAS\Test

        With this problem solved it works great! So many thanks Chris!!

        Another solution I found was to use environment variables

        Code:
        options set=localProjectPath '\\NAS\Test' ; libname DC "!localProjectPath";
        Result:

        NOTE: Libref DC was successfully assigned as follows: Engine: V9 Physical Name: \\NAS\Test

        • I have just come to the same conclusion myself. I was just about to post a comment about it. Perhaps I should have also read the comments before spending time trying to figure out why it wasn't working for me.

  7. Hi there,
    Thanks a lot for the tips on how to get the full path of the project file.
    Is it possible to get the path of the folder that is one level above the project file?
    (I would like use this to make paths relative to this "higher" folder level and retrieve data in several subfolders).
    For example,
    my project file is in:
    C:\MyExperiments\E1056_Imaging\180106_imaging_brain\01_SAS_identification.egp
    and I would like to get the path (and use it as libname):
    C:\MyExperiments\E1056_Imaging\

    Cheers.

    • Chris Hemedinger
      Chris Hemedinger on

      Your approach depends on whether you're working forward from a root path to a certain level, or backwards from the file path to a certain level. Here's an example of working forward from a root path, using CALL SCAN to find the right cutoff level.

      data _null_;
       length name $ 255;
       name = dequote(&_clientprojectpath);
       call scan (name,4,cutoff,length,'\');
       path = substr(name,1,cutoff-1);
       call symput('libpath',path);
      run;
      %put &libpath;
      libname source "&libpath.";
      

  8. Thank you Chris!
    Your tip/code has partly solved my problem.
    I modified call scan to make use of a negative count (using -2 instead of 4); this gets me the libpath that I need.
    However, when I now use &libpath to import a text file, for example datafile= "&libpath\180106_imaging_brain\test1.tab",
    then I get the error message: "File Name value exceeds maximum length of 201 characters".
    I tried modifying the code (incl. changing $ 255), but without success.

    Can you please recommend me what to do to import the (simple) .tab file?
    using the relative path.

    Thanks!

    • Chris Hemedinger
      Chris Hemedinger on

      Try using the FILENAME statement instead of the path in PROC IMPORT, like this:

      filename in "&libpath\180106_imaging_brain\test1.tab";
      proc import
       datafile=in
       /* remainder of step */
      

  9. Hi again,

    Here is the code and the log (now giving another error):

    code-------------
    data _null_;
    length name $ 255;
    name = dequote(&_clientprojectpath);
    call scan (name,-2,cutoff,length,'\');
    path = substr(name,1,cutoff-1);
    call symput('libpath',path);
    run;
    %put &libpath;
    libname source "&libpath.";

    filename in "&libpath\180106_imaging_brain\test1.tab";
    proc import
    datafile=in
    dbms=tab replace;
    getnames=yes;
    run;
    -------------

    log (part of)-------------
    NOTE: Libref SOURCE was successfully assigned as follows:
    Engine: V9
    Physical Name: C:\000000_MyStuff\Experiments 1000-1099\E1056_LipidImaging_with_shane
    29
    30
    31 filename in "&libpath\180106_imaging_brain\test1.tab";
    WARNING: The quoted string currently being processed has become more than 262 characters long. You might have unbalanced quotation
    marks.
    WARNING: The quoted string currently being processed has become more than 262 characters long. You might have unbalanced quotation
    marks.
    ERROR: Invalid physical name.
    ERROR: Error in the FILENAME statement.
    32 proc import
    33 datafile=in
    34 /* remainder of step */
    35 dbms=tab replace;
    ERROR: Output SAS data set must be provided.
    NOTE: The SAS System stopped processing this step because of errors.
    -------------

    When I locate the absolute path (of the .egp file) with your %sysfunc example, then I have no problem executing the PROC IMPORT step (with datafile= "&libpath\test1.tab").
    Why is this now different?

    Thank you very for your help!

    C.

    • Chris Hemedinger
      Chris Hemedinger on

      I think you might have trailing blanks in the &libpath. name. Try changing the CALL SYMPUT to CALL SYMPUTX -- a good practice anyway.

  10. Is there an equivalent for a stored process? CLIENTPROJECTPATH isn't available. Maybe I just need to hard code it.

    • Chris Hemedinger
      Chris Hemedinger on

      Tom, even when running the stored process in EG, usually it's running on a stored process server, and so does not have the same Workspace server context. So yes, you might need to hard-code or come up with another approach. Check the details of the stored process log to see all of the available macro vars. Maybe include a %PUT _ALL_ (temporarily) in your stored process to see what's available.

      • Tom Vincent on

        I ended up doing this (when running as a SP, it uses _PROGRAM):
        %if %symexist(_clientprojectpath) %then %let inpath = &_clientprojectpath;
        %if %symexist(_PROGRAM) %then %let inpath = &_PROGRAM;

Back to Top