Page 1 of 2

COLOR codeblock

Posted: Tue Dec 25, 2018 2:19 pm
by Janko
I generate a browser using a for-next loop like in this code:

Code: Select all

 bColor:= {|| if(val(DC_GetColArray(2,oBrowse)) <val(DC_GetColArray([b]k[/b] ,oBrowse)) ,,{GRA_CLR_WHITE,GRA_CLR_DARKBLUE}  )}

for k:=3 to 14
DCBROWSECOL ELEMENT k   HEADER "Razlika v %" + aHead[k]  PARENT oBrowse  FOOTER str(k,2)   WIDTH 8  PRESENTATION  bPres ;
              EVAL { |o|o:colorBlock := bColor }  // COLOR Bcolor
 next k

Of course, this code is not working. Index 'k', which is used in color block definition (to compare the content of the cell with
DC_GetColArray(2,oBrowse) is not recognised as valid.

If each DCBROWSECOL is added line by line using hard numbers an not variable 'k', everything Works as expected.

I beleive you there is a simple solution, but I am loosing hours without succes.

Any hint is appreciated

Regards
JAnko

Re: COLOR codeblock

Posted: Wed Dec 26, 2018 1:28 am
by skiman
Hi,

This way it should work.

Code: Select all


for k:=3 to 14
bColor:= &("{|| if(val(DC_GetColArray(2,oBrowse)) <val(DC_GetColArray("+str(k,2)+" ,oBrowse)) ,,{GRA_CLR_WHITE,GRA_CLR_DARKBLUE}  )}")
DCBROWSECOL ELEMENT k   HEADER "Razlika v %" + aHead[k]  PARENT oBrowse  FOOTER str(k,2)   WIDTH 8  PRESENTATION  bPres ;
              EVAL { |o|o:colorBlock := bColor }  // COLOR Bcolor
 next k

Re: COLOR codeblock

Posted: Wed Dec 26, 2018 9:05 am
by rdonnay
Janko -

When creating code blocks in a FOR..NEXT loop that are bound to the value of k, you must "anchor" each value of k. Chris showed you that this anchoring can be done with a macro, however macro expressions require that all elements are public functions and public or private variables.

Anchoring using a Macro:

Code: Select all

bColor :=  &("{|| if(val(DC_GetColArray(2,oBrowse)) <val(DC_GetColArray("+str(k,2)+" ,oBrowse)) ,,{GRA_CLR_WHITE,GRA_CLR_DARKBLUE}  )}")
This macro technique would require that oBrowse must be a private or public variable. It cannot be local. It would also fail because the color definitions cannot be resolved by the macro compiler and converted to numeric values. Macro compiling in a loop is not advised.

A better technique is to anchor each value of k by using "detached locals". This is accomplished with a call to a function that will build the code block. All resolutions of variables, functions and defines will be accomplished by the XPP compiler rather than the macro compiler and will allow k and oBrowse to be declared as LOCAL.

Anchoring using detached locals:

Code: Select all

bColor := ColorAnchor(k,oBrowse)

STATIC FUNCTION ColorAnchor(k,oBrowse)

RETURN {|| if(val(DC_GetColArray(2,oBrowse)) <val(DC_GetColArray(k ,oBrowse)) ,,{GRA_CLR_WHITE,GRA_CLR_DARKBLUE}  )}
Also, you don't need to use the EVAL clause in your DCBROWSECOL command. Simply the COLOR bColor clause will work.

Macros have some advantages in Xbase++, but not in this case. They require that every element of the expression exist in the "symbol table". To be added to the symbol table, they must be private or public. They cannot be static or local. DC_GetColArray() is a public function, so that is not a problem. If you use the anchoring technique I advise, then any element of the expression can be static, local, public or private. Even function calls can be to static functions. This allows you to safely encapsulate your variables and functions. The XPP compiler can warn you if you make a coding error and will not allow the .EXE to be created. The macro is compiled at "runtime" and therefore coding errors are often discovered by the user of the program not the programmer. This is a bad idea.

Re: COLOR codeblock

Posted: Wed Dec 26, 2018 10:11 am
by Eugene Lutsenko
Roger and Clifford told me a long time ago how to do something like this. Everything works fine. Look for context: "Anchor" in the source test:" http://lc.kubagro.ru/__AIDOS-X.txt"

Re: COLOR codeblock

Posted: Sat Dec 29, 2018 9:43 am
by Janko
Dear Chris, Roger and Eugene,

it is obvious that handling macros is not so simple than I thought. I remember Chris helped me already one time.
Roger, special thanks for your simple and detailed explanation. I only write software for my bussines, I do not resell it and of course, time spent on understanding of some problems is not sufficient. Your forum is an excellent opportunity.

Eugene, thanks to you too.

Happy and healthy new year
JAnko

Re: COLOR codeblock

Posted: Sun Feb 03, 2019 8:42 am
by Janko
Dear Roger,

after many attempts trying to use 'anchor technique', I can't make it work as desired:

Code: Select all


 for k:=3 to 14
   bColor := ColorAnchor(k,oBrowse)
   DCBROWSECOL ELEMENT k   HEADER "Razlika v %" + aHead[k]  PARENT oBrowse  FOOTER str(k,2)   WIDTH 7  COLOR bColor

 next k

…….
STATIC FUNCTION ColorAnchor( k, oBrowse)
RETURN {|| if(val(DC_GetColArray(2,oBrowse)) < val(DC_GetColArray(k ,oBrowse)) , ,{GRA_CLR_WHITE,GRA_CLR_DARKBLUE}  )  }

or colors are not OK or runtime error is generated.

Could you be so kind to help me out?

BR JAnko

Re: COLOR codeblock

Posted: Sun Feb 03, 2019 10:32 am
by rdonnay
Try this:

RETURN {|| if(val(DC_GetColArray(2,oBrowse)) < val(DC_GetColArray(k ,oBrowse)) ,{nil,nil} ,{GRA_CLR_WHITE,GRA_CLR_DARKBLUE}

If that doesn't work, then give me a sample program that I can compile and run.

Re: COLOR codeblock

Posted: Tue Feb 05, 2019 4:44 am
by Janko
Roger,

no it is not working. I'll prepare a sample.

Kind regards
Janko

Re: COLOR codeblock

Posted: Tue Feb 05, 2019 10:28 am
by Janko
Roger,

attached is a zip file with prg and arr( array) with data which is retrived in the begining of the program.

I hope you do no need more to test.

Kind regards
JAnko

Re: COLOR codeblock

Posted: Tue Feb 05, 2019 11:58 am
by rdonnay
Your problem was that the oBrowse object was not created until after the Anchoring code block was created.

Change this: bColor := ColorAnchor(k,Browse)
to this: bColor := ColorAnchor(k,@oBrowse)

Here is another method:

bColor := ColorAnchor(k)

STATIC FUNCTION ColorAnchor(k)

RETURN {|a,oColumn,oBrowse|oBrowse := oColumn:parent, ;
if(val(DC_GetColArray(2,oBrowse)) ;
<=val(DC_GetColArray(k,oBrowse)) , ;
{nil,nil},{GRA_CLR_WHITE,GRA_CLR_DARKBLUE} )}