LesezeichenAbonnierenRSS-Feed abonnieren
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.

Hallo zusammen,

ich möchte erreichen, dass charvars in double quotes eingebettet sind, das funktioniert auch soweit. Do-Loop im letzten Datastep über alle charvars

mit byte(34) davor und dahinter. Der SAS-Dataset sieht auch wie gewünscht aus (1.Screenshot). Der anschließende PROC EXPORT fügt jeweils vorne wie hinten noch einmal zwei double quotes hinzu (2. Screenshot). Hat jemand eine Ahnung warum und falls möglich, was zu ändern ist?
Das Coding ist ganz unten, das ist ein Auschnitt aus einem Call Execute, es sollte aber lesbar sein.

VG

Wolfgang

 

Ergebnis Dataset.jpg

Ergebnis PROC EXPORT.jpg

 

data _null_;
set sas_meta.META_TO_SDP(where=(memname='META_FKG_CLUSTERBUENDEL'));
call execute(

'filename out "&path.liefer_oref/tables/'!!compress(memname)!!'.csv";
options mprint;

data work.'!!compress(memname)!!compbl(drop_date)!!';
/*
Vor dem SET-Statement die Reihenfolge festlegen und das Length-Statement erhöhen,
damit durch Anhängen der DoubleQuotes die Länge nicht überschritten und somit abgeschnitten wird. 
*/
length '!!chars!!' $1024;
format '!!chars!!' $1024.;
retain '!!retains!!' "";

set sas_meta.'!!compress(memname)!!compress(where_date)!!';

/* Array aller Character, Do-Loop über alle Chars und in DoubleQuotes byte(34) einschließen*/

   array Chars[*] _character_;
   do i = 1 to dim(Chars);
      Chars[i] = cats(byte(34),compress(Chars[i]),byte(34));
   end;
   drop i;
run;

proc export data=work.'!!compress(memname)!!' file=out dbms=csv replace;
delimiter=";";
run;
filename out clear;
'
);
run;

 

1 AKZEPTIERTE LÖSUNG

Akzeptierte Lösungen
Tom
Super User Tom
Super User

If the goal is to give SNOWFLAKE extra hints that a field should be handled as character then perhaps you can just use ODS CSV to create the file instead of PROC EXPORT?  That tool will add quotes around every character value, whether or not the value actually NEEDS to have quotes around it.

ods csv file=csv;
proc print data=sashelp.class noobs; run;
ods csv close;

Result:

"Name","Sex","Age","Height","Weight"
"Alfred","M",14,69.0,112.5
"Alice","F",13,56.5,84.0
"Barbara","F",13,65.3,98.0
"Carol","F",14,62.8,102.5
"Henry","M",14,63.5,102.5
"James","M",12,57.3,83.0
"Jane","F",12,59.8,84.5
"Janet","F",15,62.5,112.5
"Jeffrey","M",13,62.5,84.0
"John","M",12,59.0,99.5
"Joyce","F",11,51.3,50.5
"Judy","F",14,64.3,90.0
"Louise","F",12,56.3,77.0
"Mary","F",15,66.5,112.0
"Philip","M",16,72.0,150.0
"Robert","M",12,64.8,128.0
"Ronald","M",15,67.0,133.0
"Thomas","M",11,57.5,85.0
"William","M",15,66.5,112.0

Or you would write your own data step (or generate it from the metadata of the dataset) and use the ~ modifier in the PUT statement after each character variable.  Then you could also switch to using semicolon instead of comma as the delimiter.

data _null_;
  file csv dsd dlm=';' ;
  set sashelp.class;
  put name ~ sex ~ age height weight;
run;

Result:

"Alfred";"M";14;69;112.5
"Alice";"F";13;56.5;84
"Barbara";"F";13;65.3;98
"Carol";"F";14;62.8;102.5
"Henry";"M";14;63.5;102.5
"James";"M";12;57.3;83
"Jane";"F";12;59.8;84.5
"Janet";"F";15;62.5;112.5
"Jeffrey";"M";13;62.5;84
"John";"M";12;59;99.5
"Joyce";"F";11;51.3;50.5
"Judy";"F";14;64.3;90
"Louise";"F";12;56.3;77
"Mary";"F";15;66.5;112
"Philip";"M";16;72;150
"Robert";"M";12;64.8;128
"Ronald";"M";15;67;133
"Thomas";"M";11;57.5;85
"William";"M";15;66.5;112

 

Lösung in ursprünglichem Beitrag anzeigen

9 ANTWORTEN 9
Tom
Super User Tom
Super User

There is nothing that needs to change. That is how delimited files work.

 

If your data has double quote characters in it then those need to be quoted when writing a delimited file.  Otherwise there is confusion between the double quotes that are in the data and those that are required to protected embedded delimiters in the data.

E_Berger
Fluorite | Level 6

Gefällt die Lösung?

Die Datei über einen Data step mit file-statement rauslassen.

Das Setzen der Gänsefüßchen erfolgt hier anders als bei meiner Lösung 1. Da war mir nicht klar, dass ein Export nach csv gebraucht wird.


%let M_datei= sashelp.class;

proc contents
data =&M_datei.

out= char_vari (keep= name type)
noprint;
run;


proc sql noprint;
select name
into :M_variliste
separated by ' '
from char_vari
where type = 2;
quit;

data d (keep = &M_variliste. hiwi);

format lfd_nr $4.;

set sashelp.class;

hiwi= catx('"; "' , of &M_variliste.);
hiwi= catt('"',hiwi,'"');

run ;


data d_ex;
set d;

file "&M_output.d.CSV"
RECFM=V
LRECL=800
encoding='wlatin1'
delimiter=";";

if _N_ = 1 then do;
put "&M_variliste.";
end;

put&M_variliste.;

run;

 

 

lg eric

E_Berger
Fluorite | Level 6

Sorry, waren noch 2 Fehler drin.

 

Nun die  richtig Lösung

 

%let M_datei= sashelp.class;

proc contents
data =&M_datei.

out= char_vari (keep= name type)
noprint;
run;

 

proc sql noprint;

select name
into :M_variliste
separated by ' '
from char_vari
where type = 2;


select name
into :M_variliste2
separated by ';'
from char_vari
where type = 2;

quit;

data d (keep = &M_variliste. hiwi);

format lfd_nr $4.;

set sashelp.class;

hiwi= catx('"; "' , of &M_variliste.);
hiwi= catt('"',hiwi,'"');

run ;


data d_ex;
set d;

file "&M_output.d.CSV"
RECFM=V
LRECL=800
encoding='wlatin1'
delimiter=";";

if _N_ = 1 then do;
put "&M_variliste2.";
end;

put hiwi;

run;

WolfgangHornung
Obsidian | Level 7

Das Problem ist, dass wir in ein sog. S3-Bucket nach Snowflake reinschreiben, die Struktur muss erhalten bleiben und mit der DDL der Tabelle  übereinstimmen, zudem muss ich zwischen chars und nums unterscheiden. Ich denke, da muss ich einfach basteln, nums und chars separat behandeln, die DDLs nochmal anpassen und die csv-Datei zu Fuß schreiben. Ich dachte da gibt es einen schöneren Weg. Trotzdem danke für die Lösungsansätze, ich denke daraus kann ich etwas machen.

 

LG, Wolfgang

Tom
Super User Tom
Super User

If the goal is to give SNOWFLAKE extra hints that a field should be handled as character then perhaps you can just use ODS CSV to create the file instead of PROC EXPORT?  That tool will add quotes around every character value, whether or not the value actually NEEDS to have quotes around it.

ods csv file=csv;
proc print data=sashelp.class noobs; run;
ods csv close;

Result:

"Name","Sex","Age","Height","Weight"
"Alfred","M",14,69.0,112.5
"Alice","F",13,56.5,84.0
"Barbara","F",13,65.3,98.0
"Carol","F",14,62.8,102.5
"Henry","M",14,63.5,102.5
"James","M",12,57.3,83.0
"Jane","F",12,59.8,84.5
"Janet","F",15,62.5,112.5
"Jeffrey","M",13,62.5,84.0
"John","M",12,59.0,99.5
"Joyce","F",11,51.3,50.5
"Judy","F",14,64.3,90.0
"Louise","F",12,56.3,77.0
"Mary","F",15,66.5,112.0
"Philip","M",16,72.0,150.0
"Robert","M",12,64.8,128.0
"Ronald","M",15,67.0,133.0
"Thomas","M",11,57.5,85.0
"William","M",15,66.5,112.0

Or you would write your own data step (or generate it from the metadata of the dataset) and use the ~ modifier in the PUT statement after each character variable.  Then you could also switch to using semicolon instead of comma as the delimiter.

data _null_;
  file csv dsd dlm=';' ;
  set sashelp.class;
  put name ~ sex ~ age height weight;
run;

Result:

"Alfred";"M";14;69;112.5
"Alice";"F";13;56.5;84
"Barbara";"F";13;65.3;98
"Carol";"F";14;62.8;102.5
"Henry";"M";14;63.5;102.5
"James";"M";12;57.3;83
"Jane";"F";12;59.8;84.5
"Janet";"F";15;62.5;112.5
"Jeffrey";"M";13;62.5;84
"John";"M";12;59;99.5
"Joyce";"F";11;51.3;50.5
"Judy";"F";14;64.3;90
"Louise";"F";12;56.3;77
"Mary";"F";15;66.5;112
"Philip";"M";16;72;150
"Robert";"M";12;64.8;128
"Ronald";"M";15;67;133
"Thomas";"M";11;57.5;85
"William";"M";15;66.5;112

 

E_Berger
Fluorite | Level 6

Tolle Lösungen von Tom! Danke

 

Frage:

Gibt es bei der ods-csv Lösung die Möglichkeit die Spaltenüberschriften in der ersten Zeile   NICHT in Hochkommata  erscheinen zulassen ?

 

lg eric

WolfgangHornung
Obsidian | Level 7

Hi Eric,

Lösungsmöglichkeit zu Deiner Frage in meiner Antwort an Tom.

LG, Wolfgang

WolfgangHornung
Obsidian | Level 7

Danke Tom, das hat sehr geholfen. Ich habe noch modifiziert, weil ich die Header ohne double quotes gebraucht habe.

Ich habe die Header mit PROC EXPORT und obs=0 in eine separate csv-Datei geschrieben und die Daten mit dem ~ modifier geschrieben.

Für das PUT-Statement habe ich die Variablen zusammengebastelt. Die beiden csv-Dateien habe ich dann mit %sysexec und dem Linux cat-Befehl aneinandergehängt

 

proc sql;
create table metainfo as
 select memname, name, type, varnum from sashelp.vcolumn
 where upcase(libname)="SASHELP" and upcase(memname)="CLASS"
 order by varnum
;
quit;

data outvars(keep=memname outvars);
set metainfo end=lastrec;
length outvars out $1024;
retain outvars;
by varnum;
if _n_=1 then do;
  outvars="";
end;
if upcase(type)="CHAR" then out=compbl(cat(upcase(name)," ~ "));
else out=upcase(name);
outvars=catx(" ",outvars,out);
if lastrec;
call symput('outvars',outvars);
run;

%let path=<path>;

filename outhead "&path./header.csv" lrecl=1024;
filename out "&path./data.csv" lrecl=1024;


proc export data=sashelp.class(obs=0) file=outhead dbms=csv replace;
delimiter=",";
run;

data _null_;
  file out dsd dlm="," ;
  set sashelp.class;
  put &outvars.;
run;

filename out clear;
filename outhead clear;

%sysexec cat &path./header.csv &path./data.csv > &path./class.csv;
WolfgangHornung
Obsidian | Level 7

@Tom @E_Berger Hier noch als Macro

 

%macro custom_ds_to_csv(path=,libref=,dsname=);

proc sql;
create table metainfo as
 select memname, name, type, varnum from sashelp.vcolumn
 where upcase(libname)="%upcase(&libref.)" and upcase(memname)="%upcase(&dsname.)"
 order by varnum
;
quit;

data outvars(keep=memname outvars);
set metainfo end=lastrec;
length outvars out $1024;
retain outvars;
by varnum;
if _n_=1 then do;
  outvars="";
end;
if upcase(type)="CHAR" then out=compbl(cat(upcase(name)," ~ "));
else out=upcase(name);
outvars=catx(" ",outvars,out);
if lastrec;
call symput('outvars',outvars);
run;


filename outhead "&path./&dsname._header.csv" lrecl=1024;
filename out "&path./&dsname._data.csv" lrecl=1024;


proc export data=&libref..&dsname.(obs=0) file=outhead dbms=csv replace;
delimiter=",";
run;

data _null_;
  file out dsd dlm="," ;
  set &libref..&dsname.;
  put &outvars.;
run;

filename out clear;
filename outhead clear;

%sysexec cat &path./&dsname._header.csv &path./&dsname._data.csv > &path./&dsname..csv;

%mend custom_ds_to_csv;

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

Diskussionsstatistiken
  • 9 Antworten
  • 771 Aufrufe
  • 4 Kudos
  • 3 in Unterhaltung