All:
when performing IN operator to match words in a macro string, the quotes are required. But, the results are frustrated, would someone remind me what I have missed.
This macro string is created from proc sql as below
'''
proc sql noprint;
select memname into :domains separated by ' '
from sashelp.vtable
where libname='SDTM';
quit;
'''
Next, I quoted the string using this statement
'''
%let domains_quoted = %nrbquote(')%qsysfunc(prxchange(s/\s+/%nrbquote(',')/oi,-1,&domains))%nrbquote(');
'''
In log, it displayed no issues
SYMBOLGEN: Macro variable DOMAINS_QUOTED resolves to 'AE','CM','DM','DS','EG','EX',...
Then, I wish I can filter the output datasets.
'''
data want;
set have;
if dname in (&domains_quoted);
run;
'''
I got the error message saying:
SYMBOLGEN: Some characters in the above value which were subject to macro quoting have been unquoted for printing.
ERROR 22-322: Syntax error, expecting one of the following: a quoted string, a numeric constant, a datetime constant,
a missing value, iterator, (.
Would some one remind me what I have missed in these steps? Great appreciated.
Use the QUOTE() function to avoid the PRX step.
proc sql noprint;
select quote(memname) into :domains separated by ' '
from sashelp.vtable
where libname='SDTM';
quit;
data want;
set have;
if dname in (&domains_quoted);
run;
Related
I have had to look up hundreds (if not thousands) of free-text answers on google, making notes in Excel along the way and inserting SAS-code around the answers as a last step.
The output looks like this:
This output contains an unnecessary number of blank spaces, which seems to confuse SAS's search to the point where the observations can't be properly located.
It works if I manually erase superflous spaces, but that will probably take hours. Is there an automated fix for this, either in SAS or in excel?
I tried using the STRIP-function, to no avail:
else if R_res_ort_txt=strip(" arild ") and R_kom_lan=strip(" skåne ") then R_kommun=strip(" Höganäs " );
If you want to generate a string like:
if R_res_ort_txt="arild" and R_kom_lan="skåne" then R_kommun="Höganäs";
from three variables, let's call them A B C, then just use code like:
string=catx(' ','if R_res_ort_txt=',quote(trim(A))
,'and R_kom_lan=',quote(trim(B))
,'then R_kommun=',quote(trim(C)),';') ;
Or if you are just writing that string to a file just use this PUT statement syntax.
put 'if R_res_ort_txt=' A :$quote. 'and R_kom_lan=' B :$quote.
'then R_kommun=' C :$quote. ';' ;
A saner solution would be to continue using the free-text answers as data and perform your matching criteria for transformations with a left join.
proc import out=answers datafile='my-free-text-answers.xlsx';
data have;
attrib R_res_ort_txt R_kom_lan length=$100;
input R_res_ort_txt ...;
datalines4;
... whatever all those transforms will be performed on...
;;;;
proc sql;
create table want as
select
have.* ,
answers.R_kommun_answer as R_kommun
from
have
left join
answers
on
have.R_res_ort_txt = answers.res_ort_answer
& have.R_kom_lan = abswers.kom_lan_answer
;
I solved this by adding quotes in excel using the flash fill function:
https://www.youtube.com/watch?v=nE65QeDoepc
I am adding a prefix to each word in a macro variable. However, when using my current method, the first word does not receive the prefix. Looking at my code, there is good reason for this as there is no space in front of the word.
The code i use is:
%LET independent_vars = FF_1 FF_4 FF_7 FF_10;
%LET log_independent_vars = %SYSFUNC(TRANWRD(&independent_vars.,%str( ),%str( ln_)));
%PUT &log_independent_vars.;
Current output is:
FF_1 ln_FF_4 ln_FF_7 ln_FF_10
Expected output is:
ln_FF_1 ln_FF_4 ln_FF_7 ln_FF_10
I've tried using prxchange but I don't understand it
Only the first space is stripped
You can circumvent this problem by adding one 'ln_' in front of your formula
%LET independent_vars = FF_1 FF_4 FF_7 FF_10;
%LET log_independent_vars = ln_%SYSFUNC(TRANWRD(&independent_vars.,%str( ),%str( ln_)));
%PUT &log_independent_vars.;
ln_FF_1 ln_FF_4 ln_FF_7 ln_FF_10
I am exporting data from a SQL Server table to a .csv file, and then I use sp_send_email to email the file with data.
My problem is with this value:
Cantata Number 212 "Peasants Cantata", BWV 212
The value gets split into two columns in the .csv file that gets emailed. This value should be only in one column.
Some titles might contain a comma, which needs to be left in the string for those instances.
For example:
Cantata Number 212 Peasants Cantata" BWV 212"
I tried this method, but is not working:
Note: This SELECT statement resides inside a view vw_WeeklyReport
SELECT TOP 100 PERCENT
'"' + [p].[Title] + '"' [Title]
FROM
table
The code that exports the data and emails the .csv file:
BEGIN
SET NOCOUNT ON;
DECLARE #qry VARCHAR(8000);
-- Create the query, concatenating the column name as an alias
SET #Qry = 'SET NOCOUNT ON; SELECT Title FROM [vw_WeeklyReport] SET NOCOUNT OFF';
-- Send the e-mail with the query results in attachment.
EXEC [msdb].[dbo].[sp_send_dbmail]
#profile_name = 'default',
#recipients = '6lack#email.com',
#subject = 'Weekly Report',
#body = 'An attachment has been included in this email.',
#query_attachment_filename = 'WeeklyRep.csv',
#query = #qry,
#attach_query_result_as_file = 1,
#query_result_separator = ',',
#query_result_width = 32767,
#query_result_no_padding = 1;
END;
When there are comma's (or separators) in the field, that field should be enclosed with double quotes, and any double quotes within have to be escaped with another double quote:
"Cantata Number 212 ""Peasants Cantata"", BWV 212"
Once double quotes are used around fields, all fields containing double quotes should also be quoted and inside quotes escaped as well.
Maybe you could look for an option to export to csv using quoted fields.
Removing all the comma's could also be an option, but then you lose some information.
On the other hand, if there is only one column (as in your SELECT statement) there is no need at all to use csv. A plain text file can be used instead.
Change your query in the stored proc to something like this:
SET #Qry = 'SET NOCOUNT ON; SELECT replace(Title, ',', '') as Title FROM [vw_WeeklyReport] SET NOCOUNT OFF';
Note this is untested, but should give you what you're looking for. This is under the presumption that stripping out commas is acceptable, as was indicated in the initial post. If the commas need to remain intact, the answer isn't quite as simple.
when using %STR(amy.goodman#yaho.com;bill.goodman#yaho.com;jack.goodman#yaho.com);
This gives me the result: amy.goodman#yaho.com;bill.goodman#yaho.com;jack.goodman#yaho.com
which is what I want. and this is a macro variable called &email. I need this semicolon in between any two emails but no semicolon after the last email
But for someone who has an single quote in her email address like O'Connor,
%str will automatically match the single quote
using %STR(amy.goodman#yaho.com;bill.goodman#yaho.com;lily.O'Connor#yaho.com) will cause error.
How can I get the result amy.goodman#yaho.com;bill.goodman#yaho.com;lily.O'Connor#yaho.com
by using %str or any other macro quote function like %bquote or anything else to keep that single quote unmatched?
THE EMAIL LIST IS imported from excel list and I already put% before the single quote in the excel file: lily.O%'Connor#yaho.com
and HOW can I get the the macro variable &email. value inside the %str(), namely:
amy.goodman#yaho.com;bill.goodman#yaho.com;lily.O%'Connor#yaho.com
then I can put macro variable into %str()?
If you have the value already in a macro variable, say from a data step via CALL SYMPUTX() function call or from PROC SQL via INTO clause, then you can use %SUPERQ() macro function to macro quote the value.
data _null_;
call symputx('unquoted',"O'Connor#domain.com");
run;
%put Email list = %superq(unquoted);
If the value is already in a macro variable the the %BQUOTE() function would also work.
%put Email list = %bquote(&unquoted);
You could even use the RESOLVE() function to call %SUPERQ() to get the macro variable redefined with macro quoting immediately after creating it. So if you have a dataset MYTABLE with a variable EMAIL_LIST you could generate a series of separate macro variables (list1,list2, etc) from the data using code like this.
data _null_;
set mytable ;
length mvar rc $32 ;
mvar = cats('list',_n_);
call symputx(mvar,email_list);
rc = resolve(catx(' ','%let',mvar,'=%superq(',mvar,');'));
run;
The first example data step works since the string literal used double quotes on the outside and thus protected the unbalanced single quote. You could do the same thing in macro code by using the %QSYSFUNC() macro function to call the DEQUOTE() function. Note that you would have trouble if the value includes double quote characters. They would need to be converted to two adjacent double quotes.
%put Email list = %qsysfunc(dequote("O'Connor#domain.com"));
With %STR, you need to mark unmatched quotes with a % sign. So try:
%STR(amy.goodman#yaho.com;bill.goodman#yaho.com;lily.O%'Connor#yaho.com)
I'm attempting to retreive a resultset from a MS Access database using VBA for Excel. In the VBA code, I'm constructed a string equal to:
strSql = "SELECT * FROM Pricing WHERE Account In (''1234'', ''ABCD'') '; "
Note that there are 2 single quotes around the strings within the SQL statement. There is also a single quote before the semi-colon. If I'm not mistaken, this evaluates to:
SELECT * FROM Pricing WHERE Account In ('1234', 'ABCD') ;
This query works fine when run directly in MS Access. However, in Excel VBA, I keep getting the Run-time error:
Syntax error (missing operator) in query expression 'Account In (''1234'', ''ABCD'') '; '
Notice that this error actually cut off the first half of the SQL statement.
I've tried a few variations, using double-quotes, double double-quotes, no quotes, etc. etc.
Any advice?
Thanks.
In Excel VBA the string identifier is the " (double quote) character. You do not need to double the single quote characters for them to pass through to the database when enclosed by double quotes.
Try this:
strSql = "SELECT * FROM Pricing WHERE Account In ('1234', 'ABCD')"
Please try it with this:
strSql = "SELECT * FROM Pricing WHERE Account In ('1234', 'ABCD')"