Inspecting SAS macro variables in SAS Enterprise Guide

The SAS macro variable "inspector" is a custom task that plugs into SAS Enterprise Guide 4.3. You can use it to view the current values for all SAS macro variables that are defined within your SAS session. You can also evaluate "immediate" macro expressions in a convenient quick view window. If you develop or run SAS macro programs, this task can be a valuable debugging and learning tool.

UPDATE 28Nov2011: I've received several comments about this task, both here on the blog and in e-mail. Based on some of your very good suggestions, I've updated the task with additional features. If you downloaded the task before 28Nov2011, you might want to refresh your copy.

UPDATE 16Dec2011: The download package for this task now also includes a SAS Options viewer task, described on this separate blog post.

I've been working with SAS macros quite a bit lately, and I decided that a task like this could come in handy as a sort of "watch" window for macro values. I built the task using the custom task APIs and Microsoft .NET. I hope that you find the task useful. If you try it out and have suggestions for how to make it better, please share by adding a comment to the blog.

The custom task and an accompanying README.pdf file (containing description and detailed installation instructions) are available for download in this ZIP file. Installation is simple: copy the DLL to a designated folder on your PC, and SAS Enterprise Guide will detect the task automatically.

This add-in offers the following main features:

Always-visible window: Once you open the task from the Tools menu, you can leave it open for your entire SAS Enterprise Guide session. The window uses a "modeless" display, so you can still interact with other SAS Enterprise Guide features while the window is visible. This makes it easy to switch between SAS programs and other SAS Enterprise Guide windows and the macro variable viewer to see results.

Select active SAS server: If your SAS environment contains multiple SAS workspace connections, you can switch among the different servers to see macro values on multiple systems.

One-click refresh: Refresh the list of macro variables by clicking on the Refresh button in the toolbar.

View by scope or as a straight list: View the macro variables in their scope categories (for example, Global and Automatic) or as a straight list, sorted by variable name or current value. Click on the column headers to sort the list.

Filter results (NEW!): Type a string of characters in the "Filter results" field, and the list of macro variable results will be instantly filtered to those that contain the sequence that you type. The filtered results will match on variable names as well as values, and the search is case-insensitive. This is a convenient way to narrow the list to just a few variables that you're interested in. To clear the filter, click on the X button next to the "Filter results" field, or "blank out" the text field. (Note: this is in the 28Nov2011 update!)

Set window transparency: You can make the window appear "see-through" so that it doesn't completely obscure your other windows as you work with it.

Copy macro variables as %LET statements: Select one or more macro variables within the window, right-click and select Copy assignments. This generates a series of %LET statements -- one for each macro variable/value pair -- which you can then paste into a SAS program.

Macro expression "quick view": Have you ever wanted to test out a macro expression before using it in a longer program? This window allows you to get immediate feedback on a macro expression, whether a simple macro reference or a more complex expression with nested functions. If the expression generates a SAS warning or error, the feedback window shows that as well. Note: the expression can be any macro expression that is valid for the right-side of a macro variable assignment (%let statement).

More macro productivity in SAS Enterprise Guide is just a few clicks away! Download the task today and let me know what you think!

tags: .net, debugging, macro programming, SAS custom tasks, SAS Enterprise Guide, SAS programming

38 Comments

  1. Posted November 22, 2011 at 8:04 pm | Permalink

    This would be so convenient when trying to troubleshoot what your macro was doing versus what you think it was doing. When you pick up someone else's code this is especially useful.

    I'm anxious to try it.

    Thanks for the tip!

  2. Rudolf
    Posted November 23, 2011 at 4:26 am | Permalink

    Hi Chris,

    This is great for debugging purposes and very useful, thank you! I have some comments and suggestions:
    - Variables defined as %local in a Macro are not shown, but this is probably expected behavior because you cannot evaluate them outside the macro?
    - A search text field would be a nice addition to limit the list of variables. so for instance, when the user types 'TMP' all variables are shown that have 'TMP' in the name.
    - 'Toggle groups' is not remenbered when you click 'Refresh', it always switches back to the group view.

    Rudolf.

    • Chris Hemedinger Chris Hemedinger
      Posted November 23, 2011 at 8:44 am | Permalink

      Rudolf, these are great suggestions!

      Yes, you're correct that %local variables won't show, because they are, by definition, out of scope with the way this tool operates. I had a plan for the "search" field, as well as to fix the toggle groups setting. I decided to leave those options for "version 2". It's great to hear you suggest them though, as that validates the ideas I've yet to implement...

    • Chris Hemedinger Chris Hemedinger
      Posted November 28, 2011 at 12:30 pm | Permalink

      Rudolf, I've updated the task with your suggested features. Grab a new copy and tell me what you think!

      • Rudolf
        Posted November 29, 2011 at 3:34 am | Permalink

        Wow that's quick, thanks!

  3. Ronan
    Posted November 23, 2011 at 5:55 am | Permalink

    Hi Chris,

    Thanks a lot, this nice feature should now be part of EG. Very helpful and well-designed. I like very much the inspector display in a "floating" window : a real value add-on imho. Will definitively replace the tedious "%put _all_" line I'm used to type.

    Ronan

  4. Andreas
    Posted November 23, 2011 at 2:14 pm | Permalink

    Here are my suggestions:
    - fix the following bug: click 'toggle groups', sort the view by clicking on column header 'Macro variable', click 'toggle groups' again and the content of the view completely disappears.
    - add another column with the variable scope. When the variables are not grouped by scope, you don't know the actual scope.
    - add an option to hide automatic global variables which are used by EG like _client*.
    - you could also add some information which Macros are already compiled in your session. You can get that information from the SQL Dictionary Tables:
    proc sql;
    create table info as
    select *
    from dictionary.catalogs
    where objtype = "MACRO";
    quit;

    - the same addin would be nice for SAS Options. It would be nice if i could see the SAS options effecting my current session without writing some SAS Code with proc options or querying the Dictionary/SASHELP Views.

    - last but not least i would really like to see the .net source code of this addin. Is there any chance to contribute to some nice addins like this? If the source was public i think some people like me would be willing to fix some bugs and help to enhance the addin.

    Andreas

    • Chris Hemedinger Chris Hemedinger
      Posted November 28, 2011 at 12:29 pm | Permalink

      Andreas, I've added a few of your suggestions. Be sure to grab an updated copy of the task. Your other ideas are very good as well. I hope to respond to those in a future post.

    • Chris Hemedinger Chris Hemedinger
      Posted December 16, 2011 at 4:57 pm | Permalink

      Andreas, I've just released a version of an Options viewer task. Check it out and let me know how it works for you.

  5. Posted November 24, 2011 at 9:32 am | Permalink

    Nice job Chris, extremely useful, especially with the ability to evaluate macro expressions on the fly. I like the suggestions others have made too. In my opinion EG is fast becoming the tool of choice for the SAS programmer....

  6. Posted November 24, 2011 at 1:34 pm | Permalink

    Chris
    this is great!
    It replaces the first thing I would set up in a DM environment - a customized FSview of a customised sashelp.vmacro!
    And it provides the macro expression evaluator!

  7. Mark Jordan Mark Jordan
    Posted November 28, 2011 at 10:21 am | Permalink

    Chris - this is a VERY useful tool! Thanks for sharing it.

  8. Stacey Syphus Stacey
    Posted December 1, 2011 at 2:44 am | Permalink

    Hey Chris! I just happened to be teaching our macro course this week to a bunch of EG users... How timely! Can't wait to show them this task.

  9. Thomas
    Posted December 2, 2011 at 5:42 am | Permalink

    Thank you Chris for this handy tool!
    One question, which permissions are required by the tool? It works flawlessly when connected to our dev-system but will only show automatic variables when connected to the prod-system?

    br Thomas

    • Chris Hemedinger Chris Hemedinger
      Posted December 2, 2011 at 9:15 am | Permalink

      Thomas, the tool queries the SASHELP.VMACRO view to retrieve the current values for all macro variables. No special permissions are necessary. However, if you invoke the tool as the first task before doing any other operation on the SAS session, you should know that no EG-specific autoexec or initialization code has been run yet. If you submit a small program and then refresh the macro viewer, you'll see some additional values.

      If it still seems to have problems, let me know. A report of what's in SASHELP.VMACRO would help to diagnose, in case the task is somehow misinterpreting the results of the query.

  10. Karin Gross
    Posted December 2, 2011 at 6:21 am | Permalink

    Hi Chris, I'm just teaching PRG1 in the EG environment and the customers have to submit lots of code with predefined macro variables. We have already found a mistake... Thank you, this is really helpful and we all enjoy this supporting tool!

  11. Venkata R Potluri
    Posted April 9, 2012 at 11:54 pm | Permalink

    Hi Chris,
    Taking SAS EG Custom tasks as example. I have build a SAS EG Custom Task Addin.
    Which is working fine. I'm sure SAS custom built Tasks are going to change the way you can work with SAS EG. I just want to expand its functionality. Can you please tell me how to messages to SAS EG Task Status.

    • Chris Hemedinger Chris Hemedinger
      Posted April 10, 2012 at 8:07 am | Permalink

      Venkata,

      I assume that you mean that you want to update the task status window that you see when you select View->Task Status.

      There are two ways to update that content. When running a SAS program, you can use the SYSECHO statement to annotate your SAS code. As the statements execute, the comments you add to SYSECHO will appear in the status window. This approach is discussed more in Tracking progress in SAS programs in SAS Enterprise Guide.

      Within a custom task that "does its own work", without running a SAS program, there is another way to update the status window. The task should implement ISASTaskExecution, which allows EG to "delegate" the ability to "run yourself" to the task. The custom tasks API page has an example that you can download: Custom Execution and Results.

      But while this example shows how a task can run its own custom operation, it does not show how to update the status window. To update the status window, you must implement ISASTaskExecution2 (instead of ISASTaskExecution) and raise an event to the application.

      In your task class, add this handler:

      private event TaskExecutionStatusChangedHandler _statusChanged = null;
      public event TaskExecutionStatusChangedHandler StatusChanged
      {
        add { _statusChanged += value; }
        remove { _statusChanged -= value; }
      }
      

      Then in your task's Run method, periodically update the status during the task's operation, like this:

      // raise the event for the application status window
      if (_statusChanged != null)
          _statusChanged(this, new TaskExecutionStatusEventArgs("Accessing records from database"));
      
      • Venkata R Potluri
        Posted April 12, 2012 at 11:40 pm | Permalink

        Thank you very much for your response.
        I'm not a C sharp Programmer I'm a Visual basic person.
        Still I hope I can understand and do what I want to do.
        Basically I build a PCA tool which takes user inputs to run
        Post Camapaign Analysi and output results to Excel Templates ,
        for Market Analyics team.

      • Venkata R Potluri
        Posted April 13, 2012 at 9:11 pm | Permalink

        Hi Chris,
        Thank you for the response.
        May be until your book on Developing Custom Tasks for SAS EG is in the market
        I may ask you few questions through this blog. Once again thank you very much you are very helpful.
        When I'm submitting SAS Code I'm using model.SubmitSASProgramAndWait to make my application work right. If use model.SubmitSASProgram I'm not achieving the result as I want. Because of this the screen looks frozen until SAS program is executed fully and user gets confused , is there any way that I can show Application.UseWaitCursor = False while my sas program is executing and still I can use model.SubmitSASProgramAndWait . You help in this regard is highly appreciated.

        Ramana

        • Chris Hemedinger Chris Hemedinger
          Posted April 16, 2012 at 1:00 pm | Permalink

          Ramana,
          If you want the UI to remain responsive (not frozen), you must use the asynchronous approach: SubmitSasProgram(). When using the async approach, you must take care to redirect any UI update operations back to the main UI thread.

          Here is a snippet of an example:

           private void btnRunAsync_Click(object sender, EventArgs e)
           {
            // use your SAS program here
            string sasProgram = "proc options; run;"
            SasSubmitter submitter = new SasSubmitter(
              Consumer.AssignedServer
              );
            submitter.SubmitSasProgramComplete += 
                new SubmitCompleteHandler(
                    submitter_SubmitSasProgramComplete);
            submitter.SubmitSasProgram(
                sasProgram,
                "Running custom program");
           }
          
           /// 
           /// This event might be raised on a non-UI, non-STA thread.
           /// 
           void submitter_SubmitSasProgramComplete(object sender, 
             SubmitCompleteEventArgs args)
           {
               if (args.Success)
               {
                   // marshal back to the UI thread
                   this.BeginInvoke(new MethodInvoker(
                     delegate() { YourMethodToUpdateUI(); }
                     ));
               }
               else
               {
                   // marshal back to the UI thread
                   this.BeginInvoke(new MethodInvoker(
                    delegate() { ShowLog(args.Log); }
                    ));
               }
           }
          
          private void ShowLog(string log)
          {
              SAS.Tasks.Toolkit.Controls.SASLogViewDialog dlg =
                  new SASLogViewDialog("Errors", "", log);
              dlg.ShowDialog(this);
          }
          
          
          • Venkata R Potluri
            Posted May 23, 2012 at 4:59 pm | Permalink

            Hi Chris,
            Thank you for all the help. Can you please tell me if there is way to assign the value of a macro variable to vb variable straight away with out much coding and work arounds.I mean some thing like this
            dim VBVar as string = .....some statement(&SASMacroVar) ........
            With regards
            Ramana

          • Venkata R Potluri
            Posted May 24, 2012 at 7:01 pm | Permalink

            Hi Chris,
            How can I run task in SAS EG repeatedly?

            With regards

            Ramana

          • Chris Hemedinger Chris Hemedinger
            Posted May 25, 2012 at 8:26 am | Permalink

            Ramana, are you looking for a type of "loop" construct? There isn't one in the EG user interface. But you can use EG automation to accomplish this from script.

  12. Christian Kjeldsen
    Posted May 7, 2012 at 5:58 am | Permalink

    Hi Chris

    Thanks a lot for all your work in educating the rest of us. I have been going through some of the examples on the official SAS support site, however, I find it quite difficult to obtain an overview of what the SAS.Tasks.Toolkit contains and how to use it. The examples shows some ways, but I am sure it may do a lot more than what these examples show. Unfortunately I haven't been able to find a description of the SAS.Tasks.Toolkit, so it is quite a lot of trial-and-error (and especially error) when starting developing my own custom tasks. So do you know a good reference for SAS.Tasks.Toolkit? Maybe that will be a part of your book, however, until that is out on the market, I hope you know where I can get more information.

    Just one of the problem I have, is that I would like to develop an add-in, which will appear in its own category in Tools->Add-In (Like you have "Programmer Utilities"). However, when I set this.TaskCategory in the InitializeComponent method to something I would like, then it still won't appear in EG. I have tried to set [SASTaskCategory("...")] annotation as well, but I still can't make it create the level. Maybe you can help on this particular detail.

    Again thanks for all your work. It is highly appreciated!

    Christian Kjeldsen

    • Chris Hemedinger Chris Hemedinger
      Posted May 8, 2012 at 8:33 am | Permalink

      Christian,

      Here is a high-level overview of what the task toolkit does for you:
      - Makes it easy to implement the custom task interfaces. The SAS.Task.Toolkit.SasTask class implements most of what you need from ISASTask, ISASTaskDescription, and ISASTaskAddIn. Hundreds of lines of code can be reduced to just a handful.
      - Provides easy access to SAS-related objects. The SAS.Task.Toolkit.SasServer class provides a useful model of your SAS workspace, and several classes in the SAS.Task.Toolkit.Data namespace allow you to access SAS data, libraries, columns, and even SAS catalogs.
      - Provides access to SAS services, such as submitting programs. Classes and methods within the toolkit make it easy to submit SAS programs, synchronously or asynchronously, and collect the SAS log and the results from those programs.
      - Provides a library of useful user interface controls. The toolkit includes common controls that tasks can use to navigate data sources, display SAS programs, and more. (These controls are implemented using Windows Forms in SAS Enterprise Guide 4.2, 4.3., and 5.1).

      Yes, there is more information in my forthcoming book, which is now in the tech review stage. For your particular issue, what you want to do is set the TaskCategory property in the Designer view of the task class (the SasTask-derived class that implements your main task). Note that the menu grouping *does not* appear unless at least two tasks share the same category.

      • Christian Kjeldsen
        Posted May 9, 2012 at 12:17 pm | Permalink

        Hi Chris

        Thanks for the answer. I guess it is mainly an overview of how and when to use the methods of the SAS.Tasks.Toolkit I need. However, I know it is dificult to do that, without a complete book. But I am sure, that when your book hits the market, it will come in handy.

        It was the feature of two tasks having to share the same category before the menu grouping appears that casued my confusion. Thanks for making that clear.

        Christian Kjeldsen

  13. Ramana Potluri
    Posted May 26, 2012 at 12:26 pm | Permalink

    Hi Chris,
    Thank you for all the help. Can you please tell me if there is way to assign the value of a macro variable to vb variable straight away with out much coding and work arounds.I mean some thing like this
    dim VBVar as string = .....some statement(&SASMacroVar) ........
    With regards
    Ramana

    • Chris Hemedinger Chris Hemedinger
      Posted May 29, 2012 at 2:59 pm | Permalink

      Ramana,

      Yes, you can do this with very little code in Visual Basic by using the SAS.Tasks.Toolkit.SasServer class:

      Dim value As String
      Dim server As SasServer
      server = New SasServer("SASApp")
      value = server.GetSasMacroValue("MYMACROVARIABLE")
      

      Note that you supply the macro variable name, but don't reference it with the ampersand.

      • Venkata R Potluri
        Posted May 29, 2012 at 4:15 pm | Permalink

        Hi Chris,
        Thank you very much.
        I guess this is possible only for global variables?
        I'm just waiting for your book to come out.Can you please
        when it is comming out?
        With regards
        Ramana

        Ramana

        • Chris Hemedinger Chris Hemedinger
          Posted May 29, 2012 at 4:22 pm | Permalink

          Ramana,
          Yes, this approach works only for GLOBAL or AUTOMATIC variables. LOCAL macro variables are scoped only within the actual macro processing, and your custom task wouldn't be able to inject any processing/queries while that's happening.

          The book is just finished with tech review (thanks to my team of reviewers), and I'm working on incorporating the feedback and finalizing content. I hope that it will be published by the end of year. In the meantime, I'm willing to help you and others with questions here.

          • Venkata R Potluri
            Posted May 30, 2012 at 3:40 pm | Permalink

            Hi Chris,
            Thank you for all your help.
            Every time I open my SAS addon that I have developed is looking for some data avaialable to open. Is it possible to by pass this or is this a default behaviour for SAS addons.

            With regards

            Ramana

          • Chris Hemedinger Chris Hemedinger
            Posted May 30, 2012 at 3:45 pm | Permalink

            Yes, it's easy to change this.

            At the top of the task class (inherited from SasTask), you should see an attribute that indicates "InputRequired". In Visual Basic it looks like this:

            <InputRequired(InputResourceType.Data)>
            

            Change it to:

            <InputRequired(InputResourceType.None)>
            
  14. Michael Bogdan
    Posted July 11, 2012 at 9:53 am | Permalink

    Hi Chris,
    I'm curious if the SAS Macro Variable Viewer works with Enterprise Guide 5.1. Could you let us know where to copy the DLL file? Thanks!

    • Chris Hemedinger Chris Hemedinger
      Posted July 11, 2012 at 3:50 pm | Permalink

      Yes, it should work with 5.1 - in my tests it does. Copy the same DLL to %appdata%\SAS\EnterpriseGuide\5.1\Custom.

  15. Ravi Lele
    Posted February 19, 2013 at 3:25 am | Permalink

    I have an issue while refreshing the workbook using v5.1, which was not in v4.3
    The issue is when i call sas.Refresh in a macro, refresh process starts (there appears a popup having name of the process SAS currently working on), but macro continues is next code, it does not wait for the refresh process to complete.

    please help me with this issue.

    Regards,

10 Trackbacks

  1. [...] the heels of the release of the popular SAS macro variable viewer that I released last month, I'm providing another custom task that I hope will prove useful. This one is a SAS options viewer, [...]

  2. [...] Inspecting SAS macro variables in SAS Enterprise Guide This post is just a month old, but I've been very happy with the engagement: lots of comments and tweets. "Custom tasks" are one of my favorite topics, and my hope is that this macro viewer task (and a more recent SAS options viewer) will help long-time SAS users to appreciate the capabilities of SAS Enterprise Guide. [...]

  3. [...] I run just these statements in SAS Enterprise Guide, I can use my SAS Macro Variable Viewer to see how my macro variables were [...]

  4. [...] accompanying image shows the resulting macro variables in the SAS Macro Variable Viewer, neatly collated in numerical order. (Remember that if you do add the leading zeros, you may need [...]

  5. [...] you can easily see all of the available macro variables, along with their current values, by using the SAS Macro Variable viewer custom task. tags: macro programming, SAS Enterprise Guide Bookmark on Delicious Digg this post Recommend on [...]

  6. [...] SAS Macro Variable Viewer - a window to view all of your SAS macro variables. Also includes a tool to evaluate macro expressions instantly. [...]

  7. [...] to be useful as-is, and not just theoretical exercises. Here are a few that you should try: SAS Macro Variable Viewer, SAS System Options Viewer, Copy Files task, and the Top N [...]

  8. [...] and install? These tasks provide all sorts of capabilities, including new analysis and reports, productivity tools for programmers and utilities that help you to manage your projects. Many of these tasks also work with the SAS [...]

  9. [...] SAS Macro Variable Viewer [...]

  10. [...] illustrate, I used another popular custom task -- the SAS Macro Variable Viewer -- to show the inner value of a SAS macro variable: Notice the funky arrow characters. Is that what [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <p> <pre lang="" line="" escaped=""> <q cite=""> <strike> <strong>