Save Word files as DOCX using SAS DDE - ms-word

I'm using SAS v9.4
I am trying to write a macro that reads a word template, makes some modifications, then saves the new document as a .docx file. I have managed to get it to work for saving to a .doc file, but when I change the extension I get the following error:
Incompatible File Type and File Extension
Does anyone know how I can save files as docx or if that's even possible?
Any help would be appreciated
Code is below:
filename sas2word dde 'winword|system';
%macro setupWd(outfile);
options noxsync noxwait xmin;
/* Open Blank Word Document */
data _null_;
length fid rc start stop time 8;
fid=fopen('sas2word','s');
if (fid le 0) then do;
rc=system('start winword');
start=datetime();
stop=start+1;
do while (fid le 0);
fid=fopen('sas2word','s');
time=datetime();
if (time ge stop) then fid=1;
end;
end;
rc=fclose(fid);
run;
/* Save to given location */
data _null_;
file sas2word;
put '[FileSaveAs.Name="' "&outfile" '",.Format=0]';
run;
%mend setupWd;
Works:
%setupWd(outfile = M:\SAS\Output\MacroTest.doc)
Doesnt Work:
%setupWd(outfile = M:\SAS\Output\MacroTest.docx)

Re-write the save bit without the format option:
data _null_;
file sas2word;
put '[FileSaveAs.Name="' "&outfile" '"]';
run;
Alos, the options for Format (in case anyone was wondering) are:
Format = 0: .doc
Format = 1: .dot
Format = 2: .txt
The only way to get .docx is to put it in the file path name and not specify a format

Related

SAS change date format

I want to define a date format that takes the following format : 12JAN2010
I tried using this code :
/* partie B question 2*/
data projet.Ophtalmo_new;
set projet.Ophtalmo_new (RENAME=(date_diagnostic=date_dia)) (RENAME=
(date_examen=date_exa));
date_diagnostic = input (date_dia, DDMMYY10.);
date_examen = input (date_exa, DDMMYY10.);
format date_diagnostic date_examen date9.;
run;
But it sends me the following syntax error :
ERROR 22-322: Syntax error, expecting one of the following: un nom, une chaƮne
entre guillemets, ;,
CUROBS, END, INDSNAME, KEY, KEYRESET, KEYS, NOBS, OPEN, POINT,
_DATA_, _LAST_, _NULL_.
I'm still a sas beginner and i can't manage to get it to work properly, hope you can help, thanks.
The syntax for data set options is a single parenthetical expression. The rename option fits within:
data-set-name ( ... options ... rename=(...) );
The syntax of the RENAME option is the following:
rename=(old-name-1=new-name-1 old-name-2=new-name-2 ...)
So the correct set statement would be
set projet.Ophtalmo_new (RENAME=(date_diagnostic=date_dia date_examen=date_exa));
Because you state your are a beginner I added this section.
The code you show indicates input of the variables originally named date_diagnostic and date_examen. If these variables are indeed character variables to start, then the input is necessary to convert from character to a SAS date (which is simply a number with special meaning). If, however, the variables were already a SAS date with a format different than the one you want, you only need to update the format of the variables (or use a FORMAT statement to change the format to use during a PROC step)
data have;
x = '01-jan-2017'd;
format x ddmmyy10.;
run;
* demonstrate that the permanent format of x is ddmmyy10.;
data _null_;
put x=;
run;
* demonstrate temporary formatting of variable during step;
data _null_;
set have;
format x date9.; * modify the format temporarily during execution of data _null_;
put x=;
run;
* permanently change format of variable;
* only the dataset metadata (or header data) changes, the entire data set is NOT rewritten;
proc datasets nolist lib=work;
modify have;
format x date9.;
run;
* demonstrate that the permanent format of x has changed to date9.;
data _null_;
set have;
put x=;
run;
I believe the issue is the RENAME statement. You can only call it once.
Change this:
set projet.Ophtalmo_new (RENAME=(date_diagnostic=date_dia)) (RENAME=
(date_examen=date_exa));
to this:
set projet.Ophtalmo_new (RENAME=(date_diagnostic=date_dia date_examen=date_exa));
You can't rename the dates and then use those variables in your INPUT statement. They've been renamed and no longer exist, so trying to access date_dia in the INPUT function will at worst result in all missing values.
You also shouldn't use the notation of having the same data set name in your DATA and SET statement. This means once this step is run, the original data no longer exists. So you need to back up several steps and recreate your original data first before you can even fix your code. In general, this leads to errors that are harder to diagnose and fix because even if you fix your code your original data is wrong so you still think you have errors.
So, changes:
1. Change name of output data set in data statement.
2. Remove RENAME data set options.
3. Add DROP statement to remove the variables no longer desired.
/* partie B question 2*/
data projet.Ophtalmo2;
set projet.Ophtalmo_new;
date_diagnostic = input (date_dia, DDMMYY10.);
date_examen = input (date_exa, DDMMYY10.);
format date_diagnostic date_examen date9.;
drop date_dia date_exa;
run;

How to write macro for importing multiple excel files(xlsx) in sas and append it

I am having some 50 excel files (xlsx format) to be imported to sas and then need to append it for analysis. All the excel files header are same i.e., the variable names are same for all the file. I need macro for importing and appending all of them at a time rather than importing all the files one by one and then later append it. Your help is much appreciated.
The other issue with the excel file is that there is a blank column next between the variable name and data points. I have written a code remove it using data step but came we write this also in the macro while importing.
Data XXX.yyy;
Set XXX.yyy;
if missing(coalesceC(of ASC Brand Cdesc1 Cust_ DGM Desc Family Grp1 High_Level_Product_Desc
Issf Name Prod_Desc Product__Code RVP SA_Desc Terr_ UOM Yr
)) and missing(coalesce(of Acc Int_Margin M_Cost Mth Net_Sales Sls__ Uts )) then delete;
run;
It sounds as though your existing code already does what you need it to do. I doubt there will be much of a performance gain from attempting to import all 50 files in one data step (which is possible via dde, but rather fiddly).
If your existing code is set up to process just one hard-coded file, I'd suggest using it to write a simple macro that takes one excel file as input, imports that file, and appends it to the master dataset. Then you can call the macro 50 times.
e.g. You could write the macro as something like this, incorporating all the relevant bits of your code, and replacing all references to specific files with macro variables:
%macro import_and_append(excel_file,base_dataset);
proc import datafile = "&excel_file" dbms = excel out = t_import;
run;
proc append base = &base_dataset data = t_import;
run;
proc datasets lib = work nolist nowarn;
delete t_import;
run;
quit;
%mend;
Then you can call the macro like so:
%import_and_append(c:\excel_file_01.xls,work.master_dataset)
Another way to do this would be to use the Excel LIBNAME Engine. You declare a library to each of your files, and then read all the sheets in 1 Data Step.
In this example, I have 2 workbooks (Book1.xlsx and Book2.xlsx) in C:\temp. All data is in Sheet1. 3 variables -- X, Y, and Z. Modify as needed for your purpose.
data files;
format file $12.;
input file $;
datalines;
Book1.xlsx
Book2.xlsx
;
run;
%macro read_excel(dir,outdata,files);
data _null_;
set &files end=last;
call execute("libname t" || strip(put(_n_,8.)) || " excel '&dir\" || strip(file) || "';");
if last then
call symput("n",_n_);
run;
data &outdata;
set
%do i=1 %to &n;
t&i.."Sheet1$"n
%end;
;
a = sum(x,y,z);
if missing(a) then delete;
run;
%do i=1 %to &n;
libname t&i clear;
%end;
%mend;
%read_excel(c:\temp,data_from_excel,files);

Convert csv file to mat file

I have a csv file as follows:
StringA,StringB ...
1.234,13.45 ...
I want to convert this into a .mat file extension but when I try to read the csv file, it throws and error due to the fact that I have strings in the first row. This makes it difficult to directly convert to a mat file as I also want the headers in my mat file. How would I go about doing this?
Given your file format, you can use importdata() like this:
M = importdata('myfile.txt', ',', 1);
The header will be saved in M.colheaders, the data will be stored in M.data.
Please have a look at the documentation for further information and a working example.

Stata - efficiently appending 200+ files (my method takes hours)

I am trying to append approx. 200 files using Stata. Below I have provided the code I am using to append. The issue is that it is taking too long -- over 5 hours to do. The ultimate appended file has over 28 million observations and is about 2GB in size. I think the issue might be that it is saving every time and hence takes too long. I also tried using the tempfile mode -- but that also takes long. My colleague, on the other hand, did the same append in minutes using SAS. I have provided his code below as well. I would very much appreciate if someone could show me how to do it efficiently in Stata -- so that it would not take hours. Thanks much!
My Stata code:
file close _all
file open myfile using "$OP\filelist_test.txt", read
file read myfile line
cd "$OP"
insheet using "`line'", comma clear
tostring optionconditioncode, replace
save "$data\options_all", replace
file read myfile line
while r(eof)==0{
insheet using "`line'", comma clear
tostring optionconditioncode, replace
append using "$data\options_all"
save "$data\options_all", replace
file read myfile line
}
file close myfile
My colleague's SAS code:
data all_text (drop=fname);
length myfilename $100;
set dirlist;
filepath = "&dirname\"||fname;
infile dummy filevar = filepath length=reclen end=done missover dlm=',' firstobs=2 dsd;
do while(not done);
myfilename = filepath;
input var1
var2
var3
var4
output;
end;
Seems like the OP has not been around lately. The solution given by Robert Picard from the Stata forum link that the OP has provided is as follows:
> Take a look at -filelist- from SSC. It can create a Stata dataset of
> files (with full path). The help file has an example that does what
> you want efficiently. Here's a copy:
>
> use "csv_datasets.dta", clear
> local obs = _N
> forvalues i=1/`obs' {
> use "csv_datasets.dta" in `i', clear
> local f = dirname + "/" + filename
> insheet using "`f'", clear
> tempfile save`i'
> save "`save`i''"
> }
>
> use "`save1'", clear
> forvalues i=2/`obs' {
> append using "`save`i''"
> }

Call System output in Macro Variable

I want to get the file size of a csv file in AIX and using following X and Call System Command to do. The problem is I cant get the "File Size" in a macro variable which I will be using later in the program.
data _null_;
call system('du -g p_bhj_c_hh100uk01po1.csv');
call symput('space','X du -g p_bhj_c_hh100uk01po1.csv');
%put &space;
run;
WARNING: Apparent symbolic reference SPACE not resolved.
First, the SYMPUT subroutine you call does not work like you are trying to use it (ala Perl). I recommend reading the documentation on it.
The error you get on the SPACE macro is because it is inside the DATA Step. Macros "write" SAS code for you, so it &SPACE macro is trying to be resolved BEFORE the DATA Step executes.
Here is a code example to do what you are looking for:
data _null_;
rc = filename("ref","e:\temp\reg.pdf");
fid = fopen("ref");
infonum = foptnum(fid);
do i=1 to infonum;
infoname = foptname(fid,i);
infoval=finfo(fid,infoname);
put infoname= infoval=;
end;
close = fclose(fid);
run;
/*In Windows, attribute is "File Size (bytes)"*/
data _null_;
rc = filename("ref","e:\temp\reg.pdf");
fid = fopen("ref");
size=finfo(fid,"File Size (bytes)");
call symput("size",size);
close = fclose(fid);
run;
%put &size;
The File Size attribute may be different in AIX. Run the first part to see all the attributes available. Then modify the second accordingly. Likewise, you will need to add the call to produce the file like you are already doing.