<?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: SAS macro to import multiple Excel sheets, clean invalid data, etc... in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60695#M13151</link>
    <description>[pre]&lt;BR /&gt;
options validvarname=any;&lt;BR /&gt;
[/pre]&lt;BR /&gt;
will allow you to use 01/21/2010 as a variable name, ues function vname() to get that,then you do not need to transform them.&lt;BR /&gt;
&lt;BR /&gt;
Ksharp</description>
    <pubDate>Tue, 03 May 2011 03:40:39 GMT</pubDate>
    <dc:creator>Ksharp</dc:creator>
    <dc:date>2011-05-03T03:40:39Z</dc:date>
    <item>
      <title>SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60693#M13149</link>
      <description>Hi, as Patrick suggested in my last post on SAS macro to generate a list of variables, let me describe a bit the data set I have downloaded from Datastream.&lt;BR /&gt;
&lt;BR /&gt;
To download monthly data for each variable, I have an Excel workbook with 27 sheets. Each sheets contains 9,000 firms (ISIN codes) and data is collected over 17 years. So each sheet has 9,000 rows and 200+ columns, each column corresponding to each quarter of each year. The raw data looks like below&lt;BR /&gt;
&lt;BR /&gt;
Code _1_Jan_95 _1_Feb_95........_1_Mar_11 _1_Apr_11&lt;BR /&gt;
ABC   534       353               353           555&lt;BR /&gt;
CDF  445         554              252           252&lt;BR /&gt;
GHI  $$ERRORS    556              335            552&lt;BR /&gt;
&lt;BR /&gt;
I have been download data for around 30 variables.&lt;BR /&gt;
My tasks include:&lt;BR /&gt;
1) Import all 27 Excell sheets into SAS&lt;BR /&gt;
2) Clean invalid values such as $$, ERRORS, NA, vv... whenever the firm doesn't have data for one particular quarter or year&lt;BR /&gt;
3) Convert all those values for each of the quarters from character value to numeric values. This is because if the firm in the 1st row in a given Excell sheet doesn't have data or have invalid data then after importing SAS documents it as a character values rather than numeric values, so 85.65 is arranged to left because it is recognized as characters&lt;BR /&gt;
4) Stack up/append vertically all these 27 datasets&lt;BR /&gt;
5) Transpose the final stacked-up dataset to panel data form, rename variables, etc...&lt;BR /&gt;
&lt;BR /&gt;
For importing 27 Excell sheets, I came up with the following macro&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
/*Import multiple Excel sheets in an Excel workbook*/&lt;BR /&gt;
&lt;B&gt;%let filepath=C:\RESEARCH\DataCollection\DS RequestManager;&lt;BR /&gt;
%let filename=VO.xlsm; &lt;BR /&gt;
%macro import_Excel_sheets(first_sheet=, last_sheet=);&lt;BR /&gt;
%local i; /*Loop over the datasets/sheets*/&lt;BR /&gt;
%do i=&amp;amp;first_sheet. %to &amp;amp;last_sheet. %by 1;&lt;BR /&gt;
	proc import	datafile="&amp;amp;filepath.\&amp;amp;filename."&lt;BR /&gt;
			out=Sheet&amp;amp;i. dbms=EXCEL replace;&lt;BR /&gt;
			sheet="Sheet&amp;amp;i.";&lt;BR /&gt;
			getnames=yes;&lt;BR /&gt;
			mixed=yes;&lt;BR /&gt;
	run;&lt;BR /&gt;
%end;&lt;BR /&gt;
%mend import_Excel_sheets;&lt;/B&gt;&lt;BR /&gt;
&lt;BR /&gt;
I'm really, really reluctant to use INFILE as one of you suggested. I'm not familiar with it, and to be honest, I still find it confusing to understand the advantage of using INFILE or anything involving INPUT X Y Z. Why? If I use INPUT X Y Z, I always have to count the columns or sth like that? How can I count? I have a list of 250,000 international firms, some firms have more codes than the others, how can I know what is the longest codes so I can declare sth like INPUT X $ longest_char_num (say, INPUT X $ 25)? &lt;BR /&gt;
&lt;BR /&gt;
Secondly, with 200++ columns I bet that I will have an extremely hard time typing all those variables INPUT var1 $ 12 var2$ 15 ..... var240 $ 22;&lt;BR /&gt;
&lt;BR /&gt;
So I think I must use Proc Import. &lt;BR /&gt;
&lt;BR /&gt;
Previously when I collect data like this, what I did was I cleaned data in Excell directly. I renamed variables, stacked sheets on top of each others. This time, one Excell file is really heavy. Even openning one file takes like 1 minute to open, then saving it also. Sometimes it just freezes. &lt;BR /&gt;
&lt;BR /&gt;
I can't change the way an Excel sheet of data looks because the data vendor dictates the way it looks.&lt;BR /&gt;
&lt;BR /&gt;
Back to the data cleaning, when it comes to transpose the stacked-up dataset, I must declare the BY variables, which is 200++, and so I initially must type all these _1_Jan_95 up until _1_Apr_11. I made errors once and it took days to spot where it is. The SAS logs runs like forever, and I intially must sit there and clear the logs (now I know I can use Proc Printto).&lt;BR /&gt;
&lt;BR /&gt;
Then it comes the invalid date _1_Feb_95 and I must extract parts of it and transform them to day, month and year. I have a long list of something like: &lt;B&gt;else if substr(_name_,4,3)="Feb" &amp;amp; substr(_name_,8,2)="95" then date='01Feb1995'D;&lt;/B&gt;&lt;BR /&gt;
&lt;BR /&gt;
By the way, I still find it hard to use INFILE and INPUT? How do you do it in practice? Do you manually count the position of the columns? Manually count the number of spaces for each variable?&lt;BR /&gt;
&lt;BR /&gt;
Message was edited by: smilingmelbourne

Message was edited by: smilingmelbourne</description>
      <pubDate>Mon, 02 May 2011 06:44:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60693#M13149</guid>
      <dc:creator>smilingmelbourne</dc:creator>
      <dc:date>2011-05-02T06:44:29Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60694#M13150</link>
      <description>If your variables are changing then proc import may work better. &lt;BR /&gt;
&lt;BR /&gt;
However, you should never need to type the variables out in a by statement, that sounds insanely inefficient. You may want to go into array processing. &lt;BR /&gt;
&lt;BR /&gt;
See a brief example below that might help.  I'd suggest cleaning/validating within the loop as well to output the final clean value rather than using a separate step. &lt;BR /&gt;
&lt;BR /&gt;
HTH,&lt;BR /&gt;
Reeza&lt;BR /&gt;
[pre]&lt;BR /&gt;
*Create random data set;&lt;BR /&gt;
data have;&lt;BR /&gt;
	do i=1 to 10;&lt;BR /&gt;
		a1=i;&lt;BR /&gt;
		a2=i*2;&lt;BR /&gt;
		output;&lt;BR /&gt;
	end;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
data have2;&lt;BR /&gt;
*rename variables to similar to your format;&lt;BR /&gt;
	set have (rename = (a1=_1_APR_95 a2=_1_MAY_95));&lt;BR /&gt;
&lt;BR /&gt;
*create array based on your data structure;&lt;BR /&gt;
	array orig{*} _1_:;&lt;BR /&gt;
	&lt;BR /&gt;
*loop over array;&lt;BR /&gt;
	do i=1 to dim(orig);&lt;BR /&gt;
		*get variable name in to process;&lt;BR /&gt;
		temp=vname(orig(i));&lt;BR /&gt;
*convert name to month date format;&lt;BR /&gt;
		variable_name=input(substr(temp, 4, 3)||substr(temp, 8,2), monyy5.);&lt;BR /&gt;
*get value of observation, you may need to use a temp value and clean it up before assigning final value;&lt;BR /&gt;
		value=orig(i);&lt;BR /&gt;
*output to transposed dataset;&lt;BR /&gt;
		output;&lt;BR /&gt;
	end;&lt;BR /&gt;
*drop variables that you don't need anymore;&lt;BR /&gt;
	drop _1_:;&lt;BR /&gt;
	format variable_name monyy7.;&lt;BR /&gt;
&lt;BR /&gt;
run;&lt;BR /&gt;
[/pre]</description>
      <pubDate>Mon, 02 May 2011 17:27:24 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60694#M13150</guid>
      <dc:creator>Reeza</dc:creator>
      <dc:date>2011-05-02T17:27:24Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60695#M13151</link>
      <description>[pre]&lt;BR /&gt;
options validvarname=any;&lt;BR /&gt;
[/pre]&lt;BR /&gt;
will allow you to use 01/21/2010 as a variable name, ues function vname() to get that,then you do not need to transform them.&lt;BR /&gt;
&lt;BR /&gt;
Ksharp</description>
      <pubDate>Tue, 03 May 2011 03:40:39 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60695#M13151</guid>
      <dc:creator>Ksharp</dc:creator>
      <dc:date>2011-05-03T03:40:39Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60696#M13152</link>
      <description>Hi&lt;BR /&gt;
&lt;BR /&gt;
From how you describe your data/data structure I believe below code should do the job.&lt;BR /&gt;
&lt;BR /&gt;
Just change the path in the libname to the location of your excel workbook and run the code.&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
libname MyWB EXCEL 'c:\temp\test.xls';&lt;BR /&gt;
options source2;&lt;BR /&gt;
&lt;BR /&gt;
proc sql noprint;&lt;BR /&gt;
   create table ctrl as&lt;BR /&gt;
      select libname, memname, name, type ,varnum&lt;BR /&gt;
      from dictionary.columns&lt;BR /&gt;
      where libname='MYWB'&lt;BR /&gt;
      order by libname, memname&lt;BR /&gt;
   ;&lt;BR /&gt;
   select name into :FirstCol_VarName &lt;BR /&gt;
   from ctrl&lt;BR /&gt;
   where varnum=1&lt;BR /&gt;
   ;&lt;BR /&gt;
&lt;BR /&gt;
quit;&lt;BR /&gt;
&lt;BR /&gt;
filename SET temp;&lt;BR /&gt;
filename ASSIGN temp;&lt;BR /&gt;
data _null_;&lt;BR /&gt;
  set ctrl;&lt;BR /&gt;
  by libname memname;&lt;BR /&gt;
&lt;BR /&gt;
  file SET;&lt;BR /&gt;
  if first.memname then&lt;BR /&gt;
     put libname +(-1) ".'" memname +(-1) "'n"  "(rename=(";&lt;BR /&gt;
  if type='char' and substr(name,1,1)='_' then&lt;BR /&gt;
     put name "=C_C" name;&lt;BR /&gt;
  if last.memname then&lt;BR /&gt;
    put "))";&lt;BR /&gt;
&lt;BR /&gt;
  file ASSIGN;&lt;BR /&gt;
  if type='char' and substr(name,1,1)='_' then&lt;BR /&gt;
  do;&lt;BR /&gt;
    put name "=coalesce(" name ",input(C_C" name ",?? 8.));";&lt;BR /&gt;
   put "drop C_C" name ";";&lt;BR /&gt;
  end;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
data want(keep=&amp;amp;FirstCol_VarName date value indsname);&lt;BR /&gt;
   set %include SET; indsname=inds;&lt;BR /&gt;
   %include ASSIGN;&lt;BR /&gt;
&lt;BR /&gt;
   format date date9.;&lt;BR /&gt;
   array CharDt {*} _: ;&lt;BR /&gt;
   do i=1 to dim(CharDt);&lt;BR /&gt;
      if NOT missing(CharDt(i)) then&lt;BR /&gt;
      do;&lt;BR /&gt;
         date=input(compress(vname(CharDt(i))),?? date9.);&lt;BR /&gt;
         value=CharDt(i);&lt;BR /&gt;
         indsname= inds;&lt;BR /&gt;
         output;&lt;BR /&gt;
      end;&lt;BR /&gt;
   end;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
libname MyWB ;&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
HTH&lt;BR /&gt;
Patrick</description>
      <pubDate>Tue, 03 May 2011 05:21:26 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60696#M13152</guid>
      <dc:creator>Patrick</dc:creator>
      <dc:date>2011-05-03T05:21:26Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60697#M13153</link>
      <description>Thank you, Reeza. Each of my datasets contains roughly 200+  columns, which I don't know whether they are numeric or character due to data errors in the first rows (if numers on the first row, then the column is numeric in SAS; otherwise, it's character), although they all should be numeric. &lt;BR /&gt;
&lt;BR /&gt;
So you mean I can use _CHARACTER_ and _NUMERIC_ to create 2 arrays, one for numeric and the other for characters. And after that, I should convert the character arrays from char to num?&lt;BR /&gt;
&lt;BR /&gt;
Thanks a lot</description>
      <pubDate>Tue, 03 May 2011 08:37:10 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60697#M13153</guid>
      <dc:creator>smilingmelbourne</dc:creator>
      <dc:date>2011-05-03T08:37:10Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60698#M13154</link>
      <description>Thank you very much for the hint!</description>
      <pubDate>Tue, 03 May 2011 08:37:51 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60698#M13154</guid>
      <dc:creator>smilingmelbourne</dc:creator>
      <dc:date>2011-05-03T08:37:51Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60699#M13155</link>
      <description>Thank you, Patrick. Your codes are very advanced to me! (but obviously very useful since I will learn a lot from that). I will read to understand the codes and will come back later if I have questions.</description>
      <pubDate>Tue, 03 May 2011 08:39:30 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60699#M13155</guid>
      <dc:creator>smilingmelbourne</dc:creator>
      <dc:date>2011-05-03T08:39:30Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60700#M13156</link>
      <description>Hi&lt;BR /&gt;
&lt;BR /&gt;
As it sounds all your columns in the Excel sheets will have a majority of numeric values. And what you want is that the resulting SAS dataset has all these columns numeric with missings for the cels in source with character values.&lt;BR /&gt;
&lt;BR /&gt;
If so then probabely using "mixed=no" for Proc Import would give you what you want (it also depends on your registry settings).&lt;BR /&gt;
Give it a try. More details in the doc: &lt;A href="http://support.sas.com/documentation/cdl/en/acpcref/63184/HTML/default/viewer.htm#a003103761.htm" target="_blank"&gt;http://support.sas.com/documentation/cdl/en/acpcref/63184/HTML/default/viewer.htm#a003103761.htm&lt;/A&gt;&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
In regards of my "advanced code":&lt;BR /&gt;
What I do there is:&lt;BR /&gt;
- use the Excel libname engine (this reads all excel sheets of a workbook into SAS data sets).&lt;BR /&gt;
- read the dictionary information of these newly created SAS datasets.&lt;BR /&gt;
- use the dictionary information ("metadata"=data about the data/the tables) to dynamically create statements to read all the existing tables and change character variables to numeric.&lt;BR /&gt;
&lt;BR /&gt;
"filename &lt;FILEREF&gt; temp" assigns a temporary external file. I then use a "data _null_" step to create SAS statements which I write ("put") to these external files.&lt;BR /&gt;
&lt;BR /&gt;
In the next data step I include these external files ("%include"). %include is a macro command which runs before the data step gets compiled. So it's basically just inserting the SAS code I've previously written to the temporary external files.&lt;BR /&gt;
&lt;BR /&gt;
Using "options source2" you see in the log what code the %include statements actually add.&lt;BR /&gt;
&lt;BR /&gt;
So again: %include just inserts the text (SAS code) written to the temporary exteral text file at the place where it's used and only after this the SAS compiler comes and compiles the data step.&lt;BR /&gt;
&lt;BR /&gt;
HTH&lt;BR /&gt;
Patrick&lt;BR /&gt;
&lt;BR /&gt;
Message was edited by: Patrick&lt;/FILEREF&gt;</description>
      <pubDate>Tue, 03 May 2011 09:06:25 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60700#M13156</guid>
      <dc:creator>Patrick</dc:creator>
      <dc:date>2011-05-03T09:06:25Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60701#M13157</link>
      <description>Hi, I doesn't work with "MIXED=NO". After importing into SAS, a lot of columns/variables have values that look sth like:&lt;BR /&gt;
&lt;BR /&gt;
- $$ERR,2660, NO DATA AVAILABLE&lt;BR /&gt;
- $$ERR,INVALID CODE&lt;BR /&gt;
- NA&lt;BR /&gt;
&lt;BR /&gt;
etc...&lt;BR /&gt;
&lt;BR /&gt;
If a column has a numeric value on the 1st rows, then it's perfectly OK and that whole columns looks exactly what I like. Otherwise, then all down the column are characters which I later have to convert to numeric. &lt;BR /&gt;
&lt;BR /&gt;
Previously when I collected smaller datasets with such problems, I relied on a simple trick of enterng any numeric value like 1, 2, 3 on the 1st row of the Excel sheet. Then, I imported them into SAS and everything was numeric. $$ERR, NA, etc... became dots which is exactly what I want. This time, for 230K firms over 17 years the Excel file becomes rather heavy. It takes like forever to click open or to save a change I made.&lt;BR /&gt;
&lt;BR /&gt;
Thank you very much</description>
      <pubDate>Tue, 03 May 2011 09:29:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60701#M13157</guid>
      <dc:creator>smilingmelbourne</dc:creator>
      <dc:date>2011-05-03T09:29:29Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60702#M13158</link>
      <description>Hi&lt;BR /&gt;
&lt;BR /&gt;
'doesn't work with "MIXED=NO". '&lt;BR /&gt;
That's why I referred you to the doc as it's written there that the behavior of "MIXED=NO" depends on the setting of "guessingrow".&lt;BR /&gt;
&lt;BR /&gt;
But nevertheless: If the data structure is as you've described it then the code I've posted should work.&lt;BR /&gt;
&lt;BR /&gt;
HTH&lt;BR /&gt;
Patrick</description>
      <pubDate>Tue, 03 May 2011 09:57:51 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60702#M13158</guid>
      <dc:creator>Patrick</dc:creator>
      <dc:date>2011-05-03T09:57:51Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60703#M13159</link>
      <description>smilingmelbourne &lt;BR /&gt;
 &lt;BR /&gt;
sounds like you should read and "transpose" your input in the first step to touch your data. That isn't supplied "out-of-the-box".&lt;BR /&gt;
For your data source, a libname statement pointing at the workbook could simplify access to the data, but you will need to ensure the first 8 lines of each sheet clarify the data types for those columns.&lt;BR /&gt;
Although you could read excel directly through DDE, most experts deprecate that technology.  &lt;BR /&gt;
If your data are CSV-type, then a simple data step allows you to achieve directly what you need.  &lt;BR /&gt;
Because you would "transpose" as you read data, you won't need to define much more than "code", "date" and "value" as output columns. &lt;BR /&gt;
If you want a special flag for those "$$ERRORS" cells, that is not much more work either. &lt;BR /&gt;
Let the INFILE and INPUT do the hard work&lt;BR /&gt;
Even if your datastream is created with 100,000 columns (highly unlikely) the program becomes no larger.&lt;BR /&gt;
 &lt;BR /&gt;
but of course, as you say you don't want(/need?) to learn INFILE/INPUT (how to make your task simpler with a little learning):&lt;BR /&gt;
Still, I would suggest your solution will become more manageable once you understand these things, and:&lt;BR /&gt;
* trailing @&lt;BR /&gt;
* output&lt;BR /&gt;
* do loop&lt;BR /&gt;
More examples and discussion can be found in&lt;BR /&gt;
&lt;A href="http://support.sas.com/documentation/cdl/en/basess/58133/HTML/default/a001302699.htm" target="_blank"&gt;http://support.sas.com/documentation/cdl/en/basess/58133/HTML/default/a001302699.htm&lt;/A&gt;  &lt;BR /&gt;
&lt;BR /&gt;
peterC</description>
      <pubDate>Tue, 03 May 2011 15:46:03 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60703#M13159</guid>
      <dc:creator>Peter_C</dc:creator>
      <dc:date>2011-05-03T15:46:03Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60704#M13160</link>
      <description>Other than his comment about DDE (i.e., not using something simply because of others' opinions .. especially when we don't all agree), I agree with Peter's comments.  However, if these are data that you scrapped from the web, why are you adding the extra layer of complexity by first putting the data into Excel files?&lt;BR /&gt;
&lt;BR /&gt;
Using the same techniques that Peter suggested, you could download the files directly and not risk introducing the whole range of import and conversion problems that can result from trying to interface with Excel.&lt;BR /&gt;
&lt;BR /&gt;
Art&lt;BR /&gt;
---------&lt;BR /&gt;
&amp;gt; smilingmelbourne &lt;BR /&gt;
&amp;gt;  &lt;BR /&gt;
&amp;gt; Sounds like you should read and "transpose" your input&lt;BR /&gt;
&amp;gt; in the first step to touch your data. That isn't&lt;BR /&gt;
&amp;gt; supplied "out-of-the-box".&lt;BR /&gt;
&amp;gt; For your data source, a libname statement pointing at&lt;BR /&gt;
&amp;gt; the workbook could simplify access to the data, but&lt;BR /&gt;
&amp;gt; you will need to ensure the first 8 lines of each&lt;BR /&gt;
&amp;gt; sheet clarify the data types for those columns.&lt;BR /&gt;
&amp;gt; Although you could read excel directly through DDE,&lt;BR /&gt;
&amp;gt; most experts deprecate that technology.  &lt;BR /&gt;
&amp;gt; If your data are CSV-type, then a simple data step&lt;BR /&gt;
&amp;gt; allows you to achieve directly what you need.  &lt;BR /&gt;
&amp;gt; Because you would "transpose" as you read data, you&lt;BR /&gt;
&amp;gt; won't need to define much more than "code", "date"&lt;BR /&gt;
&amp;gt; and "value" as output columns. &lt;BR /&gt;
&amp;gt; If you want a special flag for those "$$ERRORS"&lt;BR /&gt;
&amp;gt; cells, that is not much more work either. &lt;BR /&gt;
&amp;gt; Let the INFILE and INPUT do the hard work&lt;BR /&gt;
&amp;gt; Even if your datastream is created with 100,000&lt;BR /&gt;
&amp;gt; columns (highly unlikely) the program becomes no&lt;BR /&gt;
&amp;gt; larger.&lt;BR /&gt;
&amp;gt;  &lt;BR /&gt;
&amp;gt; But of course, as you say you don't want(/need?) to&lt;BR /&gt;
&amp;gt; learn INFILE/INPUT (how to make your task simpler&lt;BR /&gt;
&amp;gt; with a little learning):&lt;BR /&gt;
&amp;gt; Still, I would suggest your solution will become more&lt;BR /&gt;
&amp;gt; manageable once you understand these things, and:&lt;BR /&gt;
&amp;gt; * trailing @&lt;BR /&gt;
&amp;gt; * output&lt;BR /&gt;
&amp;gt; * do loop&lt;BR /&gt;
&amp;gt; More examples and discussion can be found in&lt;BR /&gt;
&amp;gt; &lt;A href="http://support.sas.com/documentation/cdl/en/basess/581" target="_blank"&gt;http://support.sas.com/documentation/cdl/en/basess/581&lt;/A&gt;&lt;BR /&gt;
&amp;gt; 33/HTML/default/a001302699.htm  &lt;BR /&gt;
&amp;gt; &lt;BR /&gt;
&amp;gt; peterC</description>
      <pubDate>Tue, 03 May 2011 18:37:40 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60704#M13160</guid>
      <dc:creator>art297</dc:creator>
      <dc:date>2011-05-03T18:37:40Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60705#M13161</link>
      <description>Thank you so much for the very useful material...</description>
      <pubDate>Wed, 04 May 2011 07:09:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60705#M13161</guid>
      <dc:creator>smilingmelbourne</dc:creator>
      <dc:date>2011-05-04T07:09:29Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60706#M13162</link>
      <description>Hi Art, thank you for reply. The data vendor (Datastream/Worldscope, etc...) has an Excel add-on that I must use in collecting their batch data. So I must set up a list of firms in Excel and download data for the firms into Excel. I can't use SAS Connect in collecting data from them.</description>
      <pubDate>Wed, 04 May 2011 07:16:47 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60706#M13162</guid>
      <dc:creator>smilingmelbourne</dc:creator>
      <dc:date>2011-05-04T07:16:47Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60707#M13163</link>
      <description>Hi Pattrick, I'm trying to absord your codes which I learnt a lot. Actually, I'm currently a student and the only SAS book I've read so far is The Little SAS Book plus several SUGI papers for beginners/intermediate users. &lt;BR /&gt;
&lt;BR /&gt;
This thing I found interesting since I've never seen it before, and after running it I saw all 27 Excel sheets in SAS. I could see things in each of the datasets. Never heard/seen this kind of thing before!&lt;BR /&gt;
&lt;BR /&gt;
&lt;B&gt;libname MyWB EXCEL 'C:\DataCollection\DS RequestManager\Sales.xlsm'; /*Assign Excel libnam engine*/&lt;/B&gt;&lt;BR /&gt;
&lt;BR /&gt;
Why is there minus/plus sign in your codes?&lt;BR /&gt;
&lt;BR /&gt;
&lt;B&gt;if first.memname then put libname +(-1) ".'" memname +(-1) "'n" "(rename=(";&lt;/B&gt;&lt;BR /&gt;
&lt;BR /&gt;
Actually, I run the program but it almost got through. An error: It says one variable is both numeric and character. So I didn't have a chance to look at the final dataset (as it has 0 row) in order to understand what is going on in the code.&lt;BR /&gt;
&lt;BR /&gt;
Thanks a lot for the codes. I've surely learnt a lot, a lot...</description>
      <pubDate>Wed, 04 May 2011 07:22:44 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60707#M13163</guid>
      <dc:creator>smilingmelbourne</dc:creator>
      <dc:date>2011-05-04T07:22:44Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60708#M13164</link>
      <description>the demo code using a data step (mostly comments) follows[pre]&lt;BR /&gt;
%let path= ~ ;     * unix ;&lt;BR /&gt;
%let path= !temp ; *windows ;&lt;BR /&gt;
* CREATE A DATA FILE ;&lt;BR /&gt;
data _null_ ;&lt;BR /&gt;
file "&amp;amp;path/vo.sheet1.csv" ;&lt;BR /&gt;
input ; list;&lt;BR /&gt;
put _infile_;&lt;BR /&gt;
CARDS;&lt;BR /&gt;
Code,_1_Jan_95,_1_Feb_95........_1_Mar_11,_1_Apr_11&lt;BR /&gt;
ABC,534,353,353,555 &lt;BR /&gt;
CDF,445,554,252,252 &lt;BR /&gt;
GHI,$$ERRORS,556,335,552&lt;BR /&gt;
;&lt;BR /&gt;
&lt;BR /&gt;
data datastream( keep= code date value ) ;&lt;BR /&gt;
    length        code $8   date value 8 ;&lt;BR /&gt;
    format date monyy7. ;&lt;BR /&gt;
    infile "&amp;amp;path/vo.sheet1.csv" DSD DLM=',' column=col ;&lt;BR /&gt;
******** column=col defines COL as a variable to hold the position &lt;BR /&gt;
         on the line  after each input statement executes.&lt;BR /&gt;
         By default, the next input statement will read at this position &lt;BR /&gt;
    ;&lt;BR /&gt;
    IF _N_ = 1 THEN DO ; * 1st time through, get start date from heading line ;&lt;BR /&gt;
        INPUT dummy $ DATE1 :$20. ; &lt;BR /&gt;
        list ; *echo line to log ;&lt;BR /&gt;
        DATE0 + input( compress( date1,'_'), ?? date11. ) ;&lt;BR /&gt;
        * this form of statement normally defines an accumulator&lt;BR /&gt;
          which are retained.&lt;BR /&gt;
          Here we remove "_" characters from the date-style column &lt;BR /&gt;
          header to make it suitable for the DATE. informat which&lt;BR /&gt;
          will provide a date that corresponds to the first value.&lt;BR /&gt;
          Thereafter columns are monthly - with dates which more easily &lt;BR /&gt;
          derived than "loaded" ;&lt;BR /&gt;
        if not date0 then stop ;&lt;BR /&gt;
        delete ;  * having no other use for this line ;&lt;BR /&gt;
    end ;&lt;BR /&gt;
    ********************** now read the data ;&lt;BR /&gt;
    date= date0 ; **** date of first value column ;&lt;BR /&gt;
    * start reading a line with the CODE column ;&lt;BR /&gt;
    input @1 code  @ ; &lt;BR /&gt;
    do until( colO &amp;gt;= col ) ; * stop looking once at end of line;&lt;BR /&gt;
        colO = col ;&lt;BR /&gt;
        * input moves the column pointer COL, until end-of-line ;&lt;BR /&gt;
        INPUT value ?? @@ ; &lt;BR /&gt;
        *           ?? ignores invalid data like $$ERROR &lt;BR /&gt;
                       returning just missing value = . &lt;BR /&gt;
                    @@ holds the line until next data step iteration ;   &lt;BR /&gt;
        if value then do ;&lt;BR /&gt;
            * having found some more data, release a row of code,date and value ;&lt;BR /&gt;
            output ;&lt;BR /&gt;
        end ; &lt;BR /&gt;
        date = intnx( 'month', date, 1 ) ; * adjust date for next months column ;&lt;BR /&gt;
    end ;&lt;BR /&gt;
    * this step iterates once for each line on the input file ;&lt;BR /&gt;
run ;</description>
      <pubDate>Wed, 04 May 2011 08:10:38 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60708#M13164</guid>
      <dc:creator>Peter_C</dc:creator>
      <dc:date>2011-05-04T08:10:38Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60709#M13165</link>
      <description>Thank you so much for the help. I will definitely learn a lot from your codes. Best regards</description>
      <pubDate>Thu, 05 May 2011 13:27:23 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60709#M13165</guid>
      <dc:creator>smilingmelbourne</dc:creator>
      <dc:date>2011-05-05T13:27:23Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60710#M13166</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Hey. I have similar problems. But instead of large number of sheets, I have about ten thousand files. What can I do?&lt;BR /&gt;Plz help me with it.&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Tue, 29 Jan 2013 19:41:18 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60710#M13166</guid>
      <dc:creator>alexOU</dc:creator>
      <dc:date>2013-01-29T19:41:18Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60711#M13167</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Alex,&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Yuo get a list of file names to iterate over, you can use a&lt;STRONG&gt; filename pipe ..... &lt;/STRONG&gt;to get a list of files.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Then iterate over Peter's code above to read the files if they are spreadsheets.&amp;nbsp; If not spreadsheets, then you might have to build your own code to handle reading the data.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;I am attaching a paper I presented a couple of years ago which addresses this problem.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Larry&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Tue, 29 Jan 2013 20:55:57 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60711#M13167</guid>
      <dc:creator>LarryWorley</dc:creator>
      <dc:date>2013-01-29T20:55:57Z</dc:date>
    </item>
    <item>
      <title>Re: SAS macro to import multiple Excel sheets, clean invalid data, etc...</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60712#M13168</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;I meant to add a liitle sample code.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Assuming windows OS, this code will be a data set with list of filenames in a directory&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;filename &lt;STRONG&gt;my_files &lt;/STRONG&gt;pipe '&lt;STRONG&gt;dir /b c:\my_directory&lt;/STRONG&gt;' ;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;data file_list ;&lt;/P&gt;&lt;P&gt;&amp;nbsp; infile my_files ;&lt;/P&gt;&lt;P&gt;&amp;nbsp; input file_name ;&lt;/P&gt;&lt;P&gt;run ;&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Tue, 29 Jan 2013 20:58:37 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-macro-to-import-multiple-Excel-sheets-clean-invalid-data-etc/m-p/60712#M13168</guid>
      <dc:creator>LarryWorley</dc:creator>
      <dc:date>2013-01-29T20:58:37Z</dc:date>
    </item>
  </channel>
</rss>

