* %age -- see Ian and my paper on %ifn() at [[changchung.com|http://changchung.com/]]\n* %zdiv -- by [[Kevin Myers|http://www.listserv.uga.edu/cgi-bin/wa?A2=ind0511a&L=sas-l&D=1&O=D&P=17764]]'s clever use of a pair of {{{ifn()}}} functions and polished by [[Dale McLerran|http://www.listserv.uga.edu/cgi-bin/wa?A2=ind0511a&L=sas-l&D=1&O=D&P=34938]] in a long thread started by [[Julie|http://www.listserv.uga.edu/cgi-bin/wa?A2=ind0510E&L=sas-l&P=R6826&D=1&O=D]]

This must have been asked frequently, since the stata.com has this FAQ entry written by none other than Gould himself. http://www.stata.com/support/faqs/data/arrays.html\n\nNow mata is available, I found doing this feels much closer to actually looping over arrays. In the following, I am looping over 60 variables from

A programming guru once said that "COM is Love." That's fine. But wouldn't you say that it is lovely to share ideas, problems, tips, and possibly big dreams? :-)\n\nWelcome to Changarilla, where Chang shares his stories about programming. Enjoy!

!Just create two {{{gph}}}'s and do {{{gr combine}}}:\n{{{\n* list them\ngraph dir, detail\n\n* remove those in the memory\ngraph drop _all\n\n* or you can free up more memory and close any open dialog boxes with\ndiscard\n\n* remove those on disk, e.g. male.gph\nerase male.gph\n\n* use a data and create two .gph's\nsysuse uslifeexp, clear\nline le_male year, saving(male)\nline le_female year, saving(female)\n\n* and combine: col(1) puts the two top and bottom\ngr combine male.gph female.gph, col(1) \n\n* save it as a png format\ngr export grCombine1.png\n}}}\n[img[this | http://changchung.com/changarilla/grCombine1.png]]\n\n! Controlling {{{plot region}}} Aspect Ratio \n* Learn [[how graphs are constructed | http://www.stata.com/help.cgi?region_options]]\n* If used, the relative sizes will be based on the {{{min(width, height)}}} of the ''combined'' graph! -- so it does not help to use relative sizes in the component graphs.\n* Individual graph's aspect ratio can be best controlled ''indirectly'' with {{{xsize() ysize()}}}\n* Individual graph's {{{plot region}}} aspect ratio can ''directly'' controlled by {{{aspectratio()}}} option and this will remain even after combined.\n\n!Controlling Size of the Text and Markers\n* When combined, the size of text and markers are multiplied by the default {{{iscale()}}}, which is a function of //G//, the number of graphs combined.\n\n!{{{altshrink}}} option for the graph combine\n* According to Stata: {{{altshrink}}} specifies an alternative method of determining everything (text, markers, line thicknesses, and line patterns). When specified,\n<<<\nThe size of everything drawn on each individual graph is as though the graph were drawn at full size, but at the aspect ratio of the combined individual graph, and then the individual graph and everything on it were shrunk to the size shown in the combined graph.\n<<<\n\n! A Better Control\n* By combining the individual {{{aspectratio()}}} and combined {{{altshrink}}}, you can have a reliable control over the combined graph so that the individual graphs keep their original look and simply combined.\n{{{\ndiscard\nerase male.gph\nerase female.gph\n\n* use a data and create two .gph's\nsysuse uslifeexp, clear\n\n* square male\nline le_male year, saving(male) aspectratio(1) \n\n* 3 by 5 female\nline le_female year, saving(female) aspectratio(`=3/5')\n\n* and combine: col(1) puts the two top and bottom\ngr combine male.gph female.gph, col(1) altshrink \n\n* save it as a png format\ngr export grCombine2.png\n}}}\n[img[this | http://changchung.com/changarilla/grCombine2.png]]\n\n\n\n\n

Stata macro references are immediately resolved. In addition, the non-existing macro references are resolved to nothing with no errors generated. Thus, the following attempt fails: \n{{{\nlocal initials My initials are `myinitials'\nlocal myinitials ABC\ndisplay "`initials'"\n// My initials are (nothing here)\n}}}\nThe reason why we don't see the initials(ABC) on display is that the myinitials are resolved in the first line, when the macro does not exist yet. If you want to change the myinitials value and wants this to be reflected in your initials, then you have to delay the resolution of myinitials. Can this be done?\n\nYes, of course. Just hide the back-tick from Stata until desired:\n{{{\nlocal initials My initials are \s`myinitials' \nlocal myinitials ABC\ndisplay "`initials'"\n// My initials are ABC\n\nlocal myinitials CYC\ndisplay "`initials'"\n// My initials are CYC\n}}}

Stata reads a command from left to right and certain characters (macro expansion punctuations, {{{`}}} and {{{$}}}) trigger macro substitution. You prevent this happening by "escaping" the punctuations by leading backslash ({{{\s}}}). There are four rules (which used to be cleaner upto release 8. With 9, it is less clean.)\n\n|! You type: |! Stata sees: |! note|\n| {{{\s$}}} | {{{$}}} | i.e., stata sees a non-macro-trigger, just a character {{{$}}} |\n| {{{\s`}}} | {{{`}}} | ditto |\n| {{{\s\s}}} | {{{\s}}} | only when the second backslash precedes {{{`}}} or {{{$}}} |\n| {{{\s}}} | {{{\s}}} | after applying the above rules first |\n\nThe above are from stata [[FAQ|http://www.stata.com/support/faqs/lang/backslash.html]] and the item number 29 in the Programming section of [[What'sNew8to9|http://www.stata.com/help.cgi?whatsnew8to9#programming]].\n\nGet it? It is easy, just remember stata does not go back and do recursive resolution at all. just one pass with look-ahead, that's it. Suppose that you already did:\n{{{\nlocal myMac "ABC"\n}}}\nWhat does stata print out, when you do the following? \n{{{\ndisplay `"\s\s\s`myMac'"'\n}}}\nStata spits back the following -- because first slash remains as slash and the second and third slashes become one slash since they are immediately followed by a back tick.\n{{{\n\s\sABC\n}}}\nNow, guess what the following will display?\n{{{\ndisplay `"\s\s\s\s`myMac'"'\n}}}\nYes, of course. Three slashes since the first two slashes remain as they are.\n{{{\n\s\s\sABC\n}}}\nNow, how about this one?\n{{{\nlocal quoted "\s`myMac'"\nlocal `quoted' "D"\ndisplay `" `quoted' "' \ndisplay `" ``quoted'' "'\n}}}\nThe answers are:\n{{{\nABC\nD\n}}}\nThis is because even though the macro trigger can be masked when it is first being evaluated, stata macro does not store it. The second one is just a straight-forward double resolution. See the output from macro list. (preceding underscore character means a local macro variable -- this is how stata knows what is local and what is global, simple, huh?)\n{{{\n. macro list\n...\n_ABC: D\n_quoted: `myMac'\n_myMac: ABC\n...\n}}}

In ms excel find-and-replace, the asterisk {{{*}}} and the question mark {{{?}}} are wild characters, matching any and single characters, respectively. In order to escape them, use the tilde {{{~}}}. In order to escape the tilde, double it up. That is,\n\n|! to match this character |! use this |\n| {{{*}}} | {{{~*}}} |\n| {{{?}}} | {{{~?}}} |\n| {{{~}}} | {{{~~}}} |\n\nThe help page within excel regarding this is titled "Find or replace text and numbers on a worksheet." (Excel 11 (2003) sp1)

You need ''sas/access interface to ole db'' to do this. Basically it bypasses the service, and connects directly to Jet provider.\n\n{{{\nlibname e oledb \n provider="Microsoft.Jet.OLEDB.4.0" \n properties=('Data Source'='d:\schang\sg\stest.xls') \n provider_string="Excel 8.0;hdr=no" \n preserve_tab_names=yes ; \n%put &sysdbmsg; /* any message returned? */\n\ndata one; \n set e.'Sheet1$a1:b3'n( \n dbmax_text=32767 \n dbsastype=( \n f1='char(4)' \n f2=numeric ) ); \n rename f1=name f2=v2; \nrun;\n\nproc print data=one; /* always check */ \nrun;\nproc contents data=one;\nrun;\n\nlibname e clear; /* prevent sas from locking the excel file up */\n}}}\n\nThe above example reads data from the range a1 to b3 in the c:\schang\sg\stest.xls workbook. Column A becomes a character variable, name (length=$4) and column b a numeric variable, v2. Notes are in the below:\n\nCapability \n# reading, updating, creating, and deleting tables possible, through this approach. \n# adding or deleting columns are not. use sql pass-through facility, instead. \n# cannot control excel application either. Try sashelp.fsp.hauto class for OLE Automation in scl.\n\nLibname \n# if this excel file is already open, then sas returns the, confusing, "file not found" error when you set in the datastep. One way to prevent it is to make the excel workbook shared (see in the below). \n# Excel 8.0 works for both 97 and 2000 .xls format. (works for 2002, too) \n# hdr=yes means that the first row has the variable name. \n# preserve_tab_names=yes works with 'sheet1$a1:b2'n style table name. \n# sysdbmsg returns some message when de-referenced immediately after attemping a connection, as we do with libname.\n\nData Step \n# an excel sheet name can only be upto 31 characters long. \n# a max range for an excel sheet is a1:iv65536. \n# dbmax_text=32767 prevents truncation of a possiblly lengthy character values in the cell. \n# dbsastype designates the type for the SAS variable created. Conversion will be done in the database side -- this will minimize loss of precision. Other types are: numeric, datetime, date, or time. When you write to an excel sheet, use dbtype= option to control how SAS converts values into oledb type. (defaults are ~DBTYPE_STR(size) or ~DBTYPE_R8.) default var names are f1, f2, ...

Suppose that you are assigning a long string to a macro variable. Remember that stata's expression evaluator silently //truncates// a string (the max is 244 chars). This leads to a pretty subtle error.\n{{{\nclear\n// create a test dataset with a lot of variables\nsysuse auto\nds\nlocal varlist "`r(varlist)'"\nforeach var of local varlist {\n rename `var' `var'0\n forvalues n = 1/5 {\n gen `var'`n' = `var'0\n }\n}\n\n// here things getting interesting\n// this works fine!\nds\nlocal long "`r(varlist)'"\nforeach var of local long {\n di "`var'"\n}\n\n// here the variable list is truncated because the local statement invokes the expression evaluator\nds\nlocal short = "`r(varlist)'"\nforeach var of local short {\n di "`var'"\n}\n}}}

!Vince Wiggin's NASUG 2004 Presentation\nRead Vince Wiggins's presentation at the 3rd [[NASUG(2004)|http://www.stata.com/meeting/3nasug/abstracts.html#wiggins]] -- the presentation materials can be installed using the {{{net}}} command.\n{{{\nnet from http://www.stata.com/users/vwiggins\nnet describe boston04\nnet install boston04\n\nbgrtalk\nwhelp bgrtalk\n}}}\n\n!Some extracts from the Vince talk\n!!What?\n* are the {{{Stata graphs}}}:\n> nested collections of class-system objects, containing sub-objects including {{{styles}}}, being capable of drawing themselves, containing scripts for reproducing themselves\n* is the {{{graph}}} command:\n> a not-so-thin parsing and object creation engine that creates objects in the class system\n* are {{{saved graphs}}}:\n> data in [[serset|http://www.stata.com/help.cgi?serset]], log of commands to re-create the graph (a story), and sundry information to identify the graph\n\n!!Anatomy1 -- name of the parts\n|[[anatomy|http://changchung.com/g/stataGraphAnatomy.png]]|\nYou can manipulate through options, and nested options:\n{{{\n// change the title to a huge red, "New title" \n... title(New title, color(red) size(huge))\n}}}\n\n!!Anatomy2 -- {{{.Graph}}} and other objects \n|[[graph objects|http://changchung.com/g/stataGraphObjects.png]]|\nYou can directly manipulate each objects with a method call like {{{.editstyle}}}:\n{{{\n// changing the style of the title\n.Graph.title.style.editstyle color(red) size(huge) editcopy\ngraph display\n\n// changing the fill color of an area plot\n.Graph.plotregion1.plot1.style.editstyle area(shadestyle(color(green))) editcopy\ngraph display\n}}}\n

|>|! Golden Rule|\n| Never code | {{{... `a'^2 ...}}} |\n| Do code |{{{... (`a')^2 ...}}} |\n\nThis is because a change that stata made (from version 4 to 5) in evaluating expressions involving the power operator ({{{^}}}). I ''hate'' stata for making this change, since the burden is on the programmer to remember to use the parens. Gould explains why this has happened in a Stata [[FAQ|http://stata.com/support/faqs/lang/macpow.html]].

This question came up in 2003 on stata listserver: by someone named [[laszlo|http://newwww.stata.com/statalist/archive/2003-12/msg00381.html]]. Two answers: by [[Nick Cox|http://newwww.stata.com/statalist/archive/2003-12/msg00385.html]], and by [[Bill Gould|http://newwww.stata.com/statalist/archive/2003-12/msg00391.html]]. The latter seems to be worth repeating here:\n{{{\nThe point of c_local is to be a tool for developing programming-language \nstatements. For instance, imagine I wanted to create a new command, \n\n bill_gould x : ...\n\nto be used in other programs. The point of the new -bill_gould- command \nis to assign something to the local macro x. Inside bill_gould.ado, I\nwould code the line\n\n c_local `1' ...\n\nThus assigning back to the local macro in the caller's space.\n\n-- Bill\nwgould@stata.com\n}}}\nToday, someone told me about this command as a good way of making local macro variables (defined in a selected-and-then-submitted section of a do file) "stick" to the console session -- which is an ingenious way of using {{{c_local}}}.

An interesting point made by a "little birdie" -- an annonymous sas institute insider answering to the questions posted on sas discussion group, sas-l on [[April 1st, 2004|http://listserv.uga.edu/cgi-bin/wa?A2=ind0404a&L=sas-l&D=0&P=8470]] -- (it was not a joke!)\n\n----\nCan someone explain what SAS resolves {{{compress('')}}} as?\n----\n{{{''}}} is a single blank.\n\n{{{compress('')}}} removes all blanks from {{{''}}} and therefore returns a string containing zero characters.\n\n{{{put(compress(''),$hex.)}}} returns two blanks because the {{{$hex.}}} format seems to have a minimum field width of two. Since there are no data to put into the field, the field is padded with blanks.\n\nWhen you compare two strings with the {{{=}}} operator, the shorter string is padded with blanks out to the length of the longer string.\n\nIt seems that the behavior of the {{{=:}}} operator is not clearly documented. An expression of the form {{{X=:Y}}} compares a prefix of {{{X}}} with a prefix of {{{Y}}}. The length of the prefix of {{{X}}} is: {{{min( length of X, max(1, length of Y) )}}} where "length" means the number of characters including trailing blanks. The length of the prefix of Y is: {{{min( length of Y, max(1, length of X) )}}} Furthermore, if one prefix is shorter than the other, it is not padded with blanks, and prefixes of unequal length are considered unequal to each other. This expression: {{{compress('')=:''}}} returns false because {{{compress('')}}} has a length of zero but {{{''}}} has a length of one.\n\nIf you're wondering why all this works the way it does, it's because the person who originally wrote the {{{DATA}}} step ''disliked'' strings with a length of zero, but we later discovered that there are times when people need zero-length strings.\n----