返回顶部

OAF中输出PDF报表文件超链接

OAF中输出PDF报表文件超链接解决方案

解决思路

获取PDF文件的输出流

获取输出流之后将其转换为BLOB

将转化后的BLOB存储在附件表fnd_blobs中

构造该BLOB文件的URL

将URL存储在客户化表里形成一条唯一的记录,返回唯一ID FORM通过返回得唯一ID找到URL,调用方法,在浏览器打开URL

技术要点

  1. 使用TemplateHelper.processTemplate方法生成目标PDF的InputStream流
  2. 调用程序包将InputStream传入数据库中的BLOB字段中,并生成对应的记录
    . 获取到唯一记录的 file_id,使用API生成对应的 URL

实现过程

  1. 使用TemplateHelper.processTemplate方法生成目标PDF的InputStream流

    首先选择页面数据代码,点击多选框后,需要在触发事件中写入

    /**
    
    - 查询界面  选择需要输出的数据(多选),调用获取xmlClob的程序包
    - @param pageContext
    - @param webBean
      */
      public static void doPrint_req(OAPageContext pageContext, OAWebBean webBean,String poNumber) {
          OAApplicationModule am = 
              pageContext.getApplicationModule(webBean); //getRootApplicationModule();
          CUX90POOrderDateilsVOImpl vo = 
              (CUX90POOrderDateilsVOImpl)am.findViewObject("CUX90POOrderDateilsVO1");
          CUX90POOrderDateilsVORowImpl row = null;
          String str = "";
          String param = "";
          boolean flag3 = true;
          int i = 0;
          int j = 0;
          row = (CUX90POOrderDateilsVORowImpl)vo.first(); //定位记录指针到第一条 
          while (row != null) {
      //            String checkFlag = row.getCheckFlag();
              if (poNumber.equals(row.getDocumentNum())) {
                  j = j + 1;
              }
              if (vo.hasNext()) {
                  row = (CUX90POOrderDateilsVORowImpl)vo.next();
              } else {
                  break;
              }
          }
          if (j != 0) {
              Number[] params = new Number[j]; //iface_line_id
              row = (CUX90POOrderDateilsVORowImpl)vo.first(); //定位记录指针到第一条 
              while (row != null) {
                   if (poNumber.equals(row.getDocumentNum())) {
                      Number lineId = row.getLineId();
                      System.out.println("lineId:"+lineId);
                      params[i] = lineId;
                     // param = param + lineId + ",";
                      i = i + 1;
                  }
                  if (vo.hasNext()) {
                      row = (CUX90POOrderDateilsVORowImpl)vo.next();
                  } else {
                      break;
                  }
             }
             //获取XMLClob。
              getXMLClob_req(pageContext, webBean, params,poNumber);
          }
      }
    
    

    然后看一下获取选择数据的xmlClob的方法getXMLClob_req

        /**
         * (有多选框版本)调用AM执行PLSQL返回CLOB类型  
         * @param pageContext
         * @param webBean
         */
        public static void getXMLClob_req(OAPageContext pageContext, OAWebBean webBean, 
                                      Number[] params,String poNumber) {
            OAApplicationModule am = pageContext.getApplicationModule(webBean);
            Serializable[] methodParams = { params };
            Class[] methodParamTypes = { params.getClass() };
            CLOB tempClob = 
                (CLOB)am.invokeMethod("getXmlColb", methodParams, methodParamTypes);
            //在EBS中定义好之后报表需要输出的RTF模板,写入模板名称。
            String templateName = "CUXEBSPODOCUMENTRPT";
            //调用打印PDF的方法,将xml数据对象以及数据模板作为参数传入
            PrintPDF_req(pageContext, webBean, tempClob,templateName,poNumber); 
        }
    

    可以看一下AM中调用getXmlColb的方法,其中大概就是使用OAF调用获取xml数据的程序包,将参数传入,然后将XML数据返回,跟做xml报表并无区别,只是将xml作为CLOB数据返回,具体就不细看了。

    
        /**
         * 执行PLSQL  返回CLOB类型数据
         * @param params 数值类型参数,存放选择数据的LINE_ID
         * @return
         */
        public CLOB getXmlColb(Number[] params) {
            String result = null;
            String num = null;
            CLOB tempClob = null;
            OADBTransaction oadbtransaction = getOADBTransaction();
            OracleConnection oracleConnection = (OracleConnection)oadbtransaction.getJdbcConnection();
            if (params[0] != null)
            {
              ARRAY vdrArray = null;
              try
              {
                ArrayDescriptor tableOfNumber =
                  oracle.sql.ArrayDescriptor.createDescriptor("FND_TABLE_OF_NUMBER",
                                                              oracleConnection);
                vdrArray = new ARRAY(tableOfNumber, oracleConnection, params);
                String sql = "BEGIN cux_ebs_po_equipment_unitrpt.main(errbuf => :1, retcode=>:2, p_order_type=>:3, p_id_arr=>:4, x_out_xml=>:5);end;";
                OracleCallableStatement oraclecallablestatement =
                  (OracleCallableStatement)oadbtransaction.createCallableStatement(sql, 1);
               
                //PLSQL 输入参数
                 oraclecallablestatement.setString(3,"POORDER");
                oraclecallablestatement.setARRAY(4, vdrArray);
                //PACKAGE 输出参数
                oraclecallablestatement.registerOutParameter(1, OracleTypes.VARCHAR);
                oraclecallablestatement.registerOutParameter(2, OracleTypes.VARCHAR);
                oraclecallablestatement.registerOutParameter(5, OracleTypes.CLOB);
                //实行SQL
                oraclecallablestatement.execute();
                //获取值
                tempClob = oraclecallablestatement.getCLOB(5);
              } catch (Exception ex)
              {
                ex.printStackTrace();
              }
            }
            return tempClob;
        }
    

    接下来看一下调用PrintPDF_req打印PDF文件的方法。

        /**
         * 调用模板生成PDF文件
         * @param pageContext
         * @param webBean
         * @param xmlClob PLSQL返回的CLOB类型参数
         * @param templateName 系统中模板的名称
         * @param poNumber 订单编号
         */
        public static void PrintPDF_req(OAPageContext pageContext, OAWebBean webBean, 
                                    CLOB xmlClob, String templateName,String poNumber) {
    //        HttpServletResponse response = 
    //            (HttpServletResponse)pageContext.getRenderingContext().getServletResponse();
            OAApplicationModule am = pageContext.getApplicationModule(webBean);
            OADBTransaction oadbTransaction = am.getOADBTransaction();
            String fileName = "PurchaseOrder_"+poNumber+".pdf";
            try {
                Reader inputReader = xmlClob.getCharacterStream();
                //定义一个接收数据的输出流,将PDF的文件流输出。
                ByteArrayOutputStream pdfFile = new ByteArrayOutputStream();
                OADBTransactionImpl oaTrans = (OADBTransactionImpl)pageContext.getApplicationModule(webBean).getOADBTransaction();
    //            参数--应用缩写,模板名称 
                TemplateHelper.processTemplate(oaTrans.getAppsContext(), "CUX", 
                                               templateName, "zh", "CN", 
                                               inputReader, 
                                               TemplateHelper.OUTPUT_TYPE_PDF, 
                                               null, pdfFile);
                byte[] bytes = pdfFile.toByteArray();
                //定义一个输入流,将PDF文件流输入进去
                InputStream in= new ByteArrayInputStream(bytes);
                //调用程序包,将blob放进数据库。
                 OADBTransaction oadbtransaction = am.getOADBTransaction();
                 OracleConnection oracleConnection = (OracleConnection)oadbtransaction.getJdbcConnection();
                 String sql = "BEGIN apps.cux_ebs_po_oacreatepo_pkg.update_file(errbuf => :1, retcode=>:2,p_file_name=>:3,p_blob=>:4,x_file_id=>:5,p_po_number=>:6);end;";
                 OracleCallableStatement oraclecallablestatement =
                   (OracleCallableStatement)oadbtransaction.createCallableStatement(sql, 1);
                 //PLSQL 输入参数
                 oraclecallablestatement.setString(3, fileName);
                 oraclecallablestatement.setBlob(4,in);
                 oraclecallablestatement.setString(6,poNumber);
                 //PACKAGE 输出参数
                 oraclecallablestatement.registerOutParameter(1, OracleTypes.VARCHAR);
                 oraclecallablestatement.registerOutParameter(2, OracleTypes.VARCHAR);
                 oraclecallablestatement.registerOutParameter(5, OracleTypes.VARCHAR);
                 //执行SQL
                 oraclecallablestatement.execute();
                 String  resultError = oraclecallablestatement.getString(1);
                 System.out.println("resultError:"+resultError);
                 String  retcode = oraclecallablestatement.getString(2);
                 System.out.println("retcode:"+retcode);
                 String fileId=oraclecallablestatement.getString(5);
                 System.out.println("fileId:"+fileId);
            } catch (Exception e) {
    //            response.setContentType("text/html");
                throw new OAException(e.getMessage(), OAException.ERROR);
            }
        }    
    

    接下里看一下程序包中接收BLOB之后的处理

    /*==================================================
      Procedure Name :
          update_file
      Description:
          将获取到的PDF文件输入流插入fnd_lobs表中,生成一条唯一的记录,并使用API生成超链接更新进传OA的接口表中。
              
      Argument:
          errbuf          : concurrent return message buffer
          retcode         : concurrent return status code
                              0 success / 1 warning / 2 error
          x_file_id       :OAF调试中每次生成的file_id
          p_file_name     :文件名称
          p_blob          :接收到的文件BLOB
          p_po_number     :订单编号
      History: 
          1.00  2019-08-22 kaikai.zhang Creation
      ==================================================*/
      PROCEDURE update_file(errbuf      OUT VARCHAR2
                           ,retcode     OUT VARCHAR2
                           ,x_file_id   OUT VARCHAR2
                           ,p_file_name IN VARCHAR2
                           ,p_blob      IN BLOB
                           ,p_po_number IN VARCHAR2) IS
        l_return_status VARCHAR2(30);
        l_msg_count     NUMBER;
        l_msg_data      VARCHAR2(2000);
        l_file_id       NUMBER;
        l_url           VARCHAR2(240);
      BEGIN
        retcode := '0';
        SELECT fnd_lobs_s.nextval INTO l_file_id FROM dual;
        --插入文件内容到附件表 
        INSERT INTO fnd_lobs
          (file_id
          ,file_name
          ,file_content_type
          ,file_data
          ,upload_date
          ,expiration_date
          ,program_name
          ,program_tag
          ,LANGUAGE
          ,file_format)
        VALUES
          (l_file_id
          ,p_file_name
          ,'application/pdf' --SELECT * FROM fnd_mime_types 查询文件类型
          ,p_blob
          ,SYSDATE
          ,SYSDATE
          ,'ERPTOOAORDER'
          ,'XDO:10'
          ,'ZHS'
          ,'binary');
        x_file_id := l_file_id;
         -------------------------------------------------------------------------
        /* 使用file_id生成唯一的URL */
        ------------------------------------------------------------------------- 
        l_url := fnd_gfm.construct_download_url(fnd_web_config.gfm_agent,
                                                l_file_id,
                                                TRUE);
        -------------------------------------------------------------------------
        /*  将生成的超链接更新进接口表中  */
        -------------------------------------------------------------------------     
        IF l_url IS NOT NULL THEN
          UPDATE cux_oa_po_approval_iface t
          SET    t.attchment      = l_url
                ,t.attchment_flag = 'Y'
          WHERE  1 = 1
          AND    t.document_num = p_po_number;
        ELSE
          UPDATE cux_oa_po_approval_iface t
          SET    t.attchment_flag = 'N'
          WHERE  1 = 1
          AND    t.document_num = p_po_number;
        END IF;
        COMMIT;
      EXCEPTION
        WHEN fnd_api.g_exc_error THEN
          cux_30_fnd_conc_utl.log_message_list;
          retcode := '1';
          fnd_msg_pub.count_and_get(p_encoded => fnd_api.g_false,
                                    p_count   => l_msg_count,
                                    p_data    => l_msg_data);
          IF l_msg_count > 1 THEN
            l_msg_data := fnd_msg_pub.get_detail(p_msg_index => fnd_msg_pub.g_first,
                                                 p_encoded   => fnd_api.g_false);
          END IF;
          errbuf := NULL;
          errbuf := l_msg_data;
        WHEN fnd_api.g_exc_unexpected_error THEN
          cux_30_fnd_conc_utl.log_message_list;
          retcode := '2';
          fnd_msg_pub.count_and_get(p_encoded => fnd_api.g_false,
                                    p_count   => l_msg_count,
                                    p_data    => l_msg_data);
          IF l_msg_count > 1 THEN
            l_msg_data := fnd_msg_pub.get_detail(p_msg_index => fnd_msg_pub.g_first,
                                                 p_encoded   => fnd_api.g_false);
          END IF;
          errbuf := NULL;
          errbuf := l_msg_data;
        WHEN OTHERS THEN
          fnd_msg_pub.add_exc_msg(p_pkg_name       => g_pkg_name,
                                  p_procedure_name => 'MAIN',
                                  p_error_text     => substrb(SQLERRM, 1, 240));
          cux_30_fnd_conc_utl.log_message_list;
          retcode := '2';
          errbuf  := NULL;
          errbuf  := SQLERRM;
      END update_file;
    

    这样超链接就生成到传OA的接口表中,每次OA只需从接口表中获取对应记录的链接就可以获取相应的PDF报表

posted @ 2020-03-28 22:58  张十三S  阅读(347)  评论(0编辑  收藏  举报