Dynamic COLUMN-LABEL values

Rio38

New Member
I am trying to use dynamic COLUMN-LABEL values. I have a report that displays values for the previous 6 months of the year. I would like to do this dynamically. I would like to figure out what month is to be displayed and use a variable in the COLUMN-LABEL tag instead of hard-coding the label. I have a function that will set a variable to the appropriate month name and I just wish to use that variable as the COLUMN-LABEL value.

I have tried to use COLUMN-LABEL value(variablename), but this did not work.

Any suggestions?

Thanks in advance.
 
I've never managed to do this.

What I've had to do as a work around for fairly dynamic reports is to use a large array of characters (for convenience, up to 50 fields in the report, but could be more), dynamically size them depending on the data they hold, then allocate a couple of header arrays to act as column-labels, then use PUT to get them out to the report.

It sounds messier than it is.
 

Rio38

New Member
I think someone here actually found a solution. Below is an example of possibly how to use dynamic COLUMN-LABELs:

Code:
define variable a as handle.
define variable b as character.
form
    b
with frame dd width 80 down.
        
assign a = b:handle in frame dd.
        
assign a:label = "Bob".
        
display b with frame dd.

The only problem we have run into is that handles do not allow you to use variables for subscripts so each subscript would have to hardcoded in the array.

I hope this helps others.
 
That won't handle Column-labels properly, though.
:label normally affects side-labels, although it will work if your column-labels are single line.

So, it will work for
def var myword as char column-label "My Word" no-undo.
But not for
def var myword as char column-label "My!Word" no-undo.

Try this code to capture and set Column-labels for variables in a frame.

What is nice about this is when you have set the temp-tables up, you can easily set column-labels using a simple call.

I haven't tested it for multiple fields, you can increase the extent of t_group.hfield to cope. I've checked it with an extent 20 variable and with 3 entries in the column-label. It looks as though you need an extent of 1 + CL*NV where CL is the number of lines in the header and NV is the number of variables in the frame.

Hope that helps.


/*
t_label holds the information on the variable and handles to various frames/groups/column-labels.

t_group holds information on the Field Group holding the column-label widgets.

f_next_field gets the next valid field in the Field Group.

p_get_label gets the column-labels (I have assumed 2 part labels, so it looks for 2 literals, if you want more then look for more literals, but first set the column-label to "1!2!3" or whatever.

p_field_group_widgets pulls the column-labels from the Field Group.

p_set_column_label sets the column-label for the character concerned.
*/


def temp-table t_label no-undo
field name as char
field hframe as widget-handle
field hfield as widget-handle
field hgroup as widget-handle extent 2
field hcoll as widget-handle extent 5
index idx1 name.
def temp-table t_group no-undo
field hgroup as widget-handle
field hfield as widget-handle extent 50
field counter as int initial 1
index idx1 hgroup.
def var c as char extent 2 no-undo.
def var c1 as char.
def var c2 as char.
def var this_loop as int no-undo.
form
c1 column-label "c!1"
c2 column-label "c!2"
with frame f1.
form
c column-label "c!1"
with frame f2.


function f_next_field returns widget-handle ():
def var return_value as widget-handle no-undo.
if available t_group then do:
t_group.counter = t_group.counter + 1.
if t_group.counter <= extent (t_group.hfield) then return_value = t_group.hfield[t_group.counter]:handle.
end.
return return_value.
end function.
display c1 c2 with frame f1.
display c with frame f2.

run p_get_label ("c1",c1:handle in frame f1).
run p_get_label ("c2",c2:handle in frame f1).

run p_get_label ("c[1]", c[1]:handle in frame f2).
run p_get_label ("c[2]", c[2]:handle in frame f2).

run p_set_column_label ("c1","New!Label").
run p_set_column_label ("c2","Another!Label").

do this_loop = 1 to 2:
run p_set_column_label ("c[" + string (this_loop) + "]","Label!" + string (this_loop)).
end.

display c1 c2 with frame f1.
display c with frame f2.

procedure p_get_label:
def input param inp_name as char no-undo.
def input param inp_handle as widget-handle no-undo.
find first t_label where t_label.name = inp_name no-lock no-error.
if not available t_label then do:
create t_label.
t_label.name = inp_name.
t_label.hfield = inp_handle.
end.
t_label.hgroup[1] = t_label.hfield:parent.
t_label.hframe = t_label.hgroup [1]:parent.
t_label.hgroup [2] = t_label.hframe:first-child.
t_label.hgroup [2] = t_label.hgroup [2]:next-sibling.
run p_field_group_widgets (t_label.hgroup[2]).
find t_group where t_group.hgroup = t_label.hgroup [2] no-lock no-error.
t_label.hcoll [1] = f_next_field() no-error.
t_label.hcoll [2] = f_next_field() no-error.
end procedure.
procedure p_set_column_label:
def input param inp_name as char no-undo.
def input param inp_label as char no-undo.
def var label_loop as int no-undo.
find t_label where t_label.name = inp_name no-lock no-error.
if not available t_label then return.
do label_loop = 1 to min(extent (t_label.hcoll), num-entries (inp_label,"!")):
if valid-handle (t_label.hcoll[label_loop]) then t_label.hcoll[label_loop]:screen-value = entry (label_loop,inp_label,"!").
end.
end procedure.
procedure p_field_group_widgets:
def input param inp_handle as widget-handle no-undo.
def var group_loop as int no-undo.

if not valid-handle (inp_handle) then return.
find t_group where t_group.hgroup = inp_handle no-lock no-error.
if available t_group then return.

create t_group.
t_group.hgroup = inp_handle.
group_loop = 1.
t_group.hfield [group_loop] = t_label.hgroup[2]:first-child.
do while valid-handle (t_group.hfield[group_loop]:next-sibling):
group_loop = group_loop + 1.
t_group.hfield [group_loop] = t_group.hfield[group_loop - 1]:next-sibling.
end.
end procedure.

 
Think objectively.
You were on the right way of thinking.
You require similar - apply to your needs.
DO WITH BROWSE {&BROWSE-NAME}:
ASSIGN
RequiredColumnLabelName:COLUMN-LABEL = "STRING HERE"
.
END.
You are assigning the column label attribute.
 
I think he was after a report rather than a browse.

The following method works in V8.3b and I can't see why it shouldn't work for V9 or OE10. I don't know if it works in V7, but V8 is ancient enough.

The trick with doing this in a report is to use the no-underline option on the frame. You then give the fields you want to display an extra column-label and set that column-label to contain the underline.

So, if you wanted the report to have two-line column-labels you would define the fields with column-label "1!2!3" and use the last line as your underline.

Then you can go through the frame and its field groups to get handles to each field and each literal value.

Next, you determine which of the literals contain the column-labels. The best way I found to do this is to examine the :row attribute of the literals, those on the last rows are the column-labels.

Then you work out how wide each field is, what the column-labels should be, what the underline string is and where the field should start in the report.

Finally, you go through the frame fields and assign the :col attribute to be the correct column for the fields and the column-labels and the :screen-value attributes for the column-labels including the underline.

What you can't do is to assign a :screen-value or change the :col attributes for the literal that contains the underline characters in a field-group otherwise Progress crashes, at least it did for me.

So, this will give you a report that has dynamic column-labels and also dynamic column widths, so you don't have to bother defining the frame and worrying about how wide a field has to be to catch the couple of unusually long values.

It also means you can abstract the frame and display fields. I use a 30-element array to hold my display information, which gives me a 30-column report, but there's no reason why you can't have a 300 column- report. It also means I can easily assign values to each column and can display the whole lot with a simple display command. It also makes it very easy to export to Excel or to create tab-delimited/CSV files generically rather than worrying about each individual field.

You have to be a bit careful when using the header phrase as the elements of the header phrase are either literal or expression types and there are things you can't do with expressions. But, if you play around with it you can get a nice report template that allows you to build formatted reports very quickly.
 

Ivor

New Member
I have this problem too.

I am writing a report that gives a breakdown of volume sales over the last 12 months, the months printing in columns across the report.

First, I extract the data into a work table to then report from which is defined as follows:

define work-table SV
field cust-num like symix.co.cust-num
field item like symix.item.item
field volume as integer extent 12.


After populating the table, I then report as follows:

for each SV break by SV.cust-num by SV.item :
if first-of(SV.cust-num) then display SV.cust-num with stream-io.
display SV.item
SV.volume
with stream-io width 200.
end.


I can name the month columns by specifying a label for each array element as follows:

for each SV break by SV.cust-num by SV.item :
if first-of(SV.cust-num) then display SV.cust-num with stream-io.
display SV.item
SV.volume[1] column-label "Jan"
SV.volume[2] column-label "Feb"
SV.volume[3] column-label "Mar"
SV.volume[4] column-label "Apr"
SV.volume[5] column-label "May"
SV.volume[6] column-label "Jun"
SV.volume[7] column-label "Jul"
SV.volume[8] column-label "Aug"
SV.volume[9] column-label "Sep"
SV.volume[10] column-label "Oct"
SV.volume[11] column-label "Nov"
SV.volume[12] column-label "Dec"
with stream-io width 200.
end.

But the problem is that the month should include year, eg:

Oct-07 Nov-07 Dec-07 Jan-08 Feb-08 etc

Hence I need dynamic column names for the array labels.

Anyone?
 
Hi, Ivor.

You should try this piece of code, is a little adaptation from the original that is available in the progress knowledge base with KB ID 21124

Title:
How To Dynamically Refer To Array Widget Elements

I had use your code as reference.

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD ~
getArrayElementHdl wWin
FUNCTION getArrayElementHdl RETURNS HANDLE
(phFrameHdl AS HANDLE,
pcObjName AS CHAR,
piElement AS INT /* parameter-definitions */ ) FORWARD.
/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

DEF VAR L-idx AS INTEGER.
DEF VAR L-hndl AS HANDLE.
DEF VAR L-month AS INT.
DEF VAR L-year AS INT.
DEF VAR L-cdate AS DATE EXTENT 12.
DEF VAR L-cmonth AS CHAR EXTENT 12
INITIAL ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ].
define work-table SV
field cust-num like symix.co.cust-num
field item like symix.item.item
field volume as integer extent 12.

FORM
SV.cust-num
SV.ITEM
volume[1]
volume[2]
volume[3]
volume[4]
volume[5]
volume[6]
volume[7]
volume[8]
volume[9]
volume[10]
volume[11]
volume[12]
WITH FRAME X DOWN WIDTH 154 STREAM-IO.

/* I add this to get last 12 months */
L-month = MONTH(TODAY).
L-year = YEAR(TODAY).
L-idx = 12.
L-cdate[L-idx] = DATE(L-month, 1, L-year).
L-idx = L-idx - 1.
DO L-month = MONTH(L-cdate[12]) - 1 TO 1 BY -1:
L-cdate[L-idx] = DATE(L-month, 1, L-year).
L-idx = L-idx - 1.
END. /* DO L-month = MONTH(L-cdate[12]) - 1 TO 1 BY -1: */
L-year = L-year - 1.
DO L-month = 12 TO 1 BY -1:
IF L-idx > 0 THEN
L-cdate[L-idx] = DATE(L-month, 1, L-year).
L-idx = L-idx - 1.
END. /* DO L-month = 12 TO 1 BY -1: */

/* this is the code

first you get a handle to the widgets in the frame, in this case frame X
*/

ASSIGN L-hndl = FRAME X:FIRST-CHILD
L-hndl = L-hndl:FIRST-CHILD.

/* using the function getArrayElementHdl you get the handle of each
element in the array
and assign the date as the label
*/
DO L-idx = 1 TO EXTENT(Volume):
L-month = MONTH(L-cdate[L-idx]).
L-year = YEAR(L-cdate[L-idx]).
ASSIGN L-hndl = getArrayElementHdl(L-hndl,"volume":U,L-idx).
IF VALID-HANDLE(L-hndl) THEN
ASSIGN L-hndl:LABEL = L-cmonth[L-month] + "-" + SUBSTRING(STRING(L-year, "9999"), 3, 2).
END. /* DO L-idx = 1 TO EXTENT(Volume): */

for each SV break by SV.cust-num by SV.item :
if first-of(SV.cust-num) then
display SV.cust-num with FRAME x.
display SV.ITEM volume with FRAME X.
end. /* for each SV break by SV.cust-num by SV.item : */

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION getArrayElementHdl wWin
FUNCTION getArrayElementHdl RETURNS HANDLE
(phFrameHdl AS HANDLE,
pcObjName AS CHAR,
piElement AS INT /* parameter-definitions */ ) :
/*-----------------------------------------------------------------
Purpose: get handle of each element in a array
Notes:
------------------------------------------------------------------*/
DO WHILE VALID-HANDLE(phFrameHdl):
IF phFrameHdl:NAME = pcObjName AND phFrameHdl:INDEX = piElement THEN
RETURN phFrameHdl.
ASSIGN phFrameHdl = phFrameHdl:NEXT-SIBLING.
END.
END FUNCTION.
/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME
 

Ivor

New Member
Hi plus_marca

I very much appreciate your quick reply and help, I am so pleased.

I am almost there now, the only issue I have is that only the last row from the work table is being displayed when using the FORM, it's something to do with down frames?

Here is before:

Customer Item volume[1] volume[2] volume[3] volume[4] volume[5] volume[6] volume[7] volume[8] volume[9] volume[10] volume[11] volume[12]
-------- ------------------------------ ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
ZVIS001 001163-01 1 0 0 0 0 0 0 0 0 0 0 0
001163-02 1 0 0 0 0 0 0 0 0 0 0 0
001213-08 0 0 1 0 0 0 0 0 0 0 0 0
001213-55 0 0 0 0 0 0 0 0 1 0 0 0
001213-75 0 0 0 0 0 0 0 0 0 1 0 0
001239-01 0 0 0 0 0 0 0 0 0 0 1 0
001305-01 0 0 0 0 1 0 0 0 10 0 0 0
001319-01 0 0 0 0 0 0 0 0 0 0 1 0
REPAIR 0 0 0 0 0 0 0 0 0 1 0 0


Here is after adding the dynamic column-label code:

Customer Item Feb-07 Mar-07 Apr-07 May-07 Jun-07 Jul-07 Aug-07 Sep-07 Oct-07 Nov-07 Dec-07 Jan-08
-------- ------------------------------ ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
ZVIS001 REPAIR 0 0 0 0 0 0 0 0 0 1 0 0
 

sphipp

Member
Yes, it sounds like a DOWN problem to me. Have you tried "DISPLAY WITH FRAME X DOWN. DOWN WITH FRAME X."? That's the syntax I use, it probably isn't the best but it always works.

You might have a problem with column widths as well.

If you are changing the :LABEL value as in plus_marca's code then Progress sizes up the columns according to the format when the frame is defined, I think, so doesn't take into account and changes in the label.

So, you could have labels that are too big or small.

You can't have labels across more than one row using this method, so it's emulating LABEL not COLUMN-LABEL. To do that you have to get into different field groups and it get's a bit messy.
 

Ivor

New Member
Yes, I've tried 60 down etc but it keeps outputting just the one line.

I commented out the output to filename statement so it goes to screen and it keeps overwriting the same line leaving just the last one there.

The DateS and DateE I will change when I get the output working correctly.

/* SalesVolByItem.p */
/* ================ */
/* */
/* Created: 2008/01/16 ******************************************* */
/* Modified: */
/* */

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION-FORWARD ~
getArrayElementHdl wWin
FUNCTION getArrayElementHdl RETURNS HANDLE
(phFrameHdl AS HANDLE,
pcObjName AS CHAR,
piElement AS INT /* parameter-definitions */ ) FORWARD.
/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME

DEF VAR L-idx AS INTEGER.
DEF VAR L-hndl AS HANDLE.
DEF VAR L-month AS INT.
DEF VAR L-year AS INT.
DEF VAR L-cdate AS DATE EXTENT 12.
DEF VAR L-cmonth AS CHAR EXTENT 12
INITIAL ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"].

define variable dateS as date.
define variable dateE as date.

define work-table SV
field cust-num like symix.co.cust-num
field item like symix.item.item
field volume as integer extent 12.

FORM
SV.cust-num
SV.ITEM
volume[1]
volume[2]
volume[3]
volume[4]
volume[5]
volume[6]
volume[7]
volume[8]
volume[9]
volume[10]
volume[11]
volume[12]
WITH FRAME X DOWN WIDTH 200 STREAM-IO.

dateS = 02/01/07.
dateE = 01/31/08.

/* I add this to get last 12 months */
L-month = MONTH(TODAY).
L-year = YEAR(TODAY).
L-idx = 12.
L-cdate[L-idx] = DATE(L-month, 1, L-year).
L-idx = L-idx - 1.
DO L-month = MONTH(L-cdate[12]) - 1 TO 1 BY -1:
L-cdate[L-idx] = DATE(L-month, 1, L-year).
L-idx = L-idx - 1.
END. /* DO L-month = MONTH(L-cdate[12]) - 1 TO 1 BY -1: */
L-year = L-year - 1.
DO L-month = 12 TO 1 BY -1:
IF L-idx > 0 THEN
L-cdate[L-idx] = DATE(L-month, 1, L-year).
L-idx = L-idx - 1.
END. /* DO L-month = 12 TO 1 BY -1: */

current-window:width=250.
/*output to SalesByVolumeByItem.txt paged.*/

for each symix.co-ship where ship-date >= dateS
and ship-date <= dateE
no-lock
by ship-date:
find first symix.coitem where coitem.co-num = co-ship.co-num
and coitem.co-line = co-ship.co-line
and coitem.co-release = co-ship.co-release
no-lock.
find first symix.co where co.co-num = coitem.co-num
no-lock.
find first symix.item where item.item = coitem.item no-lock.
find first SV where SV.cust-num = co.cust-num
and SV.item = coitem.item
no-lock no-error.
if available SV then SV.volume[month(co-ship.ship-date)] =
SV.volume[month(co-ship.ship-date)] + co-ship.qty-shipped.
else do:
create SV.
SV.cust-num = co.cust-num.
SV.item = coitem.item.
SV.volume[month(co-ship.ship-date)] = co-ship.qty-shipped.
end.
end.

/* this is the code for Dynamic column-labels

first you get a handle to the widgets in the frame, in this case frame X
*/

ASSIGN L-hndl = FRAME X:FIRST-CHILD
L-hndl = L-hndl:FIRST-CHILD.

/* using the function getArrayElementHdl you get the handle of each
element in the array and assign the date as the label
*/
DO L-idx = 1 TO EXTENT(Volume):
L-month = MONTH(L-cdate[L-idx]).
L-year = YEAR(L-cdate[L-idx]).
ASSIGN L-hndl = getArrayElementHdl(L-hndl,"volume":U,L-idx).
IF VALID-HANDLE(L-hndl) THEN
ASSIGN L-hndl:LABEL = L-cmonth[L-month] + "-" + SUBSTRING(STRING(L-year, "9999"), 3, 2).
END. /* DO L-idx = 1 TO EXTENT(Volume): */

for each SV break by SV.cust-num by SV.item :
if first-of(SV.cust-num) then display SV.cust-num with FRAME X.
display SV.ITEM volume with FRAME X.
end. /* for each SV break by SV.cust-num by SV.item : */

&ANALYZE-SUSPEND _UIB-CODE-BLOCK _FUNCTION getArrayElementHdl wWin
FUNCTION getArrayElementHdl RETURNS HANDLE
(phFrameHdl AS HANDLE,
pcObjName AS CHAR,
piElement AS INT /* parameter-definitions */ ) :
/*-----------------------------------------------------------------
Purpose: get handle of each element in a array
Notes:
------------------------------------------------------------------*/
DO WHILE VALID-HANDLE(phFrameHdl):
IF phFrameHdl:NAME = pcObjName AND phFrameHdl:INDEX = piElement THEN
RETURN phFrameHdl.
ASSIGN phFrameHdl = phFrameHdl:NEXT-SIBLING.
END.
END FUNCTION.
/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME
 

sphipp

Member
Try

FORM
SV.cust-num
SV.ITEM
volume[1]
volume[2]
volume[3]
volume[4]
volume[5]
volume[6]
volume[7]
volume[8]
volume[9]
volume[10]
volume[11]
volume[12]
WITH FRAME X WIDTH 200 STREAM-IO.



and
if first-of(SV.cust-num) then display SV.cust-num with FRAME X.
display SV.ITEM volume with FRAME X DOWN.
DOWN WITH FRAME X.

 

Ivor

New Member
sphipp, you are a genius!

It's working now, I guess it's the last statement that fixed it.

for each SV break by SV.cust-num by SV.item :
if first-of(SV.cust-num) then display SV.cust-num with FRAME X.
display SV.ITEM volume with FRAME X DOWN.
DOWN WITH FRAME X.
end. /* for each SV break by SV.cust-num by SV.item : */
 

William Wehner

New Member
Hi -

I have taken this code and used a version of it in a report I am generating. My only issue is the label gets set to 13 characters (even though I want Feb-08). I tried using COLUMN-LABEL, but I get the error message:
**COLUMN-LABEL is not a setable attribute for FILL-IN v-bill-tot[ 1]

Does anyone know a way to force the length of the dynamic label to be a set number of characters?

Thanks, Will
 
Hi, Will.

you can try using diferent settings for the field format and for the column-label attribute initial value

like this,

def var L-array as decimal format "999,999.99" extent 5.

form
L-array column-label " " /* insert here 6 empty spaces in place of the label text */
with frame x.

but always be sure the column-label initial value has at lease the same count of characters as your dinamic label, mostly for readability reasons.

Hope this helps.
 

sphipp

Member
You can only set the LABEL attribute of an frame item. This gives you a one-line label at the top of the column if you are not using SIDE-LABELS or n COL.

To change the COLUMN-LABEL of a frame item you have to go into another Frame Group and change things there.

So, if you have a frame A, the way Progress organises the widgets is roughly:
(1) Frame Widget corresponding to Frame A.
(2) Frame Group Widget containing the Fields/Variables in Frame A.
(3) Individual Widgets for items in Frame A.
(4) Frame Group Widget containing column-labels, calculated fields and
constants in Frame A.
(5) Individual Widgets for column-labels/calculated fields/constants etc
in Frame A.

So, if you had a variable mydisplay in frame A, you could do something like:

mydisplay:label in frame a = "My Label".

which corresponds to (3) above.

To get to the column-label you have to "Walk the Widget Tree" to use a piece of Progress jargon. It's also worth storing handles etc in a temp-table so that they are easy to access and change, rather than having to find the widgets over and over again.

So, the following code example finds the frame group corresponding to mydisplay, finds the frame group corresponding to the labels, walks the widget tree and populates a temp-table then changes the column-label and column-width of the label.

Some important points:

1. The frame uses NO-UNDERLINE - do not try and change the SCREEN-VALUE of the underline literal as Progress will roll over and die. Add an extra column-label in the frame definition and put the unerline there.

2. The example only covers one variable/field. If you want more then you have to check which literla coresponds to which variable. This is fairly easy and the best way is to compare the :col to ensure the columns match. The literals should be dealt with in row order to make things easier.

3. If you want to change the width of multiple items, you need to change the :col value as well. Don't forget that changing the :width-chars and :col of the original item does not change the literals, so you have to trawl through them and change all the :col and :width-chars as well. That's why a temp-table is the easiest way to do this.

Code:
def var mydisplay as char column-label "1!2!3" no-undo.
def var h_framea as widget-handle.
def var h_framea_group1 as widget-handle.
def var h_framea_group2 as widget-handle.
def var h_framea_labels as widget-handle.
def var this_handle as widget-handle no-undo.
def var new_width as int initial 20 no-undo.
 
def temp-table t_wtree
  field whandle as widget-handle
  field dhandle as char form "x(20)"
  field name as char form "x(20)"
  field type as char form "x(20)"
  field wrow as int
  field wcol as int
  field wvalue as char
  index idx1 name wrow wcol
  index idx2 whandle.
 
form mydisplay with frame a width 30 no-underline.
 
mydisplay = "12345678901234567890".
mydisplay:label in frame a = "My Label".
display mydisplay with frame a.
 
h_framea = frame a:handle.
h_framea_group1 = mydisplay:parent in frame a.
h_framea_group2 = h_framea_group1:next-sibling.
 
 
display
  mydisplay:col in frame a
  string (h_framea)
  string (h_framea_group1)
  string (h_framea_group2)
  with frame b.
this_handle = h_framea_group2:first-child.
 
 
repeat:
  if not valid-handle (this_handle) then leave.
  create t_wtree.
  t_wtree.whandle = this_handle.
  t_wtree.dhandle = string (this_handle).
  t_wtree.name = this_handle:name.
  t_wtree.type = this_handle:type.
  t_wtree.wvalue = this_handle:screen-value.
  t_wtree.wrow = this_handle:row.
  t_wtree.wcol = this_handle:col.
  this_handle = this_handle:next-sibling.
end.
 
 
for each t_wtree use-index idx1:
  display t_wtree except t_wtree.whandle.
end.
for each t_wtree where t_wtree.wcol = mydisplay:col in frame a:
  case t_wtree.wrow:
    when 1 then assign
      t_wtree.whandle:width-chars = new_width
      t_wtree.whandle:screen-value = "My".
    when 2 then assign
      t_wtree.whandle:width-chars = new_width
      t_wtree.whandle:screen-value = "Label".
    when 3 then assign
      t_wtree.whandle:width-chars = new_width
      t_wtree.whandle:screen-value = fill ("-",new_width).
  end case.
end.
 
 
mydisplay:width-chars in frame a = new_width.
mydisplay:format in frame a = "x(20)".
display mydisplay with frame a.

I use a version of this for standard reports and it means I never have to check the format or width of a field, I never need to check the column-labels and I can use the same routines to display as to export into CSV format.
 

William Wehner

New Member
Thanks for all your help. I found everyone responses useful.

I found a solution to this which is a bit of a hack... I have one .p call my other .p with all the labels:

test.drv:

RUN test.p "Jan" "Feb" "March".

test.p:

DISPLAY v-col-1 COLUMN-LABEL "{1}"
v-col-2 COLUMN-LABEL "{2}"
v-col-3 COLUMN-LABEL "{3}"
.

Now, test.drv can be modified to dynamically generated what the column headings should be.
 

4GLNewbie

Member
Sorry to ask you more about this..

If i cant make another file to use the latest solution suggested, how can i do ?

I tried the

WITH BROWSE [name]:
[something]:COLUMN-LABEL = "ahia"
END.

but progress tells me that it is not an accessible property of the widget..

Is there anyway to do this thing without a lot of code?

Thanks in advance.
 
Top