Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用PL/SQL创建Excel文件(.xlsx)_Excel_Oracle_Plsql - Fatal编程技术网

使用PL/SQL创建Excel文件(.xlsx)

使用PL/SQL创建Excel文件(.xlsx),excel,oracle,plsql,Excel,Oracle,Plsql,关于我先前的问题, 我能够使用DBMS\u SQL和UTL\u文件生成一个Excel(.xls)文件,并传递一个SYS\u REFCURSOR(代码在前面的问题中)。 然而,我遇到的一个挑战是生成的文件超过25MB。 我将通过电子邮件发送给商业用户,这肯定会填满他们的邮箱。 当我使用sqldeveloper手动提取到xlsx时,它只生成大约4MB的数据 为了解决这个问题,是否可以通过PL/SQL执行以下操作 使用更高版本的Excel(.xlsx)生成文件以压缩大小 传输前压缩.xls文件 我也看

关于我先前的问题, 我能够使用
DBMS\u SQL
UTL\u文件生成一个Excel
(.xls)
文件,并传递一个
SYS\u REFCURSOR
(代码在前面的问题中)。 然而,我遇到的一个挑战是生成的文件超过25MB。 我将通过电子邮件发送给商业用户,这肯定会填满他们的邮箱。 当我使用
sqldeveloper
手动提取到
xlsx
时,它只生成大约4MB的数据

为了解决这个问题,是否可以通过
PL/SQL
执行以下操作

  • 使用更高版本的Excel(
    .xlsx
    )生成文件以压缩大小
  • 传输前压缩
    .xls
    文件
  • 我也看过类似的文章,比如, 但正如答案所述,它需要使用Java。所以它不适用于我。 另一篇文章也在使用
    xls
    。所以它也不适用

    有什么想法吗

    Oracle版本:

    Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
    PL/SQL Release 11.2.0.4.0 - Production
    "CORE   11.2.0.4.0  Production"
    TNS for Solaris: Version 11.2.0.4.0 - Production
    NLSRTL Version 11.2.0.4.0 - Production
    

    Oracle数据库中不支持
    xls
    xlsx
    文件


    您可以做的是创建CSV(逗号分隔)文件,然后使用使用的自定义或使用的PL/SQL过程将其压缩为zip文件。

    如果您需要生成XLSX文件并将其发送给业务用户,这听起来更像是DB之外的某些服务的工作。您应该准备返回带有报告内容的
    ref cursor
    的过程,然后设置一些使用数据的服务,生成PDF或XLSX并发送它


    如果不能在DB之外完成,那么仍然可以在Oracle内部使用Java。您可以创建将创建XLSX的Java过程。是一个Java创建Excel文件的示例。但是创建复杂的Java过程并不是最好的解决方案,可能需要您在DB服务器上安装一些JAR,因此我将创建返回
    ref cursor
    数据的过程和创建文件并将其发送到DB外部的小程序。

    我看到了Anton Scheffer的一个名为
    as_xlsx
    的包,它解决了我的问题。 我还对它进行了一些修改,添加了工作表名称,并允许将
    SYS\u REFCURSOR
    作为参数,而不是我上一篇文章()中要求的
    VARCHAR2

    我在程序重载的包规范中添加了以下内容:

    procedure query2sheet
    ( p_cur             IN OUT      SYS_REFCURSOR
    , p_column_headers  boolean     := true
    , p_directory       varchar2    := null
    , p_filename        varchar2    := null
    , p_sheet           pls_integer := null
    , p_sheetname       varchar2    := null
    );
    
    我在程序重载的包体中添加了这个(注意:行注释是我修改的行):

    这是创建文件的并发请求中的一个示例块:

    Procedure EMP_ROSTER_REPORT (p_empno        per_all_people_f.employee_number%type                              
                               , p_bg_id        per_business_groups.business_group_id%type
                               , p_email_add    per_all_people_f.email_address%type)
    is
    
        l_fh            UTL_FILE.FILE_TYPE;
        l_directory     VARCHAR2(30) := 'EXT_TAB_DATA';
        l_filename      VARCHAR2(100);
        emp_cur         SYS_REFCURSOR;
        l_message       varchar2(100);
        g_stage         varchar2(100);
        g_zipped_blob   blob;
    
        cursor  p_payroll_cur is
        select  payroll_id
            ,   payroll_name
            ,   business_group_id
        from    pay_all_payrolls_f
        where   business_group_id = p_bg_id;
    
    BEGIN
    
        -----------------------------------
        g_stage := 'setting the filename';
        -----------------------------------
    
        l_filename := 'EMPLOYEE_ROSTER_REPORT_'||TO_CHAR(SYSDATE, 'DD-MON-YYYY-HHMISS');
    
        ------------------------------------------
        g_stage := 'Assigning Emp SysRefCursor';
        ------------------------------------------
    
        for i in p_payroll_cur loop
    
            OPEN emp_cur FOR
            SELECT  'extra long query here with parameters'
            from    table_a
            where   payroll_id = i.payroll_id;
    
            ----------------------------------------------------------
            g_stage := 'open Employee Cursor and write into the File';
            ----------------------------------------------------------
    
            as_xlsx.query2sheet( p_cur          => emp_cur            -- Uses Sys_RefCursor Instead of Dynamic SQL (Varchar2)
                               , p_sheetname    => i.payroll_name);   -- This is where we assign the Sheet Names         
            as_xlsx.freeze_pane( 1,1 );                               -- Freeze the topmost and rightmost pane in the Excel Sheet
    
        end loop;
    
        ------------------------------
        g_stage := 'Create the File';
        ------------------------------
    
        as_xlsx.save( l_directory , l_filename||'.xlsx');
    
    END EMP_ROSTER_REPORT;
    

    希望这对别人有帮助!:)

    如果你关心大小,那么最好使用csv?嗨@Leo,是的,我现在正在运行
    .csv
    的测试。但主要是希望在
    .xlsx
    中使用它,因为业务用户喜欢这种方式。@Leo,不走运,该.csv文件几乎相同大小,25 MB。数据的实际大小是多少?因为在我提到csv=txt时delimiters@Leo,
    .xls
    有25.9 MB,
    .csv
    有25.4 MB。还没有研究过使用带分隔符的文本。我会检查我是否可以为它创建一个过程。嗨@kacper,是的,这是我在上一篇文章中采用的方法,但是,我在文件大小和行限制方面遇到了挑战。我通过Oracle EBS.hi@kacper中的并发程序发送这些报告,我找到了一个解决方案,请看一下我在这个问题上的答案。我还对指定的包进行了一些修改,并能够将SYS\u REFCURSOR
    作为参数传递。Hi@Gurvinder singh,我能够找到一个满足需要的本地PL/SQL包。请看下面我的答案。谢谢创建XLSX文件时,它存储在哪里?在数据库所在的远程计算机上?如何使用UTL_邮件发送此创建的文件?@sbrbot是的,它位于数据库所在的远程计算机上。有很多UTL_邮件包可以作为附件发送文件。我最大的问题是UTL_邮件在附件大小方面非常有限(32K或类似的东西)。所以我不能发送更大的文件,现在如果附件保存在外部,我能用UTL_邮件发送吗?这个包的依赖关系是什么?还是一个独立的软件包?@ManuelJE这是一个独立的软件包
    Procedure EMP_ROSTER_REPORT (p_empno        per_all_people_f.employee_number%type                              
                               , p_bg_id        per_business_groups.business_group_id%type
                               , p_email_add    per_all_people_f.email_address%type)
    is
    
        l_fh            UTL_FILE.FILE_TYPE;
        l_directory     VARCHAR2(30) := 'EXT_TAB_DATA';
        l_filename      VARCHAR2(100);
        emp_cur         SYS_REFCURSOR;
        l_message       varchar2(100);
        g_stage         varchar2(100);
        g_zipped_blob   blob;
    
        cursor  p_payroll_cur is
        select  payroll_id
            ,   payroll_name
            ,   business_group_id
        from    pay_all_payrolls_f
        where   business_group_id = p_bg_id;
    
    BEGIN
    
        -----------------------------------
        g_stage := 'setting the filename';
        -----------------------------------
    
        l_filename := 'EMPLOYEE_ROSTER_REPORT_'||TO_CHAR(SYSDATE, 'DD-MON-YYYY-HHMISS');
    
        ------------------------------------------
        g_stage := 'Assigning Emp SysRefCursor';
        ------------------------------------------
    
        for i in p_payroll_cur loop
    
            OPEN emp_cur FOR
            SELECT  'extra long query here with parameters'
            from    table_a
            where   payroll_id = i.payroll_id;
    
            ----------------------------------------------------------
            g_stage := 'open Employee Cursor and write into the File';
            ----------------------------------------------------------
    
            as_xlsx.query2sheet( p_cur          => emp_cur            -- Uses Sys_RefCursor Instead of Dynamic SQL (Varchar2)
                               , p_sheetname    => i.payroll_name);   -- This is where we assign the Sheet Names         
            as_xlsx.freeze_pane( 1,1 );                               -- Freeze the topmost and rightmost pane in the Excel Sheet
    
        end loop;
    
        ------------------------------
        g_stage := 'Create the File';
        ------------------------------
    
        as_xlsx.save( l_directory , l_filename||'.xlsx');
    
    END EMP_ROSTER_REPORT;