{"id":27,"date":"2010-03-04T20:20:58","date_gmt":"2010-03-05T01:20:58","guid":{"rendered":"http:\/\/anvil-of-time.com\/2010\/03\/04\/powerbuilder-smart-crosstab-datawindow\/"},"modified":"2021-03-08T18:36:14","modified_gmt":"2021-03-08T23:36:14","slug":"powerbuilder-smart-crosstab-datawindow","status":"publish","type":"post","link":"https:\/\/anvil-of-time.com\/powerbuilder\/powerbuilder-smart-crosstab-datawindow\/","title":{"rendered":"PowerBuilder &#8211; \u2018Smart\u2019 Crosstab Datawindow"},"content":{"rendered":"<p>I had a question from a co-worker regarding a functionality request from a user. Basically they wanted a datawindow to display information for vendors (basic stuff like name, amt 1, amt 2, amt 3, etc.) for a specific set of amount columns. Each line represents one vendor and the various amounts (if any) with a total for the line. Each column of the amounts would be totaled at the bottom. Classic &#8216;cross tab&#8217; type stuff.<\/p>\n<p>However, the users only wanted an amount column to display if it had a value in it, i.e., if no vendor had this amount, don&#8217;t put it on the datawindow. The other request was to have one specific column to not be totaled with the others for each vendor, i.e., the line total was the total of all the other amounts except a specified one. We have now left the &#8216;cross tab&#8217; universe.<\/p>\n<p>My Solution<\/p>\n<p>As a proof of concept I created a Grid Style, external datawindow with five specified columns. Column one is the vendor name; the other four are numeric (I called them box1 through box4). I then added a series of data values (vendor name and numbers). I made sure that one column of amounts was blank ( or had a value of zero).<br \/>\nTo handle the requirement of totaling all amounts except one specified, I created a computed field at the end of the others. The expression is:<\/p>\n<pre name=\"code\" class=\"VB\">if(isnull(box1[0]),0,box1[0]) + if(isnull(box2[0]),0,box2[0]) + if(isnull(box3[0]),0,box3[0])<\/pre>\n<p>In this case I want to exclude box4 from the total.<br \/>\nI also created a series of totals for each column (using the painter to generate the expression).<\/p>\n<p>The final step was to create the code which will dynamically hide any of the amount columns which have no values (or just zero amounts). The \u2018workhorse\u2019 of this code is the use of a describe to evaluate an expression on each row to determine if it has a value other than zero.<\/p>\n<p>Code from Open event of window<\/p>\n<pre name=\"code\" class=\"VB\">long        ll_i, ll_max, ll_x\nlong ll_basearraycount\nstring ls_basevisibles[], ls_basewidths[], ls_makevisible[]\nstring ls_colname, ls_coltype,  ls_msg\n\ndw_1.retrieve( )\n\ndw_1.setredraw( False)\n\n\/\/ get list of columns in the order they are displayed which may not be the same as their column number order\nll_max = Integer(dw_1.Object.DataWindow.Column.Count)  \/\/ determine number of columns\nFOR ll_i = 1 TO ll_max\n    \/\/ only need the visible columns\n    IF dw_1.describe(&quot;#&quot; + String(ll_i) + &quot;.Visible&quot;) = &#039;1&#039; THEN\n        ll_basearraycount ++\n        ls_basevisibles[ll_basearraycount] = dw_1.describe( &quot;#&quot; + string(ll_i) +  &quot;.Name&quot;)\n        ls_basewidths[ll_basearraycount] = dw_1.describe( &quot;#&quot; + string(ll_i) +  &quot;.Width&quot;)\n\n        ls_coltype = dw_1.describe( &quot;#&quot; + string(ll_i) +  &#039;.ColType&#039;)\n\n        If (UPPER(ls_coltype) = &#039;NUMBER&#039;) THEN\n            \/\/ this gives a sum which means the column has data in it, ie, we want it visible\n            ls_msg = dw_1.describe( &quot;evaluate ( &#039;sum(&quot; + &quot;#&quot; + string(ll_i) + &quot; for all)&#039; , 1)  &quot; )\n            IF Dec(ls_msg) &lt;&gt; 0 and not IsNull(Dec(ls_msg)) THEN\n                ls_makevisible[ll_basearraycount] = &#039;Y&#039;\n            END IF\n        ELSE\n            IF ls_basevisibles[ll_basearraycount] = &#039;vendor&#039; THEN \/\/ the first column is always visible\n                ls_makevisible[ll_basearraycount] = &#039;Y&#039;\n            END IF\n        END IF\n\n    END IF\nNEXT\n\n\/\/              Now make all columns invisible...\nFOR ll_i = 1 TO ll_max\n      dw_1.Modify(&quot;#&quot; + String(ll_i) + &quot;.Visible=&#039;0&#039;&quot;) \/\/ make it invisible\nNEXT\n\/\/ Now make the columns with values back visible\nll_max = UpperBound(ls_basevisibles)\nll_x = 10\nFOR ll_i = 1 TO ll_max\n    IF ls_makevisible[ll_i] = &#039;Y&#039; THEN\n        ls_msg = dw_1.Modify(ls_basevisibles[ll_i] + &quot;.Visible=&#039;1&#039;&quot;)          \/\/ make it visible\n        ls_msg = dw_1.Modify(ls_basevisibles[ll_i] + &quot;.X=&quot; + string(ll_x)) \/\/ set the X position (starts at 10)\n        ll_x +=Long(ls_basewidths[ll_i])   \/\/ keep track of running X position\n        ls_msg = dw_1.Modify(ls_basevisibles[ll_i] + &quot;.Width=&quot; + ls_basewidths[ll_i])     \/\/ set the column width\n    END IF\nNEXT\n\ndw_1.setRedraw(true)<\/pre>\n<p>Sample code files below including export of objects (need PowerBuilder 11.5\/12 or above to read pbl)<br \/>\n<a href=\"http:\/\/anvil-of-time.com\/wordpress\/wp-content\/uploads\/2010\/03\/SmartCrosstab.zip\">SmartCrosstab<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I had a question from a co-worker regarding a functionality request from a user. Basically they wanted a datawindow to display information for vendors (basic stuff like name, amt 1, amt 2, amt 3, etc.) for a specific set of amount columns. Each line represents one vendor and the various amounts (if any) with a&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3,10],"tags":[21,12,16],"_links":{"self":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/27"}],"collection":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/comments?post=27"}],"version-history":[{"count":10,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/27\/revisions"}],"predecessor-version":[{"id":1721,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/27\/revisions\/1721"}],"wp:attachment":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/media?parent=27"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/categories?post=27"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/tags?post=27"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}