<?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: Importing a paradox db file into SAS in SAS Data Management</title>
    <link>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324838#M9467</link>
    <description>&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;SAS did a better job than R.
Neither R nor SAS could convert Paradox 7 tables?
Of the Paradox 4 and 5 tables SAS read 4 and R read 3

The issue with R may be a lack of 32bit Paradox ODBC drivers?

* you can get a sample paradox database here;
* these are good samples and have many variable types (4.x,5.x,7.x);
http://www.sportamok.com/development/download;

* Roland Rashleigh-Berry provided the directory code, may he RIP;
* the old guard is dying off;
* don't forget the blank after db;

* put the members of directory d:\db in macro var dbs;

%let dbs= %utl_dir(d:\db\*.db );
%put &amp;amp;=dbs;

DBS=biolife.db  COUNTRIES.DB  country.db  events.db  FILMS.DB  venues.db

Uppercase Paradox 7 tables could not be read by SAS or R but Stattransfer could read them.

HAVE A PARADOX DATABASE WITH THESE TABLES  (Paradox 4, 5 and 7)
===============================================================

biolife.db
country.db   * R could not read this one but SAS could
events.db
venues.db

WANT SAS DATSETS
================

BIOLIFE.SAS7BDAT
COUNTRY.SAS7BDAT
EVENTS.SAS7BDAT
VENUES.SAS7BDAT


SAS SOLUTION (cannot read Paradox 7 tables, however Stat Transfer can)

options validvarname=upcase;;
data _null_;

  tables= "%utl_dir(d:\db\*.db )";
  put tables=;
  do tbl=1 to countc(tables,'.');

     table=scan(scan(tables,tbl,' '),1,'.');
     * PARADOX 7;
     if upcase(table) not in ('COUNTRIES', 'FILMS', 'CARS' 'RESTTEMP') then do;
         call symputx('table',table);
         put table=;
         rc=dosubl('
              proc import out=work.&amp;amp;table
              file="d:/db/&amp;amp;table..db"
              dbms=db replace;
              run;quit;
            ');
     end;
   end;

run;quit;


* As soon as R implements 'write_sas' this code will become
  very simple - the save will rePlaced by something like:
  for (table in tables) {write_sas(assign(table,sqlFetch(myDB, table),paste("d:/db/",table,".sas7bdat")};

However stattransfer and SAS seem to do a better job;

Howver it is rather complex now;

* I don't have a 64 bit driver so I need to use
  the 32bit version of R, note R comes with both versions;

* this works;
* you may need 32bit SAS. I used 32bit R;
* create R dataframe from db table;
%macro todb(dummy);

 %let dbs=biolife.db country.db event.db venues.db;

  %do tbl=1 %to %sysfunc(countc(&amp;amp;dbs,%str(.)));

    %let table=%sysfunc(strip(%scan(%scan(&amp;amp;dbs.,&amp;amp;tbl.,%str( )),1,%str(.))));

    %put &amp;amp;=table.;

    /* %let table=events;  */

    * you need to use double quotes so macros and macro variables are resolved;
    %utl_submit_r32("
    source('C:/Program Files/R/R-3.3.2/etc/Rprofile.site', echo=T);
    library(RODBC);
    library(sqldf);
    '&amp;amp;table';
    myDB&amp;lt;-odbcDriverConnect('Driver={Microsoft Paradox Driver (*.db )};DriverID=538;
    Fil=Paradox 5.X;DefaultDir=d:/db/;Dbq=d:/db/;CollatingSequence=ASCII');
    '&amp;amp;table';
    &amp;amp;table &amp;lt;- sqlFetch(myDB, '&amp;amp;table.');
    '&amp;amp;table';
    save(&amp;amp;table,file='d:/rds/&amp;amp;table..rda', compress = FALSE);
    &amp;amp;table;
    close(myDB);
    ");

    %utl_submit_wps64("
    options set=R_HOME 'C:/Program Files/R/R-3.3.2';
    libname wrk '%sysfunc(pathname(work))';
    proc r;
    submit;
    source('C:/Program Files/R/R-3.3.2/etc/Rprofile.site', echo=T);
    load(file = 'd:/rds/&amp;amp;table..rda');
    &amp;amp;table.;
    endsubmit;
    import r=&amp;amp;table. data=wrk.&amp;amp;table.;
    run;quit;

    ");
  %end;

%mend todb;

%todb;



/*T807320&amp;nbsp;Function-style macro to return a list of members of a directory

dir.sas  - Function-style macro to return a list of members of a directory
           on a WINDOWS platform according to the file pattern you supply.
           If you supply just the directory name then all members are
           listed. This runs the MSDOS command in the form "dir /B mydir"
           Usage: %let dirlist=%dir(C:\utilmacros);
           %let dirlist=%dir(C:\utilmacros\*.sas);

%macro utl_dir(dir);
  %unquote(%utl_readpipe(dir /B %sysfunc(dequote(&amp;amp;dir))))
%mend utl_dir;


%macro utl_readpipe(command);
  /* Roland macro */
  %local fname fid str rc res err;
  %let err=ERR%str(OR);
  %let rc=%sysfunc(filename(fname,&amp;amp;command,pipe));
  %if &amp;amp;rc NE 0 %then %do;
    %put &amp;amp;err: (qreadpipe) Pipe file could not be assigned due to the following:;
    %put %sysfunc(sysmsg());
  %end;
  %else %do;
    %let fid=%sysfunc(fopen(&amp;amp;fname,s,80,b));
    %if &amp;amp;fid EQ 0 %then %do;
  %put &amp;amp;err: (qreadpipe) Pipe file could not be opened due to the following:;
  %put %sysfunc(sysmsg());
    %end;
    %else %do;
      %do %while(%sysfunc(fread(&amp;amp;fid)) EQ 0);
        %let rc=%sysfunc(fget(&amp;amp;fid,str,80));
        %let res=&amp;amp;res%superq(str);
      %end;
      %qtrim(&amp;amp;res)
      %let rc=%sysfunc(fclose(&amp;amp;fid));
      %if &amp;amp;rc NE 0 %then %do;
  %put &amp;amp;err: (qreadpipe) Pipe file could not be closed due to the following:;
  %put %sysfunc(sysmsg());
      %end;
      %let rc=%sysfunc(filename(fname));
      %if &amp;amp;rc NE 0 %then %do;
  %put &amp;amp;err: (qreadpipe) Pipe file could not be deassigned due to the following:;
  %put %sysfunc(sysmsg());
      %end;
    %end;
  %end;
%mend utl_readpipe;


&lt;/CODE&gt;&lt;/PRE&gt;</description>
    <pubDate>Sat, 14 Jan 2017 19:13:33 GMT</pubDate>
    <dc:creator>rogerjdeangelis</dc:creator>
    <dc:date>2017-01-14T19:13:33Z</dc:date>
    <item>
      <title>Importing a paradox db file into SAS</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324687#M9462</link>
      <description>&lt;P&gt;Hello,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have a problem of importing a paradox db file into SAS. My db file includes several tables and I just want to import specific tables into SAS. The offical guide gives an example like this:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;This example imports the SAS data set, WORK.CUSTOMER, from the Paradox DB ﬁle, customer.db, on a local system.&lt;BR /&gt;PROC IMPORT OUT=WORK.CUSTOMER&lt;/P&gt;&lt;P&gt;FILE="&amp;amp;tmpdir.customer.db"&lt;/P&gt;&lt;P&gt;DBMS=DB REPLACE;&lt;/P&gt;&lt;P&gt;RUN;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;It seems only one table is in the db file so it can be import into a data set. But it does not work if there are several tables in the db file. Wondering if anyone can help me figure it out.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Much appreciated.&lt;/P&gt;</description>
      <pubDate>Fri, 13 Jan 2017 19:59:14 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324687#M9462</guid>
      <dc:creator>tzy0147</dc:creator>
      <dc:date>2017-01-13T19:59:14Z</dc:date>
    </item>
    <item>
      <title>Re: Importing a paradox db file into SAS</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324712#M9463</link>
      <description>&lt;P&gt;Have you tried to include the DATATABLE option? The specs for the proc include:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;TABLE cellspacing="2" cellpadding="4"&gt;
&lt;TBODY&gt;
&lt;TR valign="top"&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN class="strong"&gt;PROC IMPORT&lt;/SPAN&gt; &lt;BR /&gt;&lt;SPAN class="strong"&gt;DATAFILE&lt;/SPAN&gt;=&amp;lt;&lt;SPAN class="emph"&gt;'filename'&lt;/SPAN&gt;&amp;gt;|&lt;SPAN class="strong"&gt;DATATABLE&lt;/SPAN&gt;=&amp;lt;&lt;SPAN class="emph"&gt;'tablename'&lt;/SPAN&gt;&amp;gt; &lt;BR /&gt;&amp;lt;&lt;SPAN class="strong"&gt;DBMS&lt;/SPAN&gt;&amp;gt;=&amp;lt;&lt;SPAN class="emph"&gt;data-source-identifier&lt;/SPAN&gt;&amp;gt; &lt;BR /&gt;&amp;lt;&lt;SPAN class="strong"&gt;OUT&lt;/SPAN&gt;&amp;gt;=&amp;lt;&lt;SPAN class="emph"&gt;libref.SAS data-set-name&lt;/SPAN&gt;&amp;gt; &amp;lt;&lt;SPAN class="emph"&gt;SAS data-set-option(s)&lt;/SPAN&gt;&amp;gt; &lt;BR /&gt;&amp;lt;&lt;SPAN class="strong"&gt;REPLACE&lt;/SPAN&gt;&amp;gt;;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;You indicated that DBMS=DB worked, but I didn't see that in the documentation. It does, however, include DBMS=Paradox&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You could also use the libname access method instead. That would get all of the tables without having to specify them.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;HTH,&lt;/P&gt;
&lt;P&gt;Art, CEO, AnalystFinder.com&lt;/P&gt;</description>
      <pubDate>Fri, 13 Jan 2017 21:25:07 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324712#M9463</guid>
      <dc:creator>art297</dc:creator>
      <dc:date>2017-01-13T21:25:07Z</dc:date>
    </item>
    <item>
      <title>Re: Importing a paradox db file into SAS</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324783#M9464</link>
      <description>&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;SOAPBOX ON
This would be trivial if SAS had not disabled all
paradox engines and paradox sql connections.
Engines are a lot more powerful than
'import/export' because they are seamless inside and
outside the datasteps. However it is very intensive
programming to provide powerful constructs like:

select member from sashelp.vtable where libname='PARADOX';
SOAPBOX OFF

Unfortunately it looks like SAS has disabled the old dbpdox engine.
The following no longer  works.

libname PBOX dbpdox 'c:\windows\desktop\test' ;

data A ;
   set PBOX.ADRHEAD ;
run ;

I get the following log:

26   libname PBOX dbpdox 'c:\windows\desktop\test' ;

NOTE: Libref PBOX was successfully assigned as follows:
      Engine:        DBPDOX
      Physical Name: c:\windows\desktop\test

I am not fond of the import/export replacement so
I look to Python, Perl and R packages.

I will post an R solution tomorrow, using the R packages RODBC and sqldf.

WORKING CODE (something like)

myDB &amp;lt;- odbcConnect("usrdox",uid="admin",pwd="");
for (table in tables) {
    sysval(table) &amp;lt;- sqlFetch(myDB, "sysval(table)") }

I also have code which creates a dsn programmatically, thanks toRichard DeVenezia

&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Sat, 14 Jan 2017 02:55:22 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324783#M9464</guid>
      <dc:creator>rogerjdeangelis</dc:creator>
      <dc:date>2017-01-14T02:55:22Z</dc:date>
    </item>
    <item>
      <title>Re: Importing a paradox db file into SAS</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324803#M9465</link>
      <description>Thank you for your reply. However, the log says ERROR: Cannot specify both FILE= and TABLE=. I am wondering what is the libname access method? Thank you.</description>
      <pubDate>Sat, 14 Jan 2017 06:54:18 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324803#M9465</guid>
      <dc:creator>tzy0147</dc:creator>
      <dc:date>2017-01-14T06:54:18Z</dc:date>
    </item>
    <item>
      <title>Re: Importing a paradox db file into SAS</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324832#M9466</link>
      <description>&lt;P&gt;You can read about libname access at:&amp;nbsp;&lt;A href="http://statdist.its.uu.se/sas/Dokument/SASacpcref.pdf?Company=SAS" target="_blank"&gt;http://statdist.its.uu.se/sas/Dokument/SASacpcref.pdf?Company=SAS&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;However, I don't see any mention of Paradox in that document's section regarding libname access.&lt;/P&gt;
&lt;P&gt;I don't license Access for PC File Formats thus, unfortunately, can't be of any help.&lt;/P&gt;
&lt;P&gt;My comment about the engine being called Paradox is apparently only applicable to PROC EXPORT.&lt;/P&gt;
&lt;P&gt;Hopefully, someone from SAS will see this thread and supply the info that you need (if it exists).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 14 Jan 2017 15:44:17 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324832#M9466</guid>
      <dc:creator>art297</dc:creator>
      <dc:date>2017-01-14T15:44:17Z</dc:date>
    </item>
    <item>
      <title>Re: Importing a paradox db file into SAS</title>
      <link>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324838#M9467</link>
      <description>&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;SAS did a better job than R.
Neither R nor SAS could convert Paradox 7 tables?
Of the Paradox 4 and 5 tables SAS read 4 and R read 3

The issue with R may be a lack of 32bit Paradox ODBC drivers?

* you can get a sample paradox database here;
* these are good samples and have many variable types (4.x,5.x,7.x);
http://www.sportamok.com/development/download;

* Roland Rashleigh-Berry provided the directory code, may he RIP;
* the old guard is dying off;
* don't forget the blank after db;

* put the members of directory d:\db in macro var dbs;

%let dbs= %utl_dir(d:\db\*.db );
%put &amp;amp;=dbs;

DBS=biolife.db  COUNTRIES.DB  country.db  events.db  FILMS.DB  venues.db

Uppercase Paradox 7 tables could not be read by SAS or R but Stattransfer could read them.

HAVE A PARADOX DATABASE WITH THESE TABLES  (Paradox 4, 5 and 7)
===============================================================

biolife.db
country.db   * R could not read this one but SAS could
events.db
venues.db

WANT SAS DATSETS
================

BIOLIFE.SAS7BDAT
COUNTRY.SAS7BDAT
EVENTS.SAS7BDAT
VENUES.SAS7BDAT


SAS SOLUTION (cannot read Paradox 7 tables, however Stat Transfer can)

options validvarname=upcase;;
data _null_;

  tables= "%utl_dir(d:\db\*.db )";
  put tables=;
  do tbl=1 to countc(tables,'.');

     table=scan(scan(tables,tbl,' '),1,'.');
     * PARADOX 7;
     if upcase(table) not in ('COUNTRIES', 'FILMS', 'CARS' 'RESTTEMP') then do;
         call symputx('table',table);
         put table=;
         rc=dosubl('
              proc import out=work.&amp;amp;table
              file="d:/db/&amp;amp;table..db"
              dbms=db replace;
              run;quit;
            ');
     end;
   end;

run;quit;


* As soon as R implements 'write_sas' this code will become
  very simple - the save will rePlaced by something like:
  for (table in tables) {write_sas(assign(table,sqlFetch(myDB, table),paste("d:/db/",table,".sas7bdat")};

However stattransfer and SAS seem to do a better job;

Howver it is rather complex now;

* I don't have a 64 bit driver so I need to use
  the 32bit version of R, note R comes with both versions;

* this works;
* you may need 32bit SAS. I used 32bit R;
* create R dataframe from db table;
%macro todb(dummy);

 %let dbs=biolife.db country.db event.db venues.db;

  %do tbl=1 %to %sysfunc(countc(&amp;amp;dbs,%str(.)));

    %let table=%sysfunc(strip(%scan(%scan(&amp;amp;dbs.,&amp;amp;tbl.,%str( )),1,%str(.))));

    %put &amp;amp;=table.;

    /* %let table=events;  */

    * you need to use double quotes so macros and macro variables are resolved;
    %utl_submit_r32("
    source('C:/Program Files/R/R-3.3.2/etc/Rprofile.site', echo=T);
    library(RODBC);
    library(sqldf);
    '&amp;amp;table';
    myDB&amp;lt;-odbcDriverConnect('Driver={Microsoft Paradox Driver (*.db )};DriverID=538;
    Fil=Paradox 5.X;DefaultDir=d:/db/;Dbq=d:/db/;CollatingSequence=ASCII');
    '&amp;amp;table';
    &amp;amp;table &amp;lt;- sqlFetch(myDB, '&amp;amp;table.');
    '&amp;amp;table';
    save(&amp;amp;table,file='d:/rds/&amp;amp;table..rda', compress = FALSE);
    &amp;amp;table;
    close(myDB);
    ");

    %utl_submit_wps64("
    options set=R_HOME 'C:/Program Files/R/R-3.3.2';
    libname wrk '%sysfunc(pathname(work))';
    proc r;
    submit;
    source('C:/Program Files/R/R-3.3.2/etc/Rprofile.site', echo=T);
    load(file = 'd:/rds/&amp;amp;table..rda');
    &amp;amp;table.;
    endsubmit;
    import r=&amp;amp;table. data=wrk.&amp;amp;table.;
    run;quit;

    ");
  %end;

%mend todb;

%todb;



/*T807320&amp;nbsp;Function-style macro to return a list of members of a directory

dir.sas  - Function-style macro to return a list of members of a directory
           on a WINDOWS platform according to the file pattern you supply.
           If you supply just the directory name then all members are
           listed. This runs the MSDOS command in the form "dir /B mydir"
           Usage: %let dirlist=%dir(C:\utilmacros);
           %let dirlist=%dir(C:\utilmacros\*.sas);

%macro utl_dir(dir);
  %unquote(%utl_readpipe(dir /B %sysfunc(dequote(&amp;amp;dir))))
%mend utl_dir;


%macro utl_readpipe(command);
  /* Roland macro */
  %local fname fid str rc res err;
  %let err=ERR%str(OR);
  %let rc=%sysfunc(filename(fname,&amp;amp;command,pipe));
  %if &amp;amp;rc NE 0 %then %do;
    %put &amp;amp;err: (qreadpipe) Pipe file could not be assigned due to the following:;
    %put %sysfunc(sysmsg());
  %end;
  %else %do;
    %let fid=%sysfunc(fopen(&amp;amp;fname,s,80,b));
    %if &amp;amp;fid EQ 0 %then %do;
  %put &amp;amp;err: (qreadpipe) Pipe file could not be opened due to the following:;
  %put %sysfunc(sysmsg());
    %end;
    %else %do;
      %do %while(%sysfunc(fread(&amp;amp;fid)) EQ 0);
        %let rc=%sysfunc(fget(&amp;amp;fid,str,80));
        %let res=&amp;amp;res%superq(str);
      %end;
      %qtrim(&amp;amp;res)
      %let rc=%sysfunc(fclose(&amp;amp;fid));
      %if &amp;amp;rc NE 0 %then %do;
  %put &amp;amp;err: (qreadpipe) Pipe file could not be closed due to the following:;
  %put %sysfunc(sysmsg());
      %end;
      %let rc=%sysfunc(filename(fname));
      %if &amp;amp;rc NE 0 %then %do;
  %put &amp;amp;err: (qreadpipe) Pipe file could not be deassigned due to the following:;
  %put %sysfunc(sysmsg());
      %end;
    %end;
  %end;
%mend utl_readpipe;


&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Sat, 14 Jan 2017 19:13:33 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Data-Management/Importing-a-paradox-db-file-into-SAS/m-p/324838#M9467</guid>
      <dc:creator>rogerjdeangelis</dc:creator>
      <dc:date>2017-01-14T19:13:33Z</dc:date>
    </item>
  </channel>
</rss>

