Writing and Reading Text to Local File on SAP Server

Jimbo's picture

/image.php?image=misc/officegoateatingplant.jpg|http://i.imgur.com/aSE9zOt.jpg|https://s-media-cache-ak0.pinimg.com/236x/39/14/83/391483b27948d36fa0e150628f890467.jpgStoring information in a discreet file on the SAP server is a great way to remember parameters in a program without having to hard-code them in the declaration. Discreet files on the server is also a great way to store data for custom tables or for deltas, but it can cause some issues--more on that later.

A real world example

This code was used to produce a proprietary EDI file to be uploaded to an external travel agency's web portal on a daily basis. The discreet file on the server stored the records that had already been transmitted to the travel agency so that the daily report was reduced down to a delta.

Before looping through the tables containing employee-as-vendor data, the program reads in the records that have already been transmitted to the travel agency. If the file does not exist, then the OPEN DATASET code returns a non-zero return value and the program simply assumes that no records have been transmitted as the it_History internal table remains empty.

Rather than declare a new structure to hold history records, the DRAW table was recycled--rather lazily--as the structure for the work area and internal table as it has a 255-character FILEP field. The requirement to produce delta EDI extracts for transmission to the travel agency was introduced on the day of go-live after weeks of development, testing and approvals, so this was a bit of a rush job.

* Now read a table with all the changes reported in the last week.
FNAME = 'change.txt'.
OPEN DATASET FNAME FOR INPUT IN TEXT MODE ENCODING DEFAULT.
if sy-subrc eq 0.
  do.
    read dataset FNAME into wa_History-FILEP.
    IF SY-SUBRC <> 0 or p_Delta ne 'X'.  "Full report, no filtering.
      exit.
    endif.
    append wa_History to it_History.
  enddo.
  close dataset FNAME.
endif.

The program then reads in from the CDHDR all of the employee activity from the last week starting yesterday. This creates an internal table with a list of employees that have been touched in the last week which is then sorted and disambiguated.

* Start by populating an internal table with all the activity i
* the last week.  All other work will be compared against this.
dUDATE = sy-DATUM - 7.
select * from CDHDR into wa_CDHDR where OBJECTCLAS eq 'KRED'
 and UDATE ge dUDATE and UDATE ne SY-DATUM.
  if wa_CDHDR-OBJECTID+0(5) eq '00005'.
    append wa_CDHDR to it_CDHDR.
    wa_W-LIFNR = wa_CDHDR-OBJECTID.
    append wa_W to it_W.
  endif.
endselect.
sort it_w.
delete adjacent duplicates from it_w.

The proprietary nature of this client's employee data and the code to determine which employees will be included in the EDI transmission are skipped here for brevity. The nature of the data is immaterial to this snippet, but the output is pipe-delimited and the deltas are emailed to a manager.

/image.php?image=misc/pipegoatbig.jpg|/image.php?image=misc/pipegoat.jpg|https://s-media-cache-ak0.pinimg.com/236x/e8/66/3d/e8663d8db1b48400d608783bc0985c42.jpgAfter the data and pipes are concatenated into the work area, that information is compared to all of the records from the it_history table. When a match is found, the value of the work area is set to a zero-length string to denote that it has already been transmitted.

If the employee record is new then it is appended to the internal table to be written out for EDI, appended to the email text internal table and appended to the existing history records after being concatenated with the date. That date value allows old records to fall out before the table is written back out to the file on the SAP server at the end in order to be read in again the next time the program is run.

loop at it_R into wa_R.
  concatenate 
   "**** code skipped for brevity and confidence ****
    into cText.
  "Loop through the history to see if this is already submitted.
  loop at it_History into wa_History.
    if wa_History-FILEP cs cText.
      cText = ''.   "Don't report, already reported.
    endif.
  endloop.
  if cText ne ''. "Has not been reported.
    i_text = cText. append i_text.
    it_MailTxt = cText. append it_MailTxt.
    concatenate sy-datum cText into wa_History-FILEP.
    append wa_History to it_History.
  endif.
endloop.

After the EDI file is written out to the local computer and the email has been sent to the manager, the history table--along with the new records--is written back to the server. The obsolete records (more than a week old in this case) are filtered from the internal table and the remainder is used to overwrite (instead of append) the file on the server.

open dataset FNAME for output IN TEXT MODE ENCODING DEFAULT.
loop at it_History into wa_History.
  move wa_History-FILEP+0(8) to tUDATE.
  if tUDATE gt dUDATE.  "reported in the last week.
    transfer wa_History-FILEP to FNAME.
  endif.
endloop.
CLOSE DATASET FNAME.

Things to watch out for
https://s-media-cache-ak0.pinimg.com/564x/6c/6a/0b/6c6a0b7490de8d0bbe1994e303d43286.jpg|https://c2.staticflickr.com/8/7181/6926781482_c2a6cd7d29.jpg|https://s-media-cache-ak0.pinimg.com/236x/6c/6a/0b/6c6a0b7490de8d0bbe1994e303d43286.jpg|http://1.bp.blogspot.com/_m8z0LDxt1qY/TSiHknX460I/AAAAAAAABRw/X6JBwWZiWSU/s1600/far_side_mountain_goat.jpg|http://static.fjcdn.com/pictures/Mountain_19716e_291487.jpg|http://66.media.tumblr.com/0024fd820003f7975d5161974d5173da/tumblr_mo1ld3Z1wQ1s5f36lo1_250.jpg|http://2.bp.blogspot.com/_ZDEr-dli0Wg/SOOacRZfNNI/AAAAAAAAACw/rXG2q8mVPKk/s320/far+side+mountain+goat.bmp|http://rwg.cc/uploads/monthly_04_2013/post-32-136656906612.jpg|http://rwg.cc/uploads/monthly_04_2013/post-32-136656906612.jpg|http://rwg.cc/uploads/monthly_04_2013/post-32-136656906612.jpg|http://hemi.nu/Gary_Larsson/index-filer/obj14geo14pg1p3.jpg|http://img.ifcdn.com/images/6519e72b12d7877ee623f4ccb3b0db8a454938778cb36ba30c8f97de1ef54b82_1.jpg|https://media.licdn.com/mpr/mpr/p/6/005/07b/1a3/3993214.jpg|https://s-media-cache-ak0.pinimg.com/564x/bc/fc/c0/bcfcc0f3edea74bf531a93dde84b9cc2.jpg
Since no path is specified in the filename, the system defaults to writing to the tmp folder--wherever that has been declared. It makes great sense to use a filename that probably does not exist in that folder to avoid overwriting another user's "temporary" file or even use the FILE transaction to browse the folder and see what is already stored there.

Most SAP implementations have multiple front-end servers hosting the content from another database server. When logging into a GROUP, the system uses some black box logic to make a determination on which server will be logged into. The file that is written out exists only on the front-end server to which the user was logged into at run time--not every front-end server.

A better solution than storing the data on the SAP front-end server is storing the same data on the local user's computer. This whitepaper explains how to recover from a crash during a long-running report by using deltas stored on the user's computer.

One workaround for this is to configure the SAPGUI client to log into the same server every time instead of defaulting to GROUP. This can be set up easily enough by right-clicking on the SAP server in the SAPGUI client, clicking properties and selecting a server to use each time.
Configure SAPGUI.

Programming Language: 
ABAP