<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The SAS Dummy</title>
	<atom:link href="https://blogs.sas.com/content/sasdummy/feed/" rel="self" type="application/rss+xml" />
	<link>https://blogs.sas.com/content/sasdummy/</link>
	<description>A SAS® blog for the rest of us</description>
	<lastBuildDate>Tue, 31 Mar 2026 15:05:34 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6</generator>
	<item>
		<title>Using SAS with Microsoft 365 (OneDrive, Teams, and SharePoint)</title>
		<link>https://blogs.sas.com/content/sasdummy/2026/02/02/sas-programming-office-365-onedrive/</link>
					<comments>https://blogs.sas.com/content/sasdummy/2026/02/02/sas-programming-office-365-onedrive/#comments</comments>
		
		<dc:creator><![CDATA[Chris Hemedinger]]></dc:creator>
		<pubDate>Mon, 02 Feb 2026 12:00:33 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Developers]]></category>
		<category><![CDATA[Microsoft Office 365]]></category>
		<category><![CDATA[OAuth2]]></category>
		<category><![CDATA[OneDrive]]></category>
		<category><![CDATA[PROC HTTP]]></category>
		<category><![CDATA[REST API]]></category>
		<category><![CDATA[SharePoint]]></category>
		<guid isPermaLink="false">https://blogs.sas.com/content/sasdummy/?p=6683</guid>

					<description><![CDATA[<p>Learn how to use SAS code (PROC HTTP) to read and write files from your Microsoft OneDrive, Microsoft Teams or SharePoint Online. You'll learn how to create a Microsoft Office 365 app, connect to it with SAS, and automate the integration with your office productivity environment.</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2026/02/02/sas-programming-office-365-onedrive/">Using SAS with Microsoft 365 (OneDrive, Teams, and SharePoint)</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>If your work environment is like ours here at SAS, you're seeing more of your data and applications move to the cloud.  It's not yet a complete replacement for having local files on your desktop machine, but with cloud storage and apps -- like Microsoft OneDrive -- I can now access my work documents from any browser and any device, including my smartphone.  I can update now my spreadsheets while waiting in the dentist office. Oh joy.</p>
<p>For those of us who use SAS to read and create Microsoft Excel documents, cloud-based files can add an extra wrinkle when we automate the process.  It also adds some exciting possibilities!  The Microsoft 365 suite offers APIs to discover, fetch, and update our documents using code.  In this article, I'll show you how to use SAS programs to reach into your Microsoft OneDrive (or SharePoint Online) cloud to read and update your files.  <strong>Note:</strong> All of this assumes that you already have a Microsoft 365 account -- perhaps provisioned by your IT support team -- and that you're using it to manage your documents.</p>
<p>This article helps you to connect your SAS program code to Microsoft 365. If what you <em>really want to do</em> is connect your Microsoft 365 applications (Excel, PowerPoint, etc.) to SAS with "point-and-click", then <a href="https://support.sas.com/en/software/microsoft-365.html">check out SAS for Microsoft 365</a>, which you can use to work with SAS Viya content in your favorite Office apps.</p>
<h2>A SAS macro library to help with the basics</h2>
<p><em><strong>UPDATE 02Feb2026</strong>: I updated this article to address recent changes in the Microsoft authentication flow, and to introduce instructions/support for a Device Code flow option. You'll find reference implementations in PowerShell and SAS code in <a href="https://github.com/sascommunities/sas-microsoft-graph-api">my GitHub repository</a></em></p>
<p>For most SAS users, the main goal is to be able to list files and folders in Microsoft 365, download any file to SAS, and upload files from SAS to SharePoint or OneDrive. If that's your situation, then I've got you covered with some SAS macros that hide much of the complexity.</p>
<p>I've <a href="https://github.com/sascommunities/sas-microsoft-graph-api">created this project on GitHub with SAS macros to automate the most common tasks</a>. You will still need to complete Step 1 and Step 2 as described in this article, but after that the macros help with the most common tasks. I've recorded a <a href="https://communities.sas.com/t5/SAS-Viya-Workbench-Getting/Demo-SAS-Viya-Workbench-and-SAS-code-to-access-Microsoft-365/ta-p/952476">special video that shows how to get started with these macros</a>. (The video features SAS Viya Workbench, but you do not need SAS Viya Workbench or any other specialized SAS products to use this technique.)</p>
<p>These macros include logic to manage some of the trickier aspects of the Microsoft Graph API:</p>
<ul>
<li>They provide a way to manage your access token and credentials safely, whether you store them in a secure file (SAS 9 or SAS Viya) or in SAS Content folders (SAS Viya only).
</li>
<li>The routines to list folders and files will include <b>all items</b> in the collections. The Microsoft Graph APIs return a maximum of 200 items with each call, but these macros detect this situation and will make multiple calls to retrieve the full set.
</li>
<li>When publishing content from SAS to a OneDrive or SharePoint folder, the method for <b>uploading</b> files is complex. For large files, the API requires that you create an "upload session" and split the file into chunks. Each chunk is uploaded via an API call and then reassembled on the other side. These SAS macros manage the file splitting, upload session, and iterative upload requests until the file publish is complete. (Learn more about <a href="https://blogs.sas.com/content/sasdummy/2024/01/28/split-file-using-sas/">the file splitting technique in this article</a>.)
</li>
</ul>
<p>You can study the code in these macros to implement in your own way, or you can simply use them "as-is" for these common operations. This article uses this macro library in its examples.</p>
<h2>Learning more about how to connect SAS to Microsoft 365</h2>
<p><strong>Note: </strong>I've updated this article several times to include detailed steps and "gotchas." I've added use cases for SharePoint Online and Microsoft Teams.  <a href="https://communities.sas.com/t5/SAS-Communities-Library/How-to-use-SAS-to-access-Microsoft-365/ta-p/667869" rel="noopener noreferrer" target="_blank">I also recorded a 25-minute video</a> (posted on SAS Support Communities) that shows all of the steps that I followed.  </p>
<figure id="attachment_7012" aria-describedby="caption-attachment-7012" style="width: 300px" class="wp-caption alignnone"><a href="https://communities.sas.com/t5/SAS-Communities-Library/How-to-use-SAS-to-access-Microsoft-365/ta-p/667869"><img fetchpriority="high" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2018/11/ms365_video-300x180.png" alt="" width="300" height="180" class="size-medium wp-image-7012" srcset="https://blogs.sas.com/content/sasdummy/files/2018/11/ms365_video-300x180.png 300w, https://blogs.sas.com/content/sasdummy/files/2018/11/ms365_video-1024x616.png 1024w, https://blogs.sas.com/content/sasdummy/files/2018/11/ms365_video.png 1295w" sizes="(max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-7012" class="wp-caption-text">Click to watch the video tutorial.</figcaption></figure>
<p>You can also <a href="https://www.sas.com/en_us/webinars/sas-microsoft365-programming-approach.html">watch this Ask the Expert webinar</a> to learn everything that I discuss here, and see demonstrations of the techniques in action.</p>
<h2>Using SAS with Microsoft 365: an overview</h2>
<p>Microsoft 365 uses an OAuth2-style authentication flow to grant access and permissions to third-party apps.  If you're accustomed to the simpler style of just user/password authentication (ah, those were the days), OAuth2 can be intimidating.  Joseph Henry does a great <a href="http://support.sas.com/resources/papers/proceedings17/SAS0224-2017.pdf">job of deconstructing OAuth2 -- with code samples -- in this SAS Global Forum paper</a>.</p>
<p>When we're writing SAS programs to access Microsoft OneDrive or SharePoint, we're actually writing a third-party app.  This requires several setup steps, a few of which cannot be automated.  Fortunately, these need to be done just once, or at least infrequently.  Here's an outline of the steps:</p>
<ol>
<li>Register a new client application at <a href="https://portal.azure.com/">the Microsoft Azure Portal</a>.  (You will need to sign in with your Microsoft 365 credentials, which might be your primary organization credentials if you have single-signon with Active Directory.) <b>You can do this just once in your organization</b>; multiple users can connect using the same application!
</li>
<li>Using your browser while you are signed into Microsoft 365, navigate to a special web address to obtain an authorization code for your application.
</li>
<li>With your authorization code in hand, plug this into a SAS program (PROC HTTP step) to retrieve an OAuth2 access token (and a refresh token).
</li>
<li>With the access token, you can now use PROC HTTP and the Microsoft 365 APIs to retrieve your OneDrive folders and files, download files, upload files, and replace files.
</li>
</ol>
<p>You'll have to complete Step 1 just once for your application or project.  Steps 2 and 3 can be done just once, or at least just occasionally.  The access token is valid for a limited time (usually 1 hour), but you can always exchange the refresh token for a new valid access token.  This refresh token step can be automated in your program, usually run just once per session.  Occasionally that refresh token can be revoked (and thus made invalid) when certain events occur (such as you changing your account password).  When that happens, you'll need to repeat steps 2 and 3 to get a new set of access/refresh tokens.</p>
<p>Oh, and by the way, even though the examples in this article are specific to SharePoint and Teams, the exact same authentication flow and steps can be used for all of the Microsoft 365 APIs.  Have fun with OneDrive, Outlook, Teams, Excel, and all of your favorite cloud-based Microsoft apps.</p>
<h2>Step 1: Register your application</h2>
<p>Visit the <a href="https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade">Microsoft Application Registration portal</a> to register your new app.  You'll sign in with your Microsoft 365 credentials. </p>
<figure id="attachment_6690" aria-describedby="caption-attachment-6690" style="width: 658px" class="wp-caption alignnone"><a href="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg.png"><img decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg.png" alt="" width="658" height="356" class="size-full wp-image-6690" srcset="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg.png 658w, https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg-300x162.png 300w" sizes="(max-width: 658px) 100vw, 658px" /></a><figcaption id="caption-attachment-6690" class="wp-caption-text">Microsoft Application Registration portal</figcaption></figure>
<p><strong>Remember:</strong> Multiple people can use the same registered app. Each user will need to sign in and get their own personal access tokens (covered in a later step). If your team (or everyone in your company) uses the same app, then you need to do this step only once! If you do all camp on a single app, it's a good idea to tell your IT support staff that's what you intend to do. Then they will know to expect to see activity from multiple users.</p>
<p>Click <strong>New Registration</strong> to get started.  This presents you with a form where you can complete the details that define your app.  Mainly, you're giving it a name and defining its scope.  You'll probably want to limit its use to just your organization (your company) unless you're collaborating with colleagues who work elsewhere.</p>
<figure id="attachment_6997" aria-describedby="caption-attachment-6997" style="width: 729px" class="wp-caption alignnone"><a href="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg-1.png"><img decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg-1.png" alt="" width="729" height="480" class="size-full wp-image-6997" srcset="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg-1.png 729w, https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg-1-300x198.png 300w, https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg-1-214x140.png 214w" sizes="(max-width: 729px) 100vw, 729px" /></a><figcaption id="caption-attachment-6997" class="wp-caption-text">"Register an application" form</figcaption></figure>
<p>As you register your application, you also need to provide a redirect URL for the authorization flow.  In our example, our app is considered "Public client/native (mobile/desktop)."  The standard URL to indicate this is:<br />
<pre class="preserve-code-formatting">
 https://login.microsoftonline.com/common/oauth2/nativeclient 
</pre></p>
<p>In the Redirect URI section, select this option and specify this URL value.</p>
<figure id="attachment_7000" aria-describedby="caption-attachment-7000" style="width: 954px" class="wp-caption alignnone"><a href="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg_url.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg_url.png" alt="" width="954" height="167" class="size-full wp-image-7000" srcset="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg_url.png 954w, https://blogs.sas.com/content/sasdummy/files/2018/11/azure_reg_url-300x53.png 300w" sizes="(max-width: 954px) 100vw, 954px" /></a><figcaption id="caption-attachment-7000" class="wp-caption-text">Redirect URI Selections</figcaption></figure>
<p>When you create an app, you'll receive a Client ID (unique to your app) and Tenant ID (unique to your organization).  You'll need these values to obtain your authorization code and tokens later.  The application portal provides a sort of control center for all aspects of your app.  (Note: I masked out my client ID and tenant ID in this screenshot.)</p>
<figure id="attachment_6693" aria-describedby="caption-attachment-6693" style="width: 827px" class="wp-caption alignnone"><a href="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_app_details.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_app_details.png" alt="" width="827" height="503" class="size-full wp-image-6693" srcset="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_app_details.png 827w, https://blogs.sas.com/content/sasdummy/files/2018/11/azure_app_details-300x182.png 300w" sizes="(max-width: 827px) 100vw, 827px" /></a><figcaption id="caption-attachment-6693" class="wp-caption-text">Details for my sample application</figcaption></figure>
<h3>Specifying your app permissions</h3>
<p>Your app will need specific permissions in order to function.  In my example, I want my SAS program to read documents from SharePoint and OneDrive, and also add new docs and update existing docs.  The permissions I need are:</p>
<ul>
<li><strong>Files.ReadWrite.All</strong>: Allows the app to read, create, update and delete all OneDrive files <strong>that you can access</strong>.
</li>
<li><strong>User.Read</strong>: Allows you to sign in to the app with your organizational account and let the app read your profile.
</li>
<li><strong>Sites.ReadWrite.All</strong> (if using SharePoint): Allows the app to read, create, update and delete SharePoint Online files for sites <strong>that you can access</strong>.
</li>
</ul>
<p>To add these to your app, click the API Permissions tab in the control center.  To be clear, these are not permissions that your app will automatically <em>have</em>.  These are the permissions that will be <em>requested</em> when you "sign into" the app for the first time, and that you'll have to agree to in order for the app to run. </p>
<figure id="attachment_7003" aria-describedby="caption-attachment-7003" style="width: 702px" class="wp-caption alignnone"><a href="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_api_perm.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_api_perm-1024x433.png" alt="" width="702" height="297" class="size-large wp-image-7003" srcset="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_api_perm-1024x433.png 1024w, https://blogs.sas.com/content/sasdummy/files/2018/11/azure_api_perm-300x127.png 300w, https://blogs.sas.com/content/sasdummy/files/2018/11/azure_api_perm.png 1157w" sizes="(max-width: 702px) 100vw, 702px" /></a><figcaption id="caption-attachment-7003" class="wp-caption-text">Adding permissions that the app needs</figcaption></figure>
<p>Permission types have their own terminology that is important to understand:</p>
<ul>
<li>
<strong>Delegated versus Application Permissions</strong>: In our example, we are sticking to <strong>Delegated</strong> permissions, which allow the application to take actions on behalf of the signed-in user and provides access to the user's data.  However, some use cases require use of <strong>Application </strong>permissions, which allow the application to take actions without a signed-in user and potentially access data across the system and different users.
</li>
<li>
<strong>Admin Consent Required</strong>: Some permissions cannot be delegated or granted without the approval of an administrator.  This restriction permits the organization to maintain oversight of the important resources that might be accessed by the application and to prevent unauthorized uses.  The Microsoft Azure Portal provides an easy way for you to submit a request to an admin, so you can get the permissions that you need. However, I recommend that you follow up (or better yet, precede this) with a formal request to your IT support staff to state what you need and your business case.  In my experience, this helps to expedite the process. A good working relationship with IT is important for any SAS user!
</li>
</ul>
<p>The <a href="https://docs.microsoft.com/en-us/graph/permissions-reference">documentation for the Microsoft Graph API</a> provides a comprehensive list of the permission names, whether they are Delegated or Application level, and whether Admin Consent is required.  This documentation also includes a helpful 4-minute video on the topic.</p>
<p><strong>While here, look at what's needed for Device Code Flow</strong>: While defining your app, consider enabling "Allow Public Client Flows" (under Authentication settings). This is necessary if you want to use the Device Code authentication flow (described later). Since your app does not need or store client credentials -- and relies only on delegated privileges -- this is considered a safe setting.</p>
<h4>Probably required: Obtaining admin consent</h4>
<p>We're creating an app that hooks into your enterprise productivity suite -- and that's usually the domain of IT professionals.  At SAS we are a tech company with many "citizen app developers", so our IT grants us more latitude than you might find at other places.  But even at SAS, "normal" employees can't just create apps and empower them with access to our data. We have a process.</p>
<p>Because it's a common request, our IT folks created a form that makes it easy for them to review requests for new apps in our Microsoft 365 environment.  The form asks:</p>
<ul>
<li>Your app name ("SAS via PROC HTTP" for mine)
</li>
<li>Your App (client) ID
</li>
<li>Grant type – my instructions assume "Authorization code grant type"
</li>
<li>Whether you need additional Delegated API permissions: Most need 'Files.ReadWrite.All' for OneDrive, 'Sites.ReadWrite.All' for SharePoint (in addition to the default 'User.Read').
</li>
<li>Whether your app needs Application Permissions.  (Note: Answering YES here will trigger more scrutiny.)
</li>
</ul>
<h3>Download and include ms-graph-macros.sas code</h3>
<p><a href="https://github.com/sascommunities/sas-microsoft-graph-api">The GitHub repository</a> contains a SAS program (named <a href="https://github.com/sascommunities/sas-microsoft-graph-api/blob/main/ms-graph-macros.sas">ms-graph-macros.sas</a>) with all of the macro routines you need for the remaining tasks. Download this file to a local folder and use %INCLUDE to submit in SAS.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #0000ff;">%let</span> src=&lt;my-local-project&gt;\sas-microsoft-graph-api;
%include <span style="color: #a020f0;">&quot;&amp;src./ms-graph-macros.sas&quot;</span>;</pre></td></tr></table></div>

<p>You can also include directly from GitHub:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #006400; font-style: italic;">/* Run just once in your session */</span>
<span style="color: #0000ff;">options</span> dlcreatedir;
<span style="color: #0000ff;">%let</span> repopath=<span style="color: #0000ff;">%sysfunc</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">getoption</span><span style="color: #66cc66;">&#40;</span>WORK<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>/sas-microsoft-graph-api;
<span style="color: #0000ff;">libname</span> repo <span style="color: #a020f0;">&quot;&amp;repopath.&quot;</span>;
<span style="color: #000080; font-weight: bold;">data</span> <span style="color: #0000ff;">_null_</span>;
    rc = git_clone<span style="color: #66cc66;">&#40;</span> 
      <span style="color: #a020f0;">&quot;https://github.com/sascommunities/sas-microsoft-graph-api&quot;</span>, 
      <span style="color: #a020f0;">&quot;&amp;repoPath.&quot;</span> 
    			<span style="color: #66cc66;">&#41;</span>; 
    <span style="color: #0000ff;">put</span> <span style="color: #a020f0;">'Git repo cloned '</span> rc=; 
<span style="color: #000080; font-weight: bold;">run</span>;
%include <span style="color: #a020f0;">&quot;&amp;repopath./ms-graph-macros.sas&quot;</span>;</pre></td></tr></table></div>

<h3>Creating a configuration file and set its folder location</h3>
<p>There are a few app-specific values that we'll need to reference throughout the SAS programs we're writing.  The macros I've provided use a configuration file for these settings rather than hard-code them into SAS statements. </p>
<p>I created a file named config.json that looks like this (but with different tenant_id and client_id values):<br />
<pre class="preserve-code-formatting">
{
  &quot;tenant_id&quot;: &quot;206db638-6adb-41b9-b20c-95d8d04abcbe&quot;,
  &quot;client_id&quot;: &quot;8fb7804a-8dfd-40d8-bf5b-d02c2cbc56f3&quot;,
  &quot;redirect_uri&quot;: &quot;https://login.microsoftonline.com/common/oauth2/nativeclient&quot;,
  &quot;resource&quot; : &quot;https://graph.microsoft.com&quot;
}
</pre></p>
<p>Designate a secure location for this file and for your token.json file (to be created in a later step). The information within these files <strong>is sensitive and specific to you</strong> and should be protected. See <a href="https://blogs.sas.com/content/sasdummy/2018/01/16/hide-rest-api-tokens/">How to protect your REST API credentials in SAS programs</a> for guidance.</p>
<p>If you are using SAS Viya, you can optionally create this folder and file in your SAS Content area that is private to you. For example, create a ".creds" folder within "/Users/your.account/My Folder". By default, only your account will be able to read content you place there.</p>
<p>The macro routines need to know where your config.json and token.json file are located. The <strong>initConfig</strong> macro initializes this.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #006400; font-style: italic;">/* This path must contain your config.json, and will also */</span>
<span style="color: #006400; font-style: italic;">/* be the location of your token.json */</span>
%initConfig<span style="color: #66cc66;">&#40;</span>configPath=/u/yourId/Projects/ms365<span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>If you are using SAS Viya and you would like to store your config and token files in the SAS Content folders (instead of the file system), this is supported with a boolean flag on initConfig. For example, if you store config.json in a folder named .creds within your SAS Content user home, this tells the macro to look in that folder:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;">%initConfig<span style="color: #66cc66;">&#40;</span>configPath=/Users/your.account/My Folder/.creds, sascontent=<span style="color: #2e8b57; font-weight: bold;">1</span><span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>Note: This <strong>sascontent</strong> flag is needed to tell the macro to use the <a href="https://communities.sas.com/t5/SAS-Communities-Library/Accessing-SAS-Content-with-FILENAME-FILESRVC-in-SAS-Viya/ta-p/970736">FILENAME FILESVC method to access the SAS Content area</a>. It requires a different file access method than traditional file systems.</p>
<h2>Step 2: Obtain an authorization code (Auth Code Flow or Device Code Flow)</h2>
<p>Before continuing, you need to decide which authentication flow you want to use. The GitHub project includes PowerShell and SAS implementations for both <a href="https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow">Auth Code Flow</a> and <a href="https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-device-code">Device Code Flow</a>, and you can pick whichever method is easiest or most reliable in your environment.</p>
<h3>Option A: Authorization Code (Auth Code) Flow – More interactive, more steps</h3>
<p>The Auth Code flow opens a browser window and walks you through an interactive Microsoft sign‑in. This step needs to be completed from a web browser<strong> while I am signed into my Microsoft 365 account</strong>.  The web address is very long...but we can use a SAS program to generate it for us.</p>
<p>This helper macro will generate the URL you can use to generate an auth code.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;">%generateAuthUrl<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>This produces these output lines in the SAS log:<br />
<pre class="preserve-code-formatting">
 Paste this URL into your web browser:
 -- START -------
https://login.microsoftonline.com/206db638-6adb-41b9-b20c-95d8d04abcbe/oauth2/authorize?client_id=8fb7804a-8dfd-40d8-bf5b-d02c2cbc56
f3&amp;response_type=code&amp;redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient&amp;resource=https://graph.microsoft.com
 ---END ---------
</pre></p>
<p>Copy and paste the URL (<strong>all on one line, no spaces</strong>) into the address bar of your web browser.  When you press Enter, you'll be prompted to grant the required permissions:</p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_app_permissions.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_app_permissions.png" alt="" width="446" height="461" class="alignnone size-full wp-image-6688" srcset="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_app_permissions.png 446w, https://blogs.sas.com/content/sasdummy/files/2018/11/azure_app_permissions-290x300.png 290w" sizes="(max-width: 446px) 100vw, 446px" /></a></p>
<p>Once you click Accept, the browser will redirect to what <em>looks like</em> a blank page, but the URL contains the authorization code that we need:</p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_access_code.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_access_code.png" alt="" width="1064" height="71" class="alignnone size-full wp-image-6698" /></a></p>
<p>Copy the value that appears after the <strong>code=</strong> in the URL, <strong>only up to</strong> the &amp;session= part.  It's going to be a very long string -- over 700 characters.  We'll need that value for the next step.</p>
<p><strong>Note:</strong> if you don't see the permissions prompt but instead see something like this:</p>
<figure id="attachment_7006" aria-describedby="caption-attachment-7006" style="width: 364px" class="wp-caption alignnone"><a href="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_need_admin.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_need_admin.png" alt="" width="364" height="238" class="size-full wp-image-7006" srcset="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_need_admin.png 364w, https://blogs.sas.com/content/sasdummy/files/2018/11/azure_need_admin-300x196.png 300w, https://blogs.sas.com/content/sasdummy/files/2018/11/azure_need_admin-214x140.png 214w" sizes="(max-width: 364px) 100vw, 364px" /></a><figcaption id="caption-attachment-7006" class="wp-caption-text">App needs permission to access resources</figcaption></figure>
<p>Then you probably need to work with your IT support to grant consent for your app.  See the section "Probably required: Obtaining admin consent" above.</p>
<p>If you just generated your auth code for the first time or needed to get a new one because the old one was revoked or expired, then you need to use the auth code to get an initial access token.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #006400; font-style: italic;">/* Note: this code can be quite long -- 700+ characters. */</span>
<span style="color: #0000ff;">%let</span> auth_code=PASTE-YOUR-AUTH-CODE-HERE;
&nbsp;
<span style="color: #006400; font-style: italic;">/*
  Now that we have an authorization code we can get the access token
  This step will write the token.json file that we can use in our
  production programs.
*/</span>
%get_access_token<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff; font-weight: bold;">&amp;auth_code</span>.<span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>When successful, token.json will be created/updated in the config directory you specified.</p>
<p><strong>Note:</strong> This method is the traditional OAuth 2.0 approach, and it still works but there is an important recent change. Microsoft now displays an <em>anti‑phishing warning</em> during the redirect, and the browser automatically navigates away from the code result after a short delay, making it harder to manually capture or view the returned code.</p>
<p>Because of this new security behavior, the Auth Code flow is now slightly more cumbersome and timing‑sensitive, especially if you rely on manually copying the returned code value. The GitHub project includes a PowerShell helper that automates the code return and makes it easier to grab and parse the code from the URL, so if you still prefer Auth Code flow, use the included PowerShell approach rather than relying on the raw browser response.</p>
<h3>Option B: Device Code Flow – Simpler UX but requires Public Client support</h3>
<p>Device Code flow displays a brief short-lived "device code" in your terminal or SAS log and instructs you to visit https://microsoft.com/devicelogin on any browser. After you authenticate there, the program polls until the token is ready. Device Code flow is often the easiest option because:</p>
<ul>
<li>No redirect URIs are involved
</li>
<li>No embedded browser is required
</li>
<li>You can complete authentication on any device, including your phone.
</li>
</ul>
<p>To use Device Code authentication in SAS with this macro library:</p>
<ol>
<li>Call <code class="preserve-code-formatting">%generateDeviceCode();</code> to create a temporary device code
</li>
<li>Open the device login URL displayed in the SAS log
</li>
<li>Enter the device code when prompted
</li>
<li>Complete authentication in your browser
</li>
<li>Call <code class="preserve-code-formatting">%confirmDeviceCodeToken();</code> to retrieve and store your access token. By default, this macro will continuous poll the login service until you either complete the authentication or the code expires (usually 15 minutes).
</li>
</ol>
<p>The token will be saved to token.json (in your config folder) for future use. Here's an example sequence:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;">   %initConfig<span style="color: #66cc66;">&#40;</span>configPath=/path-to-config.json<span style="color: #66cc66;">&#41;</span>;
   %generateDeviceCode<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
   <span style="color: #006400; font-style: italic;">/* Use the URL and code to log in, then run the following */</span>
   %confirmDeviceCodeToken<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>This prints the device login and unique, temporary code to the SAS log:<br />
<pre class="preserve-code-formatting">
Complete the device login using your local browser:
-- INSTRUCTIONS -------
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code [UNIQUECODE] to authenticate.
---END ---------
</pre></p>
<p>Use your web browser to complete the authentication. You'll be prompted to log into your Microsoft 365 environment (including all multifactor login steps). You will then be asked to confirm the access for your application. The following screen captures illustrate the steps.<br />
<figure id="attachment_8243" aria-describedby="caption-attachment-8243" style="width: 1326px" class="wp-caption alignnone"><a href="https://blogs.sas.com/content/sasdummy/files/2025/10/devcode-flow.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2025/10/devcode-flow.png" alt="Steps/screens from Device Code flow" width="1326" height="335" class="size-full wp-image-8243" srcset="https://blogs.sas.com/content/sasdummy/files/2025/10/devcode-flow.png 1326w, https://blogs.sas.com/content/sasdummy/files/2025/10/devcode-flow-300x76.png 300w, https://blogs.sas.com/content/sasdummy/files/2025/10/devcode-flow-1024x259.png 1024w, https://blogs.sas.com/content/sasdummy/files/2025/10/devcode-flow-768x194.png 768w" sizes="(max-width: 1326px) 100vw, 1326px" /></a><figcaption id="caption-attachment-8243" class="wp-caption-text">Steps/screens from Device Code flow</figcaption></figure>
<p>If you've ever used your phone to connect a streaming service to your smart TV, the Device Code flow will feel familiar.</p>
<p>However, there are two important restrictions:</p>
<ul>
<li>Your app registration must <a href="https://learn.microsoft.com/en-us/entra/identity-platform/msal-client-applications">have "Allow public client flows" enabled</a>, because Device Code is a public‑client‑only authentication method. This is easy to set in the app properties within your Azure or Entra ID portal.<br />
"Allow Public Client Flow" is a safe setting when your app does not require/store your personal or client credentials -- all true for the process documented here.
</li>
<li>And yet, your organization may restrict Device Code flow -- some admins now allow it only for Intune‑managed devices -- or block it entirely due to recent guidance around phishing‑resistant auth policies.
</li>
</ul>
<p>If Device Code flow is permitted in your tenant, it is typically the most reliable option -- especially for automation or CLI‑based workflows.</p>
<h3>Summary: Pick the flow that fits your environment</h3>
<p>Use Device Code flow if your org allows public client flows and you want the simplest sign‑in experience. </p>
<p>Use Auth Code flow if your org blocks Device Code or if you prefer the standard OAuth pattern. PowerShell and SAS examples are included in the GitHub project.</p>
<p>Regardless of which method you choose, the remaining steps in the workflow are the same: once you obtain the authorization result (Auth Code or Device Code completion), you exchange it for your access/refresh tokens and proceed with the rest of the process.</p>
<h2>Step 3: Obtain an access token</h2>
<p>You should now have both config.json and token.json in your designated config folder. This screenshot shows an example of these files in a hidden folder named "~/.creds".</p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2024/07/creds-in-studio.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2024/07/creds-in-studio.png" alt="" width="797" height="435" class="alignnone size-full wp-image-8219" srcset="https://blogs.sas.com/content/sasdummy/files/2024/07/creds-in-studio.png 797w, https://blogs.sas.com/content/sasdummy/files/2024/07/creds-in-studio-300x164.png 300w, https://blogs.sas.com/content/sasdummy/files/2024/07/creds-in-studio-768x419.png 768w" sizes="(max-width: 797px) 100vw, 797px" /></a></p>
<p>The content of the token.json will look something like this:<br />
<a href="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_token.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_token.png" alt="" width="549" height="320" class="alignnone size-full wp-image-6712" srcset="https://blogs.sas.com/content/sasdummy/files/2018/11/azure_token.png 549w, https://blogs.sas.com/content/sasdummy/files/2018/11/azure_token-300x175.png 300w" sizes="(max-width: 549px) 100vw, 549px" /></a></p>
<p><strong>IMPORTANT:</strong> It's <strong>very important</strong> that you keep this file secure and private to you (do not share!).  With the information in this file (your refresh token) and your config.json file (with your client ID and tenant ID), anyone can use these code techniques to impersonate you and access your Microsoft 365 data.  </p>
<h2>Using Microsoft 365 APIs to access SharePoint and OneDrive content from SAS</h2>
<p>Whew!  I've spent nearly 1500 words to get this far, so thanks for sticking with me.  The good news is that these steps take much longer to describe than to actually execute.  Plus, creating apps is fun! (Right?)</p>
<p>From the screenshots I've shared, you probably already noticed that these services are working on Microsoft Azure, which is Microsoft's cloud platform for applications. For the remainder of this article, I'll be using methods from <a href="https://developer.microsoft.com/en-us/graph">the Microsoft Graph API</a>.  This REST-based API provides access to almost all of Microsoft's hosted services.  For my examples, I'll be using methods within the <a href="https://docs.microsoft.com/en-us/graph/api/resources/onedrive?view=graph-rest-1.0">Files component of the API</a>: Drives and Drive Items (folders and files).   </p>
<p>You can explore and try the Microsoft 365 APIs <a href="https://developer.microsoft.com/en-us/graph/graph-explorer" rel="noopener noreferrer" target="_blank">with the Graph Explorer application</a> from Microsoft.  If you sign in with your own account, you can use the APIs with your own data.  This is a great way to try these APIs and discover the correct methods to use before implementing them in your SAS code.</p>
<figure id="attachment_6956" aria-describedby="caption-attachment-6956" style="width: 1046px" class="wp-caption alignnone"><a href="https://blogs.sas.com/content/sasdummy/files/2018/11/graphexplorer.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2018/11/graphexplorer.png" alt="" width="1046" height="604" class="size-full wp-image-6956" srcset="https://blogs.sas.com/content/sasdummy/files/2018/11/graphexplorer.png 1046w, https://blogs.sas.com/content/sasdummy/files/2018/11/graphexplorer-300x173.png 300w, https://blogs.sas.com/content/sasdummy/files/2018/11/graphexplorer-1024x591.png 1024w" sizes="(max-width: 1046px) 100vw, 1046px" /></a><figcaption id="caption-attachment-6956" class="wp-caption-text">Example from a Graph Explorer session</figcaption></figure>
<h3>Initializing and refreshing the access token in a new session</h3>
<p>Now that we have the access and refresh tokens, we can get down to business with some actual SharePoint and OneDrive interactions.  Use the <strong>%initSessionMS365</strong> macro routine to exchange the refresh-token stored in token.json for an active non-expired access token.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"> %initSessionMS365;</pre></td></tr></table></div>

<p>When this is successful, you will see notes similar to these in the SAS log:<br />
<pre class="preserve-code-formatting">
M365: Reading token info from token.json
M365: Token expires on 26JUL2024:10:04:22
</pre></p>
<p>The Microsoft Graph API session token is stored in the macro variable &access_token, which is referenced implicitly in the other macro routines in this package.  It's going to be another long and illegible (&gt;700 characters) value.</p>
<p>(Ever hear of the "infinite monkey theorem?" That a monkey hitting a typewriter for an infinite amount of time is certain to produce a certain text, such as the complete works of Shakespeare?  Well, that monkey is <strong>not</strong> going to produce this access token.  Plus, who has a typewriter anymore?)</p>
<p>With the authenticated session established, you can use PROC HTTP to execute any API endpoint that your app permissions allow. For example, with User.Read (most apps have this), you can list your own account profile details:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #0000ff;">filename</span> resp temp;
<span style="color: #000080; font-weight: bold;">proc http</span> url=<span style="color: #a020f0;">&quot;https://graph.microsoft.com/v1.0/me&quot;</span> 
  oauth_bearer=<span style="color: #a020f0;">&quot;&amp;access_token&quot;</span> 
  out=resp;
<span style="color: #000080; font-weight: bold;">run</span>;
<span style="color: #000080; font-weight: bold;">data</span> <span style="color: #0000ff;">_null_</span>;
    rc=jsonpp<span style="color: #66cc66;">&#40;</span><span style="color: #a020f0;">'resp'</span>,<span style="color: #a020f0;">'log'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #000080; font-weight: bold;">run</span>;
<span style="color: #0000ff;">filename</span> resp clear;</pre></td></tr></table></div>

<p>This is a useful test API call to make sure everything is set up and working. If you're following along and you don't get a good result from this, it's time to back up and retrace your steps before trying the remaining examples in this article. See <a href="https://github.com/sascommunities/sas-microsoft-graph-api" rel="noopener" target="_blank">the "Troubleshooting" section on the GitHub project</a> for guidance and tools, <a href="https://github.com/sascommunities/sas-microsoft-graph-api/blob/main/examples/ms-graph-api-test.ps1" rel="noopener" target="_blank">including a PowerShell script</a> that you can use outside of your SAS environment to make sure your Microsoft 365 connection is working as expected.</p>
<h2>Example workflow: Using SAS code to explore SharePoint Online/Teams folders</h2>
<p>Let's look at content in SharePoint Online. Remember that files that you store in Microsoft Teams channels are also using SharePoint behind the scenes, so the process is the same for exploring content in Teams. </p>
<p>To simulate the experience of "drilling down" into folders and subfolders to find the file we want, we use an iterative approach to list content items. Each provided SAS macro produces an output data set with the list of folders and files in the current location. We can then use PROC SQL with SELECT INTO to store the unique ID of our next target into a macro variable, then use that macro variable as input into the next step.</p>
<p>Let's start with the <strong>%listSiteLibraries</strong> macro routine to get the root level content for our site:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #006400; font-style: italic;">/* Let's look at SharePoint / Teams folders */</span>
<span style="color: #0000ff;">%let</span> siteHost = sasoffice365.sharepoint.com;
<span style="color: #0000ff;">%let</span> sitePath = /sites/SASandMicrosoft365APIdemo;
&nbsp;
<span style="color: #006400; font-style: italic;">/* stores the libraries metadata in work.libs */</span>
%listSiteLibraries<span style="color: #66cc66;">&#40;</span> siteHost=<span style="color: #0000ff; font-weight: bold;">&amp;siteHost</span>.,sitepath=<span style="color: #0000ff; font-weight: bold;">&amp;sitePath</span>.,out=libs<span style="color: #66cc66;">&#41;</span>;
<span style="color: #006400; font-style: italic;">/* store the ID value for the library in a macro variable, where &quot;Documents&quot; is at root */</span>
<span style="color: #000080; font-weight: bold;">proc sql</span> noprint;
 <span style="color: #0000ff;">select</span> id <span style="color: #0000ff;">into</span>: libraryId <span style="color: #0000ff;">from</span> libs <span style="color: #0000ff;">where</span> name=<span style="color: #a020f0;">&quot;Documents&quot;</span>;
<span style="color: #000080; font-weight: bold;">quit</span>;
&nbsp;
<span style="color: #006400; font-style: italic;">/* LIST TOP LEVEL FOLDERS/FILES */</span>
&nbsp;
<span style="color: #006400; font-style: italic;">/* special macro to pull ALL items from root folder */</span>
<span style="color: #006400; font-style: italic;">/* stores the folder items metadata in work.paths */</span>
%listFolderItems<span style="color: #66cc66;">&#40;</span>driveId=<span style="color: #0000ff; font-weight: bold;">&amp;libraryId</span>., folderId=root, out=work.paths<span style="color: #66cc66;">&#41;</span>;
<span style="color: #000080; font-weight: bold;">proc print</span> <span style="color: #000080; font-weight: bold;">data</span>=paths <span style="color: #66cc66;">&#40;</span>obs=<span style="color: #2e8b57; font-weight: bold;">10</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p><a href="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph1.jpg"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph1.jpg" alt="" width="1459" height="95" class="alignnone size-full wp-image-8222" srcset="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph1.jpg 1459w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph1-300x20.jpg 300w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph1-1024x67.jpg 1024w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph1-768x50.jpg 768w" sizes="(max-width: 1459px) 100vw, 1459px" /></a><br />
"Drill" into that top folder to see the subfolders the next level down:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #000080; font-weight: bold;">proc sql</span> noprint;
 <span style="color: #0000ff;">select</span> id <span style="color: #0000ff;">into</span>: folderId <span style="color: #0000ff;">from</span> work.paths <span style="color: #0000ff;">where</span> name=<span style="color: #a020f0;">&quot;Team Content&quot;</span>;
<span style="color: #000080; font-weight: bold;">quit</span>;
&nbsp;
%listFolderItems<span style="color: #66cc66;">&#40;</span>driveId=<span style="color: #0000ff; font-weight: bold;">&amp;libraryId</span>., folderId=<span style="color: #0000ff; font-weight: bold;">&amp;folderId</span>., out=work.paths<span style="color: #66cc66;">&#41;</span>;
<span style="color: #000080; font-weight: bold;">proc print</span> <span style="color: #000080; font-weight: bold;">data</span>=paths <span style="color: #66cc66;">&#40;</span>obs=<span style="color: #2e8b57; font-weight: bold;">10</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p><a href="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph2.jpg"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph2.jpg" alt="" width="1441" height="101" class="alignnone size-full wp-image-8225" srcset="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph2.jpg 1441w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph2-300x21.jpg 300w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph2-1024x72.jpg 1024w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph2-768x54.jpg 768w" sizes="(max-width: 1441px) 100vw, 1441px" /></a><br />
Now drill into that folder to see its subfolders and content.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #000080; font-weight: bold;">proc sql</span> noprint;
 <span style="color: #0000ff;">select</span> id <span style="color: #0000ff;">into</span>: folderId <span style="color: #0000ff;">from</span> work.paths <span style="color: #0000ff;">where</span> name=<span style="color: #a020f0;">&quot;Reports&quot;</span>;
<span style="color: #000080; font-weight: bold;">quit</span>;
&nbsp;
%listFolderItems<span style="color: #66cc66;">&#40;</span>driveId=<span style="color: #0000ff; font-weight: bold;">&amp;libraryId</span>., folderId=<span style="color: #0000ff; font-weight: bold;">&amp;folderId</span>., out=work.paths<span style="color: #66cc66;">&#41;</span>;
<span style="color: #000080; font-weight: bold;">proc print</span> <span style="color: #000080; font-weight: bold;">data</span>=paths <span style="color: #66cc66;">&#40;</span>obs=<span style="color: #2e8b57; font-weight: bold;">10</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p><a href="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph3.jpg"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph3.jpg" alt="" width="1437" height="272" class="alignnone size-full wp-image-8228" srcset="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph3.jpg 1437w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph3-300x57.jpg 300w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph3-1024x194.jpg 1024w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph3-768x145.jpg 768w" sizes="(max-width: 1437px) 100vw, 1437px" /></a></p>
<h3>Download a file from SharePoint and import to SAS</h3>
<p>Now that we found the folder that contains the file we want (SciFi-AI.xlsx), we can use the <strong>%downloadFile</strong> macro to bring it into our SAS session. In this example, I'm storing the downloaded file in the WORK folder (so it will be deleted from here when the SAS session ends).</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #0000ff;">%let</span> localFolder = <span style="color: #0000ff;">%sysfunc</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">getoption</span><span style="color: #66cc66;">&#40;</span>WORK<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
%downloadFile<span style="color: #66cc66;">&#40;</span>driveId=<span style="color: #0000ff; font-weight: bold;">&amp;libraryId</span>., 
  folderId=<span style="color: #0000ff; font-weight: bold;">&amp;folderId</span>., 
  sourceFilename=SciFi-AI.xlsx, 
  destinationPath=<span style="color: #0000ff; font-weight: bold;">&amp;localFolder</span>.<span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>Note: We now have the IDs for the SharePoint library (drive) and the folder for this content, we can store them and use in future code, since they will not change. Then next time we want to do this download, we can skip the "query and discover" steps and go directly to the download step.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #0000ff;">%put</span> &amp;=libraryId.;
<span style="color: #0000ff;">%put</span> &amp;=folderId.;
&nbsp;
<span style="color: #0000ff;">%let</span> reportLibrary=<span style="color: #0000ff; font-weight: bold;">&amp;libraryId</span>;
<span style="color: #0000ff;">%let</span> reportFolder=<span style="color: #0000ff; font-weight: bold;">&amp;folderId</span>;</pre></td></tr></table></div>

<p>With that file downloaded and in a local folder, we can now PROC IMPORT as an Excel file.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #006400; font-style: italic;">/* Downloaded an Excel file into SAS? Now we can PROC IMPORT if we want */</span>
<span style="color: #000080; font-weight: bold;">proc import</span> <span style="color: #0000ff;">file</span>=<span style="color: #a020f0;">&quot;&amp;localFolder./SciFi-AI.xlsx&quot;</span> 
 out=scifi
 dbms=xlsx <span style="color: #0000ff;">replace</span>;
<span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
<span style="color: #006400; font-style: italic;">/* Preview the contents of this imported file */</span>
<span style="color: #000080; font-weight: bold;">proc print</span> <span style="color: #000080; font-weight: bold;">data</span>=scifi <span style="color: #66cc66;">&#40;</span>obs=<span style="color: #2e8b57; font-weight: bold;">10</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p><a href="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph3.5.jpg"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph3.5.jpg" alt="" width="512" height="281" class="alignnone size-full wp-image-8234" srcset="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph3.5.jpg 512w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph3.5-300x165.jpg 300w" sizes="(max-width: 512px) 100vw, 512px" /></a></p>
<h3>Upload a file from SAS into SharePoint</h3>
<p>Now let's use the <strong>%uploadFile</strong> macro to send a SAS-generated report file to this Teams/SharePoint folder.</p>
<p>First, let's generate a report in Excel format to share. We'll use the data that we downloaded and imported as the source material.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #000080; font-weight: bold;">proc sql</span>;
   <span style="color: #0000ff;">create</span> <span style="color: #0000ff;">table</span> withProfit <span style="color: #0000ff;">as</span> 
    <span style="color: #0000ff;">select</span> t1.<span style="color: #006400; font-style: italic;">*, (t1.BoxOfficeReceipts - t1.CostToMake) * 1000000 as Profit_Loss format=dollar12.
   from scifi t1
   order by Profit_Loss desc;</span>
<span style="color: #000080; font-weight: bold;">quit</span>;
&nbsp;
<span style="color: #0000ff;">filename</span> report <span style="color: #a020f0;">&quot;&amp;localFolder./SciFi-Summary.xlsx&quot;</span>;
&nbsp;
ods excel<span style="color: #66cc66;">&#40;</span>id=xl<span style="color: #66cc66;">&#41;</span> <span style="color: #0000ff;">file</span>=report
 <span style="color: #0000ff;">options</span><span style="color: #66cc66;">&#40;</span>sheet_interval=<span style="color: #a020f0;">'none'</span> sheet_name=<span style="color: #a020f0;">'MOVIES'</span><span style="color: #66cc66;">&#41;</span>;
ods graphics <span style="color: #0000ff;">on</span> / imagefmt=png;
&nbsp;
<span style="color: #0000ff;">Title</span> <span style="color: #a020f0;">&quot;Top 10 Profitable Sci-Fi Movies&quot;</span>;
<span style="color: #000080; font-weight: bold;">proc print</span> <span style="color: #000080; font-weight: bold;">data</span>=withProfit<span style="color: #66cc66;">&#40;</span>obs=<span style="color: #2e8b57; font-weight: bold;">10</span><span style="color: #66cc66;">&#41;</span>;
 <span style="color: #0000ff;">var</span> YearProduced MovieTitle Profit_Loss;
<span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
<span style="color: #0000ff;">title</span> height=<span style="color: #2e8b57; font-weight: bold;">3</span> <span style="color: #a020f0;">&quot;Profit amounts by Year&quot;</span>;
<span style="color: #000080; font-weight: bold;">proc sgpie</span> <span style="color: #000080; font-weight: bold;">data</span>=withProfit;
  styleattrs datacolors=<span style="color: #66cc66;">&#40;</span>cXfbb4ae cXb3cde3 cXccebc5 cXdecbe4<span style="color: #66cc66;">&#41;</span>;
  pie YearProduced / response=Profit_Loss 
  datalabelattrs=<span style="color: #66cc66;">&#40;</span>Size = 22pt<span style="color: #66cc66;">&#41;</span> 
  datalabeldisplay=<span style="color: #66cc66;">&#40;</span>category percent<span style="color: #66cc66;">&#41;</span>;
<span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
ods excel<span style="color: #66cc66;">&#40;</span>id=xl<span style="color: #66cc66;">&#41;</span> <span style="color: #0000ff;">close</span>;</pre></td></tr></table></div>

<p>This code produces report content that looks like this, and stores it in an Excel file named SciFi-Summary.xslx:</p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph5.jpg"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph5.jpg" alt="" width="677" height="858" class="alignnone size-full wp-image-8237" srcset="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph5.jpg 677w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph5-237x300.jpg 237w" sizes="(max-width: 677px) 100vw, 677px" /></a></p>
<p>Using the IDs for the SharePoint library and folder that we stored from earlier steps, we can use the <strong>%uploadFile</strong> macro to send it to SharePoint:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;">%uploadFile<span style="color: #66cc66;">&#40;</span>driveId=<span style="color: #0000ff; font-weight: bold;">&amp;reportLibrary</span>., folderId=<span style="color: #0000ff; font-weight: bold;">&amp;reportFolder</span>.,
 sourcePath=<span style="color: #0000ff; font-weight: bold;">&amp;localFolder</span>.,
sourcefilename=SciFi-Summary.xlsx<span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>The <strong>%uploadFile</strong> macro is doing a lot of work behind the scenes. It splits the source file into multiple "chunks" for uploading, and then uses a special "upload session" API to transfer those pieces to Microsoft 365. It works sort of like a Star Trek transporter: it disassembles the file on the local side, and it's reassembled in place in the SharePoint destination folder. (Beam up your file to your Teams site, Scotty!)</p>
<p>If you repeatedly upload a file to the same destination (for example, a new version of the file each day or week), SharePoint keeps track of those versions for you in its Version history:<br />
<a href="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph6.jpg"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph6.jpg" alt="" width="1191" height="460" class="alignnone size-full wp-image-8240" srcset="https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph6.jpg 1191w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph6-300x116.jpg 300w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph6-1024x395.jpg 1024w, https://blogs.sas.com/content/sasdummy/files/2024/07/ms-graph6-768x297.jpg 768w" sizes="(max-width: 1191px) 100vw, 1191px" /></a></p>
<h2>Example workflow: Using SAS code to explore OneDrive</h2>
<p>Most of the actions that we can perform with SharePoint folders, we can also do with OneDrive. The main difference is that the API to list OneDrive root content is different, so we have a special routine called <strong>%listMyDrives</strong>.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #006400; font-style: italic;">/* Exploration: get the list of top-level drives in OneDrive */</span>
%listMyDrives<span style="color: #66cc66;">&#40;</span>out=work.drives<span style="color: #66cc66;">&#41;</span>;
<span style="color: #000080; font-weight: bold;">proc print</span> <span style="color: #000080; font-weight: bold;">data</span>=drives;
<span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p>From the available "drives", we can use PROC SQL to single out the ID for the main "Documents" folder and then list its contents.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #006400; font-style: italic;">/*
 If you have multiple drives you can filter 
 the set with a where clause on the name value.
 Note that the system may track additional drives behind-the-scenes, so
 don't assume you have just one!
&nbsp;
 In my case, the main drive is labeled &quot;Documents&quot;.
*/</span>
<span style="color: #006400; font-style: italic;">/* store the ID value for the drive in a macro variable */</span>
<span style="color: #000080; font-weight: bold;">proc sql</span> noprint;
 <span style="color: #0000ff;">select</span> id <span style="color: #0000ff;">into</span>: driveId <span style="color: #0000ff;">from</span> drives <span style="color: #0000ff;">where</span> driveDisplayName=<span style="color: #a020f0;">&quot;Documents&quot;</span>;
<span style="color: #000080; font-weight: bold;">quit</span>;
&nbsp;
<span style="color: #006400; font-style: italic;">/* LIST TOP LEVEL FOLDERS/FILES */</span>
&nbsp;
<span style="color: #006400; font-style: italic;">/* special macro to pull ALL items from root folder               */</span>
<span style="color: #006400; font-style: italic;">/* Note that the APIs return only 200 items at a time             */</span>
<span style="color: #006400; font-style: italic;">/* This macro will iterate through multiple times to get the full */</span>
<span style="color: #006400; font-style: italic;">/* collection.                                                    */</span>
%listFolderItems<span style="color: #66cc66;">&#40;</span>driveId=<span style="color: #0000ff; font-weight: bold;">&amp;driveId</span>., folderId=root, out=work.paths<span style="color: #66cc66;">&#41;</span>;
<span style="color: #006400; font-style: italic;">/* preview a few of these */</span>
<span style="color: #000080; font-weight: bold;">proc print</span> <span style="color: #000080; font-weight: bold;">data</span>=paths <span style="color: #66cc66;">&#40;</span>obs=<span style="color: #2e8b57; font-weight: bold;">10</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p>From this point on, you can follow the same methods used for SharePoint, already covered earlier. Listing folder items, downloading a file, and uploading a file all work using the same routines as for SharePoint.</p>
<a href="https://communities.sas.com/t5/SAS-Innovate-Presentations/Using-SAS-With-Microsoft-365-A-Programming-Approach/ta-p/968595" class="sc-button sc-button-default"><span><span class="btnheader">WATCH | </span> ACCESSING MICROSOFT 365 FROM SAS (SAS Innovate 2025)</span></a>
<h2>More about using REST APIs from SAS</h2>
<p>This has been a monster article -- in terms of its length.  But I hope it's clear enough to follow and has sufficient detail for you to try this on your own.  If you have questions, post in the comments.</p>
<p>I've published a number of other articles about using REST APIs from SAS -- it's one of my favorite things to do.  Check out:</p>
<ul>
<li><a href="https://blogs.sas.com/content/sasdummy/2017/04/14/using-sas-to-access-google-analytics-apis/">Using Google Analytics APIs from SAS</a>
</li>
<li><a href="https://blogs.sas.com/content/sasdummy/2017/01/05/reporting-on-github-accounts-with-sas/">Using GitHub APIs from SAS</a>
</li>
<li><a href="https://blogs.sas.com/content/sasdummy/2019/09/05/sas-microsoft-teams/">How to publish to a Microsoft Teams channel using SAS</a>
</li>
<li><a href="https://blogs.sas.com/content/sasdummy/2016/07/22/slack-channel-with-sas/">Sending messages to a Slack channel with SAS</a>
</li>
<li><a href="https://blogs.sas.com/content/sasdummy/2018/01/23/check-json-and-http/">How to test PROC HTTP and the JSON library engine</a>
</li>
<li><a href="https://blogs.sas.com/content/sasdummy/2018/01/16/hide-rest-api-tokens/">Securing your REST API credentials in your SAS programs</a>
</li>
</ul>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2026/02/02/sas-programming-office-365-onedrive/">Using SAS with Microsoft 365 (OneDrive, Teams, and SharePoint)</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.sas.com/content/sasdummy/2026/02/02/sas-programming-office-365-onedrive/feed/</wfw:commentRss>
			<slash:comments>126</slash:comments>
		
		
			<enclosure url="https://blogs.sas.com/content/sasdummy/files/2018/11/onedrive_feature-150x150.png" />
	</item>
		<item>
		<title>Through the years: SAS Enterprise Guide versions</title>
		<link>https://blogs.sas.com/content/sasdummy/2025/07/03/eg-versions-through-years/</link>
					<comments>https://blogs.sas.com/content/sasdummy/2025/07/03/eg-versions-through-years/#comments</comments>
		
		<dc:creator><![CDATA[Chris Hemedinger]]></dc:creator>
		<pubDate>Thu, 03 Jul 2025 12:00:08 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[SAS 9.4]]></category>
		<category><![CDATA[SAS Enterprise Guide]]></category>
		<category><![CDATA[SAS Viya]]></category>
		<category><![CDATA[SAS Viya Workbench]]></category>
		<category><![CDATA[SGPLOT]]></category>
		<guid isPermaLink="false">http://blogs.sas.com/content/sasdummy/?p=3819</guid>

					<description><![CDATA[<p>My colleague Rick Wicklin maintains a nifty chart that shows the timeline of SAS releases since Version 8. A few of you asked if I could post a similar chart for SAS Enterprise Guide. Here it is. Like Rick, I used new features in SAS 9.4 to produce this chart [...]</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2025/07/03/eg-versions-through-years/">Through the years: SAS Enterprise Guide versions</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>My colleague Rick Wicklin maintains <a href="https://blogs.sas.com/content/iml/2013/08/02/how-old-is-your-version-of-sas-release-dates-for-sas-software/" title="SAS releases since 1999">a nifty chart that shows the timeline of SAS releases</a> since Version 8.  A few of you asked if I could post a similar chart for SAS Enterprise Guide.  Here it is.  Like Rick, I used new features in SAS 9.4 to produce this chart (in fact, I cribbed heavily from his code)...but I used SAS Enterprise Guide to run the program.</p>
<p><em><strong>Update 03Jul2025</strong>: I've updated the graph and code in this post for the most recent versions of SAS Enterprise Guide and SAS. I also gave the chart a branding facelift, reflecting the most recent SAS colors and fonts that we use.</em></p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2024/04/egversions2025.jpg"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2024/04/egversions2025.jpg" alt="EG versions as of 2025" width="1622" height="1063" class="alignnone size-full wp-image-8217" srcset="https://blogs.sas.com/content/sasdummy/files/2024/04/egversions2025.jpg 1622w, https://blogs.sas.com/content/sasdummy/files/2024/04/egversions2025-300x197.jpg 300w, https://blogs.sas.com/content/sasdummy/files/2024/04/egversions2025-1024x671.jpg 1024w, https://blogs.sas.com/content/sasdummy/files/2024/04/egversions2025-768x503.jpg 768w, https://blogs.sas.com/content/sasdummy/files/2024/04/egversions2025-1536x1007.jpg 1536w, https://blogs.sas.com/content/sasdummy/files/2024/04/egversions2025-214x140.jpg 214w" sizes="(max-width: 1622px) 100vw, 1622px" /></a></p>
<p>You might notice that my chart is a bit busier than Rick's version.  As a <a href="https://blogs.sas.com/content/sasdummy/2013/08/02/sas94-eg-versions/" title="Cross version magic">desktop client application that works across multiple SAS versions</a>, we tend to issue major releases of SAS Enterprise Guide more often than we update the core engine of SAS software.</p>
<p>On my chart, the labels on the data points indicate the "event" that motivated the release.  In some cases, we issued a new release to go with a new version of SAS (such as v1.2 with SAS 8.2).  In other cases, we "remastered" a version to support more languages or another operating system (such as Microsoft Vista support with v4.1 in 2007, or the <a href="http://en.wikipedia.org/wiki/L10n" title="what is L10N?">L10N release</a> of v4.3 in 2010). Most recently, we released a version of <a href="https://blogs.sas.com/content/sgf/2024/03/22/sas-eg-on-viya/">SAS Enterprise Guide that can connect to SAS Viya 4 and then SAS Viya Workbench</a>.</p>
<p>You might also notice that some of these releases happened very close together.  Often, SAS R&amp;D works on updates to multiple releases in parallel.  Developers make changes to multiple versions to provide maintenance and hotfix changes (based on customer needs), while still contributing to the Next Big Version that will contain the compelling new features (based on customer wishes).</p>
<p>Here's the code that produced the chart:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #000080; font-weight: bold;">data</span> Releases;
  <span style="color: #0000ff;">format</span> <span style="color: #0000ff;">Date</span> DATE7.;
  <span style="color: #0000ff;">input</span> Category $8. Release $7. <span style="color: #0000ff;">Date</span> DATE9. Details $20.;
  datalines;
Ancient <span style="color: #2e8b57; font-weight: bold;">1.0</span>    01Nov1999 SAS <span style="color: #2e8b57; font-weight: bold;">8.0</span>
Ancient <span style="color: #2e8b57; font-weight: bold;">1.1</span>    01Jul2000 SAS <span style="color: #2e8b57; font-weight: bold;">8.1</span>
Ancient <span style="color: #2e8b57; font-weight: bold;">1.2</span>    01Apr2001 SAS <span style="color: #2e8b57; font-weight: bold;">8.2</span>
Ancient <span style="color: #2e8b57; font-weight: bold;">1.3</span>    01Sep2001 
Ancient <span style="color: #2e8b57; font-weight: bold;">2.0</span>    01Sep2002 
Ancient <span style="color: #2e8b57; font-weight: bold;">2.05</span>   01May2003 SAS <span style="color: #2e8b57; font-weight: bold;">9.0</span>
Ancient <span style="color: #2e8b57; font-weight: bold;">2.1</span>    01Apr2004 SAS <span style="color: #2e8b57; font-weight: bold;">9.1</span>
Ancient <span style="color: #2e8b57; font-weight: bold;">3.0</span>    01May2004 .NET rewrite
Ancient <span style="color: #2e8b57; font-weight: bold;">3.02</span>   01Feb2005 remaster/L10N
Ancient <span style="color: #2e8b57; font-weight: bold;">4.1</span>    01Mar2006 
Ancient 4.1v   01Apr2007 Vista
Ancient <span style="color: #2e8b57; font-weight: bold;">4.2</span>    01Mar2009 SAS <span style="color: #2e8b57; font-weight: bold;">9.2</span>
Ancient <span style="color: #2e8b57; font-weight: bold;">4.22</span>   01Sep2009 SAS 9.2m2
Old     <span style="color: #2e8b57; font-weight: bold;">4.3</span>    01Aug2010
Old     4.305l 01Sep2010 L10N
Old     4.305r 01Jul2011 SAS <span style="color: #2e8b57; font-weight: bold;">9.3</span>
Old     <span style="color: #2e8b57; font-weight: bold;">5.1</span>    01Feb2012
Old     <span style="color: #2e8b57; font-weight: bold;">6.1</span>    01Jul2013 SAS <span style="color: #2e8b57; font-weight: bold;">9.4</span>
Old     <span style="color: #2e8b57; font-weight: bold;">7.1</span>    01Oct2014 
Old     <span style="color: #2e8b57; font-weight: bold;">7.11</span>   01May2015
Old     <span style="color: #2e8b57; font-weight: bold;">7.12</span>   01Feb2016
Old     <span style="color: #2e8b57; font-weight: bold;">7.13</span>   01Nov2016 SAS 9.4m4
Recent  <span style="color: #2e8b57; font-weight: bold;">7.15</span>   01Sep2017 SAS 9.4m5
Recent  <span style="color: #2e8b57; font-weight: bold;">8.1</span>    01Jun2019 Redesign
Recent  <span style="color: #2e8b57; font-weight: bold;">8.2</span>    01Nov2019
Recent  <span style="color: #2e8b57; font-weight: bold;">8.3</span>    18Aug2020 SAS 9.4m7
Recent  <span style="color: #2e8b57; font-weight: bold;">8.4</span>    19Mar2024 SAS Viya
Recent  <span style="color: #2e8b57; font-weight: bold;">8.5</span>    04Dec2024 
Recent  <span style="color: #2e8b57; font-weight: bold;">8.6</span>    19Jun2025 SAS Viya Workbench
;
&nbsp;
<span style="color: #006400; font-style: italic;">/* running in SAS EG - modify active ODS to add title to graph */</span>
ods html5<span style="color: #66cc66;">&#40;</span>id=eghtml<span style="color: #66cc66;">&#41;</span> style=htmlencore gtitle;
&nbsp;
ods graphics / height=<span style="color: #2e8b57; font-weight: bold;">850</span> width=<span style="color: #2e8b57; font-weight: bold;">1300</span> ;
<span style="color: #0000ff;">title</span> font=<span style="color: #a020f0;">&quot;Anova&quot;</span> height=<span style="color: #2e8b57; font-weight: bold;">2.2</span> color=cx0766D1 
  <span style="color: #a020f0;">&quot;SAS Enterprise Guide Releases (1999-2025)&quot;</span>;
<span style="color: #000080; font-weight: bold;">proc sgplot</span> <span style="color: #000080; font-weight: bold;">data</span>=Releases noautolegend;
  styleattrs datacolors=<span style="color: #66cc66;">&#40;</span>cxC4DEFD cxFFCC33 cx4398F9<span style="color: #66cc66;">&#41;</span>;
  block <span style="color: #0000ff;">x</span>=<span style="color: #0000ff;">date</span> block=category / transparency = <span style="color: #2e8b57; font-weight: bold;">0.75</span> 
     valueattrs=<span style="color: #66cc66;">&#40;</span>weight=bold size=14pt color=navy 
      family=<span style="color: #a020f0;">'Anova'</span><span style="color: #66cc66;">&#41;</span>;
  scatter <span style="color: #0000ff;">x</span>=<span style="color: #0000ff;">date</span> y=release / datalabel=Details 
    datalabelpos=topleft dataskin=matte
    datalabelattrs=<span style="color: #66cc66;">&#40;</span>size=10pt weight=bold Family=<span style="color: #a020f0;">&quot;Anova&quot;</span><span style="color: #66cc66;">&#41;</span>
    markerattrs=<span style="color: #66cc66;">&#40;</span>symbol=CircleFilled color=cxFF66B2 size=<span style="color: #2e8b57; font-weight: bold;">14</span><span style="color: #66cc66;">&#41;</span>;
  xaxis grid type=<span style="color: #0000ff;">time</span> offsetmax=<span style="color: #2e8b57; font-weight: bold;">0.1</span> offsetmin=<span style="color: #2e8b57; font-weight: bold;">0</span> valueattrs=<span style="color: #66cc66;">&#40;</span>Family=<span style="color: #a020f0;">&quot;Anova&quot;</span><span style="color: #66cc66;">&#41;</span> 
        ranges=<span style="color: #66cc66;">&#40;</span><span style="color: #a020f0;">'01Jan1997'</span>d-<span style="color: #a020f0;">'01Jul2025'</span>d<span style="color: #66cc66;">&#41;</span> <span style="color: #0000ff;">display</span>=<span style="color: #66cc66;">&#40;</span>nolabel<span style="color: #66cc66;">&#41;</span> ;
  yaxis type=discrete grid offsetmax=<span style="color: #2e8b57; font-weight: bold;">0.1</span> valueattrs=<span style="color: #66cc66;">&#40;</span>Family=<span style="color: #a020f0;">&quot;Anova&quot;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #0000ff;">label</span>=<span style="color: #a020f0;">&quot;Release/Event&quot;</span> labelattrs=<span style="color: #66cc66;">&#40;</span>Family=<span style="color: #a020f0;">&quot;Anova&quot;</span><span style="color: #66cc66;">&#41;</span>;
  inset <span style="color: #a020f0;">&quot;Updated &amp;SYSDATE9.&quot;</span> / 
     textattrs=<span style="color: #66cc66;">&#40;</span>weight=bold<span style="color: #66cc66;">&#41;</span> position=bottomright;
<span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2025/07/03/eg-versions-through-years/">Through the years: SAS Enterprise Guide versions</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.sas.com/content/sasdummy/2025/07/03/eg-versions-through-years/feed/</wfw:commentRss>
			<slash:comments>24</slash:comments>
		
		
			<enclosure url="https://blogs.sas.com/content/sasdummy/files/2024/04/egversions2025-150x150.jpg" />
	</item>
		<item>
		<title>How I use BirdNET-PI and SAS to track my feathered neighbors</title>
		<link>https://blogs.sas.com/content/sasdummy/2025/06/23/birdnetpi-reporting-sas/</link>
					<comments>https://blogs.sas.com/content/sasdummy/2025/06/23/birdnetpi-reporting-sas/#comments</comments>
		
		<dc:creator><![CDATA[Chris Hemedinger]]></dc:creator>
		<pubDate>Mon, 23 Jun 2025 09:00:00 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Internet of Things]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[SAS programming]]></category>
		<guid isPermaLink="false">https://blogs.sas.com/content/sasdummy/?p=8166</guid>

					<description><![CDATA[<p>How I collected birdsong detection data from BirdNET-PI and used SAS to visualize the bird visits across the seasons.</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2025/06/23/birdnetpi-reporting-sas/">How I use BirdNET-PI and SAS to track my feathered neighbors</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>They say that when you turn 50, you either get really into World War II documentaries, grilling thermometers, or birds. I chose birds. (Okay, and maybe a little grilling.) </p>
<p>For years my wife and I have enjoyed using <a href="https://merlin.allaboutbirds.org/">the Merlin app (from Cornell labs)</a> on our smartphones to identify the birds we hear around our home. The app is like Shazam for birds, but instead of telling you it's Taylor Swift, it tells you it's a Chimney Swift (or maybe a Carolina Wren). As fun as that is, the Merlin app has a limitation: it can only listen when <strong>you</strong> listen in the moment.</p>
<h2>Enter BirdNET-PI</h2>
<p>BirdNET-PI is a Raspberry Pi-based system that uses machine learning to detect and identify birdsongs in real time. </p>
<p>I set up a BirdNET-PI device in my backyard in Raleigh, NC. It listens 24/7, logs detections, and stores them in a local database. Within days, I had a treasure trove of bird call data—timestamps, species names, confidence scores, and audio clips. It's been running for over 6 months now, and it has detected over 140,000 bird songs!</p>
<p>I first learned about BirdNET-PI during a session at <a href="https://allthingsopen.org/">All Things Open</a>, a huge annual conference about open source technologies and community. (SAS has been a sponsor of the event.) You can learn more about <a href="https://www.linkedin.com/posts/cjdinger_raspberrypi-opensource-birdnet-activity-7272425902561529858-6JOD?utm_source=share&utm_medium=member_desktop&rcm=ACoAAAEDBMcBtJJ5vKKZo2DU_w84x1_x02JUjRg">my experience with BirdPI-NET by reading this post</a> I shared on LinkedIn. </p>
<h2>From Chirps to Charts with SAS</h2>
<p>Naturally, I wanted to do more than just listen. I wanted to see the patterns. So I built a SAS program to ingest the BirdNET-PI data and generate reports:</p>
<ul>
<li>Species frequency over time: Which birds are most common in the morning vs. evening?
</li>
<li>Seasonal trends: Are the warblers just passing through, or do they stick around?
</li>
<li>Confidence heatmaps: How sure is BirdNET-PI about what it hears?
</li>
</ul>
<p>Using combination of SAS code and SAS Visual Analytics, I created dashboards that let me explore the data interactively. Here are a few example insights I've captured.</p>
<p>First, a heatmap of all of the bird species and the number of detections over time. It's a long chart because there are over 100 detected species. From this chart you can see that some birds are seasonal (obviously!) while others we hear all year long!</p>
<figure style="width: 1011px" class="wp-caption alignnone"><a href="https://blogs.sas.com/content/sasdummy/files/2025/06/birdpi-heatmap.jpg"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2025/06/birdpi-heatmap.jpg" alt="" width="1011" height="2010" class="alignleft size-full wp-image-8245" srcset="https://blogs.sas.com/content/sasdummy/files/2025/06/birdpi-heatmap.jpg 1011w, https://blogs.sas.com/content/sasdummy/files/2025/06/birdpi-heatmap-151x300.jpg 151w, https://blogs.sas.com/content/sasdummy/files/2025/06/birdpi-heatmap-515x1024.jpg 515w, https://blogs.sas.com/content/sasdummy/files/2025/06/birdpi-heatmap-768x1527.jpg 768w, https://blogs.sas.com/content/sasdummy/files/2025/06/birdpi-heatmap-773x1536.jpg 773w" sizes="(max-width: 1011px) 100vw, 1011px" /></a><figcaption class="wp-caption-text">Full detections as of June 2025</figcaption></figure>
<p>Our listening device is always on and working hard. From this Daily Detections plot, you can see that it's picking up anywhere from dozens to thousands of detections per day!<br />
<figure style="width: 1160px" class="wp-caption alignnone"><a href="https://communities.sas.com/t5/image/serverpage/image-id/107951i6F73322C449DF5C4"><img loading="lazy" decoding="async" src="https://communities.sas.com/t5/image/serverpage/image-id/107951i6F73322C449DF5C4" width="1160" height="587" class="size-full" /></a><figcaption class="wp-caption-text">Daily detections of birdsongs</figcaption></figure>
<p>I've configured our BirdNET-PI device to record detections only if the machine learning algorithm scores the certainty at 0.7 (70%) or higher. In this SAS Visual Analytics table, I've enabled the "heat map" visualization for the Confidence value for each detection. The algorithm isn't just matching the bird song with 5-second snippets -- it's also considering our geography and time of year when it assigns the probability (in case a song <em>sounds a bit</em> like a European magpie, but we know that just <em>cannot be</em> in my backyard).</p>
<figure style="width: 631px" class="wp-caption alignnone"><a href="https://communities.sas.com/t5/image/serverpage/image-id/107950i907E29CBA52F35F4"><img loading="lazy" decoding="async" src="https://communities.sas.com/t5/image/serverpage/image-id/107950i907E29CBA52F35F4" width="631" height="449" class="size-full" /></a><figcaption class="wp-caption-text">Confidence heatmaps for the detections</figcaption></figure>
<p>Some species visit only in certain seasons, and hummingbirds are back! We've put out our hummingbird feeders and it's bringing them in. Our BirdNET-PI device is detecting their chirps, as you can see from this SAS Visual Analytics chart.</p>
<figure style="width: 805px" class="wp-caption alignnone"><a href="https://communities.sas.com/t5/image/serverpage/image-id/107949iDE5977F7FD9E1A35"><img loading="lazy" decoding="async" src="https://communities.sas.com/t5/image/serverpage/image-id/107949iDE5977F7FD9E1A35" width="805" height="472" class="size-full" /></a><figcaption class="wp-caption-text">Hummingbird season again!</figcaption></figure>
<p>We're always delighted when we hear owls. They are with us year round, but you can see that they are more vocal in the springtime. I'm guessing they are looking for love, or at least a hootin' good time!</p>
<figure style="width: 1171px" class="wp-caption alignnone"><a href="https://communities.sas.com/t5/image/serverpage/image-id/107952i6961242B1EFBFC77"><img loading="lazy" decoding="async" src="https://communities.sas.com/t5/image/serverpage/image-id/107952i6961242B1EFBFC77" width="1171" height="591" class="size-full" /></a><figcaption class="wp-caption-text">Owls, the original hooters</figcaption></figure>
<h2>Try it yourself: analyze our birdsong data!</h2>
<p>Interested in seeing what you can do with this data? I periodically update my GitHub site with the latest detection data from our device. You can always grab the latest with this SAS code:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #0000ff;">filename</span> birdcsv temp;
<span style="color: #000080; font-weight: bold;">proc http</span>
 method=<span style="color: #a020f0;">&quot;GET&quot;</span>
 url=<span style="color: #a020f0;">&quot;https://raw.githubusercontent.com/cjdinger/birdnet-data/refs/heads/main/alldetect.csv&quot;</span>
 out=birdcsv;
<span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
<span style="color: #000080; font-weight: bold;">proc import</span> <span style="color: #0000ff;">file</span>=birdcsv
 out=birds
 dbms=csv
 <span style="color: #0000ff;">replace</span>;
<span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p>On my GitHub project, <a href="https://github.com/sascommunities/sas-dummy-blog/blob/master/birdnet-pi/bird-events.sas">you can also grab a more complete program</a> that imports the data, summarizes it a bit, and generates the heatmap chart.</p>
<h2>Building a happy nest for birds and data</h2>
<p>This project has been the perfect mashup of my love for nature and my obsession with data. Even better? It's one of the few tech experiments my wife hasn't just tolerated—-she's genuinely into it. She checks the bird detection logs like she's reading the morning paper, and she even let me mount a microphone on the side of the house and set up a Raspberry Pi in the family room. Some might say she's humoring me in my "mature years," but I prefer to think I’ve finally proven that marrying a data nerd has its perks. At the very least, our living room now has the best bird surveillance system on the block.</p>
<h3>Want to build your own?</h3>
<p>If you're inspired to put together your own BirdNET-PI device, <a href="https://github.com/Nachtzuster/BirdNET-Pi">here's a link to the instructions that I used</a>. The Rasberry Pi device and accessories cost only about $40 US, and I already had a suitable microphone in my box of disused equipment.</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2025/06/23/birdnetpi-reporting-sas/">How I use BirdNET-PI and SAS to track my feathered neighbors</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.sas.com/content/sasdummy/2025/06/23/birdnetpi-reporting-sas/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			<enclosure url="https://blogs.sas.com/content/sasdummy/files/2025/06/birdnetpi-dailydetect-150x150.jpg" />
	</item>
		<item>
		<title>What&#039;s next for SAS 9 and SAS Enterprise Guide?</title>
		<link>https://blogs.sas.com/content/sasdummy/2025/05/13/sas-9-and-sas-eg/</link>
					<comments>https://blogs.sas.com/content/sasdummy/2025/05/13/sas-9-and-sas-eg/#comments</comments>
		
		<dc:creator><![CDATA[Chris Hemedinger]]></dc:creator>
		<pubDate>Tue, 13 May 2025 14:00:48 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[SAS 9.4]]></category>
		<category><![CDATA[SAS Enterprise Guide]]></category>
		<category><![CDATA[SAS Explore]]></category>
		<category><![CDATA[SAS Viya]]></category>
		<guid isPermaLink="false">https://blogs.sas.com/content/sasdummy/?p=7742</guid>

					<description><![CDATA[<p>SAS announces continued support and releases for SAS 9 and a new role for SAS Enterprise Guide with SAS Viya.</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2025/05/13/sas-9-and-sas-eg/">What&#039;s next for SAS 9 and SAS Enterprise Guide?</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>At SAS Explore 2023, Bryan Harris (SAS CTO) and Susan Owenby (head of the SAS 9 division in R&D) appeared on main stage with a strong message about the future of SAS 9. From my conversations with attendees afterward, it seems clear that this is exactly what many customers have been waiting for.</p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2023/09/sas9.jpg"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2023/09/sas9-300x200.jpg" alt="" width="300" height="200" class="alignright size-medium wp-image-7760" srcset="https://blogs.sas.com/content/sasdummy/files/2023/09/sas9-300x200.jpg 300w, https://blogs.sas.com/content/sasdummy/files/2023/09/sas9.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" /></a>To summarize what was announced on stage (and note, I have updated this list in <strong>May 2025</strong> to reflect latest progress and announcements):</p>
<ul>
<li>SAS 9 will be available to our customers as they transition to SAS Viya.
</li>
<li>SAS is investing in SAS 9 with the creation of the <b>SAS 9</b> division. The SAS 9 division comprises developers, testers and product managers, all devoted to keeping SAS 9 relevant and its customers productive with their platform.
</li>
<li>SAS released SAS 9.4 Maintenance 9 (SAS 9.4M9) in June 2025. (Recall that SAS released SAS 9.4 M8 in early 2023.) The team releases SAS 9.4 quarterly security updates and fixes as needed.
</li>
<li>There <b>will</b> be future releases of SAS 9. The <a href="https://support.sas.com/en/technical-support/services-policies.html">SAS software support policy promises standard support</a> for a release for 5 years from its general-availability date. With more SAS 9 releases on the horizon, support for SAS 9 will move forward beyond that for many years to come. (As <a href="https://communities.sas.com/t5/Ask-the-Expert/What-s-New-in-SAS-9-M9-Q-amp-A-Slides-and-On-Demand-Recording/ta-p/966340">confirmed in a recent webinar</a>, M10 is already the books for a future release.)
</li>
<li>Beginning with SAS Enterprise Guide 8.4, you can connect to SAS Viya. Soon you can also connect to SAS Viya Workbench (SAS Enterprise Guide 8.6, scheduled for June 2025).
</li>
</ul>
<a href="https://communities.sas.com/t5/Ask-the-Expert/What-s-New-in-SAS-9-M9-Q-amp-A-Slides-and-On-Demand-Recording/ta-p/966340" class="sc-button sc-button-default"><span><span class="btnheader">FREE WEBINAR | </span> WHAT'S NEW IN SAS 9.4 MAINTENANCE 9?</span></a>
<h2>Building a bridge to SAS Viya</h2>
<p>Even with this focus on SAS 9, SAS is not letting up on our attention to SAS Viya. The SAS Viya platform  <a href="https://communities.sas.com/t5/SAS-Viya-Release-Updates/tkb-p/releaseupdates">has monthly releases</a> and is where most new innovation takes place. However, the move to SAS Viya from SAS 9 can be a big project, and SAS continues to build new tools and processes to help customers assess and migrate their analytics work to the more modern platform.</p>
<p>As part of this effort, Bryan and Susan announced that <strong>SAS Enterprise Guide will soon be able to connect to a SAS Viya 4 environment</strong>. (And, as of March 2024, <a href="https://blogs.sas.com/content/sgf/2024/03/22/sas-eg-on-viya/">this is now available as <strong>SAS Enterprise Guide 8.4</strong></a>!) This is a change from previous direction, and is a direct result of customer feedback. Up until now, SAS Enterprise Guide was tethered to SAS 9 only, because SAS Studio (with its many enhancements) has been the deluxe coding interface for SAS Viya. SAS Studio is <em>still</em> the best environment to leverage SAS Viya features, but can use SAS Enterprise Guide as a bridge to leverage your existing projects and code workflows as you adopt SAS Viya.</p>
<a href="https://www.sas.com/en_us/webinars/enterprise-guide-integrated-viya.html" class="sc-button sc-button-default"><span><span class="btnheader">FREE WEBINAR | </span> SAS ENTERPRISE GUIDE IS NOW INTEGRATED WITH SAS VIYA 4</span></a>
<h2>SAS programmers are spoiled for choice</h2>
<p>In addition to these SAS 9 announcements, SAS Explore <a href="https://www.sas.com/en_us/software/viya/workbench.html">featured the premier of SAS Viya Workbench</a>, a light-weight cloud-native coding environment for developers using SAS, Python, and R. These are all native code experiences that leverage the SAS Viya platform with your favorite programming language. SAS Viya Workbench allows you to use VS Code, Jupyter Notebooks, and even SAS Enterprise Guide for your coding experience. Read more about these technology announcements <a href="https://www.sas.com/en_us/news/press-releases/2023/september/saas-products-rapid-ai-application-development.html">in this news release</a>.</p>
<p>And if you love VS Code (I do), you can use the <a href="https://blogs.sas.com/content/sasdummy/2024/02/13/vs-code-sas">SAS extension for VS Code right now</a> to manage and view your SAS programs, while connecting to SAS Viya or SAS 9 environments to run programs and view results.</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2025/05/13/sas-9-and-sas-eg/">What&#039;s next for SAS 9 and SAS Enterprise Guide?</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.sas.com/content/sasdummy/2025/05/13/sas-9-and-sas-eg/feed/</wfw:commentRss>
			<slash:comments>18</slash:comments>
		
		
			<enclosure url="https://blogs.sas.com/content/sasdummy/files/2023/09/LVE29847_2-150x150.jpg" />
	</item>
		<item>
		<title>SAS For Dummies: New edition for the modern SAS user</title>
		<link>https://blogs.sas.com/content/sasdummy/2025/04/14/sas-for-dummies-3rd-ed/</link>
					<comments>https://blogs.sas.com/content/sasdummy/2025/04/14/sas-for-dummies-3rd-ed/#respond</comments>
		
		<dc:creator><![CDATA[Chris Hemedinger]]></dc:creator>
		<pubDate>Mon, 14 Apr 2025 17:50:18 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[sas press]]></category>
		<category><![CDATA[sas users]]></category>
		<category><![CDATA[SAS Viya]]></category>
		<guid isPermaLink="false">https://blogs.sas.com/content/sasdummy/?p=8102</guid>

					<description><![CDATA[<p>Introducing the new third edition of SAS For Dummies, covering SAS 9.4, SAS Viya, SAS Visual Analytics, SAS Viya Workbench and more!</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2025/04/14/sas-for-dummies-3rd-ed/">SAS For Dummies: New edition for the modern SAS user</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I wrote the first edition of <em>SAS For Dummies</em> nearly 20 years ago (published in 2007 with coauthor Stephen McDaniel). It's not a stretch to say that the book altered the trajectory of my career. That book was actually the launch pad for this blog, <a href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>. Together, these propelled me to "SAS fame" (which is a special sort of fame among SAS enthusiasts) and opened the door to more customer-facing activities like user groups and other conferences. I have travelled the world and met thousands of SAS customers, all thanks to the connections I've made from the book and in my writings since. I took more customer-centric roles at SAS, first in professional services then in communications, all leading to my most recent job as leader of SAS User Engagement.</p>
<p>SAS has seen some changes since those early <em>Dummies</em> days. Until now, the most recent edition of the book was from 2009 and covered SAS 9.2 and its era of applications. So I was excited when Wiley, the publisher of all <em>Dummies</em> books, approached me in late 2024 to write a third edition. "We still sell copies of this book even though it's 15 years old. We think an updated version could be successful." (I was also a bit apprehensive, because I know how much work it is to write a book on a <em>Dummies</em> schedule. It's basically an intense 14-week sprint of writing, followed by a few weeks of quick-turnaround edits. But no way was I going to let <strong>somebody else</strong> write it!)</p>
<h2>The new <em>SAS For Dummies</em></h2>
<p>I'm pleased to say that <em><a href="https://www.redshelf.com/app/ecom/book/2840389/sas-for-dummies-2840389-9781394317400-chris-hemedinger">SAS For Dummies, 3rd Edition</a></em> is now available, and I am very proud of the results! This new edition addresses all of the ways that people use SAS today, covering SAS 9.4 and SAS Viya. It has chapters about SAS programming, data management, reporting, machine learning, and data visualization. The book shows the pantheon of modern SAS tools like SAS Visual Analytics, SAS Model Studio and Model Manager, SAS for Microsoft 365, SAS Viya Workbench, and of course the ever-enduring SAS Enterprise Guide. </p>
<figure id="attachment_8138" aria-describedby="caption-attachment-8138" style="width: 1790px" class="wp-caption alignnone"><a href="https://blogs.sas.com/content/sasdummy/files/2025/04/dummies-plots.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2025/04/dummies-plots.png" alt="" width="1790" height="1119" class="size-full wp-image-8138" srcset="https://blogs.sas.com/content/sasdummy/files/2025/04/dummies-plots.png 1790w, https://blogs.sas.com/content/sasdummy/files/2025/04/dummies-plots-300x188.png 300w, https://blogs.sas.com/content/sasdummy/files/2025/04/dummies-plots-1024x640.png 1024w, https://blogs.sas.com/content/sasdummy/files/2025/04/dummies-plots-768x480.png 768w, https://blogs.sas.com/content/sasdummy/files/2025/04/dummies-plots-1536x960.png 1536w, https://blogs.sas.com/content/sasdummy/files/2025/04/dummies-plots-343x215.png 343w" sizes="(max-width: 1790px) 100vw, 1790px" /></a><figcaption id="caption-attachment-8138" class="wp-caption-text">Except from <em>SAS For Dummies, 3rd Edition</em></figcaption></figure>
<p>You can find the book anywhere that <em>Dummies</em> titles are sold, including <a href="https://www.barnesandnoble.com/w/sas-for-dummies-chris-hemedinger/1015584364?ean=9781394317394">Barnes & Noble</a>, <a href="https://a.co/d/2Cwt9zM">Amazon</a>, and maybe even your local bookstore (support them!). You can also find it among all SAS books on RedShelf.</p>
<a href="https://www.redshelf.com/app/ecom/book/2840389/sas-for-dummies-2840389-9781394317400-chris-hemedinger" class="sc-button sc-button-default"><span><span class="btnheader">SAS For Dummies, 3rd Ed | </span> See the book on RedShelf</span></a>
<p>We'll have some copies of the book at <a href="https://innovate.sas.com/">the upcoming SAS Innovate event</a>! (I can't wait, because that might be the first time I get my hands on it too!) If you're lucky enough to snag a copy, come find me and I'll sign it for you (but only if you really want that).</p>
<h2>Book credits</h2>
<p>As the writer I curated all of the content, examples, and graphics -- but as with most tech books like this, there is a huge team of people that make it a great product. I'm especially grateful to Jennifer Tamburro, my longtime friend and colleague (and SAS documentation writer) who served as Technical Editor. And of course the multiple other editors and production crew at Wiley, who accepted my pile of chapters with edits and screen shots, and turned it into an amazing publication.</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2025/04/14/sas-for-dummies-3rd-ed/">SAS For Dummies: New edition for the modern SAS user</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.sas.com/content/sasdummy/2025/04/14/sas-for-dummies-3rd-ed/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			<enclosure url="https://blogs.sas.com/content/sasdummy/files/2025/04/sas-for-dummies-3ed-150x150.jpg" />
	</item>
		<item>
		<title>3 SAS Viya Workbench use cases for SAS Users</title>
		<link>https://blogs.sas.com/content/sasdummy/2024/12/13/sas-users-viya-workbench/</link>
		
		<dc:creator><![CDATA[Chris Hemedinger]]></dc:creator>
		<pubDate>Fri, 13 Dec 2024 19:28:50 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[SAS programming]]></category>
		<category><![CDATA[SAS Viya Workbench]]></category>
		<guid isPermaLink="false">https://blogs.sas.com/content/sasdummy/?p=8056</guid>

					<description><![CDATA[<p>Review these three cool use cases for SAS users, built using SAS Viya Workbench. SAS and Python for better working together!</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2024/12/13/sas-users-viya-workbench/">3 SAS Viya Workbench use cases for SAS Users</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I'm a "SAS first" kind of guy. If I can complete a data or programming task using SAS, that's what I'm going to do. But if there is a best practice or less complex approach that uses another programming language, then I'm happy to go on that path.</p>
<p>That's why <a href="https://www.sas.com/en_us/software/viya/workbench.html">SAS Viya Workbench is my new favorite tool</a> for SAS programming work. It's easy to spin up and load a project from a Git repository. All of my SAS code works great within it, and when I need something a little extra, like a Python task, I can accomplish that in the same environment. </p>
<p>I've recorded three short demos of work that I've done using SAS Viya Workbench.</p>
<h3>Wordle-like game in SAS Viya Workbench for Learners</h3>
<p><strong>Video:</strong> <a href="https://communities.sas.com/t5/SAS-Viya-Workbench-Getting/Demo-SAS-Viya-Workbench-for-Learners-amp-GitHub-project/ta-p/951735">Run my Wordle-like game (built in SAS) in SAS Viya Workbench for Learners</a>. </p>
<p>In this demo, I used a Git command to clone my <a href="https://blogs.sas.com/content/sasdummy/2022/03/17/wordle-sas/" rel="noopener" target="_blank">wordle-sas program</a> into a fresh environment, then was able to immediately "play" and embarrass myself with my guesses. If you are a student or faculty member at a university, <a href="https://www.sas.com/en_us/software/viya-workbench-for-learners.html" rel="noopener" target="_blank">you can use SAS Viya Workbench for Learners</a> too!</p>
<h3>SAS code to access SharePoint and OneDrive</h3>
<p><strong>Video:</strong> <a href="https://communities.sas.com/t5/SAS-Viya-Workbench-Getting/Demo-SAS-Viya-Workbench-and-SAS-code-to-access-Microsoft-365/ta-p/952476">Connect to Microsoft 365 files like SharePoint Online or OneDrive using SAS code</a>. </p>
<p>I wanted to demonstrate <a href="https://blogs.sas.com/content/sasdummy/2024/07/29/sas-programming-office-365-onedrive/" rel="noopener" target="_blank">how easy it is to connect to Microsoft 365 and work with files in SharePoint and OneDrive</a>, leveraging a library of helper macros I built in SAS.</p>
<h3>Python for Google Analytics data, SAS to analyze it</h3>
<p><strong>Video:</strong> <a href="https://communities.sas.com/t5/SAS-Viya-Workbench-Getting/Demo-SAS-Viya-Workbench-using-Python-SAS-for-Google-Analytics/ta-p/953094">Connect to Google Analytics using a supported Python client library, then analyze the data with SAS</a>. </p>
<p>Finally, I show off a real process that I use for my own reporting here at SAS -- monitoring the activity on our web sites using GA data in SAS tools. </p>
<p><a href="https://communities.sas.com/t5/SAS-Viya-Workbench/ct-p/viya-workbench"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2024/12/3-wb-demos.png" alt="" width="998" height="283" class="alignnone size-full wp-image-8068" srcset="https://blogs.sas.com/content/sasdummy/files/2024/12/3-wb-demos.png 998w, https://blogs.sas.com/content/sasdummy/files/2024/12/3-wb-demos-300x85.png 300w, https://blogs.sas.com/content/sasdummy/files/2024/12/3-wb-demos-768x218.png 768w" sizes="(max-width: 998px) 100vw, 998px" /></a></p>
<p>All of these demos -- and several more -- are available on the <a href="https://communities.sas.com/t5/SAS-Viya-Workbench-Getting/tkb-p/viya-workbench-get-started" rel="noopener" target="_blank">SAS Viya Workbench: Getting Started board</a>, hosted on SAS Communities. Check them out and let me know what you think!</p>
<a href="https://communities.sas.com/t5/SAS-Viya-Workbench-Getting/tkb-p/viya-workbench-get-started" class="sc-button sc-button-default"><span><span class="btnheader">SAS Viya Workbench | </span> Getting Started</span></a>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2024/12/13/sas-users-viya-workbench/">3 SAS Viya Workbench use cases for SAS Users</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></content:encoded>
					
		
		
			<enclosure url="https://blogs.sas.com/content/sasdummy/files/2024/12/wb-cover-150x150.png" />
	</item>
		<item>
		<title>Is SAS a programming language?</title>
		<link>https://blogs.sas.com/content/sasdummy/2024/09/13/sas-programming-language/</link>
					<comments>https://blogs.sas.com/content/sasdummy/2024/09/13/sas-programming-language/#comments</comments>
		
		<dc:creator><![CDATA[Chris Hemedinger]]></dc:creator>
		<pubDate>Fri, 13 Sep 2024 18:51:21 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Developers]]></category>
		<category><![CDATA[SAS programming]]></category>
		<category><![CDATA[SAS Viya Workbench]]></category>
		<guid isPermaLink="false">https://blogs.sas.com/content/sasdummy/?p=8017</guid>

					<description><![CDATA[<p>SAS has a programming language, but IS that all it is? Nope, but it still ranks high as a most marketable programming skill.</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2024/09/13/sas-programming-language/">Is SAS a programming language?</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>As a long-time developer and technologist, my news feed always lights up when tech media outlets release their annual "Top Programming Languages" lists. Examples include the <a href="https://www.tiobe.com/tiobe-index/">annual TIOBE Index</a>, <a href="https://survey.stackoverflow.co/2024/">StackOverflow Developer Survey</a> and the <a href="https://spectrum.ieee.org/top-programming-languages-2024">IEEE Spectrum list</a>. "SAS" always appears on these lists as a programming language, although historically it scores a middling ranking for reasons I'll describe in just a bit.</p>
<p>However, the <a href="https://spectrum.ieee.org/top-programming-languages-2024">2024 IEEE Spectrum "Top Programming Languages" list</a> recently placed SAS at the #5 position when the ranking is weighted for "job opportunities". This surprise validation has excited a lot of us SAS fans, as this confirms something that we've known all along. Organizations in all industries rely on SAS technology for mission-critical tasks, and they recruit SAS-skilled talent to maintain these and get the most from their SAS investment.</p>
<p>The methodology for tracking programming language popularity usually does not favor SAS. That's because these rankings track public activity such as "prevalence on GitHub or public repositories", "amount of search traffic" in public search engines, or "discussion activity on forums like StackOverflow or Reddit." As a vendor-supported technology, most internet activity for SAS is concentrated on SAS sites and communities. And since SAS customers often work in regulated industries building proprietary methods and models – they cannot and would not share this work on GitHub, at least not at the scale you might see for the top-ranked languages like Java or C. (By the way, SAS users <strong>do</strong> freely share their knowledge on <a href="https://communities.sas.com/">our own community</a> and <a href="https://innovate.sas.com/event/8ab28f0a-ebf2-40d1-a8e7-650dc34d7777">in-person at SAS user events</a>, which I am very grateful for.)</p>
<p>I've often said that if we could rank languages by "amount of code that is running in production systems at organizations around the world," SAS would rise to the top.</p>
<h2>But does SAS even belong on a "programming languages" list?</h2>
<p>I'm going to get pedantic here: SAS is not a programming language. SAS <em>has</em> a programming language. (Actually, SAS has several programming languages.) The SAS programming language you're thinking of (DATA step, PROCs and SAS macro) provides access to all the capabilities of SAS: data management, analytics, machine learning and AI, and more. While most SAS users leverage code to get to these capabilities, there are many other interfaces and methods that provide access as well.</p>
<p>Most of the programming languages that appear on these "top language" lists do not provide inherent capabilities for any specific discipline. For example, Java is a popular object-oriented language that is used to teach computer science concepts in schools. Its standard libraries provide basic access to operating system services and computation. But in industry, Java is most often used with specific frameworks to build things like mid-tier applications or embedded systems. Developers add these frameworks to the stew to provide the capabilities, and the Java syntax is their tool to unlock them. The same is true for C and C++. (By the way, C is the programming language that is used to build the core capabilities of SAS – so we love the C language here.)</p>
<p>Many programming languages are agnostic of discipline/industry. If you tell me that you are a Java or C programmer, then I know what syntax you use for coding but I don't know anything about your real job. Some languages provide cues about your specialty. If you tell me that you are a TypeScript programmer, then I might guess that you build web applications using the React framework…because I know that is a common use for TypeScript. (Many of our SAS application front-end experiences are built with React.) </p>
<p>But if you tell me that you "program with SAS", then I know immediately that you work with data and statistics. With SAS, you do not have to add additional frameworks or libraries to get work done – it's all built-in with hundreds of SAS procedures and analytics actions.</p>
<h3>Yes (please) Code</h3>
<p>We live in a world with much hype about "low-code" and "no-code" workflows. Companies say they don't want to require programming skills to unlock value from the systems they have invested in. While we have that covered in the SAS Viya platform, we've also doubled down on the developer who just wants to, you know, code. </p>
<h3>Are you a SAS fan or a SAS snob?</h3>
<p>Here's how I make the subtle distinction:</p>
<ul>
<li>SAS fan: "I rarely find anything in my job I cannot accomplish by using SAS."
</li>
<li>SAS snob: "If I can't accomplish a task with SAS, it's not worth doing!"
</li>
</ul>
<p>We celebrate both personas here, but even I admit that I'm just a SAS fan, not a SAS snob. As a developer I appreciate a specific tool for what it can do for me, but not to the exclusion of everything else.</p>
<h2>SAS Viya Workbench will make you a fan</h2>
<p>If you're a "get out of the way and let me code" kind of person, then you will love <a href="http://www.sas.com/workbench">SAS Viya Workbench</a>.</p>
<a href="http://www.sas.com/workbench" class="sc-button sc-button-default"><span><span class="btnheader">SAS Viya Workbench | </span> Learn more</span></a>
<p>SAS Viya Workbench is a developer-first IDE that provides access to SAS' analytic capabilities using the SAS programming language, or Python…and soon R. SAS Viya Workbench brings the developer experience to the forefront in a way that I appreciate, using the familiar VS Code environment that I'm already so familiar with. SAS Viya Workbench launches quickly in my browser, relieving me of the task of installing SAS (something I have done hundreds of times without complaint!), and it spins down when I'm not using it. I love to use it for work and it's fun to demo for SAS users.</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2024/09/13/sas-programming-language/">Is SAS a programming language?</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.sas.com/content/sasdummy/2024/09/13/sas-programming-language/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			<enclosure url="https://blogs.sas.com/content/sasdummy/files/2024/09/1712938789031-150x150.png" />
	</item>
		<item>
		<title>Lengths and formats in SAS: the long and short of it</title>
		<link>https://blogs.sas.com/content/sasdummy/2024/07/22/lengths-and-formats-the-long-and-short-of-it/</link>
					<comments>https://blogs.sas.com/content/sasdummy/2024/07/22/lengths-and-formats-the-long-and-short-of-it/#comments</comments>
		
		<dc:creator><![CDATA[Chris Hemedinger]]></dc:creator>
		<pubDate>Mon, 22 Jul 2024 12:00:00 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[formats]]></category>
		<category><![CDATA[informats]]></category>
		<category><![CDATA[SAS programming]]></category>
		<category><![CDATA[SAS tips]]></category>
		<guid isPermaLink="false">http://blogs.sas.com/sasdummy/index.php?/archives/21-Lengths-and-formats-the-long-and-short-of-it.html</guid>

					<description><![CDATA[<p>What's the difference between LENGTH and FORMAT in a SAS data set? This article shares the answer, with examples.</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2024/07/22/lengths-and-formats-the-long-and-short-of-it/">Lengths and formats in SAS: the long and short of it</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Here's a question we often see from new SAS users: when I combine two data sets with a common-named column, why does the resulting data set seem to cut the length short on the shared column? In other words, when combining SAS data sets that have same-named columns, how does SAS decide the length and format of the columns in the output data?</p>
<p>Let's start with some definitions related to columns.</p>
<p><strong>Length</strong>: The column <em>length</em>, in SAS terms, is the amount of storage allocated in the data set to hold the column values. The length is specified in bytes. For numeric columns, the valid lengths are usually 3 through 8. The longer the length, the greater the precision allowed within the column values. For character columns, the length can be 1 through 32767. For single-byte data values, that equates to the number of characters the column can hold. For multibyte data values (DBCS, Unicode, or UTF-8), where a character can occupy more than one byte, the number of characters that fit might be less than the length value of the column.</p>
<p><strong>Format</strong>: The column <em>format</em>, in SAS terms, is a basically an instruction for how to transform a raw value into an appearance that is suitable for a given purpose. A basic attribute of a format is the format length, which controls how much of the value is displayed. For example, a character column might have a storage length of 10 bytes, but a format length of 5 characters ($5. format), so when you see the formatted values you will see at most 5 characters for each record.</p>
<p>Another attribute of the format is the displayed precision. For example, the DOLLAR8. format will show you up to 8 characters of a value (including a currency symbol and thousands separator) in dollars, but no cents. DOLLAR8.2 will show you the decimal point and the value to the nearest cent (2 decimal spaces). In each case, the value displayed will not exceed 8 characters.</p>
<p>What happens if the formatted value runs into trouble squeezing into 8 characters? SAS drops the thousands separator and currency symbol to free up 2 slots first. If that's not enough, SAS begins to drop precision by lopping off the pennies, then the dimes. If that's still not enough, SAS rounds the value and uses scientific notation and other tricks to save space -- all the while keeping the integrity of your original value for use in any calculations.</p>
<p>For example, run this program:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #000080; font-weight: bold;">data</span> dollars;
 <span style="color: #0000ff;">length</span> val1 <span style="color: #2e8b57; font-weight: bold;">8</span> val2 <span style="color: #2e8b57; font-weight: bold;">8</span> val3 <span style="color: #2e8b57; font-weight: bold;">8</span> val4 <span style="color: #2e8b57; font-weight: bold;">8</span>;
 <span style="color: #0000ff;">format</span> val1 DOLLAR8. val2 DOLLAR8.2 val3 DOLLAR4.2 val4 DOLLAR10.2;
 val1=<span style="color: #2e8b57; font-weight: bold;">12345.67</span>;
 val2=<span style="color: #2e8b57; font-weight: bold;">12345.67</span>;
 val3=<span style="color: #2e8b57; font-weight: bold;">12345.67</span>;
 val4=<span style="color: #2e8b57; font-weight: bold;">12345.67</span>;
&nbsp;
<span style="color: #000080; font-weight: bold;">run</span>;
<span style="color: #000080; font-weight: bold;">proc print</span>;
<span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p>You see these values:<br />
<pre class="preserve-code-formatting">val1    $12,346
val2    12345.67
val3    12E3
val4    $12,345.67</pre><br />
In the case where you are combining two data sources that have a common column, the results depend on the sequence of things. For example, consider this SAS program:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #000080; font-weight: bold;">data</span> long;
  <span style="color: #0000ff;">length</span> name $ <span style="color: #2e8b57; font-weight: bold;">8</span>;
  <span style="color: #0000ff;">format</span> name $8.;
  <span style="color: #0000ff;">infile</span> datalines dsd;
  <span style="color: #0000ff;">input</span> name;
<span style="color: #0000ff;">datalines4</span>;
aaaaaaaa
bbbbbbbb
cccccccc
dddddddd
;;;;
<span style="color: #000080; font-weight: bold;">run</span>; 
&nbsp;
<span style="color: #000080; font-weight: bold;">data</span> short;
  <span style="color: #0000ff;">length</span> name $ <span style="color: #2e8b57; font-weight: bold;">4</span>;
  <span style="color: #0000ff;">format</span> name $4.;
  <span style="color: #0000ff;">infile</span> datalines dsd;
  <span style="color: #0000ff;">input</span> name;
<span style="color: #0000ff;">datalines4</span>;
eeee
ffff
gggg
hhhh
;;;;
<span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
<span style="color: #000080; font-weight: bold;">data</span> longfirst;
  <span style="color: #0000ff;">set</span> long short;
<span style="color: #000080; font-weight: bold;">run</span>;
<span style="color: #000080; font-weight: bold;">proc contents</span>; <span style="color: #000080; font-weight: bold;">run</span>;
<span style="color: #000080; font-weight: bold;">proc print</span>; <span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
<span style="color: #000080; font-weight: bold;">data</span> shortfirst;
  <span style="color: #0000ff;">set</span> short long;
<span style="color: #000080; font-weight: bold;">run</span>;
<span style="color: #000080; font-weight: bold;">proc contents</span>; <span style="color: #000080; font-weight: bold;">run</span>;
<span style="color: #000080; font-weight: bold;">proc print</span>; <span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p>If you SET the table with the <strong>short</strong> length and format first, the resulting table assumes the shorter format -- and thus you "lose" precision. But your SAS log warns you:</p>
<p><pre class="preserve-code-formatting">
WARNING: Multiple lengths were specified for the variable name by input data set(s). 
This may cause truncation of data. 
</pre></p>
<p>If you SET the table with the longer length and format first, then the result has the longer format. No problems or warnings with that, because you can always fit the smaller values into a larger space, just not vice versa.</p>
<p>Sometimes you don't know all of the attributes of your input columns ahead of time. In this case, experienced SAS programmers will often create an empty "template" data set that has the columns and attributes that they want to see in the final output. By adding this template data as the first in their SET statement, this establishes the correct attributes in the result.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #000080; font-weight: bold;">data</span> template;
 <span style="color: #0000ff;">length</span> name $ <span style="color: #2e8b57; font-weight: bold;">8</span>;
 <span style="color: #0000ff;">format</span> name $8.;
<span style="color: #006400; font-style: italic;">/* trick to establish the variable attributes in the header, 
   STOP with 0 observations */</span>
 <span style="color: #0000ff;">stop</span>; 
<span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
<span style="color: #006400; font-style: italic;">/* Code for SHORT and LONG DATA steps omitted */</span>
&nbsp;
<span style="color: #006400; font-style: italic;">/* FINAL will have the column attributes from TEMPLATE */</span>
<span style="color: #000080; font-weight: bold;">data</span> final;
 <span style="color: #0000ff;">set</span> template <span style="color: #006400; font-style: italic;">/* our empty data template */</span>
     short long;
<span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p>SAS formats are extremely powerful. They allow you to reuse data values for all sorts of reporting and categorization purposes without having to actually change the underlying values. My simple explanations here only scrape the surface of the flexibility and nuances of SAS formats. For more information, you might check out <a title="power of PROC Format book" href="https://www.sas.com/sas/books/authors/jonas-bilenas.html">The Power of PROC FORMAT </a>or <a title="LSB" href="http://www.sas.com/apps/pubscat/bookdetails.jsp?pc=55200">The Little SAS Book</a>.</p>
<p><em>(Note: I create this article originally in 2007 while writing <strong>SAS For Dummies</strong>. I've made just a few updates in 2024 to reshare it.)</em></p>
<a href="https://www.sas.com/gms/redirect.jsp?detail=GMS168352_234289" class="sc-button sc-button-default"><span><span class="btnheader">WANT MORE GREAT INSIGHTS MONTHLY? | </span> SUBSCRIBE TO THE SAS TECH REPORT</span></a>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2024/07/22/lengths-and-formats-the-long-and-short-of-it/">Lengths and formats in SAS: the long and short of it</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.sas.com/content/sasdummy/2024/07/22/lengths-and-formats-the-long-and-short-of-it/feed/</wfw:commentRss>
			<slash:comments>11</slash:comments>
		
		
			<enclosure url="https://blogs.sas.com/content/sasdummy/files/2007/11/174779502-150x150.jpg" />
	</item>
		<item>
		<title>How to work with emojis in SAS</title>
		<link>https://blogs.sas.com/content/sasdummy/2024/07/11/emojis-sas/</link>
					<comments>https://blogs.sas.com/content/sasdummy/2024/07/11/emojis-sas/#comments</comments>
		
		<dc:creator><![CDATA[Chris Hemedinger]]></dc:creator>
		<pubDate>Thu, 11 Jul 2024 12:00:32 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[diversity]]></category>
		<category><![CDATA[emoji]]></category>
		<guid isPermaLink="false">https://blogs.sas.com/content/sasdummy/?p=7248</guid>

					<description><![CDATA[<p>Emojis are showing up in our data. Here's what you need to know when working with emojis in your SAS code.</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2024/07/11/emojis-sas/">How to work with emojis in SAS</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>When I was a computer science student in the 1980s, our digital alphabet was simple and small. We could express ourselves with the letters A..Z (and lowercase a..z) and numbers (0..9) and a handful of punctuation and symbols. Thanks to the ASCII standard, we could represent any of these characters in a single byte (actually just 7 bits). This allowed for a generous 128 different characters, and we had character slots to spare. (Of course for non-English and especially non-latin characters we had to resort to different code pages...but that was before the Internet forced us to work together. Before Unicode, we lived in a digital Tower of Babel.)</p>
<p>Even with the limited character set, pictorial communication was possible with ASCII through the fun medium of "ASCII art." ASCII art is basically the stone-age version of emojis. For example, consider the shrug emoji: &#129335;</p>
<p>Its text-art ancestor (not strictly ASCII as a sharp reader pointed out) is this: <code class="preserve-code-formatting">¯\_(ツ)_/¯</code> While ASCII and text art currently enjoys a retro renaissance, the emoji has become indispensable in our daily communications. </p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2021/07/wordlemojiday.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2021/07/wordlemojiday.png" alt="" width="99" height="98" class="alignleft size-full wp-image-7985" /></a>I'm publishing this article to match the <a href="https://en.wikipedia.org/wiki/World_Emoji_Day">timing of World Emoji Day</a>, which happens on July 17. If you ever forget the date of this important event, just look at the traditional calendar emoji for a reminder!</p>
<p><em>(<strong>Update</strong>: I first published this article in 2021. I've updated it to include code that references the most recent Unicode emoji standards.)</em></p>
<h2>Emojis before Unicode</h2>
<p>Given the ubiquity of emojis in every communication channel, it's sometimes difficult to remember that just a few years ago emoji characters were devised and implemented in vendor-specific offerings. As the sole Android phone user in my house, I remember a time when my iPhone-happy family could express themselves in emojis that I couldn't read in the family group chat. Apple would release new emojis for their users, and then Android (Google) would leap frog with another set of their own fun symbols. But if you weren't trading messages with users of the same technology, then chunks of your text would be lost in translation.</p>
<p>Enter Unicode. A standard system for encoding characters that allows for multiple bytes of storage, Unicode has seemingly endless runway for adding new characters. More importantly, there is a standards body that sets revisions for Unicode characters periodically so everyone can use the same huge alphabet. <a href="https://emojipedia.org/emoji-1.0/">In 2015, emoji characters were added into Unicode</a> and have been revised steadily with universal agreement. </p>
<p>This standardization has helped to propel emojis as a main component of communication in every channel. Text messages, Twitter threads, Venmo payments, Facebook messages, Slack messages, GitHub comments -- everything accepts emojis. (Emojis are so ingrained and expected that if you send a Venmo payment without using an emoji and just use plain text, it could be interpreted as a slight or at the least as a miscue.)</p>
<p>For more background about emojis, read <a href="https://computer.howstuffworks.com/internet/social-networking/networks/emojis.htm">How Emjois Work (source: <strong>How Stuff Works</strong>)</a>.</p>
<p><b>Unicode is essential for emojis.</b> In SAS, the use of Unicode is possible by way of UTF-8 encoding. If you work in a modern SAS environment with a diverse set of data, you should already be using ENCODING=UTF8 as your SAS session encoding. If you use <a href="https://www.sas.com/en_us/software/on-demand-for-academics.html">SAS OnDemand for Academics</a> (the free environment for any learner), this is already set for you. And SAS Viya offers <strong>only</strong> UTF-8 -- which makes sense, because it's the best for most data and it's how most apps work these days.</p>
<h2>Emojis as data and processing in SAS</h2>
<p>Emojis are everywhere, and their presence can enrich (and complicate) the way that we analyze text data. For example, emojis are often useful cues for sentiment (smiley face! laughing-with-tears face! grimace face! poop!).  It's not unusual for a text message to be ALL emojis with no "traditional" words.</p>
<p>The website Unicode.org <a href="https://unicode.org/emoji/charts/full-emoji-list.html">maintains the complete compendium of emojis</a> as defined in the latest standards. They also provide the emoji definitions as data files, which we can easily read into SAS. This program reads all of the data as published and adds features for just the "basic" emojis:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #006400; font-style: italic;">/* MUST be running with ENCODING=UTF8 */</span>
<span style="color: #0000ff;">filename</span> raw temp;
<span style="color: #000080; font-weight: bold;">proc http</span>
  url=<span style="color: #a020f0;">&quot;https://unicode.org/Public/emoji/latest/emoji-sequences.txt&quot;</span>
 out=raw;
<span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
ods escapechar=<span style="color: #a020f0;">'~'</span>;
<span style="color: #000080; font-weight: bold;">data</span> emojis <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">drop</span>=line<span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">length</span> line $ <span style="color: #2e8b57; font-weight: bold;">1000</span> codepoint_range $ <span style="color: #2e8b57; font-weight: bold;">45</span> val_start <span style="color: #2e8b57; font-weight: bold;">8</span> val_end <span style="color: #2e8b57; font-weight: bold;">8</span> 
       type $ <span style="color: #2e8b57; font-weight: bold;">30</span> comments $ <span style="color: #2e8b57; font-weight: bold;">65</span> saschar $ <span style="color: #2e8b57; font-weight: bold;">20</span> htmlchar $ <span style="color: #2e8b57; font-weight: bold;">25</span>;
<span style="color: #0000ff;">infile</span> raw ;
<span style="color: #0000ff;">input</span>;
line = <span style="color: #0000ff;">_infile_</span>;
&nbsp;
<span style="color: #006400; font-style: italic;">/* skip comments and blank lines */</span>
<span style="color: #006400; font-style: italic;">/* data fields are separated by semicolons */</span>
<span style="color: #0000ff;">if</span> <span style="color: #0000ff;">substr</span><span style="color: #66cc66;">&#40;</span>line,<span style="color: #2e8b57; font-weight: bold;">1</span>,<span style="color: #2e8b57; font-weight: bold;">1</span><span style="color: #66cc66;">&#41;</span>^=<span style="color: #a020f0;">'#'</span> <span style="color: #0000ff;">and</span> line ^= <span style="color: #a020f0;">' '</span> <span style="color: #0000ff;">then</span> <span style="color: #0000ff;">do</span>;
&nbsp;
 <span style="color: #006400; font-style: italic;">/* read the raw codepoint value - could be single, a range, or a combo of several */</span>
 codepoint_range = <span style="color: #0000ff;">scan</span><span style="color: #66cc66;">&#40;</span>line,<span style="color: #2e8b57; font-weight: bold;">1</span>,<span style="color: #a020f0;">';'</span><span style="color: #66cc66;">&#41;</span>;
 <span style="color: #006400; font-style: italic;">/* read the type field */</span>
 type = <span style="color: #0000ff;">compress</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">scan</span><span style="color: #66cc66;">&#40;</span>line,<span style="color: #2e8b57; font-weight: bold;">2</span>,<span style="color: #a020f0;">';'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
 <span style="color: #006400; font-style: italic;">/* text description of this emoji */</span>
 comments = <span style="color: #0000ff;">scan</span><span style="color: #66cc66;">&#40;</span>line,<span style="color: #2e8b57; font-weight: bold;">3</span>,<span style="color: #a020f0;">'#;'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
 <span style="color: #006400; font-style: italic;">/* for those emojis that have a range of values */</span>
 val_start = <span style="color: #0000ff;">input</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">scan</span><span style="color: #66cc66;">&#40;</span>codepoint_range,<span style="color: #2e8b57; font-weight: bold;">1</span>,<span style="color: #a020f0;">'. '</span><span style="color: #66cc66;">&#41;</span>, hex.<span style="color: #66cc66;">&#41;</span>;
 <span style="color: #0000ff;">if</span> find<span style="color: #66cc66;">&#40;</span>codepoint_range,<span style="color: #a020f0;">'..'</span><span style="color: #66cc66;">&#41;</span> &gt; <span style="color: #2e8b57; font-weight: bold;">0</span> <span style="color: #0000ff;">then</span> <span style="color: #0000ff;">do</span>;
  val_end = <span style="color: #0000ff;">input</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">scan</span><span style="color: #66cc66;">&#40;</span>codepoint_range,<span style="color: #2e8b57; font-weight: bold;">2</span>,<span style="color: #a020f0;">'.'</span><span style="color: #66cc66;">&#41;</span>, hex.<span style="color: #66cc66;">&#41;</span>;
 <span style="color: #0000ff;">end</span>;
 <span style="color: #0000ff;">else</span> val_end=val_start;
&nbsp;
 <span style="color: #0000ff;">if</span> type = <span style="color: #a020f0;">&quot;Basic_Emoji&quot;</span> <span style="color: #0000ff;">then</span> <span style="color: #0000ff;">do</span>;
  saschar = cat<span style="color: #66cc66;">&#40;</span><span style="color: #a020f0;">'~{Unicode '</span>,<span style="color: #0000ff;">scan</span><span style="color: #66cc66;">&#40;</span>codepoint_range,<span style="color: #2e8b57; font-weight: bold;">1</span>,<span style="color: #a020f0;">' .'</span><span style="color: #66cc66;">&#41;</span>,<span style="color: #a020f0;">'}'</span><span style="color: #66cc66;">&#41;</span>;
  htmlchar = cats<span style="color: #66cc66;">&#40;</span><span style="color: #a020f0;">'&lt;span&gt;&amp;#x'</span>,<span style="color: #0000ff;">scan</span><span style="color: #66cc66;">&#40;</span>codepoint_range,<span style="color: #2e8b57; font-weight: bold;">1</span>,<span style="color: #a020f0;">' .'</span><span style="color: #66cc66;">&#41;</span>,<span style="color: #a020f0;">';&lt;/span&gt;'</span><span style="color: #66cc66;">&#41;</span>;
 <span style="color: #0000ff;">end</span>;
 <span style="color: #0000ff;">output</span>;
<span style="color: #0000ff;">end</span>;
<span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
<span style="color: #006400; font-style: italic;">/* Assuming HTML or HTML5 output destination */</span>
<span style="color: #006400; font-style: italic;">/* print the first 50 emoji records */</span>
<span style="color: #000080; font-weight: bold;">proc print</span> <span style="color: #000080; font-weight: bold;">data</span>=emojis <span style="color: #66cc66;">&#40;</span>obs=<span style="color: #2e8b57; font-weight: bold;">50</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p>(As usual, all of the SAS code <a href="https://github.com/sascommunities/sas-dummy-blog/blob/master/emojis/emoji-sequences.sas">in this article is available on GitHub</a>.)</p>
<p>The "features" I added include the Unicode representation for an emoji character in SAS, which could then be used in any SAS report in ODS or any <a href="https://blogs.sas.com/content/graphicallyspeaking/2011/11/14/the-power-of-unicode/">graphics produced in the SG procedures</a>. I also added the HTML-encoded representation of the emoji, which uses the form <code class="preserve-code-formatting">&amp;#xNNNN;</code> where NNNN is the Unicode value for the character.  Here's the raw data view:</p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2021/07/emoji1.jpg"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2021/07/emoji1.jpg" alt="" width="902" height="294" class="alignnone size-full wp-image-7281" srcset="https://blogs.sas.com/content/sasdummy/files/2021/07/emoji1.jpg 902w, https://blogs.sas.com/content/sasdummy/files/2021/07/emoji1-300x98.jpg 300w, https://blogs.sas.com/content/sasdummy/files/2021/07/emoji1-768x250.jpg 768w" sizes="(max-width: 902px) 100vw, 902px" /></a></p>
<p>When you PROC PRINT to an HTML destination, here's the view in the results browser:</p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-print-1.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-print-1.png" alt="" width="1116" height="762" class="alignnone size-full wp-image-7991" srcset="https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-print-1.png 1116w, https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-print-1-300x205.png 300w, https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-print-1-1024x699.png 1024w, https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-print-1-768x524.png 768w" sizes="(max-width: 1116px) 100vw, 1116px" /></a></p>
<h2>In search of structured emoji data</h2>
<p>The Unicode.org site can serve up the emoji definitions and codes, but this data isn't exactly ready for use within applications. One could work through the list of emojis (thousands of them!) and tag these with descriptive words and meanings. That could take a long time and to be honest, I'm not sure I could accurately interpret many of the emojis myself. So I began the hunt for data files that had this work already completed.</p>
<p>I found <a href="https://github.com/github/gemoji">the GitHub/gemoji project</a>, a Ruby-language code repository that contains a structured JSON file that describes a recent collection of emojis. From all of the files in the project, I need only one JSON file. Here's a SAS program that downloads the file with PROC HTTP and reads the data with the JSON libname engine:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #0000ff;">filename</span> rawj temp;
 <span style="color: #000080; font-weight: bold;">proc http</span>
  url=<span style="color: #a020f0;">&quot;https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json&quot;</span>
  out=rawj;
<span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
<span style="color: #0000ff;">libname</span> emoji json <span style="color: #0000ff;">fileref</span>=rawj;</pre></td></tr></table></div>

<p>Upon reading these data, I quickly realized the JSON text contains the <strong>actual Unicode character</strong> for the emoji, and not the decimal or hex value that we might need for using it later in SAS.</p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-looking.jpg"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-looking.jpg" alt="" width="429" height="471" class="alignnone size-full wp-image-7308" srcset="https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-looking.jpg 429w, https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-looking-273x300.jpg 273w" sizes="(max-width: 429px) 100vw, 429px" /></a></p>
<p>I wanted to convert the emoji character to its numeric code. That's when <a href="https://go.documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/nlsref/n16dtsekpfhk8cn1skrvzvsk1yhv.htm">I discovered the UNICODEC function</a>, which can "decode" the Unicode sequence into its numeric values. (Note that some characters use more than one value in a sequence). </p>
<p>Here's my complete program, which includes some reworking of the tags and aliases attributes so I can have one record per emoji:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sas" style="font-family:monospace;"><span style="color: #0000ff;">filename</span> rawj temp;
 <span style="color: #000080; font-weight: bold;">proc http</span>
  url=<span style="color: #a020f0;">&quot;https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json&quot;</span>
  out=rawj;
<span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
<span style="color: #0000ff;">libname</span> emoji json <span style="color: #0000ff;">fileref</span>=rawj;
&nbsp;
<span style="color: #006400; font-style: italic;">/* reformat the tags and aliases data for inclusion in a single data set */</span>
<span style="color: #000080; font-weight: bold;">data</span> tags;
 <span style="color: #0000ff;">length</span> ordinal_root <span style="color: #2e8b57; font-weight: bold;">8</span> tags $ <span style="color: #2e8b57; font-weight: bold;">60</span>;
 <span style="color: #0000ff;">set</span> emoji.tags;
 tags = catx<span style="color: #66cc66;">&#40;</span><span style="color: #a020f0;">', '</span>,of tags:<span style="color: #66cc66;">&#41;</span>;
 <span style="color: #0000ff;">keep</span> ordinal_root tags;
<span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
<span style="color: #000080; font-weight: bold;">data</span> aliases;
 <span style="color: #0000ff;">length</span> ordinal_root <span style="color: #2e8b57; font-weight: bold;">8</span> aliases $ <span style="color: #2e8b57; font-weight: bold;">60</span>;
 <span style="color: #0000ff;">set</span> emoji.aliases;
 aliases = catx<span style="color: #66cc66;">&#40;</span><span style="color: #a020f0;">', '</span>,of aliases:<span style="color: #66cc66;">&#41;</span>;
 <span style="color: #0000ff;">keep</span> ordinal_root aliases;
<span style="color: #000080; font-weight: bold;">run</span>;
&nbsp;
<span style="color: #006400; font-style: italic;">/* Join together in one record per emoji */</span>
<span style="color: #000080; font-weight: bold;">proc sql</span>;
 <span style="color: #0000ff;">create</span> <span style="color: #0000ff;">table</span> full_emoji <span style="color: #0000ff;">as</span> 
 <span style="color: #0000ff;">select</span>  t1.emoji <span style="color: #0000ff;">as</span> emoji_char, 
    unicodec<span style="color: #66cc66;">&#40;</span>t1.emoji,<span style="color: #a020f0;">'esc'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #0000ff;">as</span> emoji_code, 
    t1.description, t1.category, t1.unicode_version, 
    case 
     when t1.skin_tones = <span style="color: #2e8b57; font-weight: bold;">1</span> <span style="color: #0000ff;">then</span>  t1.skin_tones
	 <span style="color: #0000ff;">else</span> <span style="color: #2e8b57; font-weight: bold;">0</span>
	<span style="color: #0000ff;">end</span> <span style="color: #0000ff;">as</span> has_skin_tones,
    t2.tags, t3.aliases
  <span style="color: #0000ff;">from</span> emoji.root t1
  <span style="color: #0000ff;">left</span> join tags t2 <span style="color: #0000ff;">on</span> <span style="color: #66cc66;">&#40;</span>t1.ordinal_root = t2.ordinal_root<span style="color: #66cc66;">&#41;</span>
  <span style="color: #0000ff;">left</span> join aliases t3 <span style="color: #0000ff;">on</span> <span style="color: #66cc66;">&#40;</span>t1.ordinal_root = t3.ordinal_root<span style="color: #66cc66;">&#41;</span>
 ;
<span style="color: #000080; font-weight: bold;">quit</span>;
&nbsp;
<span style="color: #000080; font-weight: bold;">proc print</span> <span style="color: #000080; font-weight: bold;">data</span>=full_emoji; <span style="color: #000080; font-weight: bold;">run</span>;</pre></td></tr></table></div>

<p>Here's a snippet of the report that includes some of the more interesting sequences:</p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-print-2.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-print-2.png" alt="Emoji combos" width="1066" height="752" class="alignnone size-full wp-image-7988" srcset="https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-print-2.png 1066w, https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-print-2-300x212.png 300w, https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-print-2-1024x722.png 1024w, https://blogs.sas.com/content/sasdummy/files/2021/07/emoji-print-2-768x542.png 768w" sizes="(max-width: 1066px) 100vw, 1066px" /></a></p>
<p>The diversity and inclusion aspect of emoji glyphs is ever-expanding. For example, consider the emoji for "family":</p>
<ul>
<li>The basic family emoji code is \u0001F46A (&#x1F46A;)
</li>
<li>But since families come in all shapes and sizes, you can find a family that better represents you. For example, how about "family: man, man, girl, girl"? The code is <code class="preserve-code-formatting">\u0001F468\u200D\u0001F468\u200D\u0001F467\u200D\u0001F467</code>, which includes the codes for each component "member" all smooshed together with a <a href="https://emojipedia.org/zero-width-joiner/">"zero-width joiner" (ZWJ) code</a> in between (&#x1F468;&zwj;&#x1F468;&zwj;&#x1F467;&zwj;&#x1F467;)
</li>
<li>All of the above, but <a href="https://emojipedia.org/emoji-modifier-sequence/">with a dark-skin-tone modifier</a> (\u0001F3FF) for 2 of the family members: <code class="preserve-code-formatting">\u0001F468\u0001F3FF\u200D\u0001F468\u200D\u0001F467\u200D\u0001F467\u0001F3FF</code> (&#x1F468;&#x1F3FF;&zwj;&#x1F468;&zwj;&#x1F467;&zwj;&#x1F467;&#x1F3FF;)
</li>
</ul>
<p>Note: I noticed that not all browsers have caught up on rendering that last example. In my browser it looks like this:<br />
<a href="https://blogs.sas.com/content/sasdummy/files/2021/07/mixed-family.jpg"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2021/07/mixed-family.jpg" alt="" width="92" height="64" class="alignnone size-full wp-image-7347" /></a></p>
<h2>Conclusion: Emojis reflect society, and society adapts to emojis</h2>
<p>As you might have noticed from that last sequence I shared, a single concept can call for many different emojis.  As our society becomes more inclusive around gender, skin color, and differently capable people, emojis are keeping up. Everyone can express the concept in the way that is most meaningful for them. This is just one way that the language of emojis enriches our communication, and in turn our experience feeds back into the process and grows the emoji collection even more.</p>
<p>As emoji-rich data is used for reporting and for training of AI models, it's important for our understanding of emoji context and meaning to keep up with the times. Already <a href="https://www.cnn.com/2021/02/14/tech/crying-laughing-emoji-gen-z/index.html">we know that emoji use differs among different age generations</a> and across other demographic groups. The use and application of emojis -- separate from the definition of emoji codes -- is yet another dimension to the data.</p>
<p>Our task as data scientists is to bring all of this intelligence and context into the process when we parse, interpret and build training data sets. The mechanics of parsing and producing emoji-rich data is just the start.</p>
<p>If you're encountering emojis in your data and considering them in your reporting and analytics, please let me know how! I'd love to hear from you in the comments.</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2024/07/11/emojis-sas/">How to work with emojis in SAS</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.sas.com/content/sasdummy/2024/07/11/emojis-sas/feed/</wfw:commentRss>
			<slash:comments>15</slash:comments>
		
		
			<enclosure url="https://blogs.sas.com/content/sasdummy/files/2024/07/205182187-150x150.jpg" />
	</item>
		<item>
		<title>Visualized: US Currency in circulation, past and present</title>
		<link>https://blogs.sas.com/content/sasdummy/2024/02/27/visualized-us-currency-circulation/</link>
					<comments>https://blogs.sas.com/content/sasdummy/2024/02/27/visualized-us-currency-circulation/#comments</comments>
		
		<dc:creator><![CDATA[Chris Hemedinger]]></dc:creator>
		<pubDate>Tue, 27 Feb 2024 16:00:37 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[PROC HTTP]]></category>
		<category><![CDATA[SAS programming]]></category>
		<category><![CDATA[SGPLOT]]></category>
		<guid isPermaLink="false">http://blogs.sas.com/content/sasdummy/?p=5808</guid>

					<description><![CDATA[<p>This phenomenon has been in the news recently, so I've updated this article that I originally published in 2017. The paper currency in circulation in the US is mostly $100 bills. And not just by a little bit -- these account for 34% of the notes by denomination and nearly [...]</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2024/02/27/visualized-us-currency-circulation/">Visualized: US Currency in circulation, past and present</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><em><a href="https://www.wsj.com/personal-finance/american-dollar-currency-100-bill-c6a47c79">This phenomenon has been in the news recently</a>, so I've updated this article that I originally published in 2017.</em> The paper currency in circulation in the US is mostly $100 bills. And not just by a little bit -- these account for 34% of the notes by denomination and nearly 82% of the value (data as of 2022).</p>
<p>I originally wrote this article when I was inspired by a news story on NPR's <em>Morning Edition</em> about <a href="http://www.npr.org/sections/parallels/2017/02/09/513736356/what-can-india-tell-us-about-the-worth-of-abolishing-high-value-banknotes">the merits and risks of the $100 bill</a>.  There are a lot of them in circulation, but no one knows exactly where they are.  According to the report, they are seldom used for legitimate business transactions.  When a transaction reaches into the hundreds of dollars, the business parties tend to resort to a digital transaction (or maybe a good-old-fashioned personal check).  Large cash transactions are often used to avoid taxation or, more nefariously, to hide criminal activity.</p>
<p>It was easy to find the data on the <a href="https://www.federalreserve.gov/paymentsystems/coin_currcircvolume.htm">US Federal Reserve: Currency in Circulation</a> web site. I could have copied and pasted the table for use in SAS, but the Fed already <a href="https://www.federalreserve.gov/paymentsystems/files/coin_currcircvolume.txt">makes an ASCII version of the table</a> available for nerds like me.  With a bit of SAS code I was able to download the data (using PROC HTTP), transpose it for analysis, calculate the currency values for the counts of the various notes, and create a graph that verifies what I heard on the news.  Indeed, much of our nation's cash wealth is floating around <a href="https://en.wikipedia.org/wiki/United_States_one_hundred-dollar_bill">on a bunch of Benjamins</a>.</p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2017/02/pctval2022dk.png"><img decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2017/02/pctval2022dk.png" alt=""  class="alignnone size-full wp-image-5812" /></a><br />
The percentage of wealth represented in the $100 bill has grown over the past 20 years, perhaps at the expense of the far-more-ATM-friendly $20 bill.  In 1996, the  ratio of hundreds-to-twenties (in cash value) was 61/20.  In 2016, it was 79/12.  The following table shows the two years side-by-side.  $100 bills increased by nearly 18 percentage points, while all other notes decreased.  $20 notes were the biggest loser at -8.3 points, and $50 notes were next at -5.8 percentage points.</p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2017/02/comparenotes.png"><img loading="lazy" decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2017/02/comparenotes.png" alt="" width="480" height="240" class="alignnone size-full wp-image-5839" srcset="https://blogs.sas.com/content/sasdummy/files/2017/02/comparenotes.png 480w, https://blogs.sas.com/content/sasdummy/files/2017/02/comparenotes-300x150.png 300w" sizes="(max-width: 480px) 100vw, 480px" /></a><br />
If we look at the percent breakdown by bill counts (instead of value), you can see the shifts a bit differently.</p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2017/02/pctcount2022dk.png"><img decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2017/02/pctcount2022dk.png" alt=""  class="alignnone size-full wp-image-5811" /></a></p>
<p>I created those two plots by calculating the percentages with PROC FREQ, and then using PROC SGPLOT to graph Year, using the percentages as the response value and stacking the data by Denomination.  I used GROUPORDER=Data to keep the data colors and legend consistent across the different graphs.  The raw values are interesting to examine as well, as it more clearly shows the trends for the past 20 years.  Here are the two representations (cash value and bill counts) with their actual values and not just the percentages.  </p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2017/02/rawvalue2022dk.png"><img decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2017/02/rawvalue2022dk.png" alt="Raw values of currency in circulation"  class="alignnone size-full wp-image-5810" /></a></p>
<p><a href="https://blogs.sas.com/content/sasdummy/files/2017/02/rawcounts2022dk.png"><img decoding="async" src="https://blogs.sas.com/content/sasdummy/files/2017/02/rawcounts2022dk.png" alt="Raw counts of currency in circulation"  class="alignnone size-full wp-image-5809" /></a><br />
An interesting aside: the $2 bill remains a novelty.  I had the opportunity to spend a few of these recently, and the person receiving them had to be convinced that they were real money.  It made me want to secure more $2 bills (a.k.a. "some Jeffersons") for future transactions -- that's the sort of trouble-making consumer that I like to be.</p>
<p>In case you're interested, <a href="https://github.com/sascommunities/sas-dummy-blog/blob/master/currency/currency.sas">here's the SAS program that I used</a> -- try it yourself!  This should work fine in any recent SAS version, including in SAS OnDemand for Academics.</p>
<p>The post <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy/2024/02/27/visualized-us-currency-circulation/">Visualized: US Currency in circulation, past and present</a> appeared first on <a rel="nofollow" href="https://blogs.sas.com/content/sasdummy">The SAS Dummy</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.sas.com/content/sasdummy/2024/02/27/visualized-us-currency-circulation/feed/</wfw:commentRss>
			<slash:comments>38</slash:comments>
		
		
			<enclosure url="https://blogs.sas.com/content/sasdummy/files/2017/02/pctval-150x150.png" />
	</item>
	</channel>
</rss>
