Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
mmcisme1
Active Contributor
I try to blog. Some people will say most of it is not technical. And yes, they would be right. Today I'm issuing a challenge. It is specific to all those people who are out there writing ABAP. It could also be for non-ABAP languages. Get the theme? Technical blog.

My challenge: Write a blog about what you are working on!


Why? Because when I ask people why they don't write blogs about ABAP, the answer is that it's all been done. We don't want to just repeat things. So if you are writing about your project you won't be duplicating anything. AND we will get some new ABAP (technical type) blogs.  Heck, you can write about an old project, we wouldn't know. It can also be an old project.

You can share as little or as much code as you want!

This is cool, because there is something in it for you!


Over one million users stop in to the SAP Community. If you aren't doing something "right" then they will probably comment. Worried about that? Don't be. I don't do a lot of things "right". That's OK. I learn and get better. Note to those who comment constructive feedback is always welcome. Rude feedback is not welcome. An example would be you telling me that I'm an idiot. Yes, part of the rules. Sadly, people like me rarely read all of them.   (I did not either - but I'm going to go look at them today.)

Anyway Challenge time


So I thought - I'd just pull out a project that I worked on before.   I am on 4.6C. Yes, it's still working great! That means I have limited access to classes/objects. That's why I've been bookmarking so many things.

So I'm trying to decide what fun things to share from the project.    I think you may want to know the description. We wanted to save our "PDF" documents to a directory, be able to retrieve and mail them. This is a general area where we could put whatever documents we wanted.  I think we have more than 10 types of documents there. Some we create at the time we are using this, Some are uploaded from a directory, some are created via output types and/or messages.  It just depended on what we wanted.  And we could add or remove document types at a later date.

I decided to share the mailing piece of it because it could use some help with some of the newer ABAP objects that are available.

This is a function module that accepts the email name, the document and the body.  The document is actually a key for where we pull the information. It is also an RFM - it's called from a webpage.


 LOOP AT gt_doc INTO gs_doc.
IF gv_message IS INITIAL.
PERFORM check_input.
ELSE.
message = gv_message.
EXIT.
ENDIF.
ENDLOOP.
IF gv_message IS INITIAL.
PERFORM fill_receiver_table.
gv_start = 1.
gv_cnt = 1.
LOOP AT gt_doc INTO gs_doc.
PERFORM get_attachment.
ENDLOOP.
IF gt_contents_bin IS INITIAL.
gv_message = 'No attachments selected.'.
message = gv_message.
ELSE.
PERFORM email_create.
PERFORM send_email.
ENDIF.
message = gv_message.
ENDIF.

So this tells you next to nothing.  Here I loop through the receivers:
  LOOP AT gt_email INTO gs_email.
CLEAR gs_receivers.
gs_receivers-receiver = gs_email-email_add.
gs_receivers-com_type = lc_send_internet.
gs_receivers-rec_type = lc_internet.
APPEND gs_receivers TO gt_receivers.
ENDLOOP.

Easy! Now I'm pulling the "PDF" from our system:
 OPEN DATASET docs-file_name FOR INPUT IN BINARY MODE.

IF sy-subrc <> 0.
CONCATENATE 'Could not open file' docs-file_name
INTO message SEPARATED BY space.
PERFORM update_log USING imp
message
docs-file_name.
EXIT.
ENDIF.

DO.
READ DATASET docs-file_name INTO pdf LENGTH lv_size.
IF sy-subrc <> 0.
EXIT.
ENDIF.
pdf_size = pdf_size + lv_size.
APPEND pdf.
ENDDO.

Got it!  So now I get it ready!
* Move the 134 character table to a 255 format need for PDF attachment
CALL FUNCTION 'SX_TABLE_LINE_WIDTH_CHANGE'
EXPORTING
line_width_dst = 255
TABLES
content_in = lt_pdf[]
content_out = lt_contents_bin[]
EXCEPTIONS
err_line_width_src_too_long = 1
err_line_width_dst_too_long = 2
err_conv_failed = 3
OTHERS = 4.

* Add the contents to the table that will have all the attachments
CLEAR ls_contents_bin.
LOOP AT lt_contents_bin INTO ls_contents_bin.
APPEND ls_contents_bin TO gt_contents_bin.
CLEAR gs_contents_bin.
ENDLOOP.

CLEAR: lv_lines_bin, gs_packing_list.
* Set up the name & Description
WRITE gs_doc-document TO lv_document NO-ZERO.
WRITE gs_doc-document TO lv_document15 NO-ZERO.
WRITE gs_doc-item TO lv_item NO-ZERO.
WRITE gs_doc-item TO lv_item6 NO-ZERO.
WRITE gv_cnt TO lv_cnt NO-ZERO.
CONDENSE: lv_document NO-GAPS,
lv_document15 NO-GAPS,
lv_item NO-GAPS,
lv_item6 NO-GAPS,
lv_cnt NO-GAPS.
CONCATENATE lv_document lv_item lv_cnt
INTO gs_packing_list-obj_name.
CONCATENATE lv_document15 lv_item6 lv_cnt
INTO gs_packing_list-obj_descr
SEPARATED BY space.

* Set up the packing list describint the current attachment

DESCRIBE TABLE lt_contents_bin LINES lv_lines_bin.
READ TABLE lt_contents_bin INTO ls_contents_bin INDEX lv_lines_bin.
gs_packing_list-transf_bin = 'X'.
gs_packing_list-head_start = gv_start.
gs_packing_list-head_num = gv_start.
gs_packing_list-body_start = gv_start.
gs_packing_list-doc_type = 'PDF'.
gs_packing_list-doc_size = lv_pdf_size.
gs_packing_list-body_num = lv_lines_bin.
APPEND gs_packing_list TO gt_packing_list.

* Set up start position for next attachment
gv_start = gv_start + lv_lines_bin.
gv_cnt = gv_cnt + 1.
ENDIF.

Here's the fun part - creating the attachment.
 CLEAR: gs_contents_txt, gs_packing_list.
READ TABLE gt_doc INTO gs_doc INDEX 1.
lv_numc = gs_doc-document.
lv_vbeln = lv_numc.
* Create Message Body Title and Description
IF gs_imp-mail_mess IS INITIAL AND
gt_email_body IS INITIAL.
gs_contents_txt-line = 'See attachment.'.
APPEND gs_contents_txt TO gt_contents_txt.
ELSEIF NOT gs_imp-mail_mess IS INITIAL.
ls_text-mail_mess = gs_imp-mail_mess.
APPEND ls_text TO lt_text.
CALL FUNCTION 'CONVERT_STREAM_TO_ITF_TEXT'
EXPORTING
language = sy-langu
TABLES
text_stream = lt_text[]
itf_text = lt_mail_content[].

LOOP AT lt_mail_content INTO ls_mail_content.
gs_contents_txt-line = ls_mail_content-tdline.
APPEND gs_contents_txt TO gt_contents_txt.
ENDLOOP.
ELSE.
LOOP AT gt_email_body INTO gs_email_body.
gs_contents_txt-line = gs_email_body-email.
APPEND gs_contents_txt TO gt_contents_txt.
ENDLOOP.
ENDIF.

IF gs_imp-doc_type IS INITIAL.
READ TABLE gt_doc INTO gs_doc INDEX 1.
IF sy-subrc = 0.
gs_imp-doc_type = gs_doc-doc_type.
ENDIF.
ENDIF.

IF gs_imp-doc_type = 'TD'.

SELECT SINGLE vbeln INTO vbak FROM vbak
WHERE vbeln = lv_vbeln.
IF sy-subrc = 0.
CALL FUNCTION 'SD_SALES_DOCUMENT_READ'
EXPORTING
document_number = lv_vbeln
i_block = ' '
i_no_authority_check = 'X'
IMPORTING
ekuwev = ls_ekuwev.
IF NOT ls_ekuwev-name1 IS INITIAL.
CONCATENATE 'Deliver to ' ls_ekuwev-name1
INTO lv_obj_descript
SEPARATED BY space.
ENDIF.
ELSE.
SELECT SINGLE banfn INTO eban FROM eban
WHERE banfn = lv_vbeln.
IF sy-subrc = 0.
CONCATENATE 'Deliver to' 'Furst-McNess Company'
INTO lv_obj_descript
SEPARATED BY space.

ENDIF.

ENDIF.

ENDIF.
IF NOT gs_imp-doc_type IS INITIAL AND
lv_obj_descript IS INITIAL.
SELECT SINGLE description INTO lv_description
FROM zdoc_types
WHERE doc_type = gs_imp-doc_type.
IF sy-subrc = 0.
CONCATENATE 'McNess' lv_description 'Document'
INTO lv_obj_descript
SEPARATED BY space.
ENDIF.
ENDIF.
IF lv_obj_descript IS INITIAL.
gs_document_data-obj_descr = 'McNess Documents'.
ELSE.
gs_document_data-obj_descr = lv_obj_descript.
ENDIF.
gs_document_data-expiry_dat = sy-datum + 10.

gs_document_data-sensitivty = 'F'.
gs_document_data-doc_size = gv_total_size.

* Body of E-mail
CLEAR gs_packing_list.
gs_packing_list-head_start = 1.
gs_packing_list-head_num = 0.
gs_packing_list-body_start = 1.
gs_packing_list-body_num = gv_start.
gs_packing_list-doc_type = 'RAW'.
INSERT gs_packing_list INTO gt_packing_list INDEX 1.

 

Finally Send it!
TYPES: BEGIN OF lty_obj,
tp TYPE soos-objtp,
yr TYPE soos-objyr,
no TYPE soos-objno,
END OF lty_obj.

DATA: lv_objid TYPE sofolenti1-object_id,
ls_obj TYPE lty_obj,
lv_objtp TYPE soos-objtp.

CALL FUNCTION 'SO_NEW_DOCUMENT_ATT_SEND_API1'
EXPORTING
document_data = gs_document_data
put_in_outbox = ' '
commit_work = 'X'
IMPORTING
new_object_id = lv_objid
TABLES
packing_list = gt_packing_list[]
contents_txt = gt_contents_txt[]
contents_bin = gt_contents_bin[]
receivers = gt_receivers[]
EXCEPTIONS
too_many_receivers = 1
document_not_sent = 2
document_type_not_exist = 3
operation_no_authorization = 4
parameter_error = 5
x_error = 6
enqueue_error = 7
OTHERS = 8.
IF sy-subrc <> 0.
CASE sy-subrc.
WHEN 1.
MESSAGE e007 INTO gv_message.
WHEN 2.
MESSAGE e008 INTO gv_message.
WHEN 3.
MESSAGE e009 INTO gv_message.
WHEN 4.
MESSAGE e010 INTO gv_message.
WHEN OTHERS.
MESSAGE e011 INTO gv_message.
ENDCASE.
ELSE.
ls_obj = lv_objid.
COMMIT WORK AND WAIT.
*** Try to verify the record is ready to send - wait only 100 times
DO 100 TIMES.
SELECT SINGLE objtp INTO lv_objtp
FROM soos
WHERE objtp = ls_obj-tp AND
objyr = ls_obj-yr AND
objno = ls_obj-no.
IF sy-subrc = 0.
EXIT.
ENDIF.
ENDDO.

SUBMIT rsconn01 WITH mode = 'INT' AND RETURN.
* gv_message = 'Mail sent'.
ENDIF.

 

This is the end of just a piece of that development.  We have screens where the user can enter requests for different documents.  If they double click then they have the PDF display so they can look at it prior to sending it. AND a co-worker put together a webpage that calls some of this code. That ways it can look pretty when they call it. And yes - this was 4.6C. She used JavaScript and Visual Basic. Cool. This is prior to even Webdynpro.

GUI Result:



 

Webpage result:



 

So my challenge is to share your project.  As much or as little code as you want. I promise we will be nice!

A side challenge - use objects to send the e-mail. I didn't have them available. SO if someone could put them in the comments - that would be so nice.

Also anything else you would like to know about this? Hate the idea? Feel free to comment. I love responding to them.
9 Comments