<?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>topic Re: %sysfunc(exist, excel-tab-name) always returns 1 when using the XLSX engine on Excel spreadsheet in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559198#M156122</link>
    <description>&lt;P&gt;Everything is going to look like DATA to the XLSX libname engine.&amp;nbsp; When the only thing have is a hammer everything looks like a nail.&lt;/P&gt;</description>
    <pubDate>Thu, 16 May 2019 01:43:49 GMT</pubDate>
    <dc:creator>Tom</dc:creator>
    <dc:date>2019-05-16T01:43:49Z</dc:date>
    <item>
      <title>%sysfunc(exist, excel-tab-name) always returns 1 when using the XLSX engine on Excel spreadsheet</title>
      <link>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559129#M156098</link>
      <description>&lt;P&gt;Here is the problem:&lt;/P&gt;&lt;P&gt;libname anylib XLSX "myspreadsheet.xlsx" access=readonly;&lt;BR /&gt;&lt;BR /&gt;%put exist= %sysfunc(exist(anylib.Study)) ;&lt;BR /&gt;%put exist= %sysfunc(exist(anylib.Domains)) ;&lt;BR /&gt;%put exist= %sysfunc(exist(anylib.Domainsxxx)) ;&lt;BR /&gt;proc datasets lib=_ddtlib;&lt;BR /&gt;run;&lt;BR /&gt;quit;&lt;/P&gt;&lt;P&gt;libname _ddtlib clear;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Given the situation in which the spreadsheet does contain a tab named Study, the EXIST function should return a 1.&lt;/P&gt;&lt;P&gt;But if it does not contain a tab named Domains or Domainsxxx, it should return a 0.&lt;/P&gt;&lt;P&gt;Instead it is returning a 1.&amp;nbsp; In fact, as far as I can tell, it always returns a 1, which is very misleading.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;If the EXIST function is unable to tell if this tab exists in the spreadsheet, then I would expect a) that it would be documented in the doc on the XLSX engine (if it is, I can't find it), and b) that it return a 0 or missing value.&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Here is my log ( edited to remove spreadsheet name), The spreadsheet does NOT contain the tab Study or Domainsxxx.&amp;nbsp; The PROC DATASETS output correctly shows all of the tabs, listed with type=DATA.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;62 libname _ddtlib XLSX "path to spreadsheet\name.xlsx" access=readonly;&lt;BR /&gt;NOTE: Libref _DDTLIB was successfully assigned as follows:&lt;BR /&gt;Engine: XLSX&lt;BR /&gt;Physical Name: \\path to spreadsheet\name.xlsx&lt;BR /&gt;63&lt;BR /&gt;64 %put exist= %sysfunc(exist(_ddtlib.Study)) ;&lt;BR /&gt;exist= 1&lt;BR /&gt;65 %put exist= %sysfunc(exist(_ddtlib.Domains)) ;&lt;BR /&gt;exist= 1&lt;BR /&gt;66 %put exist= %sysfunc(exist(_ddtlib.Domainsxxx)) ;&lt;BR /&gt;exist= 1&lt;BR /&gt;67 proc datasets lib=_ddtlib;&lt;BR /&gt;68 run;&lt;BR /&gt;69 quit;&lt;BR /&gt;NOTE: PROCEDURE DATASETS used (Total process time):&lt;BR /&gt;real time 0.07 seconds&lt;BR /&gt;cpu time 0.07 seconds&lt;BR /&gt;70&lt;BR /&gt;71 libname _ddtlib clear;&lt;BR /&gt;NOTE: Libref _DDTLIB has been deassigned.&lt;BR /&gt;72&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;P&gt;Has anyone else seen this?&amp;nbsp; As it is, I'm going to have to go to a different approach to testing the existence.&lt;/P&gt;&lt;P&gt;dd&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 15 May 2019 19:36:02 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559129#M156098</guid>
      <dc:creator>DDutton</dc:creator>
      <dc:date>2019-05-15T19:36:02Z</dc:date>
    </item>
    <item>
      <title>Re: %sysfunc(exist, excel-tab-name) always returns 1 when using the XLSX engine on Excel spreadsheet</title>
      <link>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559158#M156112</link>
      <description>&lt;P&gt;I see the same thing. You should raise it with SAS Support.&lt;/P&gt;
&lt;P&gt;Here is a little macro. Not sure if you can suppress the ERROR in the log.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro xlsx_exist(data);
%local ret dsid;
%let ret=1;
%let dsid = %sysfunc(open(&amp;amp;data));
%if &amp;amp;dsid %then %let dsid=%sysfunc(close(&amp;amp;dsid));
%else %let ret=0;
&amp;amp;ret.
%mend xlsx_exist;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;PRE&gt;130  %put in.class = %xlsx_exist(in.class);
in.class = 1
131  %put in.no_such_file = %xlsx_exist(in.no_such_file);
ERROR: Couldn't find range or sheet in spreadsheet
in.no_such_file = 0&lt;/PRE&gt;
&lt;P&gt;So DICTIONARY.MEMBERS has the list of members in the XLSX file. Here is version that uses that information to test.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro xlsx_exist(libname,memname);
%local ret dsid;
%let ret=-1;
%let dsid = %sysfunc(open(sashelp.vmember(where=(libname=%upcase("&amp;amp;libname") and memname=%upcase("&amp;amp;memname")))));
%if &amp;amp;dsid %then %do;
  %let ret=%eval(0=%sysfunc(fetch(&amp;amp;dsid)));
  %let dsid=%sysfunc(close(&amp;amp;dsid));
%end;
&amp;amp;ret.
%mend xlsx_exist;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;PRE&gt;162  %put in.class = %xlsx_exist(in,class);
in.class = 1
163  %put in.no_such_file = %xlsx_exist(in,no_such_file);
in.no_such_file = 0&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 15 May 2019 21:05:59 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559158#M156112</guid>
      <dc:creator>Tom</dc:creator>
      <dc:date>2019-05-15T21:05:59Z</dc:date>
    </item>
    <item>
      <title>Re: %sysfunc(exist, excel-tab-name) always returns 1 when using the XLSX engine on Excel spreadsheet</title>
      <link>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559180#M156116</link>
      <description>&lt;P&gt;I would be somewhat hesitant to rely too much on the Dictionary tables for XLSX.&lt;/P&gt;
&lt;P&gt;I just did a test for (obviously my files):&lt;/P&gt;
&lt;PRE&gt;libname junk xlsx "x:\data\junk.xlsx";


proc sql;
   select *
   from dictionary.tables
   where libname='JUNK'
   ;
quit;&lt;/PRE&gt;
&lt;P&gt;Which reported a single member, GRAPH 1 - THE SGPLOT PROCEDU, with a Member type of data. The sheet is a graph so I question the report of member type.&lt;/P&gt;</description>
      <pubDate>Wed, 15 May 2019 21:54:40 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559180#M156116</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2019-05-15T21:54:40Z</dc:date>
    </item>
    <item>
      <title>Re: %sysfunc(exist, excel-tab-name) always returns 1 when using the XLSX engine on Excel spreadsheet</title>
      <link>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559198#M156122</link>
      <description>&lt;P&gt;Everything is going to look like DATA to the XLSX libname engine.&amp;nbsp; When the only thing have is a hammer everything looks like a nail.&lt;/P&gt;</description>
      <pubDate>Thu, 16 May 2019 01:43:49 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559198#M156122</guid>
      <dc:creator>Tom</dc:creator>
      <dc:date>2019-05-16T01:43:49Z</dc:date>
    </item>
    <item>
      <title>Re: %sysfunc(exist, excel-tab-name) always returns 1 when using the XLSX engine on Excel spreadsheet</title>
      <link>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559460#M156215</link>
      <description>&lt;P&gt;Here is some follow up.&amp;nbsp; Yes, I do plan to pass it along to Tech Support, as I think that the documentation on the XLSX engine should include a note about it.&amp;nbsp; The only thing relevant that I found is this in the EXIST documentation, "&lt;SPAN&gt;If you use a sequential library, then the results of the EXIST function are undefined.".&amp;nbsp; However, a) we don't get a blank or missing back from the function - we get 1, and b) I suppose that the XLSX engine could be considered sort of sequential, in that you cannot update or append to a tab, but you can jump around from tab to tab, so it is not completely sequential either.&amp;nbsp; And if that is the argument for the function not working correctly, then again, it should be documented.&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN&gt;As far as other techniques for verifying the existence of a tab on the spreadsheet, one more thing to note is that if the spreadsheet is open somewhere else in read/write mode, the libname assignment will be successful, but errors will result if you actually try to read from the spreadsheet (even with the access=readonly option specified).&amp;nbsp; The OPEN function also fails.&amp;nbsp; In addition, when this happens, the libname and memnames do not exist in dictionary.tables. So I have gone to a 2-step verification process.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;/* spreadsheet level error checking */&lt;BR /&gt;%let lib_available = 0;&lt;BR /&gt;%let mytab_exist = 0;&lt;BR /&gt;&lt;BR /&gt;proc sql noprint;&lt;BR /&gt;/* be sure spreadsheet can be read - it may be open */&lt;BR /&gt;select count(*) into :lib_available&lt;BR /&gt;from dictionary.tables&lt;BR /&gt;where libname eq "MYLIB"&lt;BR /&gt;;&lt;BR /&gt;/* see if MYTAB tab exists */&lt;BR /&gt;select count(*) into :mytab_exist&lt;BR /&gt;from dictionary.tables&lt;BR /&gt;where libname eq "MYLIB" and memname eq "MYTAB "&lt;BR /&gt;;&lt;BR /&gt;quit;&lt;BR /&gt;&lt;BR /&gt;%if &amp;amp;lib_available eq 0 %then&lt;BR /&gt;%do; /* spreadsheet is not available - probably is open */&lt;BR /&gt;%put ERROR: spreadsheetname..xlsx cannot be read. It may be open. Macro will stop.;&lt;BR /&gt;%goto _stop0_;&lt;BR /&gt;%end;&lt;BR /&gt;&lt;BR /&gt;%else %if &amp;amp;mytab_exist eq 1 %then&lt;BR /&gt;%do; /* whatever I want to do */&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN&gt;It's longer, but it works.&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN&gt;Thanks for all the input.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN&gt;dd&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 16 May 2019 19:28:36 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559460#M156215</guid>
      <dc:creator>DDutton</dc:creator>
      <dc:date>2019-05-16T19:28:36Z</dc:date>
    </item>
    <item>
      <title>Re: %sysfunc(exist, excel-tab-name) always returns 1 when using the XLSX engine on Excel spreadsheet</title>
      <link>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559462#M156217</link>
      <description>I did not see this behavior in SAS 9.4M3</description>
      <pubDate>Thu, 16 May 2019 19:30:24 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/sysfunc-exist-excel-tab-name-always-returns-1-when-using-the/m-p/559462#M156217</guid>
      <dc:creator>DDutton</dc:creator>
      <dc:date>2019-05-16T19:30:24Z</dc:date>
    </item>
  </channel>
</rss>

