• 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报表

    实战为王,记录在工作中技术使用的点点滴滴
  • 相关阅读:
    ASP.Net User Controls as Static or Movable PopUps
    处理WinForm多线程程序时的陷阱(摘自网络)
    《颤抖吧,无证程序员们》只为娱乐
    Javascript和CSS浏览器兼容总结
    收藏的一个c#通讯编程的帖子很全
    WEB开发人员常用速查手册
    批量修改文件名称( 收藏的一个连接)
    SQL server常用操作
    开源网站大收藏
    pragma comment的使用
  • 原文地址:https://www.cnblogs.com/kaikai-wanna-know/p/12590053.html
Copyright © 2020-2023  润新知