jobrien9
jobrien9

Reputation: 172

Updating Page Items with Respect to Filters in Oracle APEX Interactive Report

I've recently started using Interactive Reports in my Oracle APEX application. Previously, all pages in the application used Classic Reports. The Interactive Report in my new page works great, but, now, I'd like to add a summary box/table above the Interactive Report on the same page that displays the summed values of some of the columns in the Interactive Report. In other words, if my Interactive Report displays 3 distinct manager names, 2 distinct office locations, and 5 different employees, my summary box would contain one row and three columns with the numbers, 3, 2, and 5, respectively.

So far, I have made this work by creating the summary box as a Classic Report that counts distinct values for each column in the same table that my Interactive Report pulls from. The problem arises when I try to filter my interactive report. Obviously, the classic report doesn't refresh based on the interactive report filters, but I don't know how I could link the two so that the classic report responds to the filters from the interactive report. Based on my research, there are ways to reference the value in the Interactive Report's search box using javascript/jquery. If possible, I'd like to reference the value from the interactive table's filter with javascript or jquery in order to refresh the summary box each time a new filter is applied. Does anyone know how to do this?

Upvotes: 1

Views: 4102

Answers (1)

Tom
Tom

Reputation: 7028

Don't do javascript parsing on the filters. It's a bad idea - just think on how you would implement this? There's massive amounts of coding to be done and plenty of ajax. And with apex 5 literally around the corner, where does it leave you when the APIs and markup are about to change drastically?


Don't just give in to a requirement either. First make sure how feasible it is technically. And if it's not, make sure you make it abundantly clear what the implications are in regard of time consumption. What is the real value to be had by having these distinct value counts? Maybe there is another way to achieve what they want? Maybe this is nothing more than an attempted solution, and not the core of the real problem. Stuff to think about...


Having said that, here are 2 options:

First method: Count Distinct Aggregates on Interactive reports

interactive report with count distinct aggregates applied

You can add these to the IR through the Actions button. aggregate location under the actions button

aggregate definition

Note though, that this aggregate will be THE LAST ROW! In the example I've posted here, reducing the rows per page to 5 would push the aggregate row to the pagination set 3!


Second Method: APEX_IR and DBMS_SQL

You could use the apex_ir API to retrieve the IR's query and then use that to do a count.
(Apex 4.2) APEX_IR.GET_REPORT
(Apex 5.0) APEX_IR.GET_REPORT

Some pointers: Retrieve the region ID by querying apex_application_page_regions

Make sure your source query DOES NOT contain #...# substitution strings. (such as #OWNER#.)

Then get the report SQL, rewrite it, and execute it. Eg:

DECLARE
   l_report apex_ir.t_report;
   l_query varchar2(32767);

  l_statement varchar2(32000);
  l_cursor integer;
  l_rows number;
  l_deptno number;
  l_mgr number;
BEGIN 
    l_report := APEX_IR.GET_REPORT (
                    p_page_id => 30,
                    p_region_id => 63612660707108658284,
                    p_report_id => null);
    l_query := l_report.sql_query;
    sys.htp.prn('Statement = '||l_report.sql_query);
    for i in 1..l_report.binds.count
    loop
        sys.htp.prn(i||'. '||l_report.binds(i).name||' = '||l_report.binds(i).value);
    end loop;

    l_statement := 'select count (distinct deptno), count(distinct mgr) from ('||l_report.sql_query||')';

    sys.htp.prn('statement rewrite: '||l_statement);

 l_cursor := dbms_sql.open_cursor;
    dbms_sql.parse(l_cursor, l_statement, dbms_sql.native);

    for i in 1..l_report.binds.count
    loop
      dbms_sql.bind_variable(l_cursor, l_report.binds(i).name, l_report.binds(i).value);
    end loop;

    dbms_sql.define_column(l_cursor, 1, l_deptno);
    dbms_sql.define_column(l_cursor, 2, l_mgr);

    l_rows := dbms_sql.execute_and_fetch(l_cursor);

    dbms_sql.column_value(l_cursor, 1, l_deptno);
    dbms_sql.column_value(l_cursor, 2, l_mgr);

    dbms_sql.close_cursor(l_cursor);

    sys.htp.prn('Distinct deptno: '||l_deptno);
    sys.htp.prn('Distinct mgr: '||l_mgr);
  EXCEPTION WHEN OTHERS THEN
    IF DBMS_SQL.IS_OPEN(l_cursor) THEN
      DBMS_SQL.CLOSE_CURSOR(l_cursor);
    END IF;
    RAISE;
END;

I threw together the sample code from apex_ir.get_report and dbms_sql .
Oracle 11gR2 DBMS_SQL reference

Some serious caveats though: the column list is tricky. If a user has control of all columns and can remove some, those columns will disappear from the select list. Eg in my sample, letting the user hide the DEPTNO column would crash the entire code, because I'd still be doing a count of this column even though it will be gone from the inner query. You could block this by not letting the user control this, or by first parsing the statement etc...


Good luck.

Upvotes: 3

Related Questions