This is possible, but by no means easy. You can run tables in batch mode, and writing the logic for that wouldn't be so difficult, but then you would have to parse the .tab and .tai files that result from batch tabulation. This is was ICFI does the DHS tables.
If you want to actually create a .tbw file, then you'll have to write out not only the .app logic, but you'll also have to write out the .xts file, which will tell CSPro how to format the table. See attached for an example application where I do the following:
(Run generateTableCode.pff.)
1) The program parses the Parameter attribute in the .pff file, taking the row and column value sets, and then number of geography levels to which you want to tabulate. For example, the following will be an age by literacy table down to the province level.
Parameter=AGG_10_5;P11_LITERACY_VS1;1
2) The program writes out the proper logic. I created a sample table and then used that as a basis to figure out the logic. If you wanted to create tables with more than two variables, you could also create a template table and then replace the value set names as appropriate.
3) The program writes out the tabulation spec file. To do this, it has to parse the input dictionary to write out all of the value set labels (done in the function printVariable). This will not work if you use linked value sets in your application.
4) The program runs the tabulation.
5) The program uses the Table Viewer function to convert the .tbw file to a HTML document.
6) The program then opens the document in Internet Explorer. For you, instead of this step, you would then serve the document to the user.
This is rather complicated, but it does work!
PROC GLOBAL
// format of sysparm(): row variable value set; column variable value set; number of area levels
file output,dict;
alpha (200) str,lastStr;
alpha (40) rowVS, colVS;
alpha (200) breakStr;
numeric numBreaks;
function printVariable(alpha (40) vsetName)
setfile(dict,"Census Dictionary.dcf");
filewrite(output,"[Variable]");
filewrite(output,"Name=%s",strip(vsetName));
// read until we find the value set name
while fileread(dict,str) and not pos(strip(vsetName),str) do
lastStr = str;
enddo;
// lastStr will now be something like: Label=Sex
filewrite(output,"%s",strip(lastStr));
filewrite(output,"VarType=Dict");
// the total entry
filewrite(output,"[Value]");
filewrite(output,"Label=Total");
filewrite(output,"TabValueType=Total");
filewrite(output,"TabValueStatIndex=0");
// print out each value
while fileread(dict,str) and pos("Value",str) do
filewrite(output,"[Value]");
// str will be something like: Value=1;Male
filewrite(output,"Label=%s",strip(str[pos(";",str) + 1]));
filewrite(output,"TabValueType=VSetValue");
filewrite(output,"TabValueStatIndex=1");
enddo;
filewrite(output,"[EndVar]");
close(dict);
end;
PROC GENERATETABLECODE_FF
preproc
// parse the parameters
numeric semicolonPos = pos(";",sysparm());
rowVS = sysparm()[1
semicolonPos - 1 )];
str = sysparm()[semicolonPos + 1];
semicolonPos = pos(";",str);
colVS = str[1
semicolonPos - 1 )];
numBreaks = tonumber(str[semicolonPos + 1]);
if numBreaks = 1 then breakStr = "PROVINCE";
elseif numBreaks = 2 then breakStr = "PROVINCE, DISTRICT";
endif;
// write out the table application logic
setfile(output,"webTable.xtb.app");
filewrite(output,"PROC GLOBAL");
filewrite(output,"PROC QUEST");
filewrite(output,"Preproc");
filewrite(output,"BREAK BY %s;",strip(breakStr));
filewrite(output,"PROC TABLE1");
filewrite(output,"Tally");
filewrite(output,"CROSSTAB TABLE1 %s, %s",strip(rowVS),strip(colVS));
filewrite(output,"STAT %s (TOTAL, FREQ) %s (TOTAL, FREQ)",strip(rowVS),strip(colVS));
filewrite(output,"UNIT (%s by %s) PERSON",strip(rowVS),strip(colVS));
filewrite(output,"ENDUNIT");
filewrite(output,"BREAK BY %s;",strip(breakStr));
close(output);
// write out the table specs
setfile(output,"webTable.xts");
filewrite(output,"[TabSpecs]");
filewrite(output,"Version=CSPro 5.0");
filewrite(output,"Label=webTable");
filewrite(output,"Name=WEBTABLE");
filewrite(output,"GenerateLogic=No");
filewrite(output,"[Dictionaries]");
filewrite(output,"File=7/30/2012 7:30:12 AM,.\Census Dictionary.dcf");
filewrite(output,"[AreaStructure]");
if numBreaks = 1 then filewrite(output,"Names=PROVINCE"); filewrite(output,"LowestLevel=PROVINCE");
elseif numBreaks = 2 then filewrite(output,"Names=PROVINCE,DISTRICT"); filewrite(output,"LowestLevel=DISTRICT");
endif;
filewrite(output,"Standard=Yes");
filewrite(output,"[ConSpec]");
filewrite(output,"Name=TOTAL");
if numBreaks >= 1 then
filewrite(output,"[ConSpec]");
filewrite(output,"Name=PROVINCE");
filewrite(output,"Level=PROVINCE");
endif;
if numBreaks >= 2 then
filewrite(output,"[ConSpec]");
filewrite(output,"Name=DISTRICT");
filewrite(output,"Level=PROVINCE");
filewrite(output,"Level=DISTRICT");
endif;
filewrite(output,"[Table]");
filewrite(output,"Name=TABLE1");
filewrite(output,"Num=1");
filewrite(output,"[Rows]");
printVariable(rowVS);
filewrite(output,"[Cols]");
printVariable(colVS);
filewrite(output,"[Level]");
filewrite(output,"Table=TABLE1");
close(output);
execpff("webTable.xtb.pff",wait);
// now save the table as a html document
execsystem(maketext('%stblview.exe "%swebTable.xtb.tbw" /EXPT HTML "%swebTable.html"',pathname(cspro),pathname(application),pathname(application)),wait);
// open the document in Internet Explorer
execsystem(maketext('"%sInternet Explorer\iexplore.exe" "%swebTable.html"',pathname(programfiles64),pathname(application)));