excel - 想要通过 PL/SQL 将两个 Excel 工作表作为邮件附件

标签 excel oracle plsql

我的要求是将来自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/

相关文章:

sql - Oracle 带参数的存储过程

sql - 如何用 • 替换单词但仅显示第一个和最后一个字符

vba - 从Excel VBA中的单元格范围中删除重复项

c++ - OCCI异常: connect descriptor is too long (but not really)

Oracle Data Integrator 标量函数用法

Oracle OpenScript - 无法单击链接

oracle - 将 0 和 1 的数组转换为 base36 字符串

Excel Active X 控件 - 不再工作 - 2015 年 1 月

sorting - 使用自定义顺序和包含逗号的值编写 Excel VBA 排序代码

excel - 在雅虎财经中检索数据报价的 URL 问题