Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

REPORT : INSERT : SUBMIT

Former Member
0 Likes
2,190

??

If I understand correctly .. if one builds a dynamic program; each time the "authoring" program is run, the generated code gets over written. What happens in the case where two or more users execute the "authoring" code during the lifecycle of the others ??

Assuming (likely incorrectly) that the second user would destroy the first's; I attached a ID tag to the name of the generated report code. Unfortunately I can't see how to pass the report name + tag to the submit statement.

ideas ???

1 ACCEPTED SOLUTION
Read only

Clemenss
Active Contributor
0 Likes
1,946

Hi David,

the generated code needs a name. If the name is static, it can be created only once using the name. If the name of the generated program/subroutine pool is determined dynamically, it wont work.

The idea with the tag is nice if you can make sure the tag is unique. For SUBMIt, just CONCATENATE <repname> <tag> into <taggedrepname> and SUBMIT (<taggedrepname>).

Regards,

Clemens

14 REPLIES 14
Read only

Former Member
0 Likes
1,946

I guess that both programs should be generated on separate memory areas...So there's no problem if 2 users generate it at the same time...

Greetings,

Blag.

Read only

Clemenss
Active Contributor
0 Likes
1,947

Hi David,

the generated code needs a name. If the name is static, it can be created only once using the name. If the name of the generated program/subroutine pool is determined dynamically, it wont work.

The idea with the tag is nice if you can make sure the tag is unique. For SUBMIt, just CONCATENATE <repname> <tag> into <taggedrepname> and SUBMIT (<taggedrepname>).

Regards,

Clemens

Read only

Former Member
0 Likes
1,946

THANKS Folks .. seems the question remains ..

until such time when I can prove it via testing and/or get a definitive answer I'll maintain my assumtion it's "possible" a second users generated code of the same name will overwrite or at least raise some havoc ..

I've chosen to concatenate the clients username to the name of the generated report. My attempts to use the same to pass to the submit failed, so I employed a kludge .. I created a second report which calls the submit using the concatenated report name + username. This unfortunately presents the very same issue/concern, but as this report only contains one line of code, it would seem very unlikely any two users would call it simultaneously ..

THOUGHTS ???

Read only

Former Member
0 Likes
1,946

I've been watching this thread for a couple of days... yes, I'd agree that you don't want two users creating programs with the same name at the same time.

Which part of the dynamic submit isn't working for you. You should be able to do something like:



data:
  l_my_program          like trdir-name.

  get time.
  concatenate 'Z_' sy-datum sy-uzeit sy-uname 
    into l_my_program.                        "make (near)unique name
  insert report l_my_report from gt_source.   "insert into system
  submit (l_my_report) and return.            "do dynamic submit using brackets
  delete report l_my_report.                  "tidy up if needed

so I'm a bit confused what "kludge" you've needed to take. If you did need to use a single program name for all users, you could use a lock object to prevent multiple people creating at the same time i.e. enqueue, create program, run program, delete program, release enqueue.

Jonathan

Read only

Former Member
0 Likes
1,946

THANKS Jonathan ..

The Syntax SUBMIT (RepName) and RETURN. Results in a Report not found error.

It seems this should work .. ??

Read only

0 Likes
1,946

Hi..

Since the Report is called dynamically it will give the Dump if the Report does not exist.

So you can check this way.

Tables TRDIR.

Select single * from TRDIR where Name = RepName and Subc = '1'.

if sy-subrc = 0.

SUBMIT (RepName) and RETURN.

endif.

<b>Reward if Helpful.</b>

Read only

Former Member
0 Likes
1,946

Did you get this sorted...? If not, below is an expansion on my code snippet above, and there are a couple of ways of executing the dynamic code i.e. submit and external perform. This worked for me so if you hit an error then you might need to check authorisations perhaps.

Jonathan

report zlocal_jc_dynamic_submit.

types:
  gty_source(72)        type c.

start-of-selection.
  perform generate_program.

*&---------------------------------------------------------------------*
*&      Form  generate_program
*&---------------------------------------------------------------------*
form generate_program.
*" coding on the fly...
  data:
    l_name              type trdir-name,
    lt_source           type gty_source occurs 10,
    l_my_report         like trdir-name.

  get time.
*"make (near)unique name
  concatenate 'Z_' sy-datum sy-uzeit sy-uname
    into l_my_report.

  select single name into l_name
    from trdir
    where name = l_my_report.
  if sy-subrc is initial. "already exists
    write: / 'Already exists ... bad'.
    exit.
  endif.

*"build report
  perform lt_source_fill
    tables
      lt_source
    using
      l_my_report.

*"insert into system
  insert report l_my_report from lt_source.

*"do dynamic submit using brackets
  submit (l_my_report) and return.

*"try just using the subroutine in generated code instead...
  perform write_repid in program (l_my_report) if found.

*"tidy up if needed
  delete report l_my_report.

endform.                    "generate_program

*&---------------------------------------------------------------------*
*&      Form  lt_source_fill
*&---------------------------------------------------------------------*
form lt_source_fill
  tables
    ot_source
  using
    i_name              like trdir-name.
*" build dynamic code..
  data:
    l_source            type gty_source.

  clear: ot_source, ot_source[].

  concatenate 'report~' i_name '.' into l_source.
  translate l_source using '~ '.
  append l_source to ot_source.

  append 'start-of-selection.'     to ot_source.
  append '  perform write_repid.'  to ot_source.

  append 'form write_repid.  '      to ot_source.
  append '  write / sy-repid.'      to ot_source.
  append 'endform.           '      to ot_source.

endform.                    "lt_source_fill

Read only

Former Member
0 Likes
1,946

Jonathan .. THANK YOU .. you've been very helpful ..

Honestly .. I'd set this issue to the background .. have others I've been beating my head against my monitor with. It's always fun learning a new language/IDE.

Soon as I get over my latest hump, I'll be sure to give your method a whirl.

Let me bear on your experience with my current issue if I may.

The app I'm developing is completely dynamic. Perhaps I'm architecting it incorrectly but here's the scenario.

Within a RFC I import a number of 'aligned' Char vars, each of which contains deliminated data. The vars are fieldname, data type, fieldwidth, and field data. As none of the values are know till runtime, I use the RFC to parse the vars and build a REPORT which defines a struc/table and populates it. All's good until I attempt to populate the table. If I try Tab_Name-Field_Name = where Tab_Name and Field_Name are variables I receive a "Tab_Name-Field_Name" is not defined error.

If I use a Move/Write employing offsets, the code works with Chars as data, but if I attempt I/F/D I receive "The structure TABLINE+PNTR(F_WIDTH) does not start with a character type field. In unicode programs in such cases offset/length declarations are not allowed."

Most of the methods to populate tab data (and their code examples) work when the tabname/fieldname are know prior to runtime.

THOUGHTS ???

Read only

Clemenss
Active Contributor
0 Likes
1,946

Hi David,

whenever you have components not known before runtime, it's time to use field-symbols.

This is how to use:

<pre>

field-symbols:

<anyfield> type any,

<anystruc> type any.

data:

lv_fieldname type fieldname.

lv_fieldname = 'DMBTR'. "just an example

  • whatever yor dynamicaly created structure is like,

ASSIGN {your structure} to <anystruc> .

ASSIGN COMPONENT (lv_fielname) OF STRUCTURE <anystruc> to <anyfield>.

IF SY-SUBRC = 0.

<anyfield> = '3.14'. "just an example

ELSE:

WRITE: / 'Field', lv_fielname, 'is not part of the structure'.

ENDIF.

</pre>

Note: The field-symbol is something like a pointer. It represents the existing data storage location it has been assigned to.

Regards,

Clemens

Read only

Former Member
0 Likes
1,946

THANKS Clemens ..

That's what I'm playing w/ as we speak ..

THANKS !!!!!!

Read only

Former Member
0 Likes
1,946

FOLKS .. THANKS so much for your assist .. I'm at 99.9% ..

couldn't have gotten there w/o your assist.

Read only

Former Member
0 Likes
1,946

basically an unitiated ABAP novice was and greatly appreciates the assistance of forum members

Read only

Former Member
0 Likes
1,946

he's back ..

OK .. now I have an odd one. NOTE the code below. As this is my very first ABAP effort I'd appreciate your critique. Please be brutal, if you have a better way please advise.

In debug mode this code runs fine .. if I attempt to run it real time it blow up.

Short Dump reveals "GETWA_NOT_ASSIGNED". I Beleive the error occurs at the ASSIGN COMPONENT statement.

Please advise best course .. THANKS ..

also if someone could show me w/ code examples how to commit the created itab to a dbate table viewable via SE11 I'd be deeply indebted ..

FUNCTION Z_MYTEST .

*"----


""Local Interface:

*" IMPORTING

*" VALUE(ROWS) TYPE INTEGER

*" VALUE(COLS) TYPE INTEGER

*" VALUE(NAME) TYPE CHAR30

*" VALUE(FIELD_NAMES) TYPE CHAR1024

*" VALUE(ROWDATA) TYPE CHAR1024

*" VALUE(COL_WIDTH) TYPE CHAR1024

*" VALUE(DATA_TYPE) TYPE CHAR1024

*" VALUE(USER) TYPE CHAR30

*" EXPORTING

*" VALUE(SAP_MESSAGE) TYPE CHAR1024

*" VALUE(ROWDATA1) TYPE CHAR1024

*" VALUE(COLS1) TYPE INTEGER

*" VALUE(DELIM1) TYPE CHAR1

*" VALUE(FIELD_NAMES1) TYPE CHAR1024

*"----


DATA F_CNT TYPE INTEGER.

DATA F_NAME TYPE CHAR30.

DATA F_TYPE TYPE CHAR2.

DATA F_WIDTH TYPE CHAR3.

DATA DELIM TYPE C VALUE '|'.

DATA REPNAME TYPE CHAR30.

DATA TMP TYPE CHAR72.

DATA: FM type CHAR24.

DATA: TABNAME type CHAR30.

DATA: F_DAT TYPE CHAR1024.

ROWDATA1 = ROWDATA.

COLS1 = COLS.

DELIM1 = DELIM.

FIELD_NAMES1 = FIELD_NAMES.

CONCATENATE USER 'A' into TMP.

EXPORT ROWDATA1 TO MEMORY ID TMP.

CONCATENATE USER 'B' into TMP.

EXPORT DELIM1 TO MEMORY ID TMP.

CONCATENATE USER 'C' into TMP.

EXPORT COLS1 TO MEMORY ID TMP.

CONCATENATE USER 'D' into TMP.

EXPORT FIELD_NAMES1 TO MEMORY ID TMP.

DATA CODE TYPE TABLE OF rssource-line.

CONCATENATE 'Z_Bld_Struc_' USER into REPNAME.

CONCATENATE 'REPORT' REPNAME '.' into TMP SEPARATED BY SPACE.

APPEND TMP TO CODE.

APPEND 'TYPES: BEGIN OF mySTRUC,' to CODE.

F_CNT = COLS.

WHILE F_CNT > 0.

SPLIT FIELD_NAMES AT DELIM INTO F_NAME FIELD_NAMES.

SPLIT DATA_TYPE AT DELIM INTO F_TYPE DATA_TYPE.

SPLIT COL_WIDTH AT DELIM INTO F_WIDTH COL_WIDTH.

IF F_TYPE = 'C'.

F_TYPE = ' C'.

CONCATENATE F_NAME'(' F_WIDTH') TYPE' F_TYPE',' into TMP.

APPEND TMP TO CODE.

ELSE.

CONCATENATE F_NAME 'TYPE' F_TYPE ',' into TMP SEPARATED BY SPACE.

APPEND TMP TO CODE.

ENDIF.

F_CNT = F_CNT - 1.

ENDWHILE.

APPEND 'END OF mySTRUC.' to CODE.

APPEND 'FIELD-SYMBOLS:' to CODE.

APPEND '<theStruc> TYPE ANY,' to Code.

Append '<theField> TYPE ANY.' to CODE.

APPEND 'DATA: ROWDATA1 TYPE CHAR1024.' to CODE.

APPEND 'DATA: DELIM1 TYPE CHAR1.' to CODE.

APPEND 'DATA: FIELD_NAMES1 TYPE CHAR1024.' to CODE.

APPEND 'DATA: DATA_TYPE1 TYPE CHAR1024.' to CODE.

APPEND 'DATA: COLS1 TYPE INTEGER.' to CODE.

APPEND 'DATA: TABLINE TYPE myStruc.' to CODE.

APPEND 'DATA: F_DAT TYPE CHAR1024.' to CODE.

APPEND 'DATA: F_NAME1 TYPE CHAR30.' to CODE.

CONCATENATE 'DATA:' NAME 'TYPE STANDARD TABLE OF mySTRUC WITH DEFAULT KEY.' into TMP SEPARATED BY SPACE.

APPEND TMP TO CODE.

CONCATENATE 'IMPORT ROWDATA1 FROM MEMORY ID ' '''' USER 'A' '''' '.' INTO TMP.

APPEND TMP TO CODE.

CONCATENATE 'IMPORT DELIM1 FROM MEMORY ID ' '''' USER 'B' '''' '.' INTO TMP.

APPEND TMP TO CODE.

CONCATENATE 'IMPORT COLS1 FROM MEMORY ID ' '''' USER 'C' '''' '.' INTO TMP.

APPEND TMP TO CODE.

CONCATENATE 'IMPORT FIELD_NAMES1 FROM MEMORY ID ' '''' USER 'D' '''' '.' INTO TMP.

APPEND TMP TO CODE.

APPEND 'ASSIGN TABLINE TO <theStruc>.' TO CODE.

APPEND 'WHILE COLS1 > 0.' TO CODE.

APPEND 'SPLIT ROWDATA1 AT DELIM1 INTO F_DAT ROWDATA1.' TO CODE.

APPEND 'SPLIT FIELD_NAMES1 AT DELIM1 INTO F_NAME1 FIELD_NAMES1.' TO CODE.

APPEND 'Sy-subrc = 4.' TO CODE.

APPEND 'ASSIGN COMPONENT F_NAME1 OF STRUCTURE <theStruc> to <theField>.' TO CODE.

APPEND '<theField> = F_DAT.' to CODE.

APPEND 'COLS1 = COLS1 - 1.' TO CODE.

APPEND 'ENDWHILE.' TO CODE.

CONCATENATE 'APPEND TABLINE TO' NAME '.' INTO TMP SEPARATED BY SPACE.

APPEND TMP TO CODE.

CONCATENATE '''' 'DDIF_TABL_ACTIVATE' '''' into FM.

CONCATENATE '''' NAME '''' into TABNAME.

CONCATENATE 'CALL FUNCTION' FM 'EXPORTING NAME =' TABNAME '.' into TMP SEPARATED BY SPACE.

APPEND TMP TO CODE.

*CONCATENATE '''' 'TR_TADIR_INTERFACE' '''' into FM.

*CONCATENATE 'CALL FUNCTION' FM into TMP SEPARATED BY SPACE.

*APPEND TMP TO CODE.

*CONCATENATE 'EXPORTING WI_TADIR_OBJECT =' TABNAME '.' into TMP SEPARATED BY SPACE.

*APPEND TMP TO CODE.

INSERT REPORT REPNAME FROM CODE.

CLEAR Code.

APPEND 'REPORT RunCode.' to CODE.

CONCATENATE 'SUBMIT' REPNAME 'AND RETURN.' into TMP SEPARATED BY SPACE.

APPEND TMP TO CODE.

INSERT REPORT 'RunCode' FROM CODE.

SUBMIT RunCode AND RETURN.

SAP_MESSAGE = 'Table Created'.

ENDFUNCTION.

========================================

REPORT Z_Bld_Struc_BRENCHLEY .

TYPES: BEGIN OF mySTRUC,

A TYPE I ,

B TYPE F ,

C TYPE D ,

D(4) TYPE C,

E TYPE T ,

END OF mySTRUC.

FIELD-SYMBOLS:

<theStruc> TYPE ANY,

<theField> TYPE ANY.

DATA: ROWDATA1 TYPE CHAR1024.

DATA: DELIM1 TYPE CHAR1.

DATA: FIELD_NAMES1 TYPE CHAR1024.

DATA: DATA_TYPE1 TYPE CHAR1024.

DATA: COLS1 TYPE INTEGER.

DATA: TABLINE TYPE myStruc.

DATA: F_DAT TYPE CHAR1024.

DATA: F_NAME1 TYPE CHAR30.

DATA: ZX TYPE STANDARD TABLE OF mySTRUC WITH DEFAULT KEY.

IMPORT ROWDATA1 FROM MEMORY ID'BRENCHLEYA'.

IMPORT DELIM1 FROM MEMORY ID'BRENCHLEYB'.

IMPORT COLS1 FROM MEMORY ID'BRENCHLEYC'.

IMPORT FIELD_NAMES1 FROM MEMORY ID'BRENCHLEYD'.

ASSIGN TABLINE TO <theStruc>.

WHILE COLS1 > 0.

SPLIT ROWDATA1 AT DELIM1 INTO F_DAT ROWDATA1.

SPLIT FIELD_NAMES1 AT DELIM1 INTO F_NAME1 FIELD_NAMES1.

ASSIGN COMPONENT F_NAME1 OF STRUCTURE <theStruc> to <theField>.

<theField> = F_DAT.

COLS1 = COLS1 - 1.

ENDWHILE.

APPEND TABLINE TO ZX .

Read only

0 Likes
1,946

Hi David,

my most brutal critique is that you should paste your code here, than select it with the mouse and press the 'Code' button above. This preserves the formatting and boosts readability.

The rest is a case of taste. If you look at code here or in the SAP system, you will see so much that leads to questions...

"In debug mode this code runs fine .. if I attempt to run it real time it blow up." - No, this should not happen with the kind of code you posted here.

As I recommended earlier, you should check the success of every assign (at least in developing phase) and issue a message instead of risking a dump.

And if you got a dump, you may analize a little bit further. In the shortdump listing you have different sections. One will show a code excerpt with the code line where it dumped specially marked. You will also find the contents (values) of many (if not all) variables right when the dump occured. That means you can see in the dump what you should have reported :-).

But I think you may get it working.

Honestly said: I don't like this runtime-generation of code. I know it is possible. Batch-Input is possible too. I don't like it. It's kind of ugly.

And if you really need it: The new systems run on BASIS an ABAP 700, you have obects and classes like CL_ABAP_TABLEDESCR which has a method CREATE.

I can't find the example now, it has been posted and linked here a couple of times.

Ah, found a demo program (thanks to the author!) that shows you how to create a table without generating a report.

Hope this will give you some idea...

[it is really well documented and good to understand]


REPORT ZDANY_DYN_LOCAL_TYPES.
 
****************** hardcoded "old style" local type *******************
* This is a normal hardcoded local type
 types : begin of typ_hardcoded,
         l_count type i,
         lt_sflight type sflight.
 types : end of typ_hardcoded.
* create a table based on hardcoded type
 data : lt_hardcoded type table of typ_hardcoded.
 
****************** dynamic "new wave" local type *******************
 types: typ_count type i.
 
 field-symbols : <lt_dynamic> type any table.
 data: dref type ref to data,
       itab_type type ref to cl_abap_tabledescr,
       struct_type type ref to cl_abap_structdescr,
       elem_type type ref to cl_abap_elemdescr,
       comp_tab type cl_abap_structdescr=>component_table,
       comp_fld type cl_abap_structdescr=>component.
 
* We read information about each fields of SFLIGHT (see ABAP FAQ #2)
struct_type ?= cl_abap_typedescr=>describe_by_name( 'SFLIGHT' ).
 
* We also need the information about the type "typ_count", note that
* we should use class cl_abap_elemdescr instead of cl_abap_typedescr
elem_type ?= cl_abap_elemdescr=>describe_by_name( 'TYP_COUNT' ).
 
* we read all fleids of SFLIGHT and create a component table
comp_tab = struct_type->get_components( ).
 
* We add manually the counter
comp_fld-name = 'L_COUNT'.
comp_fld-type = elem_type.
insert comp_fld into comp_tab index 1.
 
* we create the structure
struct_type = cl_abap_structdescr=>create( comp_tab ).
 
* ... and the internal table
itab_type = cl_abap_tabledescr=>create( struct_type ).
 
* The new thing here is the "type handle" which create a pointer to a
* handle
create data dref type handle itab_type.
 
* we finally assign a field symbol to the pointer because we cannot
* directly access a pointer.
assign dref->* to <lt_dynamic>.
 
* At the end of this small program, internal table lt_hardcoded and
* lt_dynamic are the same
break-point.

Regards,

Clemens

P.S.: You should close the thread and start another one for the next question.