My client has a couple of Stata programs (.do files) that they have been running for a while.
Is it possible to have a front end page or a form for Stata so that we can choose different options/criteria and based on the selections certain programs on Stata are run?
Basically is there a way of creating a form for Stata programs?
One rough way of making a "form" for a program is to use macros. This is not an explicit dialog form, with textboxes, but it allows you to control a program from a single .do file.
Basically, use a bunch of global macros in a separate do file, then have the macros peppered throughout the .do files. My example below does this
Macros File (Form do-file)
global projectname stackoverflow
global exportfmt putdocx
global analysisfolder "/file/path"
global dofilesfolder "/file/path"
The macro projectname allows you to name the project, and thus I put it in all the file save commands, or I save a cleaned dataset using that name. You can even put it inside a file path.
The macro exportfmt you typically use when generating reports using the putdocx or putpdf command. Having a global variable allows me to switch between exporting a pdf or docx.
The macros analysisfolder and dofilesfolder you then use to create file paths that you can call for different projects, just by filling out the "form".
Do-files Usage
$exportfmt clear
$analysisfolder
use $project, clear
$exportfmt begin
$exportfmt paragraph
Thus, create a separate do-file (form do-file) with all your macros, and then you can change them all in one place as you see fit.
It's not a true form, but it can simplify changing of many things throughout a Stata program.
Stata can be launched in batch mode as
stata /b do whatever.do
So you can form that whatever.do file using the tools that are convenient for you, and then run it as needed. Of course you need to make sure that whatever output is being produced by the client's do-files is being saved in a computer readable format (rather than just left there in the screen for the analyst to copy and paste into Word).
This is implemented by ADePT team of the World Bank, see http://www.worldbank.org/adept. It has a C# GUI, but it runs Stata deep inside.
You can make a form that you can use from Stata's drop-down menu. See the help dialog_programming page.
Related
I'm taking over a project from a coworker that involves several extensive SAS process flows. I have all the files with all the same names and a copy of the process flows they used. Since the file paths in their processes are direct references to their computer, normally I would just re-import the files with the same output names and run the process from there. In a few cases I would have to recreate a query builder as I'm using a few .sas7bdat files from another project.
However, there are quite a few files involved and I may end up having to pass this to another coworker in a few months, and since I can't get a good look at exactly what the import task is doing I'm concerned I may have some of the variables imported incorrectly. Is there an easy way to just change the file path the import or other task refers to?
Given the updates in comments, there's two possibilities I see.
If the paths you're changing are, or can be, relative to the location of the EGP, then you can right click on the Project->Properties->File References and check "Use paths relative to the project...", which means instead of storing a file in c:\my EGP folder\my code folder\code.sas it would store it as my code folder\code.sas. So then if the whole project moves to another computer (or just any other folder) then it automatically has the right path. This is mostly useful for code or similar things.
Otherwise, you're going to have to convert things to SAS code modules. There you can use macro variables to define the locations of things.
Basically when I do sorting or join table in sas, the sas will use resources / space from local disk C: to process the code, but since I only have 100GB left on local disk C:, It will result in error whenever SAS was out of resources.
My question is how to configure / change the setting in SAS to use resources from Local Disk E: instead, since I have larger space there.
I already looking through the forum, but found no similiar question.
Please Help.
Assuming you are talking about desktop SAS, or a server that you administer, you can control where the work and utility folders are stored in a few ways.
The best way is to use the -work and -utilloc options in your sasv9.cfg file. That file can be in a few places, but often the SAS Shortcut you open SAS with specifies it with the -CONFIG option. You can also set the option in that shortcut with -WORK or -UTILLOC command line options. The article How SAS Finds and Processes Configuration Files can help you decide the location of the sasv9.cfg you want to modify; if you are using a personal copy on your own laptop, you may change the one in the Program Files folder, but if not, or if you don 't have administrative rights, you have other places you can place a config file that will override that one.
A paper that discusses a few of these options is one by Peter Eberhardt and Mengting Wang.
One way is to set up a library named user for projects that will be time intensive and this way you get it to be dynamic as needed. When you have a library called user, that becomes the default workspace instead of work. But, you need to clean up that library manually, it won't delete data sets automatically when you're done with it.
libname user '/folders/myfolders/demo';
As #Tom indicates, you can also set an option to use a library that already exists if desired.
options user = myLib;
An advantage of this method over the config file method as it only does it for projects where it's needed, rather than your full system.
I am from Slovakia, I wouldn't be surprised if most of you haven't heard about it.
However, that causes me a troubles when it comes to reports. We need to have 3 (soon 4) language versions of each report: Slovak is main language, than, Polish and English.
Since pentaho does not support Polish nor Slovak, it is really pain for me to keep these localized.
What I do is:
Create report in Slovak language
Write down all phrases from report
Send phrases to one of our partners to translate
Create its copy in either pl/en directory
Open it in Report Designer and edit every phrase accordingly
Save as another language version
As you can imagine, the process is very time consuming, and error prone. Plus, every time I add new parameter to report or change its data source (which is BeanShell script), I need to do it in 3 separated files. As a result of this, language mutations are usually out of date, way behind main language version.
I have tried to automate it with OneSky and did a python script that does 2 stages:
Stage 1 (extract and upload):
Change *.prpt files sufix to *.zip
Extract phrases from files: ~/datadefinition.xml, ~/layout.xml, ~/styles.xml, ~/datasources/inline-ds.xml
Put those phrases into *.po file
Export *.po file into OneSky
Stage 2 (download and import):
Change *.prpt files sufix to *.zip
Download translated *.po file from OneSky
Run through ~/datadefinition.xml, ~/layout.xml, ~/styles.xml, ~/datasources/inline-ds.xml files and replace original phrases by translated
While this aproach works fine, it doe not translate everything. There are still flaws of this process. I need to go through it every time I do even slightest change in data source of report or fix small mistakes. Even if I just do a small six in SQL code, I need to do it in 3 files. That of course increases chance to mistake be made.
Soo, I was wondering, how are you guys solving this issue with translating of your reports?
I will share very simple method which we are following.
1)create a properties file with key value format for each language for resource labels(for static values)
2)put it into resources folder(report-designer/resources/)
3)Based on the parameter you can specify which properties file to select and you can specify keys into value field so that it can understand which value to display in which language.
4)if you need to convert the data which are coming from database,you have to design data warehouse specify all the mappings,accordingly it can fetch the data.
5)For converting dates and currency symbols or number format you can use inbuilt functions which can handle all this things,i am using mysql and mysql has translation functions which can handle all such things.
it is difficult to explain entire process here, but if you can get and idea from this it can be useful to you.
I'm generating thumbnails for office files using c++. I open and save the files using automation similar to this: https://support.microsoft.com/en-us/kb/179494. Since there are many files, this takes a lot of time and the program should run through the night.
Everything works fine, except when a file contains an auto start macro, which doesn't even exist.
Sub AutoOpen()
Application.Run ("stupidMacroWhichDoesntExist")
End Sub
In this case, the Loop stops, and an error message appears that the macro couldn't be executed.
Off Course, I have set the macro settings in the trust center to -> disable all macros without notification
The error message still appears
In Excel, I can prevent this with:
objExcelApp.SetEnableEvents(false);
Unfortunately, the word application in c++ doesn't have a SetEnableEvents method. I have googled a lot and found a lot of VB Code to prevent this. Mostly it was something like:
objWord.WordBasic.DisableAutoMacros 1
But I haven't found anything in c++
I'm very thankful for your help.
I believe you're looking for:
WordApplication.AutomationSecurity = msoAutomationSecurityForceDisable
The Trust Center setting doesn't apply to documents being opened using automation. This property and its MsoAutomationSecurity enumeration correspond to that setting in the object model.
FWIW the WordBasic approach should also be possible using C++. I don't know C++ syntax, but with C# I'd need to use PInvoke (GetType().InvokeMember) to communicate directly with the IDispatch (I think that's the right term).
I have solved it. I'm backing up the actual macro (vbaData.xml and vbaProject.bin in the word folder), put a dummy macro into the word file, open it via automation and save it to generate the thumbnail. After that, I put back the backed up macro into the word file.
Since the dummy macro does nothing I am safe that nothing will be executed, whatever is programmed in the original macro.
I have frequently encountered the following issue in my day to day programming at the office where files can be reused from one project to the next, but the header information needs to be updated for each file, when you are dealing with hundreds of files updating them all manually is a pain, and a waste of resources.
Ideally what I would like is a program that contains a standard header with attributes like author, project code, creation date etc, that I can manually update and when executed it will add this information to all the files/programs in a directory. We use a standard header, which cover the first 20 lines of each program and each attribute is on a certain line, or can be searched for in order to replace it.
For the most part I would like to develop this myself, but any starting point as to how to apply said header to the first 20 lines of each program and how to apply it to each file in a directory. I want to add other functionality later for tracking purposes etc, but for now any help in getting started would be awesome.
I'm a big fan of using keyboard macros to generate header shells. So when I hit CTRL-H, I get a header block comment with the sort of information you described, including my name and today's date. If the assumption is that you will have to manually type something into a header for every program for every project (e.g. a revision note or whatever), then automatically adding 100 header shells doesn't save you much more than the keyboard macro approach.
That said, yes, you could do it with SAS using file statement or whatever. Could probably do it with any good text editor.
And of course a better solution would be to get a version control system.
I wouldn't modify the programs in the directory this way, but rather use %include files. We've done that on projects before, where you have a single program that includes libnames and such, and then you have
%include('header.sas');
or whatever in every program you write in that project. Modifying the code programmatically like this is a bad idea, both because you might not have the most up to date version of the headers, and because it risks damaging the programs if you do it incorrectly). Putting it as an include is easy, avoids replicating the same code 20 times (with possibility of error), and guarantees up-to-date code.
In your case, you can modify the 'header' file for the new day, and assuming you've set things up properly (which it sounds like you have), then the 100 or whatever other programs all can stay the same, unchanged, just including the updated header (automatically). This has the added advantage that you don't make lots of tiny changes to the programs, meaning you know when a meaningful update to the program occurred (as opposed to just a daily run).
In general, this modular approach is superior - divorcing the 'individual run' part of a program/process from the main part - because of these reasons, and because it makes it easier to reuse programs for other purposes as well if you have it set up so the module is already prepared and just needs a header file in the same directory to automatically run. (You can get the name of the current program and its path; if you need that, comment with what mode you use - batch or interactive - and what OS you are in).
This is also one of the places where the Enterprise Guide model is a bit better; there you have all of your project-related files in one project file (.egp), so you don't have to do even this - the project itself can have an autoexec process flow (which runs first, to set libnames and such) and can have notes/author/etc.
This should work. If a line starts with "Author:" it replaces the line with "Author: ME, ONLY ME!!!".
If you are on Windows, change all the forward slashes ("/") to backward slashes ("\").
%let infolder=/folder/where/sas/programs/are;
%let outfolder=/folder/where/new/sas/programs/are/going;
filename dummy temp;
data _null_;
attrib currentinfile currentoutfile length=$32000;
infile "&infolder/*.sas" filename=currentinfile lrecl=32000;
input;
currentoutfile="&outfolder./"!!scan(currentinfile,-1,"/");
file dummy filevar=currentoutfile lrecl=32000;
if index(_infile_,"Author:")=1 then put "Author: ME, ONLY ME!!!";
else put _infile_;
run;