在 Oracle APEX Interactive Report 中根据过滤器更新页面项

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

我最近开始在我的 Oracle APEX 应用程序中使用交互式报告。以前,应用程序中的所有页面都使用经典报表。我的新页面中的交互式报告效果很好,但是现在,我想在同一页面上的交互式报告上方添加一个摘要 box/table,以显示交互式报告中某些列的总和值。换句话说,如果我的交互式报表显示 3 个不同的经理姓名、2 个不同的办公地点和 5 个不同的员工,我的摘要框将包含一行和三列,数字分别为 3、2 和 5。

到目前为止,我已经通过将摘要框创建为经典报表来完成这项工作,该报表计算我的交互式报表所从中提取的同一 table 中每一列的不同值。当我尝试过滤交互式报告时出现问题。显然,经典报告不会根据交互式报告过滤器进行刷新,但我不知道如何 link 这两者,以便经典报告响应交互式报告中的过滤器。根据我的研究,有一些方法可以使用 javascript/jquery 来引用交互式报表搜索框中的值。如果可能,我想使用 javascript 或 jquery 引用交互式 table 过滤器的值,以便在每次应用新过滤器时刷新摘要框。有人知道怎么做吗?

不要对过滤器进行 javascript 解析。这是一个坏主意 - 想想你将如何实现它?有大量的编码工作要做,还有很多 ajax。随着 apex 5 的临近,当 API 和标记即将发生巨大变化时,它会把你留在哪里?


也不要只是屈服于要求。首先确定它在技术上的可行性。如果不是,请确保您非常清楚这对时间消耗的影响。拥有这些不同的价值计数的真正价值是什么?也许还有另一种方法可以实现他们想要的?也许这只不过是一种尝试性的解决方案,而不是真正问题的核心。需要考虑的事情...


话虽如此,这里有 2 个选项:

第一种方法:计算交互式报表上的不同聚合数

您可以通过“操作”按钮将这些添加到 IR。

不过请注意,这个聚合将是最后一行!在我在这里发布的示例中,将每页的行数减少到 5 会将聚合行推到分页集 3!


第二种方法:APEX_IR和DBMS_SQL

您可以使用 apex_ir API 检索 IR 的查询,然后使用它来进行计数。
(Apex 4.2) APEX_IR.GET_REPORT
(Apex 5.0) APEX_IR.GET_REPORT

一些建议: 通过查询 apex_application_page_regions

检索区域 ID

确保您的源查询包含#...#替换字符串。 (比如#OWNER#。)

然后获取报告SQL,重写并执行。例如:

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;

我将 apex_ir.get_report 和 dbms_sql 中的示例代码放在一起。
Oracle 11gR2 DBMS_SQL reference

但有一些严重的警告:列列表很棘手。如果用户可以控制所有列并且可以删除一些列,那么这些列将从 select 列表中消失。例如,在我的示例中,让用户隐藏 DEPTNO 列会导致整个代码崩溃,因为即使它会从内部查询中消失,我仍然会对该列进行计数。您可以通过不让用户控制它或首先解析语句等来阻止它...


祝你好运。