Is there a way to apply SAS EG processes to new files? - sas

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.

Related

Methods for opening a specific file inside the project WITHOUT knowing what the working directory will be

I've had trouble with this issue across many languages, most recently with C++.
The Issue Exemplified
Let's say we're working with C++ and have the following file structure for a project:
("Project" main folder with three [modules, data, etc] subfolders)
Now say:
Our maincode.cpp is in the Project folder
moduleA.cpp is in modules folder
data.txt is in data folder
moduleA.cpp wants to read data.txt
So the way I'd currently do it would be to assume maincode.cpp gets compiled & executed inside the Project folder, and so hardcode the path data/data.txt in moduleA.cpp to do the reading (say I used fstream fs("data/data.txt") to do so).
But what if the code was, for some reason, executed inside etc folder?
Is there a way around this?
The Questions
Is this a valid question? Or am I missing something with the wd (working directory) concept fundamentals?
Are there any methods for working around absolute paths so as to solve this issue in C++?
Are there any universal methods for doing the same with any language?
If there are no reasonable methods, how would you approach this issue?
Please leave a comment if I missed any important details with the problem's illustration!
At some point the program has to make an assumption where the file(s) are. Either by getting it from user input or a relative path with the presumed filename. As already said in the comments, C++ recently got std::filesystem added in C++17 which can help you making cross-platform code that interacts with the hosts' filesystem.
That being said, every program, big or small, has to make certain assumptions at some point, deleting or moving certain files is problematic for any program in case the program requires them to be at a certain location under a certain name. This is not solvable other than presenting the user with an error message etc.
As #Hatted Rooster said, it's not generally solvable for some arbitrary file without making some assumptions, however there are frameworks that allow you to "store" some files in the resources embedded into the executable (or otherwise). Those frameworks would usually allow your to handle such files in a opaque way, without the need to rely on a current working dir or relative paths.
For example, see the Qt Resource System.
Your program can deduce the path from argv[0] in the main call, if you know that it is always relative to your executable or you use an absolute path like "C:\myProgram\data\data.txt".
The second approach works in every language.

Using a Main program to edit all program headers in a directory?

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;

Linked directory not found

I have following scenario:
The main software I wrote uses a database created by a simulator. This database is around 10 GB big at the moment, so I want to keep only one copy of that data per system.
Assuming I have following projects:
Main Software using the data, located at /SimData
DLL using the data for debugging, searching for data at /SimData
Debugging tool to parse the image database, searching for the data at /SimData
Since I do not want to have all those programs have their own copy of SimData (not only to decrease place used, but also to ensure that all Simulation data used is always up to date for all programs).
I created for the DLL and Debugging Utility a link named SimData to MainSoftware/SimData, but when opening a file with "SimData\MyFile.data" it cannot find it, only the MainSoftware with the ACTUAL SimData folder can find it.
How can I use the MainSoftware/SimData folder without setting absolute paths?
This is on Windows 7 x64
I agree with Peter about adding the DB location as a configurable parameter. A common place to store that is in the registry.
however, If you want to create links that will be recognized by your software, try hardlinks. . fsutil should do the trick as described here.
You need a way to configure the database location. You could use an INI or other configuration file, or a registry setting, or a command-line input, or an environment variable. Or You could write your program to search a directory hierarchy... for example, if the various modules are usually siblings of each other in your directory tree, you could search for SimData/MyFile.data, ../SimData/MyFile.data, ../../MainSoftware/SimData/Myfile.data, and use the first one found.
Which answer is the "right one" depends on your situation.

Hiding application resources

I'm making a simple game with SFML 1.6 in C++. Of course, I have a lot of picture, level, and data files. Problem is, I don't want these files visible. Right now they're just plain picture files in a res/ subdirectory, and I want to either conceal them or encrypt them. Is it possible to put the raw data from the files into a resource file or something? Any solution is okay to me, I just don't want the files exposed to the user.
EDIT
Cross platform solutions best, but if they don't exist, that's okay, I'm working on windows. But I don't really want to use a library if it's not needed.
Most environments come with a resource compiler that converts images/icons/etc into string data and includes them in the source.
Another common technique is to copy them into the end of the final .exe as the last part of the build process. Then at run time, open the .exe as a file and read the data from some determined offset, see Embedding a filesystem in an executable?
The ideal way for this is to make your own archive format, which would contain all of your files' data along with some extra info needed to split files distinctly within it.

Change file order in a Windows Directory in C

Like when you drag a file on top of another one and change the order, like that.
I'm going to assume you're asking about how to rearrange the order in which files are displayed in a folder. I'm not exactly sure how to do it, but you'll want to use the various functions from the Windows shell to accomplish this. See the Shell Developer's Guide.
There is no way to do this (except maybe by hacking the directory structures on the disk using raw, sector-based APIs). The order of files on the disk is managed by the file system according to it's design and needs.
For what its worth, FAT directory entries are stored in the order in which they are added. NTFS actually indexes its directory entries, but I thought creation order still played some role in which order they're retrieved. Maybe not. Nearly every UI that does file listings does some type of sorting on display, though, usually alphabetical.
Bottom line-- if its not application-sorted and its not creation time, then there's nothing you can do.