sas horizontal bar chart-Making labels same size - charts

I'm using a macro to generate many similar horizontal bar charts. The chart width changes according to the labels (on the vertical axis) length.
How I can make all the charts the same width causing the labels to wrap automatically to adjust?
data my_annoDetailedChart&i; set FinalDim&i;
xsys='2'; ysys='2'; hsys='3'; when='a';
group=itemname;
midpoint=entity;
x=score;
function='label'; position='>'; color='grayaa'; size=1.5;
text=" "||trim(left(put(score,comma5.2)));
goptions device=png;
goptions xpixels=700 ypixels=450;
goptions noborder;
goptions cback=white;
goptions gunit=pct ftitle="albany amt/bold" ftext="albany amt" hsize=6.5 vsize= 7.6 inches
htitle=4.1 htext=1.5 ctext=gray44;************************************************************************************************************;
*---Indicators---------------------------------------------------------------------------------------------;
pattern1 v=solid c=navy; /* blue */
pattern2 v=solid c=lightgray; /* green */
pattern1 v=solid c=navy; /* blue */
pattern2 v=solid c=lightgray; /* green */
axis1 SPLIT="*" label=none order=(1 to 5 by .5) minor=none offset=(0,0)
color=graydd major=(color=gray44) value=(color=gray44);
axis2 SPLIT="*" label=none value=none ;
axis3 label=none offset=(3,3);* order=( &KOko);
legend1 position=(bottom right inside) mode=share label=none shape=bar(.15in,.15in) offset=(-1,-0.1);
proc gchart data=FinalDim&i anno=my_annoDetailedChart&i;
hbar entity / discrete type=sum sumvar=Score nostat
subgroup=entity group=itemname space=0 gspace=1
raxis=axis1 maxis=axis2 gaxis=axis3 autoref
legend=legend1 clipref ;
title color=navy h=6 font="Times New Roman" "&Dimension";

Related

Drawing using Tikz

I would like to include some shapes using tikz code in my latex thesis. This is what i have so far drawn.
\begin{document}
\begin{tikzpicture}
\node[isosceles triangle,
draw,
rotate=90,
minimum size =2cm] (T1)at (0,0){};
\end{tikzpicture}
\begin{tikzpicture}
\node[single arrow, draw=blue, very thick,
minimum width = 40pt, single arrow head extend=3pt,
minimum height=26mm,
rotate=90] {}; % length of arrow
\end{tikzpicture}
\end{document}
I need something similar to this:
But replacing the BH in the top circles with CO.
Something to get you started. I highly recommend to take a look a the TikZ manual.
\documentclass[tikz, border=1mm]{standalone}
\usetikzlibrary{hobby}
\begin{document}
\begin{tikzpicture}[scale=2]
\draw[thick, ->] (0,.5) -- (10,.5)
node[pos=.25, yshift=3mm] {$0.01$}
node[pos=.5, yshift=3mm] {$0.1$}
node[pos=.75, yshift=3mm] {$1$}
node[pos=1, anchor=east, yshift=3mm] {$\dot{M}/\dot{M}_{Edd}$};
\draw[fill=lightgray] (0,1) -- (1.25,3) -- (2.5,1) -- cycle;
\node[rotate=-90] at (1.25,1.75) {ADAF};
\draw[top color=lightgray, bottom color=black] (4,1) -- (4.1,2) .. controls (4.1,2.15) and (3.6,2) .. (3.75,2.25) -- (4.2,3) -- (4.65,2.25) .. controls (4.8,2) and (4.3,2.15) .. (4.3,2) -- (4.4,1) -- cycle;
\node[rotate=-90] at (4.2,2.45) {ADAF};
\node[rotate=-90, white] at (4.2,1.45) {Standard};
\draw[fill] (5,1) -- (5.2,2.25) -- (5.4,1) -- cycle;
\draw (5.2,2.125) -- ++(.5,.25) node[anchor=west, align=center] {unstable \\ Standard};
\draw[fill] (9,1) -- (9.1,2) .. controls (9.1,2.15) and (8.325,2) .. (8.55,2.25) -- (9.2,3) -- (9.85,2.25) .. controls (10.075,2) and (9.3,2.15) .. (9.3,2) -- (9.4,1) -- cycle;
\node[rotate=-90, white] at (9.2,2.45) {Slim};
\node[rotate=-90, white] at (9.2,1.45) {Standard};
\node[circle, white, fill=black] at (1.25,3.35) {CO};
\node[circle, white, fill=black] at (4.2,3.35) {CO};
\node[circle, white, fill=black] at (5.2,3.35) {CO};
\node[circle, white, fill=black] at (9.2,3.35) {CO};
\end{tikzpicture}
\end{document}

Iterative %DO LOOP issue in SAS macro for automated emailing of site metrics

I have a dataset titled 'SampleReport' of site specific reporting metrics and am looking to email each site their own metrics in an attached PDF. The PDFs generate and are emailed out to their respective sites, however when trying to add ODS text to the PDF, I'm having issues defining my other macros (currently only 'email' is retained as a macro variable but I also want 'site', 'Site_Contact' and 'mcnt_enrolled').
Below is the test dataset and my code; I'm new to SAS and would appreciate any help/suggestions:
site site_enrolled_total mcnt_enrolled Site_Contact Email Expected_Enrolled NetworkAvg Overall_Study_Enrollment Overall_Enrollment_to_Date
site_a 32 7 Homer Simpson hsimp#gmail.com 40 5 115 1518
site_b 36 8 Jim Schoe jimmy2schoes#aol.com 40 4 115 1518
site_ c 20 2 Hank Hill propaneking#yahoo.com 36 7 115 1518
site_d 27 7 Lisa Simpson lisasimpson#gmail.com 36 5 115 1518
And here's my code:
%macro getemail(DATA);
ods _all_ close;
%let outdir = %sysfunc(getoption(WORK));
OPTIONS NODATE NONUMBER;
ODS GRAPHICS / RESET=ALL;
** get list of unique emails;
proc sql noprint;
select distinct(email) into :wantemail separated by '~'
from samplereport
order by email;
quit;
%put &=wantemail;
**count number of separators(i.e. '~') and count number of unique emails;
%let cntsep1 = %sysfunc(count(&wantemail,~));
%let cntemail = %eval(&cntsep1+1);
** start do loop to cycle thru list of emails;
** and create the site macro var for each loop;
%do i = 1 %to &cntemail;
%let email = %scan(&wantemail,&i,~);
%put This is for by group where email = &email;
**use site macro variable for file name and WHERE and TITLE;
ODS PDF (id=dagwood)
FILE="&outdir.\PDF_&email..PDF" STARTPAGE=NO STYLE=Journal gtitle;
title j=center bold "Metrics for January 2020";
ods text= "Email: &email. ";
ods text= "Site: &site. ";
ods text= "Site Contact: &Site_Contact.";
ods text= "Enrolled this Month: &mcnt_enrolled. ";
run;
ods layout gridded columns=2;
ods graphics / width=300 height=300;
ods region;
ods pdf(id=dagwood) style=statdoc;
PROC SGPLOT DATA=work.samplereport;
where email = "&email";
Title "Enrollment Metrics for Your Site";
vbar site / response=Expected_Enrolled stat=sum DATALABEL LEGENDLABEL="Expected Enrollment for Your Site"
discreteoffset=-0.5 barwidth=0.2 fillattrs=graphdata2;
yaxis grid display=(nolabel);
xaxis display=(noline NOTICKS NOVALUES nolabel);
vbar site / response=site_enrolled_total stat=sum DATALABEL LEGENDLABEL="Enrolled for Your Site to Date"
discreteoffset=-0.2 barwidth=0.2 fillattrs=graphdata1;
yaxis grid display=(nolabel);
xaxis display=(noline NOTICKS NOVALUES nolabel);
vbar site / response=mcnt_enrolled stat=sum DATALABEL LEGENDLABEL="Enrolled this Month"
discreteoffset=0.2 barwidth=0.2 fillattrs=graphdata3;
yaxis grid display=(nolabel);
xaxis display=(noline NOTICKS NOVALUES nolabel);
vbar site / response=NetworkAvg stat=sum DATALABEL LEGENDLABEL="Your Network Avg Enrollment this Month"
discreteoffset=0.5 barwidth=0.2 fillattrs=graphdata4;
yaxis grid display=(nolabel);
xaxis display=(noline NOTICKS NOVALUES nolabel);
RUN;
ods region;
ods pdf(id=dagwood) style=statdoc;
goptions reset=all;
proc sgplot data=work.samplereport;
where email = "&email";
Title "Study-Wide Enrollment to Date and Goal";
vbar site / response=Overall_Study_Enrollment stat=sum DATALABEL LEGENDLABEL="Enrollment for All Sites"
discreteoffset=-0.3 barwidth=0.4 fillattrs=graphdata5;
yaxis grid display=(nolabel);
xaxis display=(noline NOTICKS NOVALUES nolabel);
vbar site / response=Overall_Expected_Study stat=sum DATALABEL LEGENDLABEL="Expected Enrollment Goal"
discreteoffset=0.3 barwidth=0.4 fillattrs=graphdata6;
yaxis grid display=(nolabel);
xaxis display=(noline NOTICKS NOVALUES nolabel);
run;
ODS LAYOUT END;
%end;
* get emails from DATA;
proc sql noprint;
select EMAIL into :EMAIL1- from &DATA;
select count(*) into :EMAILN from &DATA;
* cycle through emails;
%do I=1 %to &EMAILN;
filename temp email to="&&EMAIL&I"
attach="&outdir.\PDF_&&email&I...PDF"
from="myemail#gmail.com"
type="text/html"
subject="Site Metrics";
ods html file=temp;
run;
ods html close;
%end;
%mend getemail;
%getemail(samplereport);
The email %DO loop statement is not properly terminated.
* cycle through emails;
%do I=1 %to &EMAILN
Should be
* cycle through emails;
%do I=1 %to &EMAILN;
And maybe the ODS HTML CLOSE should be outside the loop.

Ghostscript -- convert PS to PNG, rotate, and scale

I have an application that creates very nice data plots rendered in PostScript with letter size and landscape mode. An example of the input file is at http://febo.com/uploads/blip.ps. [ Note: this image renders properly in a viewer, but the PNG conversion comes out with the image sideways. ] I need to convert these PostScript files into PNG images that are scaled down and rotated 90 degrees for web presentation.
I want to do this with ghostscript and no other external tool, because the conversion program will be used on both Windows and Linux systems and gs seems to be a common denominator. (I'm creating a perl script with a "PS2png" function that will call gs, but I don't think that's relevant to the question.)
I've searched the web and spent a couple of days trying to modify examples I've found, but nothing I have tried does the combination of (a) rotate, (b) resize, (c) maintain the aspect ratio and (d) avoid clipping.
I did find an example that injects a "scale" command into the postscript stream, and that seems to work well to scale the image to the desired size while maintaining the aspect ratio. But I can't find a way to rotate the resized image so that the, e.g., 601 x 792 point (2504 x 3300 pixel) postscript input becomes an 800 x 608 pixel png output.
I'm looking for the ghostscript/postscript fu that I can pass to the gs command line to accomplish this.
I've tried gs command lines with various combinations of -dFIXEDMEDIA, -dFitPage, -dAutoRotatePages=/None, or /All, -c "<> setpagedevice", changing -dDISPLAYWIDTHPOINTS and -dDISPLAYHEIGHTPOINTS, -g[width]x[height], -dUseCropBox with rotated coordinates, and other things I've forgotten. None of those worked, though it wouldn't surprise me if there's a magic combination of some of them that will. I just haven't been able to find it.
Here is the core code that produces the scaled but not rotated output:
## "$molps" is the input ps file read to a variable
## insert the PS "scale" command
$molps = $sf . " " . $sf . " scale\n" . $molps;
$gsopt1 = " -r300 -dGraphicsAlphaBits=4 -dTextAlphaBits=4";
$gsopt1 = $gsopt1 . " -dDEVICEWIDTHPOINTS=$device_width_points";
$gsopt1 = $gsopt1 . " -dDEVICEHEIGHTPOINTS=$device_height_points";
$gsopt1 = $gsopt1 . " -sOutputFile=" . $outfile;
$gscmd = "gs -q -sDEVICE=pnggray -dNOPAUSE -dBATCH " . $gsopt1 . " - ";
system("echo \"$molps\" \| $gscmd");
$device_width_points and $device_height_points are calculated by taking the original image size and applying the scaling factor $sf.
I'll be grateful to anyone who can show me the way to accomplish this. Thanks!
Better Answer:
You almost had it with your initial research. Just set orientation in the gs call:
... | gs ... -dAutoRotatePages=/None -c '<</Orientation 3>> setpagedevice' ...
cf. discussion of setpagedevice in the Red Book, and ghostscript docs (just before section 6.2)
Original Answer:
As well as "scale", you need "rotate" and "translate", not necessarily in that order.
Presumably these are single-page PostScript files?
If you know the bounding box of the Postscript, and the dimensions of the png, it is not too arduous to calculate the necessary transformation. It'll be about one line of code. You just need to ensure you inject it in the correct place.
Chapter 6 of the Blue Book has lots of details
A ubc.ca paper provides some illustrated examples (skip to page 4)
Simple PostScript file to play around with. You'll just need the three translate,scale,rotate commands in some order. The rest is for demonstrating what's going on.
%!
% function to define a 400x400 box outline, origin at 0,0 (bottom left)
/box { 0 0 moveto 0 400 lineto 400 400 lineto 400 0 lineto closepath } def
box clip % pretend the box is our bounding box
clippath stroke % draw initial black bounding box
(Helvetica) findfont 50 scalefont setfont % setup a font
% draw box, and show some text # 100,100
box stroke
100 100 moveto (original) show
% try out some transforms
1 0 0 setrgbcolor % red
.5 .5 scale
box stroke
100 100 moveto (+scaled) show
0 1 0 setrgbcolor % green
300 100 translate
box stroke
100 100 moveto (+translated) show
0 0 1 setrgbcolor % blue
45 rotate
box stroke
100 100 moveto (+rotated) show
showpage
It may be possible to insert the calculated transformation into the gs commandline like this:
... | gs ... -c '1 2 scale 3 4 translate 5 6 rotate' -# ...
Thanks to JHNC, I think I have it licked now, and for the benefit of posterity, here's what worked. (Please upvote JHNC, not this answer.)
## code to determine original size, scaling factor, rotation goes above
my $device_width_points;
my $device_height_points;
my $orientation;
if ($rotation) {
$orientation = 3;
$device_width_points = $ytotal_png_pt;
$device_height_points = $xtotal_png_pt;
} else {
$orientation = 0;
$device_width_points = $xtotal_png_pt;
$device_height_points = $ytotal_png_pt;
}
my $orientation_string =
" -dAutoRotatePages=/None -c '<</Orientation " .
$orientation . ">> setpagedevice'";
## $ps = .ps file read into variable
## insert the PS "scale" command
$ps = $sf . " " . $sf . " scale\n" . $ps;
$gsopt1 = " -r300 -dGraphicsAlphaBits=4 -dTextAlphaBits=4";
$gsopt1 = $gsopt1 . " -dDEVICEWIDTHPOINTS=$device_width_points";
$gsopt1 = $gsopt1 . " -dDEVICEHEIGHTPOINTS=$device_height_points";
$gsopt1 = $gsopt1 . " -sOutputFile=" . $outfile;
$gsopt1 = $gsopt1 . $orientation_string;
$gscmd = "gs -q -sDEVICE=pnggray -dNOPAUSE -dBATCH " . $gsopt1 . " - ";
system("echo \"$ps\" \| $gscmd");
One of the problems I had was that some options apparently don't play well together -- for example, I tried using the -g option to set the output size in pixels, but in that case the rotation didn't work. Using the DEVICE...POINTS commands instead did work.

PdfReaderContentParser.ProcessContent returns whitespace for clear text

I'd like to parse a pdf for texts containing both, binary and clear text data. When I try to do it with PdfReaderContentParser the GetResultantText method returns the right texts for the binary content but whitespaces for the clear text content. Here is the code I use:
byte[] binaryPdf = File.ReadAllBytes(this.fileName);
reader = new PdfReader(binaryPdf);
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
for (int i = 1; i <= reader.NumberOfPages; i++)
{
SimpleTextExtractionStrategy simpleStragety = parser.ProcessContent(i, new SimpleTextExtractionStrategy());
string contentText = simpleStragety.GetResultantText();
// Do something with the contentText
// ...
}
Any idea how to get all content?
Overview
In a comment the OP clarified which texts he was missing in his extracted text:
Basically for all descriptions on the left-hand side (e.g. Lifting moment) I get whitespaces instead of the actual text.
The reason for this is fairly simple: In the page content there are only spaces (if anything at all) on most of the left side. The labels you see actually are read-only form fields.
For example the "Lifting moment" is the value of the form field 13B141032.
If you want text extraction to include these fields, too, you should consider flattening the document in a first step (moving the field appearances into the regular page content stream) and extracting text from this flattened document.
Document analysis
It looks like the major part of the internationalization of the specification labels has been done using form fields.
For an overview I separated the original document
into its regular page content
and the form fields
There indeed are several strings of spaces in the page content under the form fields.
I would assume that there once was an earlier version of that document (or a template for it) which contained those labels (maybe in only one language or probably two) as page content.
Then there was a task of more dynamic internationalization, so someone replaced the existing labels in the page content by spaces and added new internationalized labels as read-only form-fields, probably because form fields are easier to manipulate.
Considering that the original labels seem to have been replaced by an equal number of spaces, though, one might speculate that there even is another program manipulating the page stream of this and similar documents at hard coded offsets, and to not break this program in the course of internationalization the actual labels had to be created outside the page content. Stranger things have happened...
Flatten and extract
As mentioned above, if you want text extraction to include these fields, too, you should consider flattening the document in a first step (moving the field appearances into the regular page content stream) and extracting text from this flattened document. This can be done like this:
[Test]
public void ExtractFlattenedTextTestSeeb()
{
FileInfo file = new FileInfo(#"PATH_TO_FILE\41851208.pdf");
Console.Out.Write("41851208.pdf, flattened before extraction\n\n");
using (MemoryStream memStream = new MemoryStream())
{
using (PdfReader readerOrig = new PdfReader(file.FullName))
using (PdfStamper stamper = new PdfStamper(readerOrig, memStream))
{
stamper.Writer.CloseStream = false;
stamper.FormFlattening = true;
}
memStream.Position = 0;
using (PdfReader readerFlat = new PdfReader(memStream))
{
PdfReaderContentParser parser = new PdfReaderContentParser(readerFlat);
for (int i = 1; i <= readerFlat.NumberOfPages; i++)
{
SimpleTextExtractionStrategy simpleStragety = parser.ProcessContent(i, new SimpleTextExtractionStrategy());
string contentText = simpleStragety.GetResultantText();
Console.Write("Page {0}:\n\n{1}\n\n", i, contentText);
}
}
}
}
The result StandardOutput:
41851208.pdf, flattened before extraction
Page 1:
90–120 l/min
(23.8–31.7 US gal./min)
60 kg
(132 lbs)
115 kg
(254 lbs)
350 l
(92.5 US gal.)
100 kg 105 kg
(220 lbs) (231 kg)
100 kg
(220 lbs)
250 l 300 l
(66.0 US gal.) (79.3 US gal.)
90 kg
(198 lbs)
180 l
(47.6 US gal.)
5305kg
(11695 lbs)
5265kg
(11607 lbs)
5395kg
(11894 lbs)
5205kg
(11475 lbs)
5010kg
(11045 lbs)
4780kg
(10538 lbs)
4470kg
(9854 lbs)
4190kg
(9237 lbs)
3930kg
(8664 lbs)
5215kg
(11497 lbs)
5045kg
(11122 lbs)
4860kg
(10714 lbs)
4650kg
(10251 lbs)
4350kg
(9590 lbs)
4100kg
(9039 lbs)
3850kg
(8488 lbs)
25.2 m
(82’ 8")
23.2 m
(76’ 1")
21.0 m
(68’ 11")
18.7 m
(61’ 4")
16.4 m
(53’ 10")
14.1 m
(46’ 3")
11.8 m
(38’ 9")
9.7 m
(31’ 10")
7.7 m
(25’ 3")
36.5 MPa (365 bar)
(5293 psi)
endlos
endless
sans finite
25.2 m
31.2 m
(82’ 8")
(102’ 4")
21.0 m
(68’ 11")
14900kg
(32848 lbs)
403.2 kNm (41.1 mt)
(297270 ft.lbs)
49.1 kNm (5.0 mt)
PK 42002–SH A–G
(36210 ft.lbs)
37.3 kNm (3.8 mt)
PK 42002–SH A–C
(27510 ft.lbs)
1GETR 2GETR
PK 42002–SH A – C
KT250 KT300 KT350 KT180
2GETR STZY
+V1
+V2
+2/4
7(F) 8(G) 6(E) 5(D) 4(C) 3(B) 2(A)
+V1
+V2
(S410–SK–D)
DTS410SHC/03
0100
11/2010
PK 42002–SH
Type Model Modell
Page Page Seite
Chapitre Chapter Kapitel
Edition Edition Ausgabe
Öltank
Mehrgewicht:
Alle Gewichtsangaben ohne Aufbauzubehör,Zusatzgeräte und Öl.
Hydr. Ausschübe:
Max. Reichweite + Fly-Jib:
Max. Reichweite:
Fördermenge der Pumpe:
Betriebsdruck:
Schwenkmoment:
Schwenkbereich:
Max. Reichweite:
Max. hydraulische Reichweite:
Max. Hubkraft:
Max. Hubmoment:
Gewicht +V ohne 2/4
Krangewicht (R3X,STZS):
Technische Daten
Konstruktionsänderungen vorbehalten, fertigungstechn. Toleranzen müssen berücksichtigt werden.
Oil tank
Excess weight:
All weights given without assembly accessory,additional devices and oil.
Hydr. boom extensions:
Max. outreach + Fly-Jib:
Max. outreach:
Pump capacity:
Operating pressure:
Slewing torque:
Slewing angle:
Max. outreach:
Max. hydraulic outreach:
Max. lifting capacity:
Lifting moment:
Weight +V without 2/4
Crane weight (R3X,STZS):
Specifications
Subject to change, production tolerances have to be taken into account.
Réservoir
Excessif poids:
Tous les poids sans huile ni accessoire de montage ni appareils accessoires
Extensions hydrauliques:
Portee maximale + Fly-Jib:
Max. portee:
Debit de pompe:
Pression d' utilisation:
Couple de rotation:
Angle de rotation:
Max. portee:
Portee hydraulique maximale:
Capacite maxi de levage:
Couple de levage:
Poids +V sans 2/4
Poids grue (R3X,STZS):
Données Techniques
Sous reserve de modifications de conception. Les tolerances relatives a la technique de production doivent etre prises en consideration.
As you see, "Lifting moment" and all the other missing labels are there now.

String Concatenating functions in Progress 4GL?

I came across a function in C#, string.Join() which is really helpful for string concatenation.
I am wondering is there any possibility of doing the same functionality in Progress 4GL ?
Typical C# example would be,
String result = “ ”;
result = string.Join(",", this.grpBox1.Controls.OfType<CheckBox>()
.Where(x => x.Checked)
.Select(c => c.Text));
MessageBox.Show(result);
I am not trying to convert C# to Progress but it would be really helpful if i could achieve the same functionality in Progress.
if you do really want your function you could wrap it and declare it as external you can re-link _progres to include your own c libs. used to be called HLC (probuild) but now its a set of scripts under a new directory name oebuild directly under the Progress install directory(DLC). The hlc and make directories are under the oebuild directory.
Instructions on the build process can be found in the README file located in the oebuild directory under the DLC directory. Prob. a sledge hammer to crack a nut you would have to understand what your doing not for the faint of heart. but if you have something written in c you want to call you can do it. prob. best to stick to the 4gl nearest thing progress has to arrays is extent not used much most people break out to a temp table . rows in a tt are far easier to handle and iterate so its a "mind set" switch a bit.
Important comments can also be found in the hlprodsp.c file located in the hlc directory, a subdirectory of oebuild.
As far as I know, there's nothing built in to that effort. But if I understand correctly, when you issue that command you get a list of that given object type (in your example, checkbox) as a CSV.
I built something that resembles it, as a start to whatever you'd like to implement. It's probably far from perfect, but it works for me. It's a window with various widget types, you select from the combo the type you'd like to search and generate, and it will show you at the end the values of two CSV variables: one with the widget names that match that type, and one with the respective values.
Here it goes:
&Scoped-define WINDOW-NAME C-Win
/*------------------------------------------------------------------------
File:
Description:
Input Parameters:
<none>
Output Parameters:
<none>
Author:
Created:
------------------------------------------------------------------------*/
/* This .W file was created with the Progress AppBuilder. */
/*----------------------------------------------------------------------*/
/* Create an unnamed pool to store all the widgets created
by this procedure. This is a good default which assures
that this procedure's triggers and internal procedures
will execute in this procedure's storage, and that proper
cleanup will occur on deletion of the procedure. */
CREATE WIDGET-POOL.
/* *************************** Definitions ************************** */
/* Parameters Definitions --- */
/* Local Variable Definitions --- */
DEFINE VARIABLE cWidgetLst AS CHARACTER NO-UNDO.
DEFINE VARIABLE cValueLst AS CHARACTER NO-UNDO.
/* ******************** Preprocessor Definitions ******************** */
&Scoped-define PROCEDURE-TYPE Window
&Scoped-define DB-AWARE no
/* Name of designated FRAME-NAME and/or first browse and/or first query */
&Scoped-define FRAME-NAME DEFAULT-FRAME
/* Standard List Definitions */
&Scoped-Define ENABLED-OBJECTS COMBO-BOX-1 BUTTON-1 SLIDER-1 SELECT-1 ~
RADIO-SET-1 TOGGLE-1 FILL-IN-2 COMBO-BOX-3
&Scoped-Define DISPLAYED-OBJECTS COMBO-BOX-1 SLIDER-1 SELECT-1 RADIO-SET-1 ~
TOGGLE-1 FILL-IN-2 COMBO-BOX-3
/* Custom List Definitions */
/* List-1,List-2,List-3,List-4,List-5,List-6 */
/* *********************** Control Definitions ********************** */
/* Define the widget handle for the window */
DEFINE VAR C-Win AS WIDGET-HANDLE NO-UNDO.
/* Definitions of the field level widgets */
DEFINE BUTTON BUTTON-1
LABEL "Generate"
SIZE 15 BY 1.14.
DEFINE VARIABLE COMBO-BOX-1 AS CHARACTER FORMAT "X(256)":U
VIEW-AS COMBO-BOX INNER-LINES 5
LIST-ITEMS "Fill-in","Radio-set","Toggle-box","Selection-List","slider","combo-box"
DROP-DOWN-LIST
SIZE 16 BY 1 NO-UNDO.
DEFINE VARIABLE COMBO-BOX-3 AS CHARACTER FORMAT "X(256)":U
LABEL "Combo 3"
VIEW-AS COMBO-BOX INNER-LINES 5
LIST-ITEMS "Large","Tall","Venti"
DROP-DOWN-LIST
SIZE 16 BY 1 NO-UNDO.
DEFINE VARIABLE FILL-IN-2 AS CHARACTER FORMAT "X(256)":U
LABEL "Fill 2"
VIEW-AS FILL-IN
SIZE 14 BY 1 NO-UNDO.
DEFINE VARIABLE RADIO-SET-1 AS INTEGER
VIEW-AS RADIO-SET VERTICAL
RADIO-BUTTONS
"Item 1", 1,
"Item 2", 2,
"Item 3", 3
SIZE 12 BY 3 NO-UNDO.
DEFINE VARIABLE SELECT-1 AS CHARACTER
VIEW-AS SELECTION-LIST SINGLE SCROLLBAR-VERTICAL
LIST-ITEMS "First","Second","Third"
SIZE 23 BY 2 NO-UNDO.
DEFINE VARIABLE SLIDER-1 AS INTEGER INITIAL 0
VIEW-AS SLIDER MIN-VALUE 0 MAX-VALUE 100 HORIZONTAL
TIC-MARKS NONE
SIZE 31 BY 2.38 NO-UNDO.
DEFINE VARIABLE TOGGLE-1 AS LOGICAL INITIAL no
LABEL "Toggle 1"
VIEW-AS TOGGLE-BOX
SIZE 13.4 BY .81 NO-UNDO.
DEFINE VARIABLE COMBO-BOX-2 AS CHARACTER FORMAT "X(256)":U
LABEL "Combo 2"
VIEW-AS COMBO-BOX INNER-LINES 5
LIST-ITEMS "Item 1"
DROP-DOWN-LIST
SIZE 16 BY 1 NO-UNDO.
DEFINE VARIABLE FILL-IN-3 AS CHARACTER FORMAT "X(256)":U
LABEL "Fill 3"
VIEW-AS FILL-IN
SIZE 14 BY 1 NO-UNDO.
DEFINE VARIABLE RADIO-SET-2 AS INTEGER
VIEW-AS RADIO-SET VERTICAL
RADIO-BUTTONS
"Item 1", 1,
"Item 2", 2,
"Item 3", 3
SIZE 12 BY 3 NO-UNDO.
DEFINE VARIABLE SLIDER-2 AS INTEGER INITIAL 0
VIEW-AS SLIDER MIN-VALUE 0 MAX-VALUE 100 HORIZONTAL
TIC-MARKS NONE
SIZE 17 BY 2.14 NO-UNDO.
DEFINE VARIABLE TOGGLE-2 AS LOGICAL INITIAL no
LABEL "Toggle 2"
VIEW-AS TOGGLE-BOX
SIZE 13.4 BY .81 NO-UNDO.
/* ************************ Frame Definitions *********************** */
DEFINE FRAME DEFAULT-FRAME
COMBO-BOX-1 AT ROW 1.95 COL 13 COLON-ALIGNED NO-LABEL WIDGET-ID 14
BUTTON-1 AT ROW 1.95 COL 32 WIDGET-ID 2
SLIDER-1 AT ROW 3.62 COL 42 NO-LABEL WIDGET-ID 18
SELECT-1 AT ROW 3.86 COL 10 NO-LABEL WIDGET-ID 16
RADIO-SET-1 AT ROW 6.24 COL 10 NO-LABEL WIDGET-ID 6
TOGGLE-1 AT ROW 6.24 COL 30 WIDGET-ID 10
FILL-IN-2 AT ROW 7.19 COL 28 COLON-ALIGNED WIDGET-ID 12
COMBO-BOX-3 AT ROW 7.29 COL 56 COLON-ALIGNED WIDGET-ID 20
WITH 1 DOWN NO-BOX KEEP-TAB-ORDER OVERLAY
SIDE-LABELS NO-UNDERLINE THREE-D
AT COL 1 ROW 1
SIZE 80 BY 16 WIDGET-ID 100.
DEFINE FRAME FRAME-A
TOGGLE-2 AT ROW 1.24 COL 51 WIDGET-ID 6
RADIO-SET-2 AT ROW 1.48 COL 3 NO-LABEL WIDGET-ID 2
FILL-IN-3 AT ROW 1.95 COL 25 COLON-ALIGNED WIDGET-ID 8
SLIDER-2 AT ROW 3.14 COL 46 NO-LABEL WIDGET-ID 12
COMBO-BOX-2 AT ROW 3.38 COL 24 COLON-ALIGNED WIDGET-ID 10
WITH 1 DOWN KEEP-TAB-ORDER OVERLAY
SIDE-LABELS NO-UNDERLINE THREE-D
AT COL 5 ROW 10.29
SIZE 72 BY 5.71
TITLE "Frame A" WIDGET-ID 200.
/* *********************** Procedure Settings ************************ */
/* Settings for THIS-PROCEDURE
Type: Window
Allow: Basic,Browse,DB-Fields,Window,Query
Other Settings: COMPILE
*/
/* ************************* Create Window ************************** */
IF SESSION:DISPLAY-TYPE = "GUI":U THEN
CREATE WINDOW C-Win ASSIGN
HIDDEN = YES
TITLE = "<insert window title>"
HEIGHT = 16
WIDTH = 80
MAX-HEIGHT = 16
MAX-WIDTH = 80
VIRTUAL-HEIGHT = 16
VIRTUAL-WIDTH = 80
RESIZE = yes
SCROLL-BARS = no
STATUS-AREA = no
BGCOLOR = ?
FGCOLOR = ?
KEEP-FRAME-Z-ORDER = yes
THREE-D = yes
MESSAGE-AREA = no
SENSITIVE = yes.
ELSE {&WINDOW-NAME} = CURRENT-WINDOW.
/* END WINDOW DEFINITION */
/* *********** Runtime Attributes and AppBuilder Settings *********** */
/* SETTINGS FOR WINDOW C-Win
VISIBLE,,RUN-PERSISTENT */
/* REPARENT FRAME */
ASSIGN FRAME FRAME-A:FRAME = FRAME DEFAULT-FRAME:HANDLE.
/* SETTINGS FOR FRAME DEFAULT-FRAME
FRAME-NAME */
DEFINE VARIABLE XXTABVALXX AS LOGICAL NO-UNDO.
ASSIGN XXTABVALXX = FRAME FRAME-A:MOVE-AFTER-TAB-ITEM (COMBO-BOX-3:HANDLE IN FRAME DEFAULT-FRAME)
/* END-ASSIGN-TABS */.
/* SETTINGS FOR FRAME FRAME-A
*/
IF SESSION:DISPLAY-TYPE = "GUI":U AND VALID-HANDLE(C-Win)
THEN C-Win:HIDDEN = no.
/* ************************ Control Triggers ************************ */
&Scoped-define SELF-NAME C-Win
ON END-ERROR OF C-Win /* <insert window title> */
OR ENDKEY OF {&WINDOW-NAME} ANYWHERE DO:
/* This case occurs when the user presses the "Esc" key.
In a persistently run window, just ignore this. If we did not, the
application would exit. */
IF THIS-PROCEDURE:PERSISTENT THEN RETURN NO-APPLY.
END.
ON WINDOW-CLOSE OF C-Win /* <insert window title> */
DO:
/* This event will close the window and terminate the procedure. */
APPLY "CLOSE":U TO THIS-PROCEDURE.
RETURN NO-APPLY.
END.
&Scoped-define SELF-NAME BUTTON-1
ON CHOOSE OF BUTTON-1 IN FRAME DEFAULT-FRAME /* Generate */
DO:
assign cWidgetLst = ''
cValueLst = ''.
run downTheRabbitHole ( input {&window-name}:handle).
MESSAGE cWidgetLst SKIP cValueLst
VIEW-AS ALERT-BOX INFO BUTTONS OK.
END.
&UNDEFINE SELF-NAME
/* *************************** Main Block *************************** */
/* Set CURRENT-WINDOW: this will parent dialog-boxes and frames. */
ASSIGN CURRENT-WINDOW = {&WINDOW-NAME}
THIS-PROCEDURE:CURRENT-WINDOW = {&WINDOW-NAME}.
/* The CLOSE event can be used from inside or outside the procedure to */
/* terminate it. */
ON CLOSE OF THIS-PROCEDURE
RUN disable_UI.
/* Best default for GUI applications is... */
PAUSE 0 BEFORE-HIDE.
/* Now enable the interface and wait for the exit condition. */
/* (NOTE: handle ERROR and END-KEY so cleanup code will always fire. */
MAIN-BLOCK:
DO ON ERROR UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK
ON END-KEY UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK:
RUN enable_UI.
IF NOT THIS-PROCEDURE:PERSISTENT THEN
WAIT-FOR CLOSE OF THIS-PROCEDURE.
END.
/* ********************** Internal Procedures *********************** */
PROCEDURE buildCSV :
/*------------------------------------------------------------------------------
Purpose:
Parameters: <none>
Notes:
------------------------------------------------------------------------------*/
DEFINE INPUT-OUTPUT PARAMETER iopcList AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER ipcValue AS CHARACTER NO-UNDO.
if ipcValue = ? then
assign ipcValue = '?'.
if ipcValue = '' then
assign ipcValue = ' '.
assign iopcList = iopcList + (if iopcList = '' then '' else ',') + ipcValue.
END PROCEDURE.
PROCEDURE disable_UI :
/*------------------------------------------------------------------------------
Purpose: DISABLE the User Interface
Parameters: <none>
Notes: Here we clean-up the user-interface by deleting
dynamic widgets we have created and/or hide
frames. This procedure is usually called when
we are ready to "clean-up" after running.
------------------------------------------------------------------------------*/
/* Delete the WINDOW we created */
IF SESSION:DISPLAY-TYPE = "GUI":U AND VALID-HANDLE(C-Win)
THEN DELETE WIDGET C-Win.
IF THIS-PROCEDURE:PERSISTENT THEN DELETE PROCEDURE THIS-PROCEDURE.
END PROCEDURE.
PROCEDURE downTheRabbitHole :
/*------------------------------------------------------------------------------
Purpose:
Parameters: <none>
Notes:
------------------------------------------------------------------------------*/
DEFINE INPUT PARAMETER iphWidget AS HANDLE NO-UNDO.
DEFINE VARIABLE hHandle AS HANDLE NO-UNDO.
assign hHandle = iphWidget:first-child.
do while valid-handle(hHandle):
if can-query(hHandle,"type") and hHandle:type = combo-box-1:screen-value in frame {&frame-name} then do:
/* something something something dark side... */
if can-query(hHandle,"name") then run buildCSV(input-output cWidgetLst,hHandle:name).
if can-query(hHandle,"screen-value") then run buildCSV(input-output cValueLst,hHandle:screen-value).
end.
if hHandle:type = "FIELD-GROUP" or hHandle:type = "FRAME" then
run downTheRabbitHole(input hHandle:first-child).
assign hHandle = hHandle:next-sibling.
end.
END PROCEDURE.
PROCEDURE enable_UI :
/*------------------------------------------------------------------------------
Purpose: ENABLE the User Interface
Parameters: <none>
Notes: Here we display/view/enable the widgets in the
user-interface. In addition, OPEN all queries
associated with each FRAME and BROWSE.
These statements here are based on the "Other
Settings" section of the widget Property Sheets.
------------------------------------------------------------------------------*/
DISPLAY COMBO-BOX-1 SLIDER-1 SELECT-1 RADIO-SET-1 TOGGLE-1 FILL-IN-2
COMBO-BOX-3
WITH FRAME DEFAULT-FRAME IN WINDOW C-Win.
ENABLE COMBO-BOX-1 BUTTON-1 SLIDER-1 SELECT-1 RADIO-SET-1 TOGGLE-1 FILL-IN-2
COMBO-BOX-3
WITH FRAME DEFAULT-FRAME IN WINDOW C-Win.
{&OPEN-BROWSERS-IN-QUERY-DEFAULT-FRAME}
DISPLAY TOGGLE-2 RADIO-SET-2 FILL-IN-3 SLIDER-2 COMBO-BOX-2
WITH FRAME FRAME-A IN WINDOW C-Win.
ENABLE TOGGLE-2 RADIO-SET-2 FILL-IN-3 SLIDER-2 COMBO-BOX-2
WITH FRAME FRAME-A IN WINDOW C-Win.
{&OPEN-BROWSERS-IN-QUERY-FRAME-A}
VIEW C-Win.
END PROCEDURE.