Qq player update version free download

August 25, 2021 / Rating: 4.9 / Views: 666

Gallery of Images "Qq player update version free download" (18 pics):

"high performance sas coding" pdf free download

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 One Drive -- 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. 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. The Microsoft Office 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 One Drive cloud to read and update your files. Note: All of this assumes that you already have a Microsoft Office 365 account -- perhaps provisioned by your IT support team -- and that you're using it to manage your documents. Before I go on, I have to give major credit to Joseph Henry, the SAS developer who maintains PROC HTTP. Joseph did the heavy lifting for putting together the code and examples in this article. He also regularly adds new features to PROC HTTP that make it a more natural fit for calling REST APIs that require special authentication flows, such as OAuth2. Microsoft Office 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 job of deconstructing OAuth2 -- with code samples -- in this SAS Global Forum paper. When we're writing SAS programs to access Microsoft One Drive, 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: 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. Oh, and by the way, even though the examples in this article are specific to One Drive, the exact same authentication flow and steps can be used for all of the Microsoft Office 365 APIs. Have fun with Outlook, Teams, Excel, and all of your favorite cloud-based Microsoft apps. Visit the Microsoft Application Registration portal to register your new app. You'll sign in with your Microsoft Office 365 credentials. Note: At the time of this writing, Microsoft was testing a new web experience for application developers. I opted for the "preview experience" with the hope that my screenshots would have a longer shelf life for future readers. 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. 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.) Your app will need specific permissions in order to function. In my example, I want my SAS program to read documents from my One Drive, and also add new docs and update existing docs. The permissions I need are: There are a few app-specific values that we'll need to reference throughout the SAS programs we're writing. I decided to create a configuration file for these settings rather than hard-code them into my SAS statements. This will make it easier for other people to reuse my code in their own applications. I created a file named that looks like this (but with different tenant_id and client_id values): By "externalizing" the IDs specific to my account/instance, I can use SAS code to read the values at run time. Note: This code, like all of the code in this article, uses features from SAS 9.4 Maintenance 5. /* Set the variables that will be needed through the code We'll need these for authorization and also for runtime use of the service. Reading these from a file so that the values are easy to adapt for different users or projects. */ Now that I've defined the application, it's time to "sign into it" and grant it the permission to read and manage content in One Drive. This step needs to be completed from a web browser while I am signed into my Microsoft Office 365 account. The web address is very long..we can use a SAS program to generate it for us. 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&response_type=code&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient&resource=https://graph.---END --------- Copy and paste the URL (all on one line, no spaces) into the address bar of your web browser. When you press Enter, you'll be prompted to grant the required permissions: Once you click Accept, the browser will redirect to what a blank page, but the URL contains the authorization code that we need: Copy the value that appears after the code= in the URL, only up to the &session= part. It's going to be a very long string -- over 700 characters. My colleague Joseph wrote a few convenient utility macros that can help manage the access token and refresh token within your SAS session. These macros include: I'm not going to walk through the macro code in this article, but the SAS programs are straightforward and well-documented. See "How to get this example code" at the end of this article. With these macros in place, we can paste the (very long) authorization code we retrieved in the previous step into a macro variable. Then we can run the %get_token macro to generate the tokens and store them in a local file. Running this step will create a new file, token.json, in your designated config folder. Here's an screenshot of what my version looks like right now: It's very important that you keep this file secure. With the information in this file (your refresh token) and your file (with your client ID and tenant ID), anyone can use these code techniques to impersonate you and access your Microsoft Office 365 data. There are techniques for storing these files such that only you can see them. I've spent nearly 1500 words to get this far, so thanks for sticking with me. ) 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. The good news is that these steps take much longer to describe than to actually execute. For the remainder of this article, I'll be using methods from the Microsoft Graph API. This REST-based API provides access to almost all of Microsoft's hosted services. For my examples, I'll be using methods within the Files component of the API: Drives and Drive Items (folders and files). Now that we have the access and refresh tokens, we can get down to business with some actual One Drive interactions. 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? Here's how to initialize your SAS session with the tokens. Well, that monkey is not going to produce this access token. ) We'll need to explore the One Drive system from the top-down, using code. It's possible for you to have multiple root drives, and if that's the case for you, you'll need to modify this code a bit. This code queries the service for your drives, and stores the identifier for just the first drive in a macro variable. We'll need that identifier later to retrieve a list of top-level items. Note that this code uses the new OAUTH_BEARER option in PROC HTTP -- a convenient addition when working with OAuth2-compliant APIs. This is shorthand -- and more intuitive syntax -- for placing "Authorization: Bearer TOKEN-VALUE" in the HTTP headers. With the drive identifier in hand, I can use the /children verb on the Microsoft Graph API to get a list of all of the top-level objects in that drive. If I'm interested in exploring a particular folder, I'll need to find the folder identifier as it's known to One Drive. These represent the folders and files that are at the root. Using PROC SQL and SELECT INTO, I can find the folder by its name and store its ID in another macro variable. Then, I use the /children verb again, but this time with the folder ID instead of the "root" constant. /* At this point, if you want to act on any of the items, you just replace "root" with the ID of the item. So to list the items in the "SASGF" folder I have: - find the ID for that folder - list the items within by using the "/children" verb */ Here are the items from my SASGF folder. I know that I keep a spreadsheet named "sas_tech_talks_18.xlsx" in this SASGF folder. With the /content verb, I can download the file from One Drive and store it in the file system that is local to my SAS session. Then, I can use PROC IMPORT to read it into a SAS data set. I've just downloaded my data from the cloud and brought it into my SAS session. We can build wonderful documents from SAS too, and it's important to be able to share those. By using the PUT method with the /content verb, we can copy a file from the local SAS session into a target folder on One Drive. Most often, this will probably be an Excel spreadsheet or maybe a PDF report. (But hey, maybe it's a good opportunity to try out the new ODS WORD destination in SAS 9.4 Maint 6? ) If you want to replace an existing file, then you'll want to perform the additional step of retrieving the unique ID for that file from One Drive. When you PUT the new version of the file into place, its history and sharing properties should remain intact. Here is my code for navigating the folder/file structure in my One Drive and finally replacing an existing file. /* If you want to replace a file instead of making a new file then you need to upload it with the existing file ID. If you don't replace it with the existing ID, some sharing properties and history could be lost. */ As you can see from my One Drive history for this file, I've tested this program a few times -- resulting in 23 revisions of this file in its history! You can find the source files for these examples on Git Hub. I've organized this code into 4 different files in order to make it easy to reuse: I also included a template for the file, with obvious placeholders for the client_id and tenant_id that you'll substitute with your own values. You'll also need to change the statements that define &CONFIG_LOC -- the location of your configuration directory where you're storing these files. I developed these examples in SAS University Edition -- yes, this works there! I also ran the code from my full SAS environment via SAS Enterprise Guide. 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. 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: In her role as Product Manager for SAS Platform Technologies (including the SAS Add-In for Microsoft Office), my colleague Amy Peters hears this question often. With many organizations adopting Microsoft Office 365 -- the "cloud" version of Office -- what does this mean for other processes that integrate with Microsoft Office applications? Microsoft has used different names for these similar offerings: Office 2016, Office 365, Microsoft 365, Office Online. The bottom line is that most users of a "365" package in the cloud, also have access to the Microsoft Office tools on their Windows desktop. They can use the full version of Excel, Power Point, Word, etc., and they also have access to these same tools via a web browser. At SAS, we recently experienced this transition ourselves. Have the Office applications on our desktops vanished? While more of our data is now on the cloud (looking at you, One Drive), it's not really changing how we work, especially when creating/maintaining content. (Like many organizations, we already had one foot in this world by using Microsoft Share Point for collaboration.) Let's look at an example of how I use SAS with Microsoft Office. Then I open Excel on my desktop and use the SAS Add-In for Microsoft Office to embed the shared report into my spreadsheet. Check out this video Tech Talk with SAS developer Tim Beese. This task does not generate a SAS program that you can reuse in a batch SAS process or SAS stored process. The task works by using SAS Workspace APIs to transfer data across your network connection, so all of the work happens "behind the scenes". However, the task does create a detailed log output that shows what files were copied, how many bytes were transferred, how long it took, and whether there were any errors. You'll find the Copy Files task in the Data category of the SAS Tasks list. But, with a little work, you can add the task to older versions. Here's the view from SAS Enterprise Guide v8.2: This task has been included in SAS Enterprise Guide since the v7.13 release (late 2017). You can download the Copy Files task from this link (Zip file). The download package includes multiple versions that depend on your version of SAS Enterprise Guide: v4.3, v5.1, v6.1, v7.1 (before v7.13), and one for v4.1 (with a reduced feature set). There is also a documentation file (PDF) that provides instruction for how to install and use the task. You might need to perform this extra step to "unblock" the downloaded DLL to avoid an error ("HRESULT: 0x80131515") when you try to add the task to your installation. The post How to copy files in SAS Enterprise Guide appeared first on The SAS Dummy. 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 One Drive -- 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. 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. 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 One Drive (or Share Point Online) cloud to read and update your files. Note: 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. Before I go on, I have to give major credit to Joseph Henry, the SAS developer who maintains PROC HTTP. Joseph did the heavy lifting for putting together the code and examples in this article. He also regularly adds new features to PROC HTTP that make it a more natural fit for calling REST APIs that require special authentication flows, such as OAuth2. Note: I've updated this article several times to include detailed steps and "gotchas." I've added use cases for Share Point Online and Microsoft Teams. I wrote a comprehensive paper for SAS Global Forum 2020. And I also recorded a 25-minute video (posted on SAS Support Communities) that shows all of the steps that I followed. 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 job of deconstructing OAuth2 -- with code samples -- in this SAS Global Forum paper. When we're writing SAS programs to access Microsoft One Drive or Share Point, 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: 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. Oh, and by the way, even though the examples in this article are specific to One Drive, the exact same authentication flow and steps can be used for all of the Microsoft 365 APIs. Have fun with Outlook, Teams, Excel, and all of your favorite cloud-based Microsoft apps. Visit the Microsoft Application Registration portal to register your new app. You'll sign in with your Microsoft 365 credentials. 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. 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: 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.) Your app will need specific permissions in order to function. In my example, I want my SAS program to read documents from my One Drive, and also add new docs and update existing docs. The permissions I need are: The documentation for the Microsoft Graph API 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. 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. 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: There are a few app-specific values that we'll need to reference throughout the SAS programs we're writing. I decided to create a configuration file for these settings rather than hard-code them into my SAS statements. This will make it easier for other people to reuse my code in their own applications. I created a file named that looks like this (but with different tenant_id and client_id values): By "externalizing" the IDs specific to my account/instance, I can use SAS code to read the values at run time. Note: This code, like all of the code in this article, uses features from SAS 9.4 Maintenance 5. /* Set the variables that will be needed through the code We'll need these for authorization and also for runtime use of the service. Reading these from a file so that the values are easy to adapt for different users or projects. */ Now that I've defined the application, it's time to "sign into it" and grant it the permission to read and manage content in One Drive. This step needs to be completed from a web browser while I am signed into my Microsoft 365 account. The web address is very long..we can use a SAS program to generate it for us. 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&response_type=code&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient&resource=https://graph.---END --------- Copy and paste the URL (all on one line, no spaces) into the address bar of your web browser. When you press Enter, you'll be prompted to grant the required permissions: Once you click Accept, the browser will redirect to what a blank page, but the URL contains the authorization code that we need: Copy the value that appears after the code= in the URL, only up to the &session= part. It's going to be a very long string -- over 700 characters. Note: if you don't see the permissions prompt but instead see something like this: Then you probably need to work with your IT support to grant consent for your app. See the section "Possibly required: Obtaining admin consent" above. My colleague Joseph wrote a few convenient utility macros that can help manage the access token and refresh token within your SAS session. These macros include: I'm not going to walk through the macro code in this article, but the SAS programs are straightforward and well-documented. See "How to get this example code" at the end of this article. With these macros in place, we can paste the (very long) authorization code we retrieved in the previous step into a macro variable. Then we can run the %get_token macro to generate the tokens and store them in a local file. Running this step will create a new file, token.json, in your designated config folder. Here's an screenshot of what my version looks like right now: It's very important that you keep this file secure. With the information in this file (your refresh token) and your file (with your client ID and tenant ID), anyone can use these code techniques to impersonate you and access your Microsoft 365 data. There are techniques for storing these files such that only you can see them. I've spent nearly 1500 words to get this far, so thanks for sticking with me. ) 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. The good news is that these steps take much longer to describe than to actually execute. For the remainder of this article, I'll be using methods from the Microsoft Graph API. This REST-based API provides access to almost all of Microsoft's hosted services. For my examples, I'll be using methods within the Files component of the API: Drives and Drive Items (folders and files). You can explore and try the Microsoft 365 APIs with the Graph Explorer application from Microsoft. If you sign in with your own account, you can use the APIs with your own data. " 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? This is a great way to try these APIs and discover the correct methods to use before implementing them in your SAS code. Well, that monkey is not going to produce this access token. ) We'll need to explore the One Drive system from the top-down, using code. It's possible for you to have multiple root drives, and if that's the case for you, you'll need to modify this code a bit. This code queries the service for your drives, and stores the identifier for just the first drive in a macro variable. We'll need that identifier later to retrieve a list of top-level items. Note that this code uses the new OAUTH_BEARER option in PROC HTTP -- a convenient addition when working with OAuth2-compliant APIs. This is shorthand -- and more intuitive syntax -- for placing "Authorization: Bearer TOKEN-VALUE" in the HTTP headers. The steps for Share Point Online are nearly the same as for One Drive, except that we need to reference the site hostname (yoursite.sharepoint.com, for example) and the /sites resource (instead of the /me/drives resource). sitepath This example uses the /drive method to access the files on the Sharepoint site -- works just like One Drive. API also supports a /lists method for Share Point lists. Use the Graph Explorer app to find the correct APIs for your purpose. https://developer.microsoft.com/en-us/graph/graph-explorer */ With the drive identifier in hand (whether One Drive or Share Point), I can use the /children verb on the Microsoft Graph API to get a list of all of the top-level objects in that drive. If I'm interested in exploring a particular folder, I'll need to find the folder identifier as it's known to One Drive. These represent the folders and files that are at the root. Using PROC SQL and SELECT INTO, I can find the folder by its name and store its ID in another macro variable. Then, I use the /children verb again, but this time with the folder ID instead of the "root" constant. /* At this point, if you want to act on any of the items, you just replace "root" with the ID of the item. So to list the items in the "SASGF" folder I have: - find the ID for that folder - list the items within by using the "/children" verb */ Here are the items from my SASGF folder. I know that I keep a spreadsheet named "sas_tech_talks_18.xlsx" in this SASGF folder. With the /content verb, I can download the file from One Drive and store it in the file system that is local to my SAS session. Then, I can use PROC IMPORT to read it into a SAS data set. I've just downloaded my data from the cloud and brought it into my SAS session. We can build wonderful documents from SAS too, and it's important to be able to share those. By using the PUT method with the /content verb, we can copy a file from the local SAS session into a target folder on One Drive. Most often, this will probably be an Excel spreadsheet or maybe a PDF report. (But hey, maybe it's a good opportunity to try out the new ODS WORD destination in SAS 9.4 Maint 6? ) If you want to replace an existing file, then you'll want to perform the additional step of retrieving the unique ID for that file from One Drive. When you PUT the new version of the file into place, its history and sharing properties should remain intact. Here is my code for navigating the folder/file structure in my One Drive and finally replacing an existing file. /* If you want to replace a file instead of making a new file then you need to upload it with the existing file ID. If you don't replace it with the existing ID, some sharing properties and history could be lost. */ As you can see from my One Drive history for this file, I've tested this program a few times -- resulting in 23 revisions of this file in its history! You can find the source files for these examples on Git Hub. I've organized this code into 5 different files in order to make it easy to reuse: I also included a template for the file, with obvious placeholders for the client_id and tenant_id that you'll substitute with your own values. You'll also need to change the statements that define &CONFIG_LOC -- the location of your configuration directory where you're storing these files. I developed these examples in SAS University Edition -- yes, this works there! I also ran the code from my full SAS environment via SAS Enterprise Guide. 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. 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: 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. Like Rick, I used new features in SAS 9.4 to produce this chart (in fact, I cribbed heavily from his code)..I used SAS Enterprise Guide to run the program. Update 25Aug2020: 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, switching to the light-on-dark theme named "Raven". It's a personal preference influenced by today's trends -- but it's not economical on printer ink if you decide you want a hard copy. You might notice that my chart is a bit busier than Rick's version. As a desktop client application that works across multiple SAS versions, we tend to issue major releases of SAS Enterprise Guide more often than we update the core engine of SAS software. 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 L10N release of v4.3 in 2010). You might also notice that some of these releases happened very close together. Often, SAS R&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). Here's the code that produced the chart: As citizens of the Internet, we are all familiar with IP addresses -- probably more so than our Internet founding fathers had ever intended. These addresses are typically represented in a 4-piece segmented list of numbers separated by dots. Each segment is called an octet because it contains 8 (count 'em, eight! The four-octect IP address is part of the IPv4 standard. Note: There is a newer IPv6 standard (featuring 16 octets) that many newer networks use and which allows for more addresses. This has become necessary because all new consumer products are required by law to connect to the Internet. (I think that each of my daughter's "Polly Pocket" pieces can connect to Wi Fi.) But in this article I'm ignoring IPv6. UPDATE 2020-Sep-04: My colleague Agata Bogacki has written a newer article that includes IPv6 and IPv4 and techniques to map to a geolocation. The easy-to-read segmented IP address is actually a 32-bit number, and sometimes it is useful to convert the display value into its numeric form. For example, consider the databases that help you to map an IP address to a geographic location in the world. These databases use a numerical range to map an address to a country or city. (For more on range-based geocoding, see this topic in the PROC GEOCODE documentation.) Here is a SAS program that converts a character-based, 4-segment IP address into its equivalent numeric value. It uses the SCAN function, a DATA step ARRAY, and a little bit of math to do the work: datalines; 1.148 117.203.114.198 1.156 119.247.220.11 12.201.116.58 128.2.38.96 128.204.197.27 128.204.207.83 134.102.237.2 141.155.113.98 169.2.124.79 1.231 1.229 173.234.211.69 1.232 178.157.198.132 1.44 1.184 1.213 1.204 1.149 188.165.187.71 ; Here's the output: With this mapping, I can then combine my collection of IP addresses with one of the IP-to-geolocation databases that are available. (SAS provides a macro to help work with Max Mind, which you can learn about in this topic.) Here's a sample result: The post Using SAS to convert IP addresses into numerical IP values appeared first on The SAS Dummy. The code and data that drive analytics projects are important assets to the organizations that sponsor them. As such, there is a growing trend to manage these items in the source management systems of record. The specific system might be Git Hub Enterprise, Git Lab, or Bitbucket -- all platforms that are based on Git. Many SAS products support direct integration with Git. This includes SAS Studio, SAS Enterprise Guide, and the SAS programming language. (That last one checks a lot of boxes for ways to use Git and SAS together.) While we have good documentation and videos to help you learn about Git and SAS, we often get questions around "best practices" -- what is the best/correct way to organize your SAS projects in Git? In this article I'll dodge that question, but I'll still try to provide some helpful advice in the process. It’s difficult for us to prescribe exactly how to organize project repositories in source control. Your best approach will depend so much on the type of work, the company organization, and the culture of collaboration. But I can provide some guidance -- mainly things to do and things to avoid -- based on experience. DO NOT build one huge repository that contains everything you currently maintain. Your work only grows over time and you'll come to regret/revisit the internal organization of a huge project. Once established, it can be tricky to change the folder structure and organization. If you later try to break a large project into smaller pieces, it can be difficult or impossible to maintain the integrity of source management benefits like file histories and differences. DO NOT organize projects based only on the teams that maintain them. And of course, don't organize projects based on individual team members. All teams reorganize over time, and you don't want to have to reorganize all of your code each time that happens. And code projects change hands, so keep the structure personnel-agnostic if you can. Major refactoring of code can introduce errors, and you don't want to risk that just because you got a new VP or someone changed departments. Instead, DO organize projects based on function/work that the code accomplishes. Think modular..don't make projects too granular (or you'll have a million projects). The one thing they have in common is that I'm the main contributor -- but I organize them into functional repos that theoretically (oh please oh please) someone else could step in to take over. This might seem a bit communist, but collaboration works best when we don't regard code that we write as "our turf." DO NOT cling to notions of code "ownership." It makes sense for teams/subject-matter experts to have primary responsibility for a project, but systems like Git are designed to help with transparency and collaboration. Be open to another team member suggesting and merging (with review and approval) a change that improves things. Git Hub, Git Lab, and Bitbucket all support mechanisms for issue tracking and merge requests. These allow changes to be suggested, submitted, revised, and approved in an efficient, transparent way. Many teams have foundational "shared code" for standard operations, coded in SAS macros or shared statements. Consider placing these into their own project that other projects and teams can import. You can even use Git functions within SAS to fetch and include this code directly from your Git repository: If you rely on a repository for shared code and components, make sure that tests are in place so changes can be validated and will not break downstream systems. You can even automate tests with continuous integration tools like Jenkins. DO document how projects relate to each other, dependencies, and prepare guidance for new team members to get started quickly. For most of us, we feel more accountable when we know that our code will be placed in central repositories visible to our peers. It may inspire cleaner code, more complete documentation, and a robust on-boarding process for new team members. Use the Markdown files (and others) in a repository to keep your documentation close to the code. Once your project files are in a Git repository, you might need to change your way of working so that you aren't going against the grain of Git benefits. DO NOT work on code changes in a shared directory with multiple team members –- you'll step on each other. The advantage of Git is that it's a distributed workflow and each developer can work with their own copy of the repository, and merge/accept changes from others at their own pace. DO use Git branching to organize and isolate changes until you are ready to merge them with the main branch. It takes a little bit of learning and practice, but when you adopt a branching approach you'll find it much easier to manage -- it beats keeping multiple copies of your code with slightly different file and folder names to mark "works in progress." DO consider learning and using Git tools such as Git Bash (command line), Git GUI, and a code IDE like VS Code. These don't replace the SAS-provided coding tools with their Git integration, but they can supplement your workflow and make it easier to manage content among several projects. When you're ready to learn more about working with Git and SAS, we have many webinars, videos, and documentation resources: was the most-streamed television show of 2020. According to reports that I've seen, the show was streamed for 57 billion minutes during this extraordinary year. I'm guessing that's in part because we've all been shut in and working from home; we crave our missing office interactions. We lived vicariously (and perhaps dysfunctionally) through watching Dunder Mifflin staff. But another major factor was the looming deadline of the departure of from Netflix as of January 1, 2021. It was a well-publicized event, so Netflix viewers had to get their binge on while they could. (Since the show has only 201 episodes we clearly we have a few repeats in there.) I built a heatmap that shows the frequency and intensity of our streaming of this popular show. People in my house are fans of the show, and they account for nearly 6,000 of those 57 billion streaming minutes. In this graph each row is a month, each square is a day. A square with any red indicates at least one virtual visit with the Scranton crew; the darker the shade, the more episodes streamed during that day. You can see that Sept 15, 2020 was a particular big binge with 17 episodes. (Each episode is about 20-21 minutes, so it's definitely achievable.) To build this heatmap, I started with my Netflix viewing history (downloaded from my Netflix account as CSV files). S.)" titles, and then merged with a complete "calendar" of dates between late 2017 and the start of 2021. Summarized and merged, the data looks something like this: With all of the data summarized in this way such that there is only one observation per X and Y value, I can use the HEATMAPPARM statement in PROC SGPLOT to visualize it. (If I needed the procedure to summarize/bin the data for me, I would use the HEATMAP statement. ) You can see the full code -- with all of the data prep -- on my Git Hub repository here. You may even run the code in your own SAS environment -- it will fetch my Netflix viewing data from another Git Hub location where I've stashed it. If you examine the heatmap I produced, you can almost see our Office enthusiasm in three different bursts. These relate directly to our 3 children and the moments they discovered the show. First was early 2018 (middle child), then late 2019 (youngest child), then late 2020 (oldest child, now 22 years old, striving to catch up). The Office ran for 9 seasons, and our kids have their favorite seasons and episodes -- hence the repeated viewings. I used PROC FREQ to show the distribution of episode views across the seasons: Season 1 is remarkably low for two reasons. First and most importantly, it contains the fewest episodes. Second, many viewers agree that Season 1 is the "cringiest" content, and can be uncomfortable to watch. (This Reddit user leaned into the cringe with his data visualization of "that's what she said" jokes.) From the data (and from listening to my kids), I know that Season 2 is a favorite. Of the 60 episodes we streamed at least 4 times, 19 of them were in Season 2. Our kids continue to embrace in other mediums as well. We have t-shirts depicting the memes for "FALSE." and "Schrute Farms." We listen to The Office Ladies podcast, hosted by two stars of the show. In 2019 our daughter's Odyssey of the Mind team created a parody skit based on When I was a computer science student in the 1980s, our digital alphabet was simple and small. 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..that was before the Internet forced us to work together. Before Unicode, we lived in a digital Tower of Babel.) 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: 🤷 Its text-art ancestor (not strictly ASCII as a sharp reader pointed out) is this: While ASCII and text art currently enjoys a retro renaissance, the emoji has become indispensable in our daily communications. 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 i Phone-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. 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. In 2015, emoji characters were added into Unicode and have been revised steadily with universal agreement. 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, Git Hub 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.) For more background about emojis, read How Emjois Work (source: How Stuff Works). 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 SAS On Demand for Academics (the free environment for any learner), this is already set for you. It's not unusual for a text message to be ALL emojis with no "traditional" words. And SAS Viya offers only UTF-8 -- which makes sense, because it's the best for most data and it's how most apps work these days. The website maintains the complete compendium of emojis as defined in the latest standards. Emojis are everywhere, and their presence can enrich (and complicate) the way that we analyze text data. They also provide the emoji definitions as data files, which we can easily read into SAS. For example, emojis are often useful cues for sentiment (smiley face! This program reads all of the data as published and adds features for just the "basic" emojis: (As usual, all of the SAS code in this article is available on Git Hub.) 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 graphics produced in the SG procedures. I also added the HTML-encoded representation of the emoji, which uses the form where NNNN is the Unicode value for the character. Here's the raw data view: When you PROC PRINT to an HTML destination, here's the view in the results browser: The 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. I found the Git Hub/gemoji project, 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: Upon reading these data, I quickly realized the JSON text contains the actual Unicode character for the emoji, and not the decimal or hex value that we might need for using it later in SAS. I wanted to convert the emoji character to its numeric code. That's when I discovered the UNICODEC function, which can "decode" the Unicode sequence into its numeric values. (Note that some characters use more than one value in a sequence). Here's my complete program, which includes some reworking of the tags and aliases attributes so I can have one record per emoji: Here's a snippet of the report that includes some of the more interesting sequences: The diversity and inclusion aspect of emoji glyphs is ever-expanding. For example, consider the emoji for "family": Note: I noticed that not all browsers have caught up on rendering that last example. In my browser it looks like this: 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. 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 we know that emoji use differs among different age generations 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. 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. If you're encountering emojis in your data and considering them in your reporting and analytics, please let me know how! The post How to work with emojis in SAS appeared first on The SAS Dummy. 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 One Drive -- 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. 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. The Microsoft Office 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 One Drive cloud to read and update your files. Note: All of this assumes that you already have a Microsoft Office 365 account -- perhaps provisioned by your IT support team -- and that you're using it to manage your documents. Before I go on, I have to give major credit to Joseph Henry, the SAS developer who maintains PROC HTTP. Joseph did the heavy lifting for putting together the code and examples in this article. He also regularly adds new features to PROC HTTP that make it a more natural fit for calling REST APIs that require special authentication flows, such as OAuth2. Microsoft Office 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 job of deconstructing OAuth2 -- with code samples -- in this SAS Global Forum paper. When we're writing SAS programs to access Microsoft One Drive, 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: 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. Oh, and by the way, even though the examples in this article are specific to One Drive, the exact same authentication flow and steps can be used for all of the Microsoft Office 365 APIs. Have fun with Outlook, Teams, Excel, and all of your favorite cloud-based Microsoft apps. Visit the Microsoft Application Registration portal to register your new app. You'll sign in with your Microsoft Office 365 credentials. Note: At the time of this writing, Microsoft was testing a new web experience for application developers. I opted for the "preview experience" with the hope that my screenshots would have a longer shelf life for future readers. 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. 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.) Your app will need specific permissions in order to function. In my example, I want my SAS program to read documents from my One Drive, and also add new docs and update existing docs. The permissions I need are: There are a few app-specific values that we'll need to reference throughout the SAS programs we're writing. I decided to create a configuration file for these settings rather than hard-code them into my SAS statements. This will make it easier for other people to reuse my code in their own applications. I created a file named that looks like this (but with different tenant_id and client_id values): By "externalizing" the IDs specific to my account/instance, I can use SAS code to read the values at run time. Note: This code, like all of the code in this article, uses features from SAS 9.4 Maintenance 5. /* Set the variables that will be needed through the code We'll need these for authorization and also for runtime use of the service. Reading these from a file so that the values are easy to adapt for different users or projects. */ Now that I've defined the application, it's time to "sign into it" and grant it the permission to read and manage content in One Drive. This step needs to be completed from a web browser while I am signed into my Microsoft Office 365 account. The web address is very long..we can use a SAS program to generate it for us. 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&response_type=code&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient&resource=https://graph.---END --------- Copy and paste the URL (all on one line, no spaces) into the address bar of your web browser. When you press Enter, you'll be prompted to grant the required permissions: Once you click Accept, the browser will redirect to what a blank page, but the URL contains the authorization code that we need: Copy the value that appears after the code= in the URL, only up to the &session= part. It's going to be a very long string -- over 700 characters. My colleague Joseph wrote a few convenient utility macros that can help manage the access token and refresh token within your SAS session. These macros include: I'm not going to walk through the macro code in this article, but the SAS programs are straightforward and well-documented. See "How to get this example code" at the end of this article. With these macros in place, we can paste the (very long) authorization code we retrieved in the previous step into a macro variable. Then we can run the %get_token macro to generate the tokens and store them in a local file. Running this step will create a new file, token.json, in your designated config folder. Here's an screenshot of what my version looks like right now: It's very important that you keep this file secure. With the information in this file (your refresh token) and your file (with your client ID and tenant ID), anyone can use these code techniques to impersonate you and access your Microsoft Office 365 data. There are techniques for storing these files such that only you can see them. I've spent nearly 1500 words to get this far, so thanks for sticking with me. ) 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. The good news is that these steps take much longer to describe than to actually execute. For the remainder of this article, I'll be using methods from the Microsoft Graph API. This REST-based API provides access to almost all of Microsoft's hosted services. For my examples, I'll be using methods within the Files component of the API: Drives and Drive Items (folders and files). Now that we have the access and refresh tokens, we can get down to business with some actual One Drive interactions. 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? Here's how to initialize your SAS session with the tokens. Well, that monkey is not going to produce this access token. ) We'll need to explore the One Drive system from the top-down, using code. It's possible for you to have multiple root drives, and if that's the case for you, you'll need to modify this code a bit. This code queries the service for your drives, and stores the identifier for just the first drive in a macro variable. We'll need that identifier later to retrieve a list of top-level items. Note that this code uses the new OAUTH_BEARER option in PROC HTTP -- a convenient addition when working with OAuth2-compliant APIs. This is shorthand -- and more intuitive syntax -- for placing "Authorization: Bearer TOKEN-VALUE" in the HTTP headers. With the drive identifier in hand, I can use the /children verb on the Microsoft Graph API to get a list of all of the top-level objects in that drive. If I'm interested in exploring a particular folder, I'll need to find the folder identifier as it's known to One Drive. These represent the folders and files that are at the root. Using PROC SQL and SELECT INTO, I can find the folder by its name and store its ID in another macro variable. Then, I use the /children verb again, but this time with the folder ID instead of the "root" constant. /* At this point, if you want to act on any of the items, you just replace "root" with the ID of the item. So to list the items in the "SASGF" folder I have: - find the ID for that folder - list the items within by using the "/children" verb */ Here are the items from my SASGF folder. I know that I keep a spreadsheet named "sas_tech_talks_18.xlsx" in this SASGF folder. With the /content verb, I can download the file from One Drive and store it in the file system that is local to my SAS session. Then, I can use PROC IMPORT to read it into a SAS data set. I've just downloaded my data from the cloud and brought it into my SAS session. We can build wonderful documents from SAS too, and it's important to be able to share those. By using the PUT method with the /content verb, we can copy a file from the local SAS session into a target folder on One Drive. Most often, this will probably be an Excel spreadsheet or maybe a PDF report. (But hey, maybe it's a good opportunity to try out the new ODS WORD destination in SAS 9.4 Maint 6? ) If you want to replace an existing file, then you'll want to perform the additional step of retrieving the unique ID for that file from One Drive. When you PUT the new version of the file into place, its history and sharing properties should remain intact. Here is my code for navigating the folder/file structure in my One Drive and finally replacing an existing file. /* If you want to replace a file instead of making a new file then you need to upload it with the existing file ID. If you don't replace it with the existing ID, some sharing properties and history could be lost. */ As you can see from my One Drive history for this file, I've tested this program a few times -- resulting in 23 revisions of this file in its history! You can find the source files for these examples on Git Hub. I've organized this code into 4 different files in order to make it easy to reuse: I also included a template for the file, with obvious placeholders for the client_id and tenant_id that you'll substitute with your own values. You'll also need to change the statements that define &CONFIG_LOC -- the location of your configuration directory where you're storing these files. I developed these examples in SAS University Edition -- yes, this works there! I also ran the code from my full SAS environment via SAS Enterprise Guide. 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. 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: In her role as Product Manager for SAS Platform Technologies (including the SAS Add-In for Microsoft Office), my colleague Amy Peters hears this question often. With many organizations adopting Microsoft Office 365 -- the "cloud" version of Office -- what does this mean for other processes that integrate with Microsoft Office applications? Microsoft has used different names for these similar offerings: Office 2016, Office 365, Microsoft 365, Office Online. The bottom line is that most users of a "365" package in the cloud, also have access to the Microsoft Office tools on their Windows desktop. They can use the full version of Excel, Power Point, Word, etc., and they also have access to these same tools via a web browser. At SAS, we recently experienced this transition ourselves. Have the Office applications on our desktops vanished? While more of our data is now on the cloud (looking at you, One Drive), it's not really changing how we work, especially when creating/maintaining content. (Like many organizations, we already had one foot in this world by using Microsoft Share Point for collaboration.) Let's look at an example of how I use SAS with Microsoft Office. Then I open Excel on my desktop and use the SAS Add-In for Microsoft Office to embed the shared report into my spreadsheet. Check out this video Tech Talk with SAS developer Tim Beese. This task does not generate a SAS program that you can reuse in a batch SAS process or SAS stored process. The task works by using SAS Workspace APIs to transfer data across your network connection, so all of the work happens "behind the scenes". However, the task does create a detailed log output that shows what files were copied, how many bytes were transferred, how long it took, and whether there were any errors. You'll find the Copy Files task in the Data category of the SAS Tasks list. But, with a little work, you can add the task to older versions. Here's the view from SAS Enterprise Guide v8.2: This task has been included in SAS Enterprise Guide since the v7.13 release (late 2017). You can download the Copy Files task from this link (Zip file). The download package includes multiple versions that depend on your version of SAS Enterprise Guide: v4.3, v5.1, v6.1, v7.1 (before v7.13), and one for v4.1 (with a reduced feature set). There is also a documentation file (PDF) that provides instruction for how to install and use the task. You might need to perform this extra step to "unblock" the downloaded DLL to avoid an error ("HRESULT: 0x80131515") when you try to add the task to your installation. The post How to copy files in SAS Enterprise Guide appeared first on The SAS Dummy. 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 One Drive -- 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. 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. 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 One Drive (or Share Point Online) cloud to read and update your files. Note: 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. Before I go on, I have to give major credit to Joseph Henry, the SAS developer who maintains PROC HTTP. Joseph did the heavy lifting for putting together the code and examples in this article. He also regularly adds new features to PROC HTTP that make it a more natural fit for calling REST APIs that require special authentication flows, such as OAuth2. Note: I've updated this article several times to include detailed steps and "gotchas." I've added use cases for Share Point Online and Microsoft Teams. I wrote a comprehensive paper for SAS Global Forum 2020. And I also recorded a 25-minute video (posted on SAS Support Communities) that shows all of the steps that I followed. 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 job of deconstructing OAuth2 -- with code samples -- in this SAS Global Forum paper. When we're writing SAS programs to access Microsoft One Drive or Share Point, 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: 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. Oh, and by the way, even though the examples in this article are specific to One Drive, the exact same authentication flow and steps can be used for all of the Microsoft 365 APIs. Have fun with Outlook, Teams, Excel, and all of your favorite cloud-based Microsoft apps. Visit the Microsoft Application Registration portal to register your new app. You'll sign in with your Microsoft 365 credentials. 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. 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: 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.) Your app will need specific permissions in order to function. In my example, I want my SAS program to read documents from my One Drive, and also add new docs and update existing docs. The permissions I need are: The documentation for the Microsoft Graph API 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. 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. 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: There are a few app-specific values that we'll need to reference throughout the SAS programs we're writing. I decided to create a configuration file for these settings rather than hard-code them into my SAS statements. This will make it easier for other people to reuse my code in their own applications. I created a file named that looks like this (but with different tenant_id and client_id values): By "externalizing" the IDs specific to my account/instance, I can use SAS code to read the values at run time. Note: This code, like all of the code in this article, uses features from SAS 9.4 Maintenance 5. /* Set the variables that will be needed through the code We'll need these for authorization and also for runtime use of the service. Reading these from a file so that the values are easy to adapt for different users or projects. */ Now that I've defined the application, it's time to "sign into it" and grant it the permission to read and manage content in One Drive. This step needs to be completed from a web browser while I am signed into my Microsoft 365 account. The web address is very long..we can use a SAS program to generate it for us. 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&response_type=code&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient&resource=https://graph.---END --------- Copy and paste the URL (all on one line, no spaces) into the address bar of your web browser. When you press Enter, you'll be prompted to grant the required permissions: Once you click Accept, the browser will redirect to what a blank page, but the URL contains the authorization code that we need: Copy the value that appears after the code= in the URL, only up to the &session= part. It's going to be a very long string -- over 700 characters. Note: if you don't see the permissions prompt but instead see something like this: Then you probably need to work with your IT support to grant consent for your app. See the section "Possibly required: Obtaining admin consent" above. My colleague Joseph wrote a few convenient utility macros that can help manage the access token and refresh token within your SAS session. These macros include: I'm not going to walk through the macro code in this article, but the SAS programs are straightforward and well-documented. See "How to get this example code" at the end of this article. With these macros in place, we can paste the (very long) authorization code we retrieved in the previous step into a macro variable. Then we can run the %get_token macro to generate the tokens and store them in a local file. Running this step will create a new file, token.json, in your designated config folder. Here's an screenshot of what my version looks like right now: It's very important that you keep this file secure. With the information in this file (your refresh token) and your file (with your client ID and tenant ID), anyone can use these code techniques to impersonate you and access your Microsoft 365 data. There are techniques for storing these files such that only you can see them. I've spent nearly 1500 words to get this far, so thanks for sticking with me. ) 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. The good news is that these steps take much longer to describe than to actually execute. For the remainder of this article, I'll be using methods from the Microsoft Graph API. This REST-based API provides access to almost all of Microsoft's hosted services. For my examples, I'll be using methods within the Files component of the API: Drives and Drive Items (folders and files). You can explore and try the Microsoft 365 APIs with the Graph Explorer application from Microsoft. If you sign in with your own account, you can use the APIs with your own data. " 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? This is a great way to try these APIs and discover the correct methods to use before implementing them in your SAS code. Well, that monkey is not going to produce this access token. ) We'll need to explore the One Drive system from the top-down, using code. It's possible for you to have multiple root drives, and if that's the case for you, you'll need to modify this code a bit. This code queries the service for your drives, and stores the identifier for just the first drive in a macro variable. We'll need that identifier later to retrieve a list of top-level items. Note that this code uses the new OAUTH_BEARER option in PROC HTTP -- a convenient addition when working with OAuth2-compliant APIs. This is shorthand -- and more intuitive syntax -- for placing "Authorization: Bearer TOKEN-VALUE" in the HTTP headers. The steps for Share Point Online are nearly the same as for One Drive, except that we need to reference the site hostname (yoursite.sharepoint.com, for example) and the /sites resource (instead of the /me/drives resource). sitepath This example uses the /drive method to access the files on the Sharepoint site -- works just like One Drive. API also supports a /lists method for Share Point lists. Use the Graph Explorer app to find the correct APIs for your purpose. https://developer.microsoft.com/en-us/graph/graph-explorer */ With the drive identifier in hand (whether One Drive or Share Point), I can use the /children verb on the Microsoft Graph API to get a list of all of the top-level objects in that drive. If I'm interested in exploring a particular folder, I'll need to find the folder identifier as it's known to One Drive. These represent the folders and files that are at the root. Using PROC SQL and SELECT INTO, I can find the folder by its name and store its ID in another macro variable. Then, I use the /children verb again, but this time with the folder ID instead of the "root" constant. /* At this point, if you want to act on any of the items, you just replace "root" with the ID of the item. So to list the items in the "SASGF" folder I have: - find the ID for that folder - list the items within by using the "/children" verb */ Here are the items from my SASGF folder. I know that I keep a spreadsheet named "sas_tech_talks_18.xlsx" in this SASGF folder. With the /content verb, I can download the file from One Drive and store it in the file system that is local to my SAS session. Then, I can use PROC IMPORT to read it into a SAS data set. I've just downloaded my data from the cloud and brought it into my SAS session. We can build wonderful documents from SAS too, and it's important to be able to share those. By using the PUT method with the /content verb, we can copy a file from the local SAS session into a target folder on One Drive. Most often, this will probably be an Excel spreadsheet or maybe a PDF report. (But hey, maybe it's a good opportunity to try out the new ODS WORD destination in SAS 9.4 Maint 6? ) If you want to replace an existing file, then you'll want to perform the additional step of retrieving the unique ID for that file from One Drive. When you PUT the new version of the file into place, its history and sharing properties should remain intact. Here is my code for navigating the folder/file structure in my One Drive and finally replacing an existing file. /* If you want to replace a file instead of making a new file then you need to upload it with the existing file ID. If you don't replace it with the existing ID, some sharing properties and history could be lost. */ As you can see from my One Drive history for this file, I've tested this program a few times -- resulting in 23 revisions of this file in its history! You can find the source files for these examples on Git Hub. I've organized this code into 5 different files in order to make it easy to reuse: I also included a template for the file, with obvious placeholders for the client_id and tenant_id that you'll substitute with your own values. You'll also need to change the statements that define &CONFIG_LOC -- the location of your configuration directory where you're storing these files. I developed these examples in SAS University Edition -- yes, this works there! I also ran the code from my full SAS environment via SAS Enterprise Guide. 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. 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: 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. Like Rick, I used new features in SAS 9.4 to produce this chart (in fact, I cribbed heavily from his code)..I used SAS Enterprise Guide to run the program. Update 25Aug2020: 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, switching to the light-on-dark theme named "Raven". It's a personal preference influenced by today's trends -- but it's not economical on printer ink if you decide you want a hard copy. You might notice that my chart is a bit busier than Rick's version. As a desktop client application that works across multiple SAS versions, we tend to issue major releases of SAS Enterprise Guide more often than we update the core engine of SAS software. 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 L10N release of v4.3 in 2010). You might also notice that some of these releases happened very close together. Often, SAS R&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). Here's the code that produced the chart: As citizens of the Internet, we are all familiar with IP addresses -- probably more so than our Internet founding fathers had ever intended. These addresses are typically represented in a 4-piece segmented list of numbers separated by dots. Each segment is called an octet because it contains 8 (count 'em, eight! The four-octect IP address is part of the IPv4 standard. Note: There is a newer IPv6 standard (featuring 16 octets) that many newer networks use and which allows for more addresses. This has become necessary because all new consumer products are required by law to connect to the Internet. (I think that each of my daughter's "Polly Pocket" pieces can connect to Wi Fi.) But in this article I'm ignoring IPv6. UPDATE 2020-Sep-04: My colleague Agata Bogacki has written a newer article that includes IPv6 and IPv4 and techniques to map to a geolocation. The easy-to-read segmented IP address is actually a 32-bit number, and sometimes it is useful to convert the display value into its numeric form. For example, consider the databases that help you to map an IP address to a geographic location in the world. These databases use a numerical range to map an address to a country or city. (For more on range-based geocoding, see this topic in the PROC GEOCODE documentation.) Here is a SAS program that converts a character-based, 4-segment IP address into its equivalent numeric value. It uses the SCAN function, a DATA step ARRAY, and a little bit of math to do the work: datalines; 1.148 117.203.114.198 1.156 119.247.220.11 12.201.116.58 128.2.38.96 128.204.197.27 128.204.207.83 134.102.237.2 141.155.113.98 169.2.124.79 1.231 1.229 173.234.211.69 1.232 178.157.198.132 1.44 1.184 1.213 1.204 1.149 188.165.187.71 ; Here's the output: With this mapping, I can then combine my collection of IP addresses with one of the IP-to-geolocation databases that are available. (SAS provides a macro to help work with Max Mind, which you can learn about in this topic.) Here's a sample result: The post Using SAS to convert IP addresses into numerical IP values appeared first on The SAS Dummy. The code and data that drive analytics projects are important assets to the organizations that sponsor them. As such, there is a growing trend to manage these items in the source management systems of record. The specific system might be Git Hub Enterprise, Git Lab, or Bitbucket -- all platforms that are based on Git. Many SAS products support direct integration with Git. This includes SAS Studio, SAS Enterprise Guide, and the SAS programming language. (That last one checks a lot of boxes for ways to use Git and SAS together.) While we have good documentation and videos to help you learn about Git and SAS, we often get questions around "best practices" -- what is the best/correct way to organize your SAS projects in Git? In this article I'll dodge that question, but I'll still try to provide some helpful advice in the process. It’s difficult for us to prescribe exactly how to organize project repositories in source control. Your best approach will depend so much on the type of work, the company organization, and the culture of collaboration. But I can provide some guidance -- mainly things to do and things to avoid -- based on experience. DO NOT build one huge repository that contains everything you currently maintain. Your work only grows over time and you'll come to regret/revisit the internal organization of a huge project. Once established, it can be tricky to change the folder structure and organization. If you later try to break a large project into smaller pieces, it can be difficult or impossible to maintain the integrity of source management benefits like file histories and differences. DO NOT organize projects based only on the teams that maintain them. And of course, don't organize projects based on individual team members. All teams reorganize over time, and you don't want to have to reorganize all of your code each time that happens. And code projects change hands, so keep the structure personnel-agnostic if you can. Major refactoring of code can introduce errors, and you don't want to risk that just because you got a new VP or someone changed departments. Instead, DO organize projects based on function/work that the code accomplishes. Think modular..don't make projects too granular (or you'll have a million projects). The one thing they have in common is that I'm the main contributor -- but I organize them into functional repos that theoretically (oh please oh please) someone else could step in to take over. This might seem a bit communist, but collaboration works best when we don't regard code that we write as "our turf." DO NOT cling to notions of code "ownership." It makes sense for teams/subject-matter experts to have primary responsibility for a project, but systems like Git are designed to help with transparency and collaboration. Be open to another team member suggesting and merging (with review and approval) a change that improves things. Git Hub, Git Lab, and Bitbucket all support mechanisms for issue tracking and merge requests. These allow changes to be suggested, submitted, revised, and approved in an efficient, transparent way. Many teams have foundational "shared code" for standard operations, coded in SAS macros or shared statements. Consider placing these into their own project that other projects and teams can import. You can even use Git functions within SAS to fetch and include this code directly from your Git repository: If you rely on a repository for shared code and components, make sure that tests are in place so changes can be validated and will not break downstream systems. You can even automate tests with continuous integration tools like Jenkins. DO document how projects relate to each other, dependencies, and prepare guidance for new team members to get started quickly. For most of us, we feel more accountable when we know that our code will be placed in central repositories visible to our peers. It may inspire cleaner code, more complete documentation, and a robust on-boarding process for new team members. Use the Markdown files (and others) in a repository to keep your documentation close to the code. Once your project files are in a Git repository, you might need to change your way of working so that you aren't going against the grain of Git benefits. DO NOT work on code changes in a shared directory with multiple team members –- you'll step on each other. The advantage of Git is that it's a distributed workflow and each developer can work with their own copy of the repository, and merge/accept changes from others at their own pace. DO use Git branching to organize and isolate changes until you are ready to merge them with the main branch. It takes a little bit of learning and practice, but when you adopt a branching approach you'll find it much easier to manage -- it beats keeping multiple copies of your code with slightly different file and folder names to mark "works in progress." DO consider learning and using Git tools such as Git Bash (command line), Git GUI, and a code IDE like VS Code. These don't replace the SAS-provided coding tools with their Git integration, but they can supplement your workflow and make it easier to manage content among several projects. When you're ready to learn more about working with Git and SAS, we have many webinars, videos, and documentation resources: was the most-streamed television show of 2020. According to reports that I've seen, the show was streamed for 57 billion minutes during this extraordinary year. I'm guessing that's in part because we've all been shut in and working from home; we crave our missing office interactions. We lived vicariously (and perhaps dysfunctionally) through watching Dunder Mifflin staff. But another major factor was the looming deadline of the departure of from Netflix as of January 1, 2021. It was a well-publicized event, so Netflix viewers had to get their binge on while they could. (Since the show has only 201 episodes we clearly we have a few repeats in there.) I built a heatmap that shows the frequency and intensity of our streaming of this popular show. People in my house are fans of the show, and they account for nearly 6,000 of those 57 billion streaming minutes. In this graph each row is a month, each square is a day. A square with any red indicates at least one virtual visit with the Scranton crew; the darker the shade, the more episodes streamed during that day. You can see that Sept 15, 2020 was a particular big binge with 17 episodes. (Each episode is about 20-21 minutes, so it's definitely achievable.) To build this heatmap, I started with my Netflix viewing history (downloaded from my Netflix account as CSV files). S.)" titles, and then merged with a complete "calendar" of dates between late 2017 and the start of 2021. Summarized and merged, the data looks something like this: With all of the data summarized in this way such that there is only one observation per X and Y value, I can use the HEATMAPPARM statement in PROC SGPLOT to visualize it. (If I needed the procedure to summarize/bin the data for me, I would use the HEATMAP statement. ) You can see the full code -- with all of the data prep -- on my Git Hub repository here. You may even run the code in your own SAS environment -- it will fetch my Netflix viewing data from another Git Hub location where I've stashed it. If you examine the heatmap I produced, you can almost see our Office enthusiasm in three different bursts. These relate directly to our 3 children and the moments they discovered the show. First was early 2018 (middle child), then late 2019 (youngest child), then late 2020 (oldest child, now 22 years old, striving to catch up). The Office ran for 9 seasons, and our kids have their favorite seasons and episodes -- hence the repeated viewings. I used PROC FREQ to show the distribution of episode views across the seasons: Season 1 is remarkably low for two reasons. First and most importantly, it contains the fewest episodes. Second, many viewers agree that Season 1 is the "cringiest" content, and can be uncomfortable to watch. (This Reddit user leaned into the cringe with his data visualization of "that's what she said" jokes.) From the data (and from listening to my kids), I know that Season 2 is a favorite. Of the 60 episodes we streamed at least 4 times, 19 of them were in Season 2. Our kids continue to embrace in other mediums as well. We have t-shirts depicting the memes for "FALSE." and "Schrute Farms." We listen to The Office Ladies podcast, hosted by two stars of the show. In 2019 our daughter's Odyssey of the Mind team created a parody skit based on When I was a computer science student in the 1980s, our digital alphabet was simple and small. 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..that was before the Internet forced us to work together. Before Unicode, we lived in a digital Tower of Babel.) 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: 🤷 Its text-art ancestor (not strictly ASCII as a sharp reader pointed out) is this: While ASCII and text art currently enjoys a retro renaissance, the emoji has become indispensable in our daily communications. 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 i Phone-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. 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. In 2015, emoji characters were added into Unicode and have been revised steadily with universal agreement. 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, Git Hub 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.) For more background about emojis, read How Emjois Work (source: How Stuff Works). 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 SAS On Demand for Academics (the free environment for any learner), this is already set for you. It's not unusual for a text message to be ALL emojis with no "traditional" words. And SAS Viya offers only UTF-8 -- which makes sense, because it's the best for most data and it's how most apps work these days. The website maintains the complete compendium of emojis as defined in the latest standards. Emojis are everywhere, and their presence can enrich (and complicate) the way that we analyze text data. They also provide the emoji definitions as data files, which we can easily read into SAS. For example, emojis are often useful cues for sentiment (smiley face! This program reads all of the data as published and adds features for just the "basic" emojis: (As usual, all of the SAS code in this article is available on Git Hub.) 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 graphics produced in the SG procedures. I also added the HTML-encoded representation of the emoji, which uses the form where NNNN is the Unicode value for the character. Here's the raw data view: When you PROC PRINT to an HTML destination, here's the view in the results browser: The 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. I found the Git Hub/gemoji project, 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: Upon reading these data, I quickly realized the JSON text contains the actual Unicode character for the emoji, and not the decimal or hex value that we might need for using it later in SAS. I wanted to convert the emoji character to its numeric code. That's when I discovered the UNICODEC function, which can "decode" the Unicode sequence into its numeric values. (Note that some characters use more than one value in a sequence). Here's my complete program, which includes some reworking of the tags and aliases attributes so I can have one record per emoji: Here's a snippet of the report that includes some of the more interesting sequences: The diversity and inclusion aspect of emoji glyphs is ever-expanding. For example, consider the emoji for "family": Note: I noticed that not all browsers have caught up on rendering that last example. In my browser it looks like this: 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. 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 we know that emoji use differs among different age generations 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. 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. If you're encountering emojis in your data and considering them in your reporting and analytics, please let me know how! The post How to work with emojis in SAS appeared first on The SAS Dummy.

date: 25-Aug-2021 22:02next


2020-2021 © d.free-online-arcade-games.com
Sitemap