Hi,
I have a series of batch programs that terminate due to "ERROR: Couldn't find range or sheet in spreadsheet". What's happening is my xlsx import is seeking 6 potential tabs from the files in the FTP directory. If the file does not have the tab i get the error during import.
Is there an OPTION to bypass this error?
I have tried the NOSYNTAXCHECK and NOERRORABEND prior to my data step and still get the error in log.
Be happy that you were alerted to the fact that you received incomplete/inconsistent data. Do NOT try to suppress such ERRORs.
The typical solution for this problem is to pre-check your incoming data to figure out exactly what it contains, and then adapt your software to only grab that data.
Tom
Here's some code that will hopefully help.
1. I switched a SQL call to the DICTIONARY table for your use of PROC CONTENTS. Probably not much difference, I'm just more familiar with it.
2. If I understand what you're trying to do, the key is to run a macro for as many occurences as you have worksheets.
Good luck!
Tom
%let i = 1;
%let file_name = ABCD;
%let folder_path = DEFG;
/*create library for xlsx file*/
libname indata xlsx "C:\workingfolder\TestXL.xlsx";
/* Get the member names in the library */
proc sql noprint;
create table work.contents as
select memname from dictionary.members where libname="INDATA";
run;
%macro GetSheet(sheet_name, i);
data file_src_&i (drop=Tries ID);
length file_name $200. file_path $200.;
set indata."&sheet_name"n;
sheet="&sheet_name";
file_name = "&file_name";
file_path = "&folder_path";
file_count = &i;
run;
%mend;
data _null_;
set contents (keep=memname);
ExecuteLine = '%GetSheet('||strip(memname)||','||strip(put(_n_, best15.))||');';
call execute(ExecuteLine);
run;
Hi, @Ksmit
Nope, my mind is completely blank (as usual!)
Oddly enough, I had just copied the first sheet into the other two, so I wasn't even able to tell if that was happening with me! But I've modified the data, and the code seems to be working fine in my environment.
Here's a few thoughts.
Here's a modifed version of the last "data _null_" step, where it keeps the results. In my case, the "LinesToSubmit" dataset looks like this
SASSHEET1 %GetSheet(SASSHEET1,1);
SASSHEET2 %GetSheet(SASSHEET2,2);
SASSHEET3 %GetSheet(SASSHEET3,3);
which is exactly what I would expect.
data LinesToSubmit;
set contents (keep=memname);
ExecuteLine = '%GetSheet('||strip(memname)||','||strip(put(_n_, best15.))||');';
call execute(ExecuteLine);
run;
See what it looks like in your case.
Also, I'm attaching the Excel file that I'm using. If you're comfortable opening it, you can take a look and see if I've misunderstood something that you're trying to do.
Can't wait to hear,
Tom
Okay, now it's becoming clearer. If I understand correctly, you want to do this process, but for multiple Excel workbooks. So we need to repeat the line
libname indata xlsx "C:\workingfolder\TestXL.xlsx";
for multiple Windows files. Please correct me if I'm wrong.
First question; how do you know the names of all of the workbooks that you want to retrieve data from?
Tom
When I saw you're first post, I heard a little voice in my head saying "Don't reply! Don't reply!". 😂
Okay, here's an attempt to loop through multiple workbooks, and then to loop through multiple spreadsheets within the workbooks. Give it a spin, and hopefully it'll give you some thoughts that will put you on the right path.
Good luck!
Tom
data all_files;
length file_name file_path $500;
file_path = "C:\workingfolder";
input file_name;
cards;
TestXL1.xlsx
TestXL2.xlsx
TestXL3.xlsx
run;
%macro GetFile(folder_path, file_name, i);
%macro GetSheet(folder_path, file_name, sheet_name, i, j);
data file_src_&i._&j.;
length file_name $200. file_path $200.;
set indata."&sheet_name"n;
sheet="&sheet_name";
file_name = "&file_name";
file_path = "&folder_path";
file_count1 = &i;
file_count2 = &j;
run;
%mend;
/*create library for xlsx file*/
libname indata xlsx "&folder_path.\&file_name.";
/* Get the member names in the library */
proc sql noprint;
create table work.contents as
select memname from dictionary.members where libname="INDATA";
quit;
data SheetsToSubmit;
length ExecuteLine $500;
set contents (keep=memname);
ExecuteLine = '%GetSheet(' || strip("&folder_path.") || ',' || strip("&file_name.") || ',' || strip(memname) || ',' || strip("&i.") || ',' || strip(put(_n_, best15.)) || ');';
call execute(ExecuteLine);
run;
%mend;
data BooksToSubmit;
length ExecuteLine $500;
set all_files;
ExecuteLine = '%GetFile(' || strip(file_path) || ',' || strip(file_name) || ',' || strip(put(_n_, best15.)) || ');';
call execute(ExecuteLine);
run;
Very pleased that you got to where you needed to go!
Tom
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.