1. <legend id='OGD2L'><style id='OGD2L'><dir id='OGD2L'><q id='OGD2L'></q></dir></style></legend>
    1. <small id='OGD2L'></small><noframes id='OGD2L'>

      • <bdo id='OGD2L'></bdo><ul id='OGD2L'></ul>
      <i id='OGD2L'><tr id='OGD2L'><dt id='OGD2L'><q id='OGD2L'><span id='OGD2L'><b id='OGD2L'><form id='OGD2L'><ins id='OGD2L'></ins><ul id='OGD2L'></ul><sub id='OGD2L'></sub></form><legend id='OGD2L'></legend><bdo id='OGD2L'><pre id='OGD2L'><center id='OGD2L'></center></pre></bdo></b><th id='OGD2L'></th></span></q></dt></tr></i><div id='OGD2L'><tfoot id='OGD2L'></tfoot><dl id='OGD2L'><fieldset id='OGD2L'></fieldset></dl></div>
      <tfoot id='OGD2L'></tfoot>
    2. 使用 PL/SQL 创建 Excel 文件 (.xlsx)

      时间:2023-09-18

    3. <small id='gSVaP'></small><noframes id='gSVaP'>

          <tbody id='gSVaP'></tbody>
        • <legend id='gSVaP'><style id='gSVaP'><dir id='gSVaP'><q id='gSVaP'></q></dir></style></legend>
          <tfoot id='gSVaP'></tfoot>
            <bdo id='gSVaP'></bdo><ul id='gSVaP'></ul>

              1. <i id='gSVaP'><tr id='gSVaP'><dt id='gSVaP'><q id='gSVaP'><span id='gSVaP'><b id='gSVaP'><form id='gSVaP'><ins id='gSVaP'></ins><ul id='gSVaP'></ul><sub id='gSVaP'></sub></form><legend id='gSVaP'></legend><bdo id='gSVaP'><pre id='gSVaP'><center id='gSVaP'></center></pre></bdo></b><th id='gSVaP'></th></span></q></dt></tr></i><div id='gSVaP'><tfoot id='gSVaP'></tfoot><dl id='gSVaP'><fieldset id='gSVaP'></fieldset></dl></div>

                本文介绍了使用 PL/SQL 创建 Excel 文件 (.xlsx)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                问题描述

                关于我之前的问题 返回显式的 SQL 语句光标,我能够使用 DBMS_SQLUTL_FILE 生成一个 Excel (.xls) 文件并传递一个 SYS_REFCURSOR(代码在上一个问题中).但是,我遇到的一个挑战是生成的文件超过 25 MB.我将通过电子邮件将其发送给企业用户,它肯定会填满他们的邮箱大小.当我使用 SQL Developer 手动提取到 xlsx 时,它只会生成大约 4 MB 的数据.

                In relation to my previous question Return the SQL Statement of an Explicit Cursor, i was able to generate an Excel (.xls) file using DBMS_SQL and UTL_FILE and passing a SYS_REFCURSOR (code is in the previous question). However, one challenge i'm encountering is the generated file is over 25 MB. I will be transmitting this over Email to Business Users and it would surely fill up their mailbox size. When I do manual extracts to xlsx using SQL Developer it just generates around 4 MB of data.

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

                To Address this, would it be possible through PL/SQL to do the following?

                1. 使用更高版本的 Excel (.xlsx) 生成文件以压缩大小
                2. 传输前压缩.xls文件
                1. Generate a file using a later version of Excel (.xlsx) to compress the size
                2. Compress the .xls file before transmitting

                我还在 SO 中查看了类似的帖子,例如 使用Oracle中的UTL_FILE包在ExcelSheet中编写,但正如答案所述,它需要使用 Java.所以它不适用于我.另一篇文章,从 Oracle 数据库创建 Excel 电子表格,也在使用 xls.所以它也不适用.

                I've also reviewed similar posts here in SO such as Writing in ExcelSheet using UTL_FILE package in Oracle, but as the answer stated, it needs to use Java. So its not applicable to me. Another post, Create an Excel Spreadsheet from a Oracle Database, is also using xls. So its not applicable as well.

                有什么想法吗?

                甲骨文版本:

                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
                

                推荐答案

                我看过 Anton Scheffer 的一个名为 as_xlsx 的包,使用 PL/SQL 创建 Excel 文件 它解决了我的问题.我还稍微修改了它以放入工作表名称并允许 SYS_REFCURSOR 作为参数而不是我上一篇文章中要求的 VARCHAR2 (返回显式游标的SQL语句).

                I've seen a package called as_xlsx by Anton Scheffer, Create an Excel-file with PL/SQL and it addressed my problem. I also modified it a bit to put in Worksheet Names and to allow SYS_REFCURSOR as a Parameter instead of a VARCHAR2 as required in my Previous Post (Return the SQL Statement of an Explicit Cursor).

                我在过程重载的包规范中添加了这个:

                I added this in the Package Specification for Procedure Overloading:

                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
                );
                

                我在程序重载的包体中添加了这个(注意:行注释是我修改的行):

                I added this in the Package Body for Procedure Overloading (note: the line comments were lines I modified):

                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
                )
                is
                    t_sheet     pls_integer;
                    t_c         integer;
                    t_col_cnt   integer;
                    t_desc_tab2 dbms_sql.desc_tab2;
                    t_desc_tab  dbms_sql.desc_tab;
                    d_tab       dbms_sql.date_table;
                    n_tab       dbms_sql.number_table;
                    v_tab       dbms_sql.varchar2_table;
                    t_bulk_size pls_integer := 200;
                    t_r         integer;
                    t_cur_row   pls_integer;
                    t_d         number;
                begin
                    -- Changed
                    if p_sheetname is not null then
                        new_sheet(p_sheetname);      
                    else
                        new_sheet;
                    end if;
                    -- End of Change
                    --t_c := dbms_sql.open_cursor;                       
                    --dbms_sql.parse( t_c, p_sql, dbms_sql.native );
                
                    t_d := DBMS_SQL.TO_CURSOR_NUMBER(p_cur);
                
                    --dbms_sql.describe_columns2( t_c, t_col_cnt, t_desc_tab );
                    dbms_sql.describe_columns( t_d, t_col_cnt, t_desc_tab );
                
                    for c in 1 .. t_col_cnt
                    loop
                        if p_column_headers
                        then
                        cell( c, 1, t_desc_tab( c ).col_name, p_sheet => t_sheet );
                        end if;
                        --dbms_output.put_line( t_desc_tab( c ).col_name || ' ' || t_desc_tab( c ).col_type );
                        case
                        when t_desc_tab( c ).col_type in ( 2, 100, 101 )
                        then
                            --dbms_sql.define_array( t_c, c, n_tab, t_bulk_size, 1 );
                            dbms_sql.define_array( t_d, c, n_tab, t_bulk_size, 1 );
                        when t_desc_tab( c ).col_type in ( 12, 178, 179, 180, 181 , 231 )
                        then
                            --dbms_sql.define_array( t_c, c, d_tab, t_bulk_size, 1 );
                            dbms_sql.define_array( t_d, c, d_tab, t_bulk_size, 1 );
                        when t_desc_tab( c ).col_type in ( 1, 8, 9, 96, 112 )
                        then
                            --dbms_sql.define_array( t_c, c, v_tab, t_bulk_size, 1 );
                            dbms_sql.define_array( t_d, c, v_tab, t_bulk_size, 1 );
                        else
                            null;
                        end case;
                    end loop;
                    --
                    t_cur_row := case when p_column_headers then 2 else 1 end;
                    t_sheet := nvl( p_sheet, workbook.sheets.count() );
                    --
                    --t_r := dbms_sql.execute( t_c );
                    loop
                        --t_r := dbms_sql.fetch_rows( t_c );
                        t_r := dbms_sql.fetch_rows( t_d );
                        if t_r > 0
                        then
                        for c in 1 .. t_col_cnt
                        loop
                            case
                            when t_desc_tab( c ).col_type in ( 2, 100, 101 )
                            then
                                --dbms_sql.column_value( t_c, c, n_tab );
                                dbms_sql.column_value( t_d, c, n_tab );
                                for i in 0 .. t_r - 1
                                loop
                                if n_tab( i + n_tab.first() ) is not null
                                then
                                    cell( c, t_cur_row + i, n_tab( i + n_tab.first() ), p_sheet => t_sheet );
                                end if;
                                end loop;
                                n_tab.delete;
                            when t_desc_tab( c ).col_type in ( 12, 178, 179, 180, 181 , 231 )
                            then
                                --dbms_sql.column_value( t_c, c, d_tab );
                                dbms_sql.column_value( t_d, c, d_tab );
                                for i in 0 .. t_r - 1
                                loop
                                if d_tab( i + d_tab.first() ) is not null
                                then
                                    cell( c, t_cur_row + i, d_tab( i + d_tab.first() ), p_sheet => t_sheet );
                                end if;
                                end loop;
                                d_tab.delete;
                            when t_desc_tab( c ).col_type in ( 1, 8, 9, 96, 112 )
                            then
                                --dbms_sql.column_value( t_c, c, v_tab );
                                dbms_sql.column_value( t_d, c, v_tab );
                                for i in 0 .. t_r - 1
                                loop
                                if v_tab( i + v_tab.first() ) is not null
                                then
                                    cell( c, t_cur_row + i, v_tab( i + v_tab.first() ), p_sheet => t_sheet );
                                end if;
                                end loop;
                                v_tab.delete;
                            else
                                null;
                            end case;
                        end loop;
                        end if;
                        exit when t_r != t_bulk_size;
                        t_cur_row := t_cur_row + t_r;
                    end loop;
                    --dbms_sql.close_cursor( t_c );
                    dbms_sql.close_cursor( t_d );
                    if ( p_directory is not null and  p_filename is not null )
                    then
                        save( p_directory, p_filename );
                    end if;
                exception
                when others
                then
                    --if dbms_sql.is_open( t_c )
                    if dbms_sql.is_open( t_d )
                    then
                    --dbms_sql.close_cursor( t_c );
                    dbms_sql.close_cursor( t_d );
                    end if;
                end query2sheet;
                

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

                This is a Sample Block in my Concurrent Request that Creates the File:

                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;
                

                希望这对某人有所帮助!:)

                Hope this helps someone! :)

                这篇关于使用 PL/SQL 创建 Excel 文件 (.xlsx)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                上一篇:Spring Batch ORA-08177:运行单个作业时无法序列化此事务的访问,SERIALIZED 隔离级别 下一篇:有没有办法在 Oracle 中刷新 PL/SQL 的输出?

                相关文章

              2. <i id='LjG70'><tr id='LjG70'><dt id='LjG70'><q id='LjG70'><span id='LjG70'><b id='LjG70'><form id='LjG70'><ins id='LjG70'></ins><ul id='LjG70'></ul><sub id='LjG70'></sub></form><legend id='LjG70'></legend><bdo id='LjG70'><pre id='LjG70'><center id='LjG70'></center></pre></bdo></b><th id='LjG70'></th></span></q></dt></tr></i><div id='LjG70'><tfoot id='LjG70'></tfoot><dl id='LjG70'><fieldset id='LjG70'></fieldset></dl></div>

                1. <legend id='LjG70'><style id='LjG70'><dir id='LjG70'><q id='LjG70'></q></dir></style></legend>
                  • <bdo id='LjG70'></bdo><ul id='LjG70'></ul>

                  <small id='LjG70'></small><noframes id='LjG70'>

                  <tfoot id='LjG70'></tfoot>