proc template; define tagset Tagsets.Csv; notes "This is the CSV definition"; mvar _CURRENCY_SYMBOL _DECIMAL_SEPARATOR _THOUSANDS_SEPARATOR _CURRENCY_AS_NUMBER _PERCENTAGE_AS_NUMBER _DELIMITER; define event initialize; trigger set_options; trigger documentation; trigger compile_regexp; end; define event options_set; trigger set_options; trigger documentation; trigger compile_regexp; end; define event documentation; trigger help /if cmp( $options["DOC"], "help"); trigger quick_reference /if cmp( $options["DOC"], "quick"); end; define event help; putlog "=============================================================================="; putlog "The CSV Tagset Help Text."; putlog " "; putlog "This Tagset/Destination creates output in comma separated value format."; putlog " "; putlog "Numbers, Currency and percentages are correctly detected and show as numeric values."; putlog "Dollar signs, commas and percentages are stripped from numeric values by default."; putlog " "; trigger quick_reference; end; define event quick_reference; putlog "=============================================================================="; putlog " "; putlog "These are the options supported by this tagset."; putlog " "; putlog "Sample usage:"; putlog " "; putlog "ods csv options(doc='Quick'); "; putlog " "; putlog "ods csv options(currency_as_number='yes' percentage_as_number='yes' delimiter=';'); "; putlog " "; putlog "Doc: No default value."; putlog " Help: Displays introductory text and options."; putlog " Quick: Displays available options."; putlog " "; putlog "Delimiter: Default Value ','"; putlog " Sets the delimiter for the values. Comma is the default. Semi-colon is"; putlog " a popular setting for european sites."; putlog " "; putlog "currency_as_number: Default Value 'No'"; putlog " If 'Yes' currency values will not be quoted."; putlog " The currency values are stripped of punctuation and currency symbols"; putlog " so they can be used as a number."; putlog " "; putlog "percentage_as_number: Default Value 'No'"; putlog " If 'Yes' percentage values will not be quoted."; putlog " The percentages are stripped of punctuation and the percent sign"; putlog " so they can be used as a number."; putlog " "; putlog "Currency_symbol: Default Value '$'"; putlog " Used for detection of currency formats and for "; putlog " removing those symbols so excel will like them."; putlog " Will be deprecated in a future release when it is"; putlog " no longer needed. "; putlog " "; putlog "Decimal_separator: Default Value '.'"; putlog " The character used for the decimal point."; putlog " Will be deprecated in a future release when it is no longer needed."; putlog " "; putlog "Prepend_Equals: Default Value 'no'"; putlog " Put an equal sign in front of quoted number values."; putlog " This only works in conjunction with quote_by_type."; putlog " "; putlog "quote_by_type: Default Value 'no'"; putlog " Put values based on the type, not based on what the regex match for number."; putlog " "; putlog "Table_Headers: Default Value 'yes'"; putlog " If no, skip the header section of all tables."; putlog " "; putlog "Thousands_separator: Default Value ','"; putlog " The character used for indicating thousands in numeric values."; putlog " Used for removing those symbols from numerics so excel will like them."; putlog " Will be deprecated in a future release when it is no longer needed."; putlog " "; putlog "Quoted_columns: Default Value ''"; putlog " A list of column numbers that indicate which values should be quoted"; putlog " ie. Quoted_columns=""123"""; putlog " "; putlog "Bylines: Default Value: No"; putlog " If yes bylines will be printed"; putlog " "; putlog "Titles: Default Value: No"; putlog " If yes titles and footnotes will be printed"; putlog " "; putlog "Notes: Default Value: No"; putlog " If yes Note, Warning, Error, and Fatal notes will be printed"; putlog " "; putlog "Proc_Titles: Default Value: No"; putlog " If yes titles generated by the procedures will be printed"; putlog " "; putlog "=============================================================================="; end; define event set_options; unset $currency_sym; unset $decimal_separator; unset $thousand_separator; unset $currency_number; unset $percentage_number; unset $delimiter; set $options["junk" ] "junk" /if ^$options; set $currency_sym $options["CURRENCY_SYMBOL" ]; set $currency_sym _CURRENCY_SYMBOL /if ^$currency_sym; set $currency_sym "$" /if ^$currency_sym; set $currency_sym_re "\" $currency_sym; set $decimal_separator $options["DECIMAL_SEPARATOR" ]; set $decimal_separator _DECIMAL_SEPARATOR /if ^$decimal_separator; set $decimal_separator "\." /if ^$decimal_separator; set $thousands_separator $options["THOUSANDS_SEPARATOR" ]; set $thousands_separator _THOUSANDS_SEPARATOR /if ^$thousands_separator; set $thousands_separator "," /if ^$thousands_separator; set $currency_number "True" /if cmp( $options["CURRENCY_AS_NUMBER"], "yes"); do /if ^$currency_number; set $currency_number "True" /if cmp( _CURRENCY_AS_NUMBER , "yes"); done; set $percentage_number "True" /if cmp( $options["PERCENTAGE_AS_NUMBER"], "yes"); do /if ^$percentage_number; set $percentage_number "True" /if cmp( _PERCENTAGE_AS_NUMBER , "yes"); done; set $delimiter $options["DELIMITER" ]; set $delimiter _DELIMITER /if ^$delimiter; set $delimiter "," /if ^$delimiter; do /if cmp( $options["BYLINES"], "yes"); set $Bylines "True"; else; unset $Bylines; done; do /if cmp( $options["TABLE_HEADERS"], "no"); set $dont_print_table_head "True"; else; unset $dont_print_table_head; done; do /if cmp( $options["PREPEND_EQUALS"], "yes"); set $prepend_equals "True"; else; unset $prepend_equals; done; do /if cmp( $options["QUOTE_BY_TYPE"], "yes"); set $quote_by_type "True"; else; unset $quote_by_type; done; do /if cmp( $options["TITLES"], "yes"); set $titles "True"; else; unset $titles; done; do /if cmp( $options["PROC_TITLES"], "yes"); set $proc_titles "True"; else; unset $proc_titles; done; do /if cmp( $options["NOTES"], "yes"); set $notes "True"; else; unset $notes; done; do /if $options["QUOTED_COLUMNS"]; set $quoted_columns $options["QUOTED_COLUMNS" ]; else; unset $quoted_columns; done; end; define event compile_regexp; do /if $currency_number; set $punctuation $currency_sym %nrstr(",%%+"); else; set $punctuation $thousands_separator %nrstr("%%+"); done; set $integer_re "\d+"; set $sign_re "[+-]?"; set $group_re "\d{1,3}(?:" $thousands_separator "\d{3})*"; set $whole_re "(?:" $group_re "|" $integer_re ")"; set $exponent_re "[eE]" $sign_re $integer_re; set $fraction_re "(?:" $decimal_separator "\d*)"; set $real_re "(?:" $whole_re $fraction_re "|" $fraction_re $integer_re "|" $whole_re ")"; set $percent_re $sign_re $real_re %nrstr("\%%"); set $scinot_re $sign_re "(?:" $real_re $exponent_re "|" $real_re ")"; set $cents_re "(?:" $decimal_separator "\d\d)"; set $money_re $sign_re $currency_sym_re "(?:" $whole_re $cents_re "|" $cents_re "|" $whole_re ")"; set $number_re "/^(?:" $real_re "|" $percent_re "|" $scinot_re "|" $money_re ")\Z/"; eval $number prxparse($number_re); end; define event put_value_cr; put VALUE NL; end; define event verbatim; finish: put NL; end; define event verbatim_text; put VALUE; put NL; end; define event proc; set $proc_name name; end; define event paragraph; put value NL; end; define event table_head; start: do /if $dont_print_table_head; block row; block data; block header; done; finish: do /if $dont_print_table_head; unblock row; unblock data; unblock header; done; end; define event caption; put text NL /if text; end; define event table; finish: put NL; end; define event row; finish: do /if $cell_count; close; eval $cell_count 0; else /if $$row; put $$row; unset $$row; done; put NL; end; define event header; start: trigger put_delimiter; trigger quotes start; put strip(VALUE); finish: trigger quotes finish; end; define event quotes; start: break /if cmp( event_name, "stacked_value"); break /if $inquotes; do /if $quote_by_type & cmp( $type, "Number"); put "=" /if $prepend_equals; done; put """"; set $inquotes "True"; finish: break /if cmp( event_name, "stacked_value"); break /if ^$inquotes; put """"; unset $inquotes; end; define event data; start: break /if is_stacked; do /if ^$cell_count; do /if cmp( rowspan, "2"); flush; open row; eval $cell_count 1; eval $end_of_row_start inputn(colstart,"BEST"); done; else; eval $cell_count $cell_count +1; done; trigger put_delimiter; trigger put_value; finish: break /if is_stacked; trigger quotes finish; end; define event put_delimiter; unset $rowspanfilled /breakif $rowspanfilled; put $delimiter /if ^cmp( COLSTART, "1"); end; define event stacked_cell; start: trigger put_delimiter; trigger quotes start; finish: trigger quotes finish; end; define event stacked_value; start: put " " /if ^cmp( first_stacked_value, "1"); trigger put_value; end; define event stacked_value_header; trigger stacked_value; end; define event data_note; start: trigger data; finish: trigger data; end; define event colspanfill; put $delimiter; end; define event table_body; start: set $body_section "True"; finish: unset $body_section; end; define event rowspancolspanfill; break /if $$row; do /if $body_section; eval $count inputn(colspan,"BEST"); do /if missing($count); eval $count 1; done; else; eval $count inputn(colspan,"BEST"); done; do /while $count; put $delimiter; eval $count $count -1; set $rowspanfilled "TRUE"; done; end; define event rowspanfill; break /if $$row; put $delimiter /if ^VALUE; end; define event breakline; trigger quotes finish; put NL; end; define event splitline; put NL; end; define event put_value; unset $value; unset $type; break /if ^VALUE; set $value strip(VALUE); trigger value_type; trigger quotes finish; do /if $quote_by_type; do /if cmp( type, "String"); trigger quotes start; done; else /if cmp( $type, "String"); trigger quotes start; done; put $value; trigger quotes finish; end; define event value_type; do /if $quoted_columns; do /if contains( $quoted_columns, colstart); set $type "String"; break; else; set $type "Number"; done; done; done; /* do /if cmp( proc_name, "Print");*/ /* set $type type;*/ /* set $type "Number" /breakif cmp( type, "double");*/ /* done;*/ eval $is_numeric prxmatch($number,$value); do /if $is_numeric; set $type "Number"; do /if ^$currency_number; do /if index($value, $currency_sym); set $type "String"; done; done; do /if ^$percentage_number; do /if index(value, %nrstr("%%")); set $type "String"; done; done; set $value compress($value,$punctuation) /if cmp( $type, "Number"); else; set $type "String"; done; end; define event byline; break /if ^$bylines; putq value NL; end; define event proc_title; break /if ^$proc_titles; put VALUE NL; end; define event title_format_section; break /if ^$titles; put value; end; define event system_title; start: break /if ^$titles; put VALUE; finish: break /if ^$titles; put NL NL; end; define event system_footer; start: break /if ^$titles; put VALUE; finish: break /if ^$titles; put NL NL; end; define event note; break /if ^$notes; put VALUE NL; end; define event fatal; break /if ^$notes; put VALUE NL; end; define event error; break /if ^$notes; put VALUE NL; end; define event warning; break /if ^$notes; put VALUE NL; end; mapsub = "/""""/"; map = """"; registered_tm = "(r)"; trademark = "(tm)"; copyright = "(c)"; output_type = "csv"; stacked_columns = OFF; end; run;