我的要求是将来自oracle表的数据作为excel表格附件通过邮件发送给客户。我可以从一张表中获取一张 Excel 工作表作为附件,但我需要从两个表中获取两张 Excel 工作表。
DECLARE
p_email VARCHAR2(255) ;
p_subject VARCHAR2(255) := 'Weekly Report';
p_message CLOB;
l_mailhost VARCHAR2(255) := 'mail.ABC.com';
l_mail_conn utl_smtp.connection;
v_clob CLOB := EMPTY_CLOB();
v_len INTEGER;
v_index INTEGER;
s_clob CLOB := EMPTY_CLOB();
s_len INTEGER;
s_index INTEGER;
headerLines_v CLOB := EMPTY_CLOB();
headerLines_s CLOB := EMPTY_CLOB();
length_v INTEGER;
length_s INTEGER;
crlf VARCHAR2(2) := chr(13)||chr(10);
v_date VARCHAR2(15) := TO_CHAR(TRUNC(SYSDATE),'DD_MM_YYYY');
CURSOR cur_a
IS
SELECT
a, b, c
FROM TABLE1
CURSOR cur_b
IS
SELECT
x, y, z
FROM TABLE2
BEGIN
/*Table header in attachment*/
DBMS_LOB.CreateTemporary( v_clob, true );
headerLines_v := 'a,b,c'|| UTL_TCP.crlf; --// create CSV header line
DBMS_LOB.WriteAppend( v_clob, length(headerLines_v), headerLines_v ); --// write it to CLOB
DBMS_LOB.CreateTemporary( s_clob, true );
headerLines_s := 'x,y,z'|| UTL_TCP.crlf; --// create CSV header line
DBMS_LOB.WriteAppend( s_clob, length(headerLines_s), headerLines_s ); --// write it to CLOB
--// start loop to add data lines to CSV
SELECT TO_CHAR(TRUNC(SYSDATE),'MM_DD_YYYY') INTO v_date FROM dual;
--SELECT * INTO p_email FROM email WHERE module_name = 'REPORT';
p_message:=
'<html>
<BODY>
<P> <font color="black",font face ="arial",font size ="2.5">
Hello All, <br/><br/>
Please find the attachment for download details <br/>
<br/>Thanks
<br/> Application Team
</P>
</BODY>
</html>';
l_mail_conn := utl_smtp.open_connection(l_mailhost, 25);
utl_smtp.helo(l_mail_conn, l_mailhost);
utl_smtp.mail(l_mail_conn, '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="32535051724b535a5d5d1c5b5c" rel="noreferrer noopener nofollow">[email protected]</a>');
utl_smtp.rcpt(l_mail_conn, '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8beae9e8cbece6eae2e7a5e8e4e6" rel="noreferrer noopener nofollow">[email protected]</a>');
utl_smtp.open_data(l_mail_conn );
utl_smtp.write_data(l_mail_conn,
'MIME-VERSION: 1.0' || crlf ||
'FROM: ' || '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b7d6d5d4f7ced6dfd8d899ded9" rel="noreferrer noopener nofollow">[email protected]</a>' || crlf ||
'Subject: '||'dowload status'||'['||v_date||']'|| crlf ||
'TO: ' || '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0667646546616b676f6a2865696b" rel="noreferrer noopener nofollow">[email protected]</a>'|| crlf ||
'CONTENT-TYPE: multipart/mixed;' || crlf ||
' boundary="---YOURBOUNDARY"' || crlf ||crlf);
-- Email body
utl_smtp.write_data(l_mail_conn, '-----YOURBOUNDARY'||crlf);
utl_smtp.write_data(l_mail_conn, 'Content-Type: text/html' || crlf);
utl_smtp.write_data(l_mail_conn, 'Content-Transfer-Encoding: 8bit' || crlf || crlf);
utl_smtp.write_data(l_mail_conn, p_message||crlf);
-- begin the attachment
utl_smtp.write_data(l_mail_conn, '-----YOURBOUNDARY'||crlf);
utl_smtp.write_data(l_mail_conn, 'Content-Type: text/plain;'||crlf);
utl_smtp.write_data(l_mail_conn, 'Content-Transfer-Encoding: 8bit' || crlf);
--utl_smtp.write_data(l_mail_conn, 'Mime-Type: application/zip' || crlf);
utl_smtp.write_data(l_mail_conn, 'Content-Disposition: attachment;'|| crlf);
utl_smtp.write_data(l_mail_conn, ' filename="Download_Data_1||.csv"'||crlf||crlf);
UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf);
FOR rec IN cur_van
LOOP
v_clob :=
v_clob
|| a
|| ','
|| b
|| ','
|| c
|| UTL_TCP.crlf;
END LOOP;
v_len := DBMS_LOB.getlength(v_clob);
v_index := 1;
WHILE v_index <= v_len
LOOP
UTL_SMTP.write_data(l_mail_conn, DBMS_LOB.SUBSTR(v_clob, 32000, v_index));
v_index := v_index + 32000;
END LOOP;
UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf);
utl_smtp.close_data(l_mail_conn );
if DBMS_LOB.IsOpen( v_clob ) = 1 then
DBMS_LOB.FreeTemporary( v_clob );
end if;
-- begin the attachment
utl_smtp.open_data(l_mail_conn );
utl_smtp.write_data(l_mail_conn, '-----YOURBOUNDARY'||crlf);
utl_smtp.write_data(l_mail_conn, 'Content-Type: text/plain;'||crlf);
utl_smtp.write_data(l_mail_conn, 'Content-Transfer-Encoding: 8bit' || crlf);
--utl_smtp.write_data(l_mail_conn, 'Mime-Type: application/zip' || crlf);
utl_smtp.write_data(l_mail_conn, 'Content-Disposition: attachment;'|| crlf);
utl_smtp.write_data(l_mail_conn, ' filename="download_data_2||.csv"'||crlf||crlf);
UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf);
FOR rec_2 IN cur_syn
LOOP
s_clob :=
s_clob
|| x
|| ','
|| y
|| ','
|| z
|| UTL_TCP.crlf;
END LOOP;
s_len := DBMS_LOB.getlength(s_clob);
s_index := 1;
WHILE s_index <= s_len
LOOP
UTL_SMTP.write_data(l_mail_conn, DBMS_LOB.SUBSTR(s_clob, 32000, s_index));
v_index := s_index + 32000;
END LOOP;
UTL_SMTP.WRITE_DATA(l_mail_conn, UTL_TCP.CRLF);
utl_smtp.write_data(l_mail_conn, '-----YOURBOUNDARY'||crlf);
UTL_SMTP.WRITE_DATA(l_mail_conn,
UTL_TCP.CRLF || '.' || UTL_TCP.CRLF);
if DBMS_LOB.IsOpen( s_clob ) = 1 then
DBMS_LOB.FreeTemporary( s_clob );
end if;
utl_smtp.close_data(l_mail_conn );
utl_smtp.quit(l_mail_conn);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE ('ERROR: '|| SQLCODE ||'Err Msg :'||SQLERRM);
END;
最佳答案
经过一番努力,终于达到了上述要求。其代码是:
DECLARE
v_from_name VARCHAR2(100) := '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="72131011320b131a1d1d5c1b1c" rel="noreferrer noopener nofollow">[email protected]</a>';
v_to_name VARCHAR2(100) := '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5736353417303a363e3b7934383a" rel="noreferrer noopener nofollow">[email protected]</a>';
v_subject VARCHAR2(100);
v_message_body CLOB;
v_message_type VARCHAR2(100) := ' text/html';
v_smtp_server VARCHAR2(255) := 'mail.abc.com';
n_smtp_server_port NUMBER := 25;
conn utl_smtp.connection;
v_date VARCHAR2(15) := TO_CHAR(TRUNC(SYSDATE),'DD/MM/YYYY');
TYPE attach_info IS RECORD (
attach_name VARCHAR2(40),
data_type VARCHAR2(40) DEFAULT 'text/plain',
attach_content CLOB DEFAULT ''
);
TYPE array_attachments IS TABLE OF attach_info;
attachments array_attachments := array_attachments();
n_offset NUMBER;
n_amount NUMBER := 1900;
crlf VARCHAR2(5) := CHR(13) || CHR(10);
v_clob CLOB := EMPTY_CLOB();
v_len INTEGER;
v_index INTEGER;
s_clob CLOB := EMPTY_CLOB();
s_len INTEGER;
s_index INTEGER;
c_mime_boundary CONSTANT VARCHAR2(256) := 'the boundary can be almost anything';
headerLines_v CLOB := EMPTY_CLOB();
headerLines_s CLOB := EMPTY_CLOB();
length_v INTEGER;
length_s INTEGER;
CURSOR cur_a
IS
SELECT a,b,c
FROM Table1
where trunc(DATA_DATE) = TRUNC (SYSDATE);
CURSOR cur_b
IS
SELECT x,y, z
FROM Table2
WHERE TRUNC (CS_start_time) = TRUNC (SYSDATE);
BEGIN
DBMS_LOB.CreateTemporary( v_clob, true );
headerLines_v := 'a,b,c'|| UTL_TCP.crlf; --// create CSV header line
DBMS_LOB.WriteAppend( v_clob, length(headerLines_v), headerLines_v ); --// write it
FOR rec IN cur_a
LOOP
v_clob :=
v_clob
|| rec.ROWID
|| ','
||a
|| ','
||b
|| ','
||c
|| UTL_TCP.crlf;
END LOOP;
DBMS_LOB.CreateTemporary( s_clob, true );
headerLines_s := ' x,y,z'|| UTL_TCP.crlf; --// create CSV header line
DBMS_LOB.WriteAppend( s_clob, length(headerLines_s), headerLines_s ); --// write it to CLOB
--// start loop to add data lines to CSV
FOR rec_2 IN cur_b
LOOP
s_clob :=
s_clob
|| a
|| ','
|| b
|| ','
||c
|| UTL_TCP.crlf;
END LOOP;
-- Fill data for example
attachments.extend(2);
FOR i IN 1..2
LOOP
SELECT 'File1'|| '.csv','text/plain',v_clob || to_char(1)
INTO attachments(1)
FROM dual;
SELECT 'File2' || '.csv','text/plain',s_clob || to_char(2)
INTO attachments(2)
FROM dual;
END LOOP;
SELECT TO_CHAR(TRUNC(SYSDATE),'MM/DD/YYYY') INTO v_date FROM dual;
--SELECT * INTO p_email FROM email WHERE module_name = 'REPORT';
v_message_body:=
'<html>
<BODY>
<P> <font color="black",font face ="arial",font size ="2.5">
Hello All, <br/><br/>
<br/>
Please find the attachment for today's download details<br/>
<br/>Thanks
<br/>Application Team
</P>
</BODY>
</html>';
-- Open the SMTP connection ...
conn := utl_smtp.open_connection(v_smtp_server,n_smtp_server_port);
utl_smtp.helo(conn, v_smtp_server);
utl_smtp.mail(conn, v_from_name);
utl_smtp.rcpt(conn, v_to_name);
-- Open data
utl_smtp.open_data(conn);
-- Message info
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('To: ' || v_to_name || crlf));
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('Date: ' || to_char(sysdate, 'Dy, DD Mon YYYY hh24:mi:ss') || crlf));
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('From: ' || v_from_name || crlf));
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('Subject: ' || 'Dowload status'||'['||v_date||']'||crlf));
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('MIME-Version: 1.0' || crlf));
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('Content-Type: multipart/mixed; boundary="SECBOUND"' || crlf || crlf));
-- Message body
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('--SECBOUND' || crlf));
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('Content-Type: ' || v_message_type || crlf || crlf));
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(v_message_body || crlf));
-- Attachment Part
FOR i IN attachments.FIRST .. attachments.LAST
LOOP
-- Attach info
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('--SECBOUND' || crlf));
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('Content-Type: ' || attachments(i).data_type
|| ' name="'|| attachments(i).attach_name || '"' || crlf));
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('Content-Disposition: attachment; filename="'
|| attachments(i).attach_name || '"' || crlf || crlf));
-- Attach body
n_offset := 1;
WHILE n_offset < dbms_lob.getlength(attachments(i).attach_content)
LOOP
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(dbms_lob.substr(attachments(i).attach_content, n_amount, n_offset)));
n_offset := n_offset + n_amount;
END LOOP;
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('' || crlf));
END LOOP;
-- Last boundry
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw( '--SECBOUND' || crlf));
if DBMS_LOB.IsOpen( v_clob ) = 1 then
DBMS_LOB.FreeTemporary( v_clob );
end if;
if DBMS_LOB.IsOpen( s_clob ) = 1 then
DBMS_LOB.FreeTemporary( s_clob );
end if;
-- Close data
utl_smtp.close_data(conn);
utl_smtp.quit(conn);
END;
关于excel - 想要通过 PL/SQL 将两个 Excel 工作表作为邮件附件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27241332/