<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>Renato_sas Tracker</title>
    <link>https://communities.sas.com/kntur85557/tracker</link>
    <description>Renato_sas Tracker</description>
    <pubDate>Mon, 25 May 2026 20:28:45 GMT</pubDate>
    <dc:date>2026-05-25T20:28:45Z</dc:date>
    <item>
      <title>Viya Jobs returning temporary and dynamically generated images</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Viya-Jobs-returning-temporary-and-dynamically-generated-images/ta-p/980394</link>
      <description>&lt;DIV class="lia-message-template-content-zone"&gt;
&lt;P&gt;In one of the many customer iterations I had recently, I was asked to help develop a solution to allow an image that was dynamically created by a third-party library/API to be embedded in a SAS Visual Analytics (VA) report. In addition to some input parameters passed to that external API that are irrelevant to our discussion, there was one in special that contained the full path and name of the output image to be generated. Although it seems a simple task, it doesn’t take too long to realize some of the challenges:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;If the output image is stored with a fixed path and name, it doesn’t work well in VA reports with concurrent users:
&lt;UL&gt;
&lt;LI&gt;Image file names and/or locations must be unique and dynamically generated to allow concurrency, so different users don’t overwrite each other.&lt;/LI&gt;
&lt;/UL&gt;
&lt;/LI&gt;
&lt;LI&gt;If you generate random distinct names for each request, after the solution has been running for a while, you may have many image files stored somewhere:
&lt;UL&gt;
&lt;LI&gt;You must have a mechanism that manages the number of images stored, so it doesn’t grow forever.&lt;/LI&gt;
&lt;/UL&gt;
&lt;/LI&gt;
&lt;LI&gt;The client application consuming the images runs on a browser, so we must be able to stream the images or reference them by a URL or URI:
&lt;UL&gt;
&lt;LI&gt;The third-party API doesn’t accept URL or URI as parameters, so you must perform a conversion of some sort.&lt;/LI&gt;
&lt;/UL&gt;
&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I’ve decided to use SAS code as a Viya Job to be able to deal with the constraints above. With the SAS code I’d be able to:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Leverage temporary files via &lt;STRONG&gt;&lt;EM&gt;filename&lt;/EM&gt;&lt;/STRONG&gt; statements to generate the image names – those file names are unique, and files get automatically deleted when the SAS session ends, helping with challenges 1 and 2.&lt;/LI&gt;
&lt;LI&gt;Leverage Viya Content Server to temporarily store the image files – files stored in the Content Server can be referenced by a URI and are automatically deleted after some time, helping with challenges 2 and 3.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I only needed to find a way to transfer the image generated by the external API to the Viya Content Server, and it only took me one Google search for “sas copy binary files” to find the solution I was looking for in the first hit, a blog by &lt;A href="https://blogs.sas.com/content/author/chrishemedinger/" target="_blank" rel="noopener"&gt;Chris Hemedinger&lt;/A&gt;, more precisely the portion that uses the FCOPY function from SAS:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://blogs.sas.com/content/sasdummy/2013/09/17/copy-file-macro/" target="_blank" rel="noopener"&gt;https://blogs.sas.com/content/sasdummy/2013/09/17/copy-file-macro/&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This is the SAS code with the key elements:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;* Close all ODS output;
ods _all_ close;

* Set the temporary file location;
filename _bcin TEMP recfm=n; * RECFM=N means that the input is read as a stream (there are no records);

* Obtain the temporary /path/file value;
%let tmpfile=%qsysfunc(pathname(_bcin));

* Here you would add the code to call the external API passing &amp;amp;tmpfile as parameter;

* Fileref _webout with name _webout.html is automatically assigned in Viya Jobs;
* If fileref with name _webout.* has an extension that the browser knows how to visualize, such as html, jpg, etc. it will display it;
* The pre-assigned fileref _webout is not needed, so we must delete it first;
%let RC=%sysfunc(fdelete(_webout)); 

* Set content server file location;
* We need a fileref with the image's extension (so the browser can display it) and add recfm=n;
* The fileref could be called anything you want;
filename _webout filesrvc parenturi="&amp;amp;SYS_JES_JOB_URI" name="_webout.jpg" recfm=n;

* Copy API output to Content Server;
data _null_;
   length msg $ 384;
   rc=fcopy('_bcin', '_webout');
   if rc=0 then
      put 'NOTE: Copied _bcin to _webout.';
   else do;
      msg=sysmsg();
      put 'ERROR:' rc= msg=;
   end;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The code starts with closing all ODS outputs because we know we will be returning an image produced by an external API, so no ODS output is needed. Then we set the temporary file name and location using a TEMP fileref called &lt;STRONG&gt;&lt;EM&gt;_bcin&lt;/EM&gt;&lt;/STRONG&gt; and store its value in a macro variable. That macro variable is passed to the external API as the full path and name of the output image to be created. Next, we delete the existing fileref &lt;STRONG&gt;&lt;EM&gt;_webout&lt;/EM&gt;&lt;/STRONG&gt;. This fileref is automatically created for you in Viya Jobs with attribute &lt;STRONG&gt;&lt;EM&gt;name=_webout.html&lt;/EM&gt;&lt;/STRONG&gt;. All content of filerefs with &lt;STRONG&gt;&lt;EM&gt;name=_webout.*&lt;/EM&gt;&lt;/STRONG&gt; are automatically streamed back to the calling application, but we need a fileref that is slightly different. We need a fileref with &lt;STRONG&gt;&lt;EM&gt;RECFM=N&lt;/EM&gt;&lt;/STRONG&gt;, to indicate the file consists of a stream of bytes in binary format with no record boundaries, which is going to be necessary later when using the function FCOPY to copy the image generated by the API to the Content Server, and we want its &lt;STRONG&gt;&lt;EM&gt;name=_webout.jpg&lt;/EM&gt;&lt;/STRONG&gt;, so the browser knows it’s an image and therefore knows how to display it. The fileref itself does not need to be called &lt;STRONG&gt;&lt;EM&gt;_webout&lt;/EM&gt;&lt;/STRONG&gt;. The final data step copies the output image to Viya Content Server leveraging both filerefs. For the cleanup, the temporary file given by the TEMP fileref will be automatically disposed when the job finishes, and its copy in the &lt;STRONG&gt;&lt;EM&gt;_webout&lt;/EM&gt;&lt;/STRONG&gt; fileref will also be automatically deleted after some time.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If for some reason you want the &lt;STRONG&gt;&lt;EM&gt;name&lt;/EM&gt;&lt;/STRONG&gt; attribute of the fileref to be something other than &lt;STRONG&gt;&lt;EM&gt;_webout.*&lt;/EM&gt;&lt;/STRONG&gt;, or send back multiple files to the calling application, then you can call the Viya Job with &lt;STRONG&gt;&lt;EM&gt;_action=json&lt;/EM&gt;&lt;/STRONG&gt;. This makes the job return a list of output files in a json structure and the calling application has the freedom to decide what to do with each output file. This is explored in this other SAS Communities publication called &lt;A href="https://communities.sas.com/t5/SAS-Communities-Library/Viya-Jobs-that-Create-Multiple-Output-Files/ta-p/915951" target="_blank" rel="noopener"&gt;Viya Jobs that Create Multiple Output Files&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In my final implementation, the code returned a couple of files (the output image and a small json file with information about the code execution status), simply because this is the template I’m currently leveraging for the Viya Jobs I develop. It also makes it simple to integrate the job with VA via DDC (Data-Driven Content), which is what I had to do for that customer. Indeed, I used that framework to provide a solution where the chart was being created in Python, using SAS PROC PYTHON, after receiving input parameters from VA, but this will be the topic for another blog.&lt;/P&gt;
&lt;/DIV&gt;</description>
      <pubDate>Mon, 08 Dec 2025 19:54:22 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Viya-Jobs-returning-temporary-and-dynamically-generated-images/ta-p/980394</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2025-12-08T19:54:22Z</dc:date>
    </item>
    <item>
      <title>Using DDC to Force VA Objects to Refresh</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Using-DDC-to-Force-VA-Objects-to-Refresh/ta-p/978045</link>
      <description>&lt;P&gt;If you have ever developed a DDC that updates a CAS table that gets consumed by the same VA report where the DDC is embedded, you might have noticed that you either need to reopen the report or switch to view mode after each time the table gets updated. Also, depending on how the table is updated, you may need to make sure you don't drop the existing CAS table to prevent errors in case the VA report tries to fetch the data at the exact time you dropped the table. This publication shares some tricks that will take care of those issues.&lt;/P&gt;</description>
      <pubDate>Tue, 28 Oct 2025 22:36:31 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Using-DDC-to-Force-VA-Objects-to-Refresh/ta-p/978045</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2025-10-28T22:36:31Z</dc:date>
    </item>
    <item>
      <title>Re: Loading Tables into CAS from SAS Visual Analytics with SAS Jobs via Data-Driven Content-Part 3</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Loading-Tables-into-CAS-from-SAS-Visual-Analytics-with-SAS-Jobs/tac-p/966399#M10495</link>
      <description>&lt;P&gt;I'm glad to hear it worked!&lt;/P&gt;</description>
      <pubDate>Tue, 13 May 2025 11:07:40 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Loading-Tables-into-CAS-from-SAS-Visual-Analytics-with-SAS-Jobs/tac-p/966399#M10495</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2025-05-13T11:07:40Z</dc:date>
    </item>
    <item>
      <title>Re: Loading Tables into CAS from SAS Visual Analytics with SAS Jobs via Data-Driven Content-Part 3</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Loading-Tables-into-CAS-from-SAS-Visual-Analytics-with-SAS-Jobs/tac-p/966359#M10493</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/301833"&gt;@klroesner&lt;/a&gt;, after loading the modified XML, you will have two reports opened with the same name. Make sure you are saving the correct one. That's the only thing I can think of. BTW, this has changed since when this blog was published and the user id is no longer part of the caslib CASUSER. If you are still having issues, I'll be glad to be on a quick call with you to investigate.&lt;/P&gt;
&lt;P&gt;Best,&lt;/P&gt;
&lt;P&gt;Renato&lt;/P&gt;</description>
      <pubDate>Mon, 12 May 2025 22:13:33 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Loading-Tables-into-CAS-from-SAS-Visual-Analytics-with-SAS-Jobs/tac-p/966359#M10493</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2025-05-12T22:13:33Z</dc:date>
    </item>
    <item>
      <title>Re: Deploy DDC Implementation Files in SAS Content Server via SAS Viya GUIs</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Deploy-DDC-Implementation-Files-in-SAS-Content-Server-via-SAS/tac-p/950632#M9847</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/435705"&gt;@edwinvbe&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I agree with you that being able to reference a more user-friendly URL would be nice. The information shared in this blog is just a "hack" of the Content Server to work as a Web Server. Having said that, it's more of a workaround to allow for quick prototypes utilizing interfaces that you might already have access to than an ideal solution that would depend on IT to help you deploy the DDC and its files in a Web Server.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you look closer, you will notice that the image is the only file that is not deployed using the SAS Job Execution Web Application. This interface allows for some mime types that we leverage for html, css, and javascript files, but there is nothing for images. For images we've utilized the SAS Drive interface, which doesn't provide a custom URL to access content loaded through it, so we've used the image's URI to construct the URL, which leverages a different service called File Service.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Again, the Content Server was never meant to be used to service files like we are doing here, but it works, although with certain limitations as you've observed.&lt;/P&gt;</description>
      <pubDate>Wed, 13 Nov 2024 18:23:22 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Deploy-DDC-Implementation-Files-in-SAS-Content-Server-via-SAS/tac-p/950632#M9847</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2024-11-13T18:23:22Z</dc:date>
    </item>
    <item>
      <title>Re: SAS Visual Analytics Advanced Calculations (part 2 of 4): AggregateTable</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/SAS-Visual-Analytics-Advanced-Calculations-part-2-of-4/tac-p/943802#M9577</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/469530"&gt;@sas22337&lt;/a&gt;,&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In Viya 3.5 and 4 you can do that by defining an &lt;STRONG&gt;Aggregated Data&lt;/STRONG&gt; (not covered in the blog - the blog talks about &lt;STRONG&gt;AggregateTable&lt;/STRONG&gt; function). Once you add German Sales calculated item in the aggregated data table, that value is no longer treated as a calculation. It becomes a fixed number and therefore if you filter Germany out, the values are preserved for the other rows in the table. The Aggregated Data can be created by clicking on the "Data source menu" icon on the side of the top left dropdown containing the list of tables used in the report, and selecting "New data from aggregation of &amp;lt;your source table&amp;gt;".&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Renato_sas_0-1726232899104.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/100285iCF34414BF815F4E2/image-size/medium?v=v2&amp;amp;px=400" role="button" title="Renato_sas_0-1726232899104.png" alt="Renato_sas_0-1726232899104.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Renato_sas_2-1726233203641.png" style="width: 999px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/100287i86D0FBB7B38E98D6/image-size/large?v=v2&amp;amp;px=999" role="button" title="Renato_sas_2-1726233203641.png" alt="Renato_sas_2-1726233203641.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In the more recent Viya 4 releases, there is something new called &lt;STRONG&gt;dynamic parameters&lt;/STRONG&gt; that can also be used to solve this challenge. This is my preferred way. It uses less memory and performs better than the proposed solution above. You need to create a parameter that takes an expression that results in the German sales value (same expression we used in the blog) as its source, then create a calculated item based on that parameter. This trick works because the parameter is not affected by filters, so the calculated item is isolated from filtering Germany out.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Renato_sas_3-1726234179359.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/100292iBA8B383DFDD46DE7/image-size/medium?v=v2&amp;amp;px=400" role="button" title="Renato_sas_3-1726234179359.png" alt="Renato_sas_3-1726234179359.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Renato_sas_4-1726234304574.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/100293iDD53B0F7C4E373A5/image-size/medium?v=v2&amp;amp;px=400" role="button" title="Renato_sas_4-1726234304574.png" alt="Renato_sas_4-1726234304574.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Renato_sas_6-1726234620073.png" style="width: 999px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/100296i23EC8465D41EEF5D/image-size/large?v=v2&amp;amp;px=999" role="button" title="Renato_sas_6-1726234620073.png" alt="Renato_sas_6-1726234620073.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 13 Sep 2024 13:42:41 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/SAS-Visual-Analytics-Advanced-Calculations-part-2-of-4/tac-p/943802#M9577</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2024-09-13T13:42:41Z</dc:date>
    </item>
    <item>
      <title>Using Text Input object to enter list of values for filtering</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Using-Text-Input-object-to-enter-list-of-values-for-filtering/ta-p/930743</link>
      <description>&lt;DIV class="lia-message-template-content-zone"&gt;
&lt;P&gt;A customer once asked me how to use a text box to filter multiple values. He wanted to type a list of zip codes and use that list to filter other objects in the report. If he had Viya 2020.1.1 (December 2020) or later, I could have referred him to the search feature for List control objects, but he was running Viya 3.5, so we had to be creative and develop our own solution.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The solution was obviously an advanced filter applied to the object to be filtered, and the &lt;STRONG&gt;Contains&lt;/STRONG&gt; operator was the fist thing that came up to my mind. In Viya 3.5, the syntax for &lt;STRONG&gt;Contains&lt;/STRONG&gt; is the following:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;'Parameter'p Contains 'ZipCode'n&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This of course was the solution at a high level, but it didn’t take too long to realize we would need to:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Define a separator for the values in the list.&lt;/LI&gt;
&lt;LI&gt;Take care of certain exceptions, such as when the Text Input control is empty.&lt;/LI&gt;
&lt;LI&gt;Deal with blank spaces that could appear at the beginning and/or at the end of typed zip code values.&lt;/LI&gt;
&lt;LI&gt;Deal with mixed upper and lower case characters to support all types of zip codes around the world that could contain letters.&lt;/LI&gt;
&lt;LI&gt;Refine our requirements – for example: what happens if an incomplete zip code is typed, such as &lt;STRONG&gt;234&lt;/STRONG&gt;? Should we select all zip codes that contain &lt;STRONG&gt;234&lt;/STRONG&gt; or should it be a full match? What about the opposite – user types &lt;STRONG&gt;12345-678&lt;/STRONG&gt; and the table contains &lt;STRONG&gt;12345&lt;/STRONG&gt; – should they match?&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here is what we have decided:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Using comma as the separator would work just fine, as comma is not a character used in zip codes.&lt;/LI&gt;
&lt;LI&gt;If the Text Input control is left empty, then it should have the same behavior as Visual Analytics: no filter is applied.&lt;/LI&gt;
&lt;LI&gt;Leading and trailing blanks for each of the values should be ignored, as they are not part of the zip code values being searched.&lt;/LI&gt;
&lt;LI&gt;We would standardize in upper case characters only.&lt;/LI&gt;
&lt;LI&gt;Typed values and values stored in the table should match entirely, so &lt;STRONG&gt;12345&lt;/STRONG&gt; would not match &lt;STRONG&gt;12345-678&lt;/STRONG&gt; and vice-versa.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;To test if the input list of zip codes (a character parameter) is empty, we used the &lt;STRONG&gt;IsSet&lt;/STRONG&gt; operator, and to ignore the filter if it’s empty, we used the expression &lt;STRONG&gt;1 = 1&lt;/STRONG&gt; (which returns TRUE, as Visual Analytics doesn’t have a Boolean type):&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;IF ( 'Parameter'p IsSet )
RETURN (&amp;lt;expression&amp;gt;)
ELSE ( 1 = 1 )&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Now we needed to work on the &amp;lt;expression&amp;gt;. To remove blanks, we used the &lt;STRONG&gt;RemoveBlanks&lt;/STRONG&gt; function. We could have used the &lt;STRONG&gt;RemoveChars&lt;/STRONG&gt; function instead, which is more generic and would work for other types of characters. To standardize the input, we applied the &lt;STRONG&gt;UpCase&lt;/STRONG&gt; function:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;UpCase(RemoveBlanks('Parameter'p, _All_))&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Our &amp;lt;expression&amp;gt; then became:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;UpCase(RemoveBlanks('Parameter'p, _All_)) Contains UpCase(RemoveBlanks('ZipCode'n, _All_))&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Observe that the same transformations were applied to both sides, just to make sure we are comparing apples to apples.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For the full match of individual values, the operator &lt;STRONG&gt;Contains&lt;/STRONG&gt; naturally takes care of cases where the user types &lt;STRONG&gt;12345&lt;/STRONG&gt; on the list of values and the table contains a zip code like &lt;STRONG&gt;12345-678&lt;/STRONG&gt; (it’s a no match as defined), but the opposite is not true:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;“zipcodeA,12345,zipcodeB” Contains “12345-678” --&amp;gt; returns FALSE (not a match): &lt;FONT color="#339966"&gt;correct&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;“zipcodeA,12345-678,zipcodeB” Contains “12345” --&amp;gt; returns TRUE (a match): &lt;FONT color="#FF0000"&gt;incorrect&lt;/FONT&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If the user types &lt;STRONG&gt;12345-678&lt;/STRONG&gt; in the Text Input control, it would match zip code &lt;STRONG&gt;12345&lt;/STRONG&gt;, and potentially any other subset of the input value, such as those bad zip codes:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;12345-&lt;/LI&gt;
&lt;LI&gt;123&lt;/LI&gt;
&lt;LI&gt;45-6&lt;/LI&gt;
&lt;LI&gt;-678&lt;/LI&gt;
&lt;LI&gt;-&lt;/LI&gt;
&lt;LI&gt;7&lt;/LI&gt;
&lt;LI&gt;etc…&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;To guarantee the full match of what was being typed, we had to search for the entire value, and an easy way to do that was to include characters to mark the beginning and the end of the values in the search string. Well, it turned out that by definition, all values were already separated by comma in the input text, so it naturally became the character to indicate start and end of values. All we had to do was to include the separator in the expression, by concatenating a comma before and after the zip codes stored in the table, using the operator &lt;STRONG&gt;Concatenate&lt;/STRONG&gt; twice:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;Concatenate(
            ',',
            Concatenate(
                        UpCase(RemoveBlanks('ZipCode'n, _All_)), 
                        ','
                        )
            )&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;After concatenating comma before and after:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;“zipcodeA,12345, zipcodeB” Contains “,12345-678,” --&amp;gt; returns FALSE (not a match): &lt;FONT color="#339966"&gt;correct&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;“zipcodeA,12345-678, zipcodeB” Contains “,12345,” --&amp;gt; returns FALSE (not a match): &lt;FONT color="#339966"&gt;correct&lt;/FONT&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This seemed all we had to do, except for one thing: if user types &lt;STRONG&gt;12345-678&lt;/STRONG&gt; as the first or the last element on the search list, or if it’s the only element in the list, it will not contain the separator character, and valid zip code values will not be found:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;“12345-678,zipcodeB” Contains “,12345-678,” --&amp;gt; returns FALSE (not a match): &lt;FONT color="#FF0000"&gt;incorrect&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;“zipcodeA,12345-678” Contains “,12345-678,” --&amp;gt; returns FALSE (not a match): &lt;FONT color="#FF0000"&gt;incorrect&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;“12345-678” Contains “,12345-678,” --&amp;gt; returns FALSE (not a match): &lt;FONT color="#FF0000"&gt;incorrect&lt;/FONT&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;To fix that we needed to append a comma at the beginning and at the end of the entire typed input parameter string, exactly as we did before with the zip codes stored in the table:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;Concatenate(
            ',',
            Concatenate(
                        UpCase(RemoveBlanks('Parameter'p, _All_)), 
                        ','
                        )
            )&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;After we did that:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;“,12345-678,zipcodeB,” Contains “,12345-678,” --&amp;gt; returns TRUE (a match): &lt;FONT color="#339966"&gt;correct&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;“,zipcodeA,12345-678,” Contains “,12345-678,” --&amp;gt; returns TRUE (a match): &lt;FONT color="#339966"&gt;correct&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;“,12345-678,” Contains “,12345-678,” --&amp;gt; returns TRUE (a match): &lt;FONT color="#339966"&gt;correct&lt;/FONT&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Putting everything together, this is how the filter expression looked like (before Viya 2023.06 syntax):&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;IF ( 'Parameter'p IsSet )
RETURN ( Concatenate(',', Concatenate(UpCase(RemoveBlanks('Parameter'p, _All_)), ',')) 
         Contains 
         Concatenate(',', Concatenate(UpCase(RemoveBlanks('ZipCode'n, _All_)), ',')) )
ELSE ( 1 = 1 )
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Same expression starting with Viya 2023.06 syntax (basically &lt;STRONG&gt;IsSet&lt;/STRONG&gt; and &lt;STRONG&gt;Contains&lt;/STRONG&gt; are functions instead of operators and the key work &lt;STRONG&gt;_All_&lt;/STRONG&gt; no longer has underscores):&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;IF IsSet('Parameter'p)
RETURN Contains(
          Concatenate(',', Concatenate(UpCase(RemoveBlanks('Parameter'p, All)), ',')),
          Concatenate(',', Concatenate(UpCase(RemoveBlanks('ZipCode'n, All)), ','))
       )
ELSE ( 1 = 1 )
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;In our case, zip codes were already stored as characters in the source table, but if that was not the case, we could simply apply the &lt;STRONG&gt;Format&lt;/STRONG&gt; function to transform them into characters, and the rest of the expression would be the same.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Obviously, as long as the requirements remain the same, this expression can be leveraged for other use cases, such as searching for car makes.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Suppose that you have a bar chart, and you want to be able to type one or more vehicle Makes separated by comma in the Text Input control object at the top to filter the chart:&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Figure 01-Text input and bar chart objects" style="width: 999px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/96985i2B1EF3AD8A590BCD/image-size/large?v=v2&amp;amp;px=999" role="button" title="Figure 01-Text input and bar chart objects.png" alt="Figure 01-Text input and bar chart objects" /&gt;&lt;span class="lia-inline-image-caption" onclick="event.preventDefault();"&gt;Figure 01-Text input and bar chart objects&lt;/span&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;Let’s take a look at how you would do that in three easy steps.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;FIRST&lt;/STRONG&gt;, you create a parameter with the following attributes:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;EM&gt;Name&lt;/EM&gt;: list of Makes separated by comma&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Type&lt;/EM&gt;: Character&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Multiple values&lt;/EM&gt;: unchecked&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Current value&lt;/EM&gt;: empty&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Figure 02-Create character parameter" style="width: 480px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/96986iDD6884B9F737A088/image-size/large?v=v2&amp;amp;px=999" role="button" title="Figure 02-Create character parameter.png" alt="Figure 02-Create character parameter" /&gt;&lt;span class="lia-inline-image-caption" onclick="event.preventDefault();"&gt;Figure 02-Create character parameter&lt;/span&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;Knowing that this parameter will carry multiple values, you may be attempted to check the box for multiple values, but a text input control object, where this parameter is going to be assigned to receive its value, does not accept multiple values – the object is a text box, and therefore it accepts only a single value, which is a string.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;SECOND&lt;/STRONG&gt;, you assign the parameter to the Text Input control object. Note that before Viya 2024.05, the parameter is assigned in the object’s Roles pane:&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Figure 03-Assign parameter to text input object prior to Viya 2024.05" style="width: 396px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/96992i46E4298B184628EA/image-size/large?v=v2&amp;amp;px=999" role="button" title="Figure 03-Assign parameter to text input object prior to Viya 2024.05.png" alt="Figure 03-Assign parameter to text input object prior to Viya 2024.05" /&gt;&lt;span class="lia-inline-image-caption" onclick="event.preventDefault();"&gt;Figure 03-Assign parameter to text input object prior to Viya 2024.05&lt;/span&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Starting in Viya 2024.05, this assignment is done in the object’s Actions pane:&amp;nbsp;&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Figure 04-Assign parameter to text input object in Viya 2024.05 and beyond" style="width: 431px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/96982iD9DB3766058509AF/image-size/large?v=v2&amp;amp;px=999" role="button" title="Figure 04-Assign parameter to text input object in Viya 2024.05 and beyond.png" alt="Figure 04-Assign parameter to text input object in Viya 2024.05 and beyond" /&gt;&lt;span class="lia-inline-image-caption" onclick="event.preventDefault();"&gt;Figure 04-Assign parameter to text input object in Viya 2024.05 and beyond&lt;/span&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;THIRD&lt;/STRONG&gt;, you add the advanced filter discussed previously into the bar chart’s Filters pane – remember that the name of the parameter and the data item being searched are different in this example.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Now let’s suppose you type &lt;STRONG&gt;“Toyota,,&amp;nbsp;&amp;nbsp; ,&amp;nbsp;&amp;nbsp;&amp;nbsp; bmw,&amp;nbsp; hoNdA&amp;nbsp; ,Mercedes,Volks Wagen&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; , xyz, Nissan SUV, Land rover”&lt;/STRONG&gt;, without the quotation marks, in the Text Input object and hit Enter – you must hit Enter for the value to be assigned to the parameter. Starting from the inner most operators/functions and moving outwards, this is what happens:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Remove all blanks (space characters) from the input parameter. You should get this: &lt;STRONG&gt;Toyota,,,bmw,hoNdA,Mercedes,VolksWagen,xyz,NissanSUV,Landrover&lt;/STRONG&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;OL start="2"&gt;
&lt;LI&gt;Make everything upper case as a best practice for string comparison: &lt;STRONG&gt;TOYOTA,,,BMW,HONDA,MERCEDES,VOLKSWAGEN,XYZ,NISSANSUV,LANDROVER&lt;/STRONG&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;OL start="3"&gt;
&lt;LI&gt;Concatenate a comma at the end. Note that comma is used as the separator. It must be a character or combination of characters that do not appear in the data being filtered - all possible values that Make can assume in this example. This is what you have so far: &lt;STRONG&gt;TOYOTA,,,BMW,HONDA,MERCEDES,VOLKSWAGEN,XYZ,NISSANSUV,LANDROVER,&lt;/STRONG&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;OL start="4"&gt;
&lt;LI&gt;Concatenate a comma (or the other elected separator) at the beginning. Let’s call this result the standardized parameter: &lt;STRONG&gt;,TOYOTA,,,BMW,HONDA,MERCEDES,VOLKSWAGEN,XYZ,NISSANSUV,LANDROVER,&lt;/STRONG&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;OL start="5"&gt;
&lt;LI&gt;Repeat the same steps for the Make column to create the standardized Make, so you can compare apples to apples. For example, if the value of the Make being compared is &lt;STRONG&gt;Land Rover&lt;/STRONG&gt;, it would become: &lt;STRONG&gt;,LANDROVER,&lt;/STRONG&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;OL start="6"&gt;
&lt;LI&gt;Check if the standardized parameter contains the searched standardized Make.&lt;/LI&gt;
&lt;LI&gt;Only do all of that if the parameter is set. If it’s not set, return true, meaning all Make values should be displayed, which is the default in SAS Visual Analytics.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Figure 05-Results" style="width: 999px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/96984i525CE15B6A10228D/image-size/large?v=v2&amp;amp;px=999" role="button" title="Figure 05-Results.png" alt="Figure 05-Results" /&gt;&lt;span class="lia-inline-image-caption" onclick="event.preventDefault();"&gt;Figure 05-Results&lt;/span&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Note that &lt;STRONG&gt;Mercedes&lt;/STRONG&gt; did not show up in the bar chart because it’s stored as &lt;STRONG&gt;Mercedes-Benz&lt;/STRONG&gt; in the table. In another hand, &lt;STRONG&gt;Nissan&lt;/STRONG&gt; is a valid car make but &lt;STRONG&gt;Nissan SUV&lt;/STRONG&gt; is not, so it was not returned. Also, because the implemented filter is not case sensitive, &lt;STRONG&gt;Honda&lt;/STRONG&gt; was displayed as expected, even if typed with mixed casing in a strange way. Because spaces are eliminated, mistakenly typed &lt;STRONG&gt;Volks Wagen&lt;/STRONG&gt; (two words), matched the make &lt;STRONG&gt;Volkswagen&lt;/STRONG&gt;. Non-existing makes such as &lt;STRONG&gt;xyz&lt;/STRONG&gt;, empty values, and extra blank spaces didn’t affect the results.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Please, let me know in the comments what you think about this solution and how or for what purpose you have used it. If you have Viya release 2020.1.1 (December 2020) or above, I’m particularly interested in knowing why you had to adopt this solution instead the List control object with search capabilities available out of the box.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;/DIV&gt;</description>
      <pubDate>Mon, 03 Jun 2024 22:22:48 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Using-Text-Input-object-to-enter-list-of-values-for-filtering/ta-p/930743</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2024-06-03T22:22:48Z</dc:date>
    </item>
    <item>
      <title>Re: How to count Unique/Distinct values in VA? From parts of a spreadsheet</title>
      <link>https://communities.sas.com/t5/SAS-Visual-Analytics/How-to-count-Unique-Distinct-values-in-VA-From-parts-of-a/m-p/930302#M18067</link>
      <description>&lt;P&gt;I just came across this old question that for some reason was left unanswered. The solution is similar to what&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/61362"&gt;@Stu_SAS&lt;/a&gt;&amp;nbsp;had posted before:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;Total Family Members =&amp;nbsp;AggregateTable(_Sum_, Table(_Sum_, Fixed("Family id"n), 1))&lt;/PRE&gt;</description>
      <pubDate>Thu, 30 May 2024 17:05:18 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Visual-Analytics/How-to-count-Unique-Distinct-values-in-VA-From-parts-of-a/m-p/930302#M18067</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2024-05-30T17:05:18Z</dc:date>
    </item>
    <item>
      <title>Re: Deploy DDC Implementation Files in SAS Content Server via SAS Viya GUIs</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Deploy-DDC-Implementation-Files-in-SAS-Content-Server-via-SAS/tac-p/921788#M8834</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/438695"&gt;@hyunwoo_kim&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P&gt;Have you set the content to JavaScript, as shown in figure 12?&lt;/P&gt;</description>
      <pubDate>Tue, 26 Mar 2024 13:36:33 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Deploy-DDC-Implementation-Files-in-SAS-Content-Server-via-SAS/tac-p/921788#M8834</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2024-03-26T13:36:33Z</dc:date>
    </item>
    <item>
      <title>Viya Jobs that Create Multiple Output Files</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Viya-Jobs-that-Create-Multiple-Output-Files/ta-p/915951</link>
      <description>&lt;P&gt;Recently in the SAS Community Library: SAS' &lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/1484"&gt;@Renato_sas&lt;/a&gt;&amp;nbsp;reveals how to use data-driven content to run SAS Viya jobs so you can have more than one output generated, total control about what to do with them and better job execution error handling.&lt;/P&gt;</description>
      <pubDate>Fri, 16 Feb 2024 15:20:49 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Viya-Jobs-that-Create-Multiple-Output-Files/ta-p/915951</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2024-02-16T15:20:49Z</dc:date>
    </item>
    <item>
      <title>Re: Using list of values from Excel file to filtering VA report</title>
      <link>https://communities.sas.com/t5/SAS-Visual-Analytics/Using-list-of-values-from-Excel-file-to-filtering-VA-report/m-p/910610#M17743</link>
      <description>&lt;P&gt;For your reference, here are some links to additional information that might be helpful (each one has multiple parts):&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P lang="x-none"&gt;&lt;A href="https://communities.sas.com/t5/SAS-Communities-Library/Data-Driven-Content-leveraging-third-party-visualizations-in-SAS/ta-p/437303" target="_blank"&gt;https://communities.sas.com/t5/SAS-Communities-Library/Data-Driven-Content-leveraging-third-party-visualizations-in-SAS/ta-p/437303&lt;/A&gt;&lt;/P&gt;
&lt;P lang="x-none"&gt;&lt;A href="https://communities.sas.com/t5/SAS-Communities-Library/Introduction-to-Integration-of-SAS-Visual-Analytics-with-SAS/ta-p/670823" target="_blank"&gt;https://communities.sas.com/t5/SAS-Communities-Library/Introduction-to-Integration-of-SAS-Visual-Analytics-with-SAS/ta-p/670823&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Fri, 05 Jan 2024 13:45:50 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Visual-Analytics/Using-list-of-values-from-Excel-file-to-filtering-VA-report/m-p/910610#M17743</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2024-01-05T13:45:50Z</dc:date>
    </item>
    <item>
      <title>Re: Deploy DDC Implementation Files in SAS Content Server via SAS Viya GUIs</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Deploy-DDC-Implementation-Files-in-SAS-Content-Server-via-SAS/tac-p/910456#M8488</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/439126"&gt;@OnkarD11&lt;/a&gt;, I'm not sure I understand what the problem is now. In your last screenshot you have the expected HTML output with all three elements: CSS, JS, and image. Besides the fact that your image doesn't have a transparent background, it looks good to me.&lt;/P&gt;</description>
      <pubDate>Thu, 04 Jan 2024 14:40:37 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Deploy-DDC-Implementation-Files-in-SAS-Content-Server-via-SAS/tac-p/910456#M8488</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2024-01-04T14:40:37Z</dc:date>
    </item>
    <item>
      <title>Re: Deploy DDC Implementation Files in SAS Content Server via SAS Viya GUIs</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Deploy-DDC-Implementation-Files-in-SAS-Content-Server-via-SAS/tac-p/910269#M8481</link>
      <description>&lt;P&gt;Do you see any error in the browser console?&lt;/P&gt;
&lt;P&gt;It seems that the job doesn't exist. Have you created a job and added the html form into it?&lt;/P&gt;</description>
      <pubDate>Wed, 03 Jan 2024 15:03:58 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Deploy-DDC-Implementation-Files-in-SAS-Content-Server-via-SAS/tac-p/910269#M8481</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2024-01-03T15:03:58Z</dc:date>
    </item>
    <item>
      <title>Re: Deploy DDC Implementation Files in SAS Content Server via SAS Viya GUIs</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Deploy-DDC-Implementation-Files-in-SAS-Content-Server-via-SAS/tac-p/910097#M8471</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/439126"&gt;@OnkarD11&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;When you added the *.js file, have you set its Content to JavaScript, as shown in figure 12?&lt;/P&gt;
&lt;P&gt;Note: this option is only available for Viya releases post 3.5.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Best,&lt;/P&gt;
&lt;P&gt;Renato&lt;/P&gt;</description>
      <pubDate>Tue, 02 Jan 2024 16:03:54 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Deploy-DDC-Implementation-Files-in-SAS-Content-Server-via-SAS/tac-p/910097#M8471</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2024-01-02T16:03:54Z</dc:date>
    </item>
    <item>
      <title>Re: SAS VA - load List Control with a pre-selected value</title>
      <link>https://communities.sas.com/t5/SAS-Visual-Analytics/SAS-VA-load-List-Control-with-a-pre-selected-value/m-p/907125#M17679</link>
      <description>&lt;P&gt;This is not possible with default VA control objects, but a DDC that implements an HTML form could be used to do it.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The DDC HTML would need to leverage CAS REST API to query the CAS table containing the desired report ID and pull the parameter settings from that report, supposedly stored in that CAS table. Because the custom HTML provides the prompts, you have the ability to manipulate them via JavaScript to pre-set the prompt values according to what had been saved.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I'm not saying it's simple, but it's definitely doable.&lt;/P&gt;</description>
      <pubDate>Fri, 08 Dec 2023 21:16:39 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Visual-Analytics/SAS-VA-load-List-Control-with-a-pre-selected-value/m-p/907125#M17679</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2023-12-08T21:16:39Z</dc:date>
    </item>
    <item>
      <title>Re: Passing paramters to job execution</title>
      <link>https://communities.sas.com/t5/SAS-Visual-Analytics/Passing-paramters-to-job-execution/m-p/904258#M17654</link>
      <description>&lt;P&gt;The ProxyDDCForVAJobCASIntegration does not have a &amp;lt;form&amp;gt; tag because all the information it needs is coming from VA via DDC message and the form is dynamically created via JavaScript.&lt;BR /&gt;If you want to have prompts defined directly in the HTML, in addition to those coming from VA, you can have them, but not in a form. The form would submit the parameters to a pre-defined URL, but you still need to add the parameters from VA, so you would need the help of JavaScript for that.&lt;/P&gt;
&lt;P&gt;I've modified (but have not validated/tested) your previous example to have a text box, a check box and a button in the HTML, and I've also added some comments. You are already setting many parameters via JavaScript, so I'd only add the extra parameters you need that come from the HTML directly, which in this example is the value in the text box. Also, the job html output will overwrite the HTML content (button, text, and check box). To have the output added below the HTML content, you would need to also return the job output in a list of files (a json structure) and use JavaScript to retrieve the output and display it in the desired location in the HTML (&lt;A href="https://go.documentation.sas.com/doc/en/pgmsascdc/v_042/jobexecug/p1kd3jm1ujesbin1denvxuflr8o0.htm" target="_blank"&gt;SAS Help Center: Returning a List of Output Files in JSON Format&lt;/A&gt;)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;

&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;Simple ODS HTML&amp;lt;/title&amp;gt;
&amp;lt;link rel="stylesheet" href="/SASJobExecution/theme"&amp;gt;
	&amp;lt;script type="text/javascript" src="https://bsxxxxx.fsyy.vwf.vwfs-ad/htmlcommons/util/messagingUtil.js"&amp;gt;&amp;lt;/script&amp;gt;
	&amp;lt;script type="text/javascript" src="https://bsxxxx.fsyy.vwf.vwfs-ad/htmlcommons/util/contentUtil.js"&amp;gt;&amp;lt;/script&amp;gt;
	&amp;lt;script type="text/javascript" src="https://bsxxxx.fsyy.vwf.vwfs-ad/htmlcommons/util/jobUtil.js"&amp;gt;&amp;lt;/script&amp;gt;
	
	&amp;lt;script&amp;gt;
		"use strict";
    	window.$ = window.parent.$;

		vat _resultData = null;
		var _job_output_cas_table_v2 = null; 	// example: "CARS_COPY";
		var _job_executing_message_v2 = null; 	// example: "Waiting for job to finish...";
		var _job_name_v2 = null; 				// example: "/Public/Jobs/SAS Communities/HelloCASWorld"
		
        function onDataReceived(resultData)
        {
            if (resultData) {
			    _resultData = resultData; // added this line to save the message received from VA to be reused when the button is clicked
				var resultName = resultData.resultName;
				
				var selections = va.contentUtil.initializeSelections(resultData); // good practice to remove eventual brush columns

				if (resultData.columns.length == 0) {
					// it needs at least one column and one row
					document.getElementById("JobResults").innerHTML = "";
					va.messagingUtil.postInstructionalMessage(resultName, "Please, assign roles");
					return;
				}
				
				var vaParameters = va.contentUtil.getVAParameters(resultData);
				_job_output_cas_table_v2  = vaParameters._job_output_cas_table_v2;
				_job_executing_message_v2 = vaParameters._job_executing_message_v2;
				_job_name_v2              = vaParameters._job_name_v2;
				if (!_job_executing_message_v2) _job_executing_message_v2 = "Executing job...";
				if (!_job_output_cas_table_v2 || !_job_name_v2) {
					// missing one or more parameters
					document.getElementById("JobResults").innerHTML = "";
					va.messagingUtil.postInstructionalMessage(
						resultName, 
						"Please, make sure the following parameters are being passed to this object:\n"+
						"(1) _job_name_v2\n"+
						"(2) _job_output_cas_table_v2\n"+
						"(3) _job_executing_message_v2 (optional)"
					);
					return;
				}
				
				/* transfer this block to new function submit() defined below, but change it slightly  
				   to remove access to the json information that is no longer returned in this example */
				/*
				document.getElementById("JobResults").innerHTML = _job_executing_message_v2;
				callJob(resultData)
					.done(function(jobOutput){
						if (jobOutput.success) {
							document.getElementById("JobResults").innerHTML = "Done!";
							setTimeout(() =&amp;gt; {document.getElementById("JobResults").innerHTML = "";}, 2000);
						}	
						else {
							 document.getElementById("JobResults").innerHTML = "Job finished with ERROR (see console for details)";
						}
					})
					.fail(function(jqXHR, textStatus, errorThrown){
						document.getElementById("JobResults").innerHTML = "Job failed to execute (see console for details)";
					});
				*/
            }
        }
		
		function submit() {
				document.getElementById("JobResults").innerHTML = _job_executing_message_v2;
				callJob(_resultData);
					/*
					.done(function(jobOutput){
						if (jobOutput.success) {
							document.getElementById("JobResults").innerHTML = "Done!";
							setTimeout(() =&amp;gt; {document.getElementById("JobResults").innerHTML = "";}, 2000);
						}	
						else {
							 document.getElementById("JobResults").innerHTML = "Job finished with ERROR (see console for details)";
						}
					})
					.fail(function(jqXHR, textStatus, errorThrown){
						document.getElementById("JobResults").innerHTML = "Job failed to execute (see console for details)";
					});
					*/
		}
		
	    function callJob(resultData) {
			va.jobUtil.PrepareVADataForSASJobs (resultData);
			var stringifiedJSON = JSON.stringify(resultData);
	
			// Your large JSON object as a Blob - Blob is like a file, and the POST method sends the file to the server
			var jsonBlob = new Blob([stringifiedJSON], {type: 'text/plain'});
			
			// Create form with input parameters
			var formData = new FormData();
			formData.append("_program", _job_name_v2);
			formData.append("_action", "execute");
			formData.append("_output_type", "html"); // the SAS code no longer returns json - ti now produces am html output
			formData.append("myjsonfile", jsonBlob);
			formData.append("castab", _job_output_cas_table_v2);
			
			// add/process information from html prompts:
			formData.append("mytext", document.getElementById("mytext")); // mytext will become a macro variable in the SAS code
			var showLog = document.getElementById("_debug").checked;
			if (showLog) {
			  formData.append("_debug", "log"); 
			}
	
			return $.ajax({
					method: "POST", 
					url: "/SASJobExecution/", 
					data: formData, 
					contentType: false, // do not send content-type
					processData: false, // do not transform data to fit to the default content-type application/x-www-form-urlencoded
					headers:{"X-CSRF-TOKEN": "$CSRF$", "Accept":"application/json"}
				})
				.done(function(jobOutput){
					if (jobOutput.success) {
						console.log("Job executed with success!");
					}		
					else {
						console.log("Job executed with ERROR");
						console.log("jobOutput=", jobOutput);
					}
				})
				.fail(function(jqXHR, textStatus, errorThrown){
					console.log("************** JOB FAILED ***************");
					console.log("jqXHR: ",jqXHR);
					console.log("textStatus: ",textStatus);
					console.log("errorThrown: ",errorThrown);
				});
	    }
	    
        va.messagingUtil.setOnDataReceivedCallback(onDataReceived);

    &amp;lt;/script&amp;gt;
	
&amp;lt;/head&amp;gt;

&amp;lt;body role="main" class="jobexec_body"&amp;gt;

&amp;lt;div class="jobexec_sample_header"&amp;gt;SAS&amp;lt;sup&amp;gt;&amp;amp;#174;&amp;lt;/sup&amp;gt; Job Execution&amp;lt;/div&amp;gt;

&amp;lt;h1 class="jobexec_sample_name"&amp;gt;Simple ODS HTML&amp;lt;/h1&amp;gt;

&amp;lt;p&amp;gt;
The PRINT procedure creates a simple HTML page that displays the data in the
SASHELP.CLASS table.
&amp;lt;/p&amp;gt;

&amp;lt;hr/&amp;gt;
&amp;lt;label for="mytext" id="mytext_label"&amp;gt;Any text:&amp;lt;/label&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;input type="text" id="mytext" name="mytext"&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;!-- this next line was replaced with the one below it --&amp;gt;
&amp;lt;!--input type="submit" value="Run code" class="jobexec_sample_input_submit"/--&amp;gt;
&amp;lt;button onclick="submit()"&amp;gt;Run Code&amp;lt;/button&amp;gt;
&amp;lt;input type="checkbox" name="_debug" id="_debug" value="log" class="jobexec_sample_input_checkbox"/&amp;gt;&amp;lt;label for="_debug"&amp;gt;Show SAS Log&amp;lt;/label&amp;gt;
&amp;lt;!-- I've added this div tag to be able to dsiplay the execution messages and show the Job output without overwriting the button and the check box --&amp;gt;
&amp;lt;div id="JobResults"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I've also removed the portion that returns json from the SAS code, as your job is now returning HTML output. You could return both, but this would make the solution quite different from what you are familiar with:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;title "&amp;amp;castab. &amp;amp;mytext.";
proc print data=sashelp.class noobs;
/* 	where age &amp;gt; &amp;amp;castab.; */
  var name sex age height weight;
run; quit;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;BTW, I intend to write a blog about jobs that return a list of files - for example, to handle json messages returned from the job to indicate the status of the execution and other job outputs - but this will most likely be in January 2024.&lt;/P&gt;</description>
      <pubDate>Wed, 22 Nov 2023 16:43:42 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Visual-Analytics/Passing-paramters-to-job-execution/m-p/904258#M17654</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2023-11-22T16:43:42Z</dc:date>
    </item>
    <item>
      <title>Re: Passing paramters to job execution</title>
      <link>https://communities.sas.com/t5/SAS-Visual-Analytics/Passing-paramters-to-job-execution/m-p/904169#M17652</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/127222"&gt;@acordes&lt;/a&gt;, the line below assigns the value in _job_output_cas_table_v2 to a parameter called castab and castab becomes a macro variable in the SAS job code:&lt;/P&gt;
&lt;PRE class="language-sas"&gt;&lt;CODE&gt;formData.append("castab", _job_output_cas_table_v2);&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;I can see that you used the code below to obtain the value of _job_output_cas_table_v2 from a VA parameter:&lt;/P&gt;
&lt;PRE class="language-sas"&gt;&lt;CODE&gt;_job_output_cas_table_v2  = vaParameters._job_output_cas_table_v2;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;Question for you:&lt;/P&gt;
&lt;P&gt;Have you performed the steps in VA that guarantee that the VA parameter is passed to the HTML code?&lt;/P&gt;
&lt;P&gt;&lt;A href="https://communities.sas.com/t5/SAS-Communities-Library/Using-parameters-with-Data-Driven-Content-in-SAS-Visual/ta-p/609557" target="_blank"&gt;Using parameters with Data-Driven Content in SAS Visual Analytics - SAS Support Communities&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 22 Nov 2023 00:00:34 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Visual-Analytics/Passing-paramters-to-job-execution/m-p/904169#M17652</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2023-11-22T00:00:34Z</dc:date>
    </item>
    <item>
      <title>Re: Challenge: Let's build a template report sporting all (common) visualizatios based on sashelp ta</title>
      <link>https://communities.sas.com/t5/SAS-Visual-Analytics/Challenge-Let-s-build-a-template-report-sporting-all-common/m-p/827616#M16317</link>
      <description>&lt;P&gt;It's a nice idea, indeed. Like&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/13794"&gt;@Sam_SAS&lt;/a&gt;, I also thought about the gallery of visualizations in the&amp;nbsp;documentation when I read about the challenge, which could be used as a guideline or source of inspiration. For a second pass on this challenge, showing how Options can modify each standard visualization could be an interesting exercise as well.&lt;/P&gt;</description>
      <pubDate>Mon, 08 Aug 2022 14:09:10 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Visual-Analytics/Challenge-Let-s-build-a-template-report-sporting-all-common/m-p/827616#M16317</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2022-08-08T14:09:10Z</dc:date>
    </item>
    <item>
      <title>Re: Introduction to Integration of SAS Visual Analytics with SAS Jobs via Data-Driven Content-Part 1</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Introduction-to-Integration-of-SAS-Visual-Analytics-with-SAS/tac-p/826655#M6800</link>
      <description>&lt;P&gt;I was talking about the browser's DevTools console log (Ctrl+Shift+i)&lt;/P&gt;</description>
      <pubDate>Tue, 02 Aug 2022 15:02:33 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Introduction-to-Integration-of-SAS-Visual-Analytics-with-SAS/tac-p/826655#M6800</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2022-08-02T15:02:33Z</dc:date>
    </item>
    <item>
      <title>Re: Introduction to Integration of SAS Visual Analytics with SAS Jobs via Data-Driven Content-Part 1</title>
      <link>https://communities.sas.com/t5/SAS-Communities-Library/Introduction-to-Integration-of-SAS-Visual-Analytics-with-SAS/tac-p/826648#M6798</link>
      <description>&lt;P data-unlink="true"&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/13255"&gt;@jimbobob&lt;/a&gt;, it would help to see the error messages in the browser's console log. Anyway, if you placed the utility js files in&amp;nbsp;/var/www/html/util like you said, then your URL should be https://10.100.3.5/util/messagingUtil.js&amp;nbsp;&amp;nbsp;(instead of&amp;nbsp;&lt;A href="https://10.100.3.5/github/util/messagingUtil.js" target="_blank"&gt;https://10.100.3.5/github/util/messagingUtil.js&lt;/A&gt;&amp;nbsp;as displayed in your screenshot).&lt;/P&gt;</description>
      <pubDate>Tue, 02 Aug 2022 14:41:42 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Communities-Library/Introduction-to-Integration-of-SAS-Visual-Analytics-with-SAS/tac-p/826648#M6798</guid>
      <dc:creator>Renato_sas</dc:creator>
      <dc:date>2022-08-02T14:41:42Z</dc:date>
    </item>
  </channel>
</rss>

