使用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;