Skip to Content

Your infrastructure team is having difficulty connecting to the SAP Content Server they’ve just installed.

Therefore, you can’t switch your SAPOffice attachments over from SOFFDB to SOFFHTTP yet. 

So therefore, you can’t pass URL’s for graphic attachments to the load method of cl_gui_picture using cl_bds_document_set->get_with_url (because there are no URL’s for these attachments?

How do you load cl_gui_picture from your physical contents stored in SOFFCONT1?

Here’s one way that’s really toxic, but should work.  Will report back to this blog post whether it does or not.

 

wa_objectid-objkey  = viqmel-qmnum.   ” i.e. – a PM notification number

wa_objectid-objtype = ‘BUS2038’.

CALL FUNCTION ‘BAPI_REL_GETRELATIONS’

  EXPORTING

    OBJECTID              = wa_objectid

    RECURSIONLEVEL        = 1

  IMPORTING

    RETURN                = v_rtrn

  TABLES

    LISTOFRELATIONS       = i_listrel.

v_cntr = 0.

v_nmbr = 0.

LOOP AT i_listrel into wa_listrel.

  IF wa_listrel-reltype <> ‘ATTA’.

    CONTINUE.

  ENDIF.

  APPEND wa_listrel TO i_listrel2.

ENDLOOP.

* make sure you have as many instances of cl_gui_picture as you

* need and as many custom containers on the screen as you need

LOOP AT i_listrel2 INTO wa_listrel.

  v_objtype = wa_listrel-objtype_b.

  v_objkey  = wa_listrel-objkey_b.

      swc_create_object v_obj1 v_objtype v_objkey.

      swc_get_property  v_obj1 ‘Description’ v_objdes.

      swc_get_property  v_obj1 ‘FileExtension’ v_fileext.

      wa_atts-name      = v_objdes.

      wa_atts-ext       = v_fileext.

      APPEND wa_atts TO i_atts.

*     1) get the actual SOFFCONT1 content by driving into SOFFPHF

*        using v_objdes+v_filext (concatenated)

*     2) manipulate the SOFFCONT1 content into a format/type

*        acceptable to the piece of code shown below from

*        SAP program BSP_UPDATE_MIMEREPOS

*     3) use what you need from the BSP_UPDATE_MIMEREPOS code below to store

*        to store a copy of the content in SAP’s MIME repos     

*         (this code includes creating a URL, of course)

*     4) pass the URL of the newly created “MIME” to the

*        load method of your picture control

ENDLOOP.

* here’s the part of bsp_update_mimerepos that you’ll need to steal code from to create a temporary copy of your graphic in the MIME repository; note that instead of uploading a graphic from a drive, you’re creating it from the contents in SOFFCONT1.

 

      CALL METHOD cl_gui_frontend_services=>gui_upload

        EXPORTING

          filename                = l_filename

          filetype                = ‘BIN’

          read_by_line            = ‘X’

        IMPORTING

          filelength              = l_filelength

        CHANGING

          data_tab                = itab_files

        EXCEPTIONS

          file_open_error         = 1

          file_read_error         = 2

          no_batch                = 3

          gui_refuse_filetransfer = 4

          invalid_type            = 5

          no_authority            = 6

          unknown_error           = 7

          bad_data_format         = 8

          header_not_allowed      = 9

          separator_not_allowed   = 10

          header_too_long         = 11

          unknown_dp_error        = 12

          access_denied           = 13

          dp_out_of_memory        = 14

          disk_full               = 15

          dp_timeout              = 16

          not_supported_by_gui    = 17

          error_no_gui            = 18

          OTHERS                  = 19.

 

      IF sy-subrc <> 0.

        WRITE: /(6) icon_red_light AS ICON, (55) text-006, l_filename.

*       Fehler beim Upload der Datei!

        CONTINUE.

      ENDIF.

 

      CLEAR: l_content.

 

* — we need the file content as xstring

      LOOP AT itab_files INTO wa_files.

        CONCATENATE l_content wa_files INTO l_content IN BYTE MODE.

      ENDLOOP.

 

* — cut according to filelength

      l_content = l_content(l_filelength).

 

      CLEAR: x, y, l_url.

 

      IF l_url IS INITIAL.

        IF onefile = ‘X’.

          CLEAR: x, y.

          DO.

            FIND ‘\’ IN wa_file_table-filename+x MATCH OFFSET y.

            IF sy-subrc = 0.

              x = x + y + 1.

            ELSE.

              EXIT.

            ENDIF.

          ENDDO.

          CONCATENATE mimepath wa_file_table-filename+x INTO l_url.

          CLEAR: x, y.

        ELSE.

          CONCATENATE mimepath wa_file_table-filename INTO l_url.

        ENDIF.

      ENDIF.

 

* — to be consistent with windows pathes

      TRANSLATE l_url USING ‘\/’.

 

* — now compare the LOIOs of local files with MR information

* — + if file is missing, we will create it with given LOIO

* — + if file is present, but LOIOs differ:

* —   ++ if checkbox ovwrloio is checked, we will delete MR file

* —   ++ otherwise we will only write a message

      IF NOT itab_loio IS INITIAL.

*        DATA: l_url_folder LIKE l_url.

*        LOOP AT itab_loio INTO wa_file_loio WHERE is_folder IS INITIAL.

        DATA: abs_name LIKE wa_file_table-filename.

        CONCATENATE l_rootdir ‘\’ wa_file_table-filename INTO abs_name.

        READ TABLE itab_loio WITH KEY name = abs_name INTO wa_file_loio.

        IF sy-subrc <> 0.

          ULINE.

          FORMAT COLOR COL_NEGATIVE ON.

          WRITE: /(6) icon_loio_class AS ICON, (255) text-033.

*         LOIO zu File konnte nicht ermttelt werden

          WRITE: /(6) icon_red_light AS ICON, (255) text-034.

          WRITE: /(6) icon_red_light AS ICON, (255) abs_name.

*         Datei wird nicht angelegt!

          FORMAT COLOR COL_NEGATIVE OFF.

          ULINE.

          CONTINUE.

        ENDIF.

*          CONCATENATE mimepath wa_file_loio-name INTO l_url.

        CLEAR: is_folder.

 

* — to be consistent with windows pathes

        TRANSLATE l_url USING ‘\/’.

 

        CALL METHOD o_mr_api->get

          EXPORTING

            i_url              = l_url

          IMPORTING

            e_is_folder        = is_folder

            e_content          = l_current

            e_loio             = l_loio

          EXCEPTIONS

            parameter_missing  = 1

            error_occured      = 2

            not_found          = 3

            permission_failure = 4

            OTHERS             = 5.

*

        IF sy-subrc <> 0.

          CASE sy-subrc.

            WHEN 3.              “* — mime not found -> go on…

              CLEAR l_current.

            WHEN 4.

              WRITE: /(6) icon_red_light AS ICON, (55) text-007, l_url.

*             Keine Leseberechtigung an Mime-Objekt

              CONTINUE.

            WHEN OTHERS.

              WRITE: /(6) icon_red_light AS ICON, (55) text-008, l_url.

*             Fehler beim Lesen des Mime-Objektes

              CONTINUE.

          ENDCASE.

        ELSE.

          IF wa_file_loio-loio NE l_loio AND withloio = ‘X’.

            WRITE: /(6) icon_yellow_light AS ICON, (55) text-019, l_url.

*           LOIOs unterschiedlich

            IF ovwrloio EQ ‘X’.

* — delete MR file, if LOIOs differ

              CALL METHOD o_mr_api->delete

                EXPORTING

                  i_url              = l_url

                  i_delete_children  = ”

                  i_check_authority  = ‘X’

*                 I_CORR_NUMBER      =

                EXCEPTIONS

                  parameter_missing  = 1

                  error_occured      = 2

                  cancelled          = 3

                  permission_failure = 4

                  not_found          = 5

                  OTHERS             = 6.

 

              IF sy-subrc <> 0.

                CASE sy-subrc.

                  WHEN 4.

                    WRITE: /(6) icon_red_light AS ICON, (55) text-023, l_url.

*                   Keine Berechtigung zum Löschen der Datei

                    CONTINUE.

                  WHEN OTHERS.

                    WRITE: /(6) icon_red_light AS ICON, (55) text-022, l_url.

*                   Fehler beim Löschen der Datei

                    CONTINUE.

                ENDCASE.

              ELSE.

                WRITE: /(6) icon_loio_class AS ICON, (55) text-024, l_url.

*               Datei wird neu angelegt (LOIO-Abgleich)

                CLEAR l_current.

              ENDIF.

 

            ENDIF.  “ovwrloio

          ENDIF.  “wa_file_loio-loio NE l_loio and withloio = ‘X

        ENDIF.  “sy-subrc

      ENDIF.  “itab_loio initial

 

* — new

      IF withloio IS INITIAL.

* — to be consistent with windows pathes

        TRANSLATE l_url USING ‘\/’.

 

        CALL METHOD o_mr_api->get

          EXPORTING

            i_url              = l_url

          IMPORTING

            e_is_folder        = is_folder

            e_content          = l_current

            e_loio             = l_loio

          EXCEPTIONS

            parameter_missing  = 1

            error_occured      = 2

            not_found          = 3

            permission_failure = 4

            OTHERS             = 5.

*

        IF sy-subrc <> 0.

          CASE sy-subrc.

            WHEN 3.              “* — mime not found -> go on…

              CLEAR l_current.

            WHEN 4.

              WRITE: /(6) icon_red_light AS ICON, (55) text-007, l_url.

*             Keine Leseberechtigung an Mime-Objekt

              CONTINUE.

            WHEN OTHERS.

              WRITE: /(6) icon_red_light AS ICON, (55) text-008, l_url.

*             Fehler beim Lesen des Mime-Objektes

              CONTINUE.

          ENDCASE.

        ENDIF.

      ENDIF.

* — end new

 

* — check, if this is a css-file

* — css -> convert to ascii, exclude timestamp and compare ascii

      DATA: l_oldascii   TYPE string.

      DATA: l_newascii   TYPE string.

      DATA: conv         TYPE REF TO cl_abap_conv_in_ce.

      DATA: length       TYPE i.

      DATA: new_offset   TYPE i, old_offset TYPE i.

 

      CLEAR: new_offset, old_offset, l_newascii, l_oldascii.

 

      length = STRLEN( l_url ) – 4.

      IF length > 0 AND l_url+length CS ‘.css’.

 

* — NEW: exclude timestamp (17B) and compare xstring…

        IF XSTRLEN( l_content ) > 17 AND XSTRLEN( l_current ) > 17.

          IF l_current+17 = l_content+17.

            CONTINUE.

          ENDIF.

        ENDIF.

*        conv = cl_abap_conv_in_ce=>create( input = l_content ).

*        conv->read( IMPORTING data = l_newascii len = length ).

*

*        IF NOT l_current IS INITIAL.

*          conv = cl_abap_conv_in_ce=>create( input = l_current ).

*          conv->read( IMPORTING data = l_oldascii len = length ).

*        ENDIF.

*

** — identify timestamp and the corresponding offset

*        IF STRLEN( l_newascii ) > 24 AND l_newascii(2) = ‘/*’ AND l_newascii+2(22) CS ‘*/’.

*          new_offset = sy-fdpos + 4.

*        ENDIF.

*        IF STRLEN( l_oldascii ) > 24 AND l_oldascii(2) = ‘/*’ AND l_oldascii+2(22) CS ‘*/’.

*          old_offset = sy-fdpos + 4.

*        ENDIF.

*

** — compare ascii

*        IF l_oldascii+old_offset = l_newascii+new_offset.

*          CONTINUE.

*        ENDIF.

*

      ELSE.

* — compare binary

        IF l_current = l_content.

          CONTINUE.

        ENDIF.

      ENDIF.

 

* — update only if content has changed

* — if no LOIO was included, the put method will

* — create a new one

      CALL METHOD o_mr_api->put

        EXPORTING

          i_url                     = l_url

          i_content                 = l_content

          i_suppress_package_dialog = ‘X’

          i_new_loio                = wa_file_loio-loio

        EXCEPTIONS

          parameter_missing         = 1

          error_occured             = 2

          cancelled                 = 3

          permission_failure        = 4

          data_inconsistency        = 5

          OTHERS                    = 6.

**************************************************************************

Like I said – really really toxic – but what are you gonna do ?

************************************************************************** 

To report this post you need to login first.

8 Comments

You must be Logged on to comment or reply to a post.

  1. David Halitsky Post author
    Well, I was only off a litlle bit. Turns out that the type of the line of the table that comes back from SDOK_PHIO_LOAD_CONTENT is not compatible with the requirement to concatenate the line into an xstring (which is what BSP_UPDATE_MIMEREPOS wants to do. So instead, we use SO_OBJECT_DOWNLOAD to put the attachment to a file on disk, and then pass the path and name of this file to the load method of the picture control.

    The complete code (for a test of one attachment is as follows:

    CALL FUNCTION ‘BAPI_REL_GETRELATIONS’
    EXPORTING
    * this is ‘BUS2038’ plus qmnum (notification number)
    objectid = gs_objectid
    recursionlevel = 1
    IMPORTING
    return = v_rtrn
    TABLES
    listofrelations = i_listrel.

    LOOP AT i_listrel INTO gs_listrel
    WHERE ( reltype = ‘ATTA’ ).
    gd_objtype = gs_listrel-objtype_b.
    gd_objkey = gs_listrel-objkey_b.
    gd_objkey2 = gs_listrel-objkey_b.

    EXIT. ” simply take first attachment
    ENDLOOP.

    swc_create_object gd_obj1 gd_objtype gd_objkey.
    swc_get_property gd_obj1 ‘Description’ gd_objdes.
    swc_get_property gd_obj1 ‘FileExtension’ gd_fileext.

    WRITE: / gd_obj1-header, gd_obj1-type, gd_obj1-handle,
    gd_objdes,
    gd_fileext.

    CONCATENATE gd_objdes gd_fileext INTO v_file_name SEPARATED BY ‘.’.

    SELECT
    SINGLE phio_id
    INTO v_phio_id
    FROM soffphf
    WHERE file_name = v_file_name.

    PHIO_OBJECT-class = ‘SOFFPHIO’.
    PHIO_OBJECT-objid = v_phio_id.

    SELECT
    SINGLE phio_id
    INTO v_phio_id
    FROM soffphf
    WHERE file_name = v_file_name.

    PHIO_OBJECT-class = ‘SOFFPHIO’.
    PHIO_OBJECT-objid = v_phio_id.

    CALL FUNCTION ‘SDOK_PHIO_LOAD_CONTENT’
    EXPORTING
    OBJECT_ID = PHIO_OBJECT
    TEXT_AS_STREAM = ‘X’
    TABLES
    FILE_ACCESS_INFO = FILE_ACCESS_INFO
    FILE_CONTENT_ASCII = CONT_ASCII
    FILE_CONTENT_BINARY = CONT_BIN

    EXCEPTIONS
    NOT_EXISTING = 105
    NOT_AUTHORIZED = 1000
    NO_CONTENT = 105
    BAD_STORAGE_TYPE = 103
    OTHERS = 1000.

    READ TABLE FILE_ACCESS_INFO INDEX 1.
    IF SY-SUBRC <> 0.
    RAISE X_ERROR.
    ENDIF.
    FILESIZE = FILE_ACCESS_INFO-FILE_SIZE.

    PERFORM TABLE_COPY
    TABLES CONT_BIN
    solixtab “UNICODE 6.10
    CHANGING RCODE.

    IF RCODE NE 0.
    RAISE X_ERROR.
    ENDIF.

    CALL FUNCTION ‘SO_SOLIXTAB_TO_SOLITAB’ “UNICODE 6.10
    EXPORTING “UNICODE 6.10
    IP_SOLIXTAB = solixtab[] “UNICODE 6.10
    IMPORTING “UNICODE 6.10
    EP_SOLITAB = objcont[]. “UNICODE 6.10

    * * Correct table objcont
    check filesize ne ‘000000000000’. “Hack because of bug in KPro
    DESCRIBE FIELD WA_OBJCONT LENGTH LEN
    in character mode. “TR UNICODE
    data rest type i. “note 833448 >>
    rest = filesize mod len.
    if rest = 0.
    RIGHT_LINES = FILESIZE DIV LEN.
    else.
    RIGHT_LINES = ( FILESIZE DIV LEN ) + 1.
    endif. “note 833448 <<
    DEL_INDEX = RIGHT_LINES + 1.
    SIGNS_OF_LAST_LINE = FILESIZE MOD LEN.
    * * Delete superfluous lines
    DO.
    DELETE OBJCONT INDEX DEL_INDEX.
    IF SY-SUBRC NE 0.
    EXIT.
    ENDIF.
    ENDDO.
    * * Delete superfluous signs in last line
    if signs_of_last_line > 0. “note 833448 >>
    READ TABLE OBJCONT INDEX RIGHT_LINES INTO WA_OBJCONT.
    WA_OBJCONT+SIGNS_OF_LAST_LINE = SPACE.
    MODIFY OBJCONT INDEX RIGHT_LINES FROM WA_OBJCONT.
    endif. “note 833448 <<

    BIN_FILESIZE = filesize.
    CONCATENATE ‘G:\160_PM_Prototype\070_Dev\’
    v_file_name
    INTO path_and_file.

    CALL FUNCTION ‘SO_OBJECT_DOWNLOAD’
    EXPORTING
    BIN_FILESIZE = bin_FILESIZE
    DEFAULT_FILENAME = ‘ ‘
    FILETYPE = ‘BIN’
    PATH_AND_FILE = path_and_file
    EXTCT = ‘ ‘
    NO_DIALOG = ‘X’
    * IMPORTING
    * FILELENGTH =
    * F_CANCELLED =
    * ACT_FILETYPE =
    * ACT_FILENAME =
    TABLES
    OBJCONT = objcont
    EXCEPTIONS
    FILE_WRITE_ERROR = 1
    INVALID_TYPE = 2
    X_ERROR = 3
    KPRO_ERROR = 4
    OTHERS = 5.

    (0) 
  2. David Halitsky Post author
    Here it is:

    FORM TABLE_COPY TABLES   SOURCE_TAB
                             TARGET_TAB
                    CHANGING P_RCODE.

    DATA: AUX_TAB LIKE SOLI OCCURS 10.

    * * Init
      REFRESH TARGET_TAB.
    * * Compress table
      CALL FUNCTION ‘TABLE_COMPRESS’
    *        IMPORTING
    *             COMPRESSED_SIZE =
           TABLES
                IN              = SOURCE_TAB
                OUT             = AUX_TAB
           EXCEPTIONS
                COMPRESS_ERROR  = 1
                OTHERS          = 2
                .
      P_RCODE = SY-SUBRC.
      CASE P_RCODE.
        WHEN 0.
    *     * OK
        WHEN OTHERS.
          P_RCODE = 1000.
          EXIT.
      ENDCASE.
    * * Decompress table
      CALL FUNCTION ‘TABLE_DECOMPRESS’
           TABLES
                IN                   = AUX_TAB
                OUT                  = TARGET_TAB
           EXCEPTIONS
                COMPRESS_ERROR       = 1
                TABLE_NOT_COMPRESSED = 2
                OTHERS               = 3.
      REFRESH AUX_TAB.
      P_RCODE = SY-SUBRC.
      CASE P_RCODE.
        WHEN 0.
    *     * OK
        WHEN 2.
    *     * OK
          P_RCODE = 0.
        WHEN OTHERS.
          P_RCODE = 1000.
          EXIT.
      ENDCASE.

    ENDFORM.                               ” TABLE_COPY

    (0) 
  3. David Halitsky Post author
    be sure to use the function SO_ATTACHMENT_LIST_READ and follow-on functions to get your content.  (See program SAPMSSOM.)  The code as given works, but there’s no way to index file-name in SOFFPHF, so a full-table scan will be invoked by this select:

      SELECT
      SINGLE phio_id
        INTO v_phio_id
        FROM soffphf
       WHERE file_name = v_file_name.

    This select was just a cheat to get something working because the pressure from global HQ for a demo has been so intense …

    Also, please recall again that all this code can be replaced by one line:

    call method cl_bds_document_set->get_with_url

    once you have a HTTP content server working (SAP’s or a third-party’s.)

    (0) 
  4. David Halitsky Post author
    When BAPI_REL_GETRELATIONS returns an object key for object type MESSAGE like:

    FOL23000000000004EXT32000000001320         

    you can take this value directly into SRGBTBREL using the secondary index on INSTID_B.  The returned row will give you the PHIO_ID as
    the column BRELGUID:

    46AB6A696021005A020000000A2A0866

    And this, of course, is also the PHIO_ID that you have to use to go into SOFFCONT1 to pick up the binary for your graphic attachment.

    This method is not only fail-safe (the PHIO_ID is unique per attachment), but also relies on indexed reads all the way through.

    Thanks again to aRS for providing the critical “intersection” table SRGBTBREL.

    (0) 
  5. David Halitsky Post author
    SRGBTBREL-BREELGUID is not the end of the story … you have to perform a subtraction of 4 on the hex in positions 5-7 (offset 0) of srgbtbrel-brelguid in order to get the correct phio_id in SOFFCONT1 (and SOFFPHIO and SOFFPHF).

    Here are three examples:

    [code]
              1         2         3
    01234567890123456789012345678901
         |||
    46AC9DEB9ABF0075000000000A2A0866  SRGBTBREL
    46AC9DE79ABF0075000000000A2A0866  SOFFCONT1
         |||
    46AC9DF79ABF0075000000000A2A0866  SRGBTBREL
    46AC9DF39ABF0075000000000A2A0866  SOFFCONT1
         |||     
    46AC9E039ABF0075000000000A2A0866  SRGBTBREL 
    46AC9DFF9ABF0075000000000A2A0866  SOFFCONT1

    [/code]

    (0) 
  6. David Halitsky Post author
    BAPI_REL_GETRELATIONS returns:

    *RELTYPE     C     4      URL
    *RELATIONID     C     22      
    *UTCTIME     P     8       20070729190750
    *LOG_SYSTEM     C     10      BFSD030
    *OBJKEY_A     C     70      000200266362
    *OBJTYPE_A     C     10      BUS2038
    *LOGSYS_A     C     10      
    *LEVEL_A     N     2      00
    *ROLETYPE_A     C     10      APPLOBJ
    *ROLEID_A     C     22      
    *UTCTIME_A     P     8                    0
    *OBJKEY_B     C     70      FOL23000000000004URL32000000000033
    *OBJTYPE_B     C     10      MESSAGE
    *LOGSYS_B     C     10      
    *LEVEL_B     N     2      00
    *ROLETYPE_B     C     10      WEB_SITE
    *ROLEID_B     C     22      
    *UTCTIME_B     P     8                    0

    Then objkey_b returns this from srgbtbrel:

    *CLIENT      030
    *BRELGUID    46ACE1CFDD1B0059000000000A2A0866
    *RELTYPE     URL
    *INSTID A    000200266362
    *TYPEID A    BUS2038
    *CATID A     BO
    *INSTID B    FOL23000000000004URL32000000000033
    *TYPEID B    MESSAGE
    *CATID B     BO
    *LOGSYS A
    *ARCH A
    *LOGSYS B
    *ARCH B
    *UTCTIME     20,070,729,190,750
    *HOMESYS

    But where do I get the actual HTTP url for the attachment ?????

    Thanks for whatever help you can provide.
    djh

    (0) 
  7. David Halitsky Post author
    On old systems (non-BDS, non-ContentServer), SO_OBJECT_READ can (must?) be used to get the LOIO_ID of an “EXT” (non-URL) attachment so that you can then take the LOIO_ID into SOFFPHIO to get the PHIO_ID to take into SOFFCONT1 when you call SDOK_PHIO_LOAD_CONTENT.

    This is just like using SO_DOCUMENT_READ_API1 to get the actual URL when BAPI_REL_GETRELATIONS returns a reltype of “URL”.

    The only difference is that when BAPI_REL_GETRELATIONS returns a reltype of ATTA, you pass the first 17 bytes of objkey_b as fol_id to SO_OBJECT_READ and the second 17 bytes of objkey_b as doc_id to SO_OBJECT_READ.

    See “program” SAPLSO32 and the forms/function modules therein.

    (0) 

Leave a Reply