So, the good people at Edenhouse decided to send me on some Cloud For Customer development training. Aside from the premium experience that SAP offer at their training facilities, and some time away from my lovely family, this was a great chance to try out some of the new C4C development environment.
My first impressions are that you can develop quite a lot of stuff in quite a short period of time. I think it's a lot like Apple products - what they do do, they do incredibly well - but I can already see the limitations...more on that later.
Just by creating an object in the ABAP Scripting Language (ABSL), and running a few wizards, you have a variety of CRUD operations, a table, and query facilities. It was all mind-blowingly quick to develop. I think this will satisfy lots of end users, and they can just get on with their business processes.
I can, however imagine a lot of users saying "Can you make it do...<insert esoteric request here>" and we'll have to just say "No".
It can call WebServices though... this is where it'll get super-good. We'll WS to the R3 backend, and then we'll have the best of both worlds!
I've not got my own development environment yet, so can't do any vids or tuts, but as soon as I've got it together, I'll throw some material up.
Oh, and by the way, Happy Christmas Everyone!!
Tuesday, 23 December 2014
Thursday, 20 November 2014
Squishing an unpredictable address structure...
We've all been there - address structures can be unpredictable, and you need to output them in a consistent format... The following ABAP code sample allows you to take the ADRC structure, put them into some kind of priority, split into a table, ignore the blank lines, and then concatenate into the final target field...
types: begin of tty_addr,
addrline type char255,
end of tty_addr.
data: t_addrlines type table of tty_addr,
w_addrlines type tty_addr.
data: w_adrc type adrc.
select single * from adrc into w_adrc where ADDRNUMBER = l_adrnr.
check sy-subrc = 0.
concatenate w_adrc-name_text
w_adrc-street
w_adrc-city1
w_adrc-STR_SUPPL1
w_adrc-STR_SUPPL2
w_adrc-STR_SUPPL3
w_arc-POST_CODE1
w_arc-POST_CODE2
w_arc-POST_CODE3
"Whatever fields MIGHT be populated from ADRC...
into l_DispatchAddress separated by '<&,>'.
split l_DispatchAddress at '<&,>' into table t_addrlines.
clear l_DispatchAddress.
loop at t_addrlines into w_addrlines.
if w_addrlines is not initial.
concatenate l_DispatchAddress w_addrlines-addrline into l_DispatchAddress separated by ', '.
endif.
endloop.
types: begin of tty_addr,
addrline type char255,
end of tty_addr.
data: t_addrlines type table of tty_addr,
w_addrlines type tty_addr.
data: w_adrc type adrc.
select single * from adrc into w_adrc where ADDRNUMBER = l_adrnr.
check sy-subrc = 0.
concatenate w_adrc-name_text
w_adrc-street
w_adrc-city1
w_adrc-STR_SUPPL1
w_adrc-STR_SUPPL2
w_adrc-STR_SUPPL3
w_arc-POST_CODE1
w_arc-POST_CODE2
w_arc-POST_CODE3
"Whatever fields MIGHT be populated from ADRC...
into l_DispatchAddress separated by '<&,>'.
split l_DispatchAddress at '<&,>' into table t_addrlines.
clear l_DispatchAddress.
loop at t_addrlines into w_addrlines.
if w_addrlines is not initial.
concatenate l_DispatchAddress w_addrlines-addrline into l_DispatchAddress separated by ', '.
endif.
endloop.
Wednesday, 29 October 2014
Stupid Flowerboxes
This one is roughly the same size as the form it's describing, and tells us absolutely nothing useful. Needless to say I scrubbed this pollution as quickly as I could, and got on with my code... (after ShamingButNotNaming on my blog, of course...)
Tuesday, 28 October 2014
Iterate Up the HR Structure
Thanks to Kat for this one... I've got to get the UserID of the Users Manager... trouble is, sometimes the OrgStructure positions aren't filled - so I have to see who's sitting in the position. If there's no-one in it, then I loop back round and get the OrgStructure's superior position (since there's no Personnel person to check on!). I repeat this until I find someone, and stop at 20 goes... If this has happened, it's either
the guy at the top of the tree (we try 20 times to work out if the guy has a useful boss, but fail because it's Paul Solomon :)
OR
there's such a massive Org Structure that's not populated with stuff, that you should probably question what the point of the structure is!!
do 20 times. "Don't want to infinite loop...
refresh t_leadpos.
CALL FUNCTION 'RH_GET_LEADING_POSITION'
EXPORTING
plvar = w_plvar
otype = l_otype "can be US (user), P (Person), S (position) or O (Org unit)
sobid = l_sobid
date = sy-datum
auth = ' '
TABLES
leading_pos = t_leadpos
EXCEPTIONS
no_lead_pos_found = 1
OTHERS = 2.
check t_leadpos[] is not initial.
read table t_leadpos into w_leadpos index 1.
REFRESH t_holders.
CALL FUNCTION 'HRWPC_RFC_PP_HOLDERS'
EXPORTING
plvar = w_plvar "usually 01
otype = 'S'
objid = w_leadpos-objid "from above table read
TABLES
holder = t_holders
EXCEPTIONS
no_active_plvar = 1
infty_not_found = 2
nothing_found = 3
OTHERS = 4.
IF sy-subrc = 0 AND t_holders IS NOT INITIAL.
READ TABLE t_holders INTO w_holders INDEX 1.
read table t_pa0105 into w_pa0105 with key pernr = w_holders-pernr
subty = '0001'.
if sy-subrc = 0.
p_output-manager = w_pa0105-usrid.
exit.
endif.
else. "Didn't find holders for the position... Go and find the Super-Position.
l_otype = w_leadpos-otype. "Probably 'S' but hey, let's make it dynamic.
l_sobid = w_leadpos-objid.
endif. "Found holders for the position.
enddo. "Iterate up the structure.
the guy at the top of the tree (we try 20 times to work out if the guy has a useful boss, but fail because it's Paul Solomon :)
OR
there's such a massive Org Structure that's not populated with stuff, that you should probably question what the point of the structure is!!
do 20 times. "Don't want to infinite loop...
refresh t_leadpos.
CALL FUNCTION 'RH_GET_LEADING_POSITION'
EXPORTING
plvar = w_plvar
otype = l_otype "can be US (user), P (Person), S (position) or O (Org unit)
sobid = l_sobid
date = sy-datum
auth = ' '
TABLES
leading_pos = t_leadpos
EXCEPTIONS
no_lead_pos_found = 1
OTHERS = 2.
check t_leadpos[] is not initial.
read table t_leadpos into w_leadpos index 1.
REFRESH t_holders.
CALL FUNCTION 'HRWPC_RFC_PP_HOLDERS'
EXPORTING
plvar = w_plvar "usually 01
otype = 'S'
objid = w_leadpos-objid "from above table read
TABLES
holder = t_holders
EXCEPTIONS
no_active_plvar = 1
infty_not_found = 2
nothing_found = 3
OTHERS = 4.
IF sy-subrc = 0 AND t_holders IS NOT INITIAL.
READ TABLE t_holders INTO w_holders INDEX 1.
read table t_pa0105 into w_pa0105 with key pernr = w_holders-pernr
subty = '0001'.
if sy-subrc = 0.
p_output-manager = w_pa0105-usrid.
exit.
endif.
else. "Didn't find holders for the position... Go and find the Super-Position.
l_otype = w_leadpos-otype. "Probably 'S' but hey, let's make it dynamic.
l_sobid = w_leadpos-objid.
endif. "Found holders for the position.
enddo. "Iterate up the structure.
Tuesday, 14 October 2014
Creating an Invoice...
Clearly you'll need to make sure that the GLAccounts, Payment Terms etc exist, but feel free to use this as a template to create your Invoices...
*&---------------------------------------------------------------------*
*& Include Z_PD_CAPS1_DEMOS_INV_CREATE *
*&---------------------------------------------------------------------*
data:
obj_type like bapiache02-obj_type,
obj_key like bapiache02-obj_key,
obj_sys like bapiache02-obj_sys,
documentheader like bapiache09,
accountgl like bapiacgl09 occurs 0 with header line,
tax_accountgl like bapiacgl09 OCCURS 0 WITH HEADER LINE,
currencyamount like bapiaccr09 occurs 0 with header line,
tax_currencyamount like bapiaccr09 OCCURS 0 WITH HEADER LINE,
return like bapiret2 occurs 0 with header line,
extension1 like bapiextc occurs 0 with header line,
t_edidd like edidd occurs 0 with header line,
bapi_retn_info like bapiret2 occurs 0 with header line.
data: error_flag.
data: wa_akont TYPE akont.
data: t_accountreceivable TYPE TABLE OF BAPIACAR09 WITH HEADER LINE.
datA: T_MWDAT TYPE TABLE OF RTAX1U15 WITH HEADER LINE.
data: wa_wrbtr type wrbtr.
data: curr_li TYPE POSNR_ACC.
data: v_tabix like sy-tabix.
documentheader-username = sy-uname.
documentheader-header_txt = 'Test using BAPI'.
documentheader-comp_code = 'CF01'.
documentheader-doc_date = sy-datum.
documentheader-pstng_date = sy-datum.
documentheader-doc_type = 'SA'.
documentheader-REF_DOC_NO = 'INVOICE_01'.
clear accountgl.
clear wa_akont.
t_accountreceivable-ITEMNO_ACC = '1'.
t_accountreceivable-customer = 'C524'.
"t_accountreceivable-TAX_CODE = 'A1'.
t_accountreceivable-gl_account = '0000400000'.
t_accountreceivable-PMNTTRMS = 'Z030'.
t_accountreceivable-ALLOC_NMBR = 'LORDS0820'.
t_accountreceivable-ITEM_TEXT = 'Facility Name'.
append t_accountreceivable.
accountgl-itemno_acc = '2'.
accountgl-gl_account = '0000802010'.
accountgl-comp_code = 'CF01'.
accountgl-pstng_date = sy-datum.
accountgl-doc_type = 'SA'.
accountgl-profit_ctr = '0000069314'.
"accountgl-costcenter = '0069314001'.
accountgl-ITEM_TEXT = 'Item Text'.
accountgl-ORDERID = 'LORDS0820'.
accountgl-TAX_CODE = 'A0'.
append accountgl.
clear accountgl.
accountgl-itemno_acc = '3'.
accountgl-gl_account = '0000802010'.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
INPUT = accountgl-gl_account
IMPORTING
OUTPUT = accountgl-gl_account.
accountgl-ITEM_TEXT = 'Item Text'.
accountgl-ORDERID = 'LORDS0820'.
accountgl-comp_code = 'CF01'.
accountgl-pstng_date = sy-datum.
accountgl-doc_type = 'SA'.
accountgl-TAX_CODE = 'A1'.
append accountgl.
clear accountgl.
accountgl-itemno_acc = '4'.
accountgl-gl_account = '0000711350'.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
INPUT = accountgl-gl_account
IMPORTING
OUTPUT = accountgl-gl_account.
.
accountgl-comp_code = 'CF01'.
accountgl-pstng_date = sy-datum.
accountgl-doc_type = 'SA'.
accountgl-TAX_CODE = 'V0'.
accountgl-costcenter = '69314001'.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
INPUT = accountgl-costcenter
IMPORTING
OUTPUT = accountgl-costcenter.
append accountgl.
currencyamount-itemno_acc = '1'.
currencyamount-currency = 'GBP'.
currencyamount-amt_doccur = '470.00'.
append currencyamount.
currencyamount-itemno_acc = '2'.
currencyamount-currency = 'GBP'.
currencyamount-amt_doccur = '-230.00'.
append currencyamount.
currencyamount-itemno_acc = '3'.
currencyamount-currency = 'GBP'.
currencyamount-amt_doccur = '-235.00'.
append currencyamount.
currencyamount-itemno_acc = '4'.
currencyamount-currency = 'GBP'.
currencyamount-amt_doccur = '-5.00'.
append currencyamount.
"PD We're now calculating the tax. Need to calculate any tax at the
"appropriate rate.
"work out the first line that tax can go on.
loop at accountgl.
endloop.
curr_li = accountgl-ITEMNO_ACC.
curr_li = curr_li + 1.
loop at accountgl.
READ TABLE currencyamount with key ITEMNO_ACC =
accountgl-ITEMNO_ACC.
check sy-subrc = 0.
v_tabix = sy-tabix.
wa_wrbtr = currencyamount-amt_doccur.
CALL FUNCTION 'CALCULATE_TAX_FROM_GROSSAMOUNT'
EXPORTING
I_BUKRS = accountgl-comp_code
I_MWSKZ = accountgl-TAX_CODE
I_WAERS = currencyamount-currency
I_WRBTR = wa_wrbtr
TABLES
T_MWDAT = t_mwdat
EXCEPTIONS
BUKRS_NOT_FOUND = 1
COUNTRY_NOT_FOUND = 2
MWSKZ_NOT_DEFINED = 3
MWSKZ_NOT_VALID = 4
ACCOUNT_NOT_FOUND = 5
DIFFERENT_DISCOUNT_BASE = 6
DIFFERENT_TAX_BASE = 7
TXJCD_NOT_VALID = 8
NOT_FOUND = 9
KTOSL_NOT_FOUND = 10
KALSM_NOT_FOUND = 11
PARAMETER_ERROR = 12
KNUMH_NOT_FOUND = 13
KSCHL_NOT_FOUND = 14
UNKNOWN_ERROR = 15
OTHERS = 16.
IF SY-SUBRC <> 0.
CONTINUE.
ENDIF.
READ TABLE T_MWDAT INDEX 1.
check sy-subrc = 0.
"There was tax there!!
if t_mwdat-wmwst is not INITIAL.
clear tax_accountgl.
tax_accountgl-gl_account = '402560'.
tax_accountgl-ITEMNO_ACC = curr_li.
tax_accountgl-tax_code = accountgl-tax_code.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
INPUT = tax_accountgl-gl_account
IMPORTING
OUTPUT = tax_accountgl-gl_account.
append tax_accountgl.
clear tax_currencyamount.
tax_currencyamount = currencyamount.
tax_currencyamount-amt_doccur = T_MWDAT-wmwst.
tax_currencyamount-ITEMNO_ACC = curr_li.
append tax_currencyamount.
currencyamount-amt_doccur = T_MWDAT-KAWRT.
modify currencyamount index v_tabix.
curr_li = curr_li + 1.
endif.
endloop.
append LINES OF tax_accountgl to accountgl.
append LINES OF tax_currencyamount to currencyamount.
CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'
EXPORTING
DOCUMENTHEADER = documentheader
TABLES
ACCOUNTGL = accountgl
ACCOUNTRECEIVABLE = t_accountreceivable
CURRENCYAMOUNT = currencyamount
RETURN = return .
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
WAIT = 'X'.
loop at return.
write return-message.
endloop.
*&---------------------------------------------------------------------*
*& Include Z_PD_CAPS1_DEMOS_INV_CREATE *
*&---------------------------------------------------------------------*
data:
obj_type like bapiache02-obj_type,
obj_key like bapiache02-obj_key,
obj_sys like bapiache02-obj_sys,
documentheader like bapiache09,
accountgl like bapiacgl09 occurs 0 with header line,
tax_accountgl like bapiacgl09 OCCURS 0 WITH HEADER LINE,
currencyamount like bapiaccr09 occurs 0 with header line,
tax_currencyamount like bapiaccr09 OCCURS 0 WITH HEADER LINE,
return like bapiret2 occurs 0 with header line,
extension1 like bapiextc occurs 0 with header line,
t_edidd like edidd occurs 0 with header line,
bapi_retn_info like bapiret2 occurs 0 with header line.
data: error_flag.
data: wa_akont TYPE akont.
data: t_accountreceivable TYPE TABLE OF BAPIACAR09 WITH HEADER LINE.
datA: T_MWDAT TYPE TABLE OF RTAX1U15 WITH HEADER LINE.
data: wa_wrbtr type wrbtr.
data: curr_li TYPE POSNR_ACC.
data: v_tabix like sy-tabix.
documentheader-username = sy-uname.
documentheader-header_txt = 'Test using BAPI'.
documentheader-comp_code = 'CF01'.
documentheader-doc_date = sy-datum.
documentheader-pstng_date = sy-datum.
documentheader-doc_type = 'SA'.
documentheader-REF_DOC_NO = 'INVOICE_01'.
clear accountgl.
clear wa_akont.
t_accountreceivable-ITEMNO_ACC = '1'.
t_accountreceivable-customer = 'C524'.
"t_accountreceivable-TAX_CODE = 'A1'.
t_accountreceivable-gl_account = '0000400000'.
t_accountreceivable-PMNTTRMS = 'Z030'.
t_accountreceivable-ALLOC_NMBR = 'LORDS0820'.
t_accountreceivable-ITEM_TEXT = 'Facility Name'.
append t_accountreceivable.
accountgl-itemno_acc = '2'.
accountgl-gl_account = '0000802010'.
accountgl-comp_code = 'CF01'.
accountgl-pstng_date = sy-datum.
accountgl-doc_type = 'SA'.
accountgl-profit_ctr = '0000069314'.
"accountgl-costcenter = '0069314001'.
accountgl-ITEM_TEXT = 'Item Text'.
accountgl-ORDERID = 'LORDS0820'.
accountgl-TAX_CODE = 'A0'.
append accountgl.
clear accountgl.
accountgl-itemno_acc = '3'.
accountgl-gl_account = '0000802010'.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
INPUT = accountgl-gl_account
IMPORTING
OUTPUT = accountgl-gl_account.
accountgl-ITEM_TEXT = 'Item Text'.
accountgl-ORDERID = 'LORDS0820'.
accountgl-comp_code = 'CF01'.
accountgl-pstng_date = sy-datum.
accountgl-doc_type = 'SA'.
accountgl-TAX_CODE = 'A1'.
append accountgl.
clear accountgl.
accountgl-itemno_acc = '4'.
accountgl-gl_account = '0000711350'.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
INPUT = accountgl-gl_account
IMPORTING
OUTPUT = accountgl-gl_account.
.
accountgl-comp_code = 'CF01'.
accountgl-pstng_date = sy-datum.
accountgl-doc_type = 'SA'.
accountgl-TAX_CODE = 'V0'.
accountgl-costcenter = '69314001'.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
INPUT = accountgl-costcenter
IMPORTING
OUTPUT = accountgl-costcenter.
append accountgl.
currencyamount-itemno_acc = '1'.
currencyamount-currency = 'GBP'.
currencyamount-amt_doccur = '470.00'.
append currencyamount.
currencyamount-itemno_acc = '2'.
currencyamount-currency = 'GBP'.
currencyamount-amt_doccur = '-230.00'.
append currencyamount.
currencyamount-itemno_acc = '3'.
currencyamount-currency = 'GBP'.
currencyamount-amt_doccur = '-235.00'.
append currencyamount.
currencyamount-itemno_acc = '4'.
currencyamount-currency = 'GBP'.
currencyamount-amt_doccur = '-5.00'.
append currencyamount.
"PD We're now calculating the tax. Need to calculate any tax at the
"appropriate rate.
"work out the first line that tax can go on.
loop at accountgl.
endloop.
curr_li = accountgl-ITEMNO_ACC.
curr_li = curr_li + 1.
loop at accountgl.
READ TABLE currencyamount with key ITEMNO_ACC =
accountgl-ITEMNO_ACC.
check sy-subrc = 0.
v_tabix = sy-tabix.
wa_wrbtr = currencyamount-amt_doccur.
CALL FUNCTION 'CALCULATE_TAX_FROM_GROSSAMOUNT'
EXPORTING
I_BUKRS = accountgl-comp_code
I_MWSKZ = accountgl-TAX_CODE
I_WAERS = currencyamount-currency
I_WRBTR = wa_wrbtr
TABLES
T_MWDAT = t_mwdat
EXCEPTIONS
BUKRS_NOT_FOUND = 1
COUNTRY_NOT_FOUND = 2
MWSKZ_NOT_DEFINED = 3
MWSKZ_NOT_VALID = 4
ACCOUNT_NOT_FOUND = 5
DIFFERENT_DISCOUNT_BASE = 6
DIFFERENT_TAX_BASE = 7
TXJCD_NOT_VALID = 8
NOT_FOUND = 9
KTOSL_NOT_FOUND = 10
KALSM_NOT_FOUND = 11
PARAMETER_ERROR = 12
KNUMH_NOT_FOUND = 13
KSCHL_NOT_FOUND = 14
UNKNOWN_ERROR = 15
OTHERS = 16.
IF SY-SUBRC <> 0.
CONTINUE.
ENDIF.
READ TABLE T_MWDAT INDEX 1.
check sy-subrc = 0.
"There was tax there!!
if t_mwdat-wmwst is not INITIAL.
clear tax_accountgl.
tax_accountgl-gl_account = '402560'.
tax_accountgl-ITEMNO_ACC = curr_li.
tax_accountgl-tax_code = accountgl-tax_code.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
INPUT = tax_accountgl-gl_account
IMPORTING
OUTPUT = tax_accountgl-gl_account.
append tax_accountgl.
clear tax_currencyamount.
tax_currencyamount = currencyamount.
tax_currencyamount-amt_doccur = T_MWDAT-wmwst.
tax_currencyamount-ITEMNO_ACC = curr_li.
append tax_currencyamount.
currencyamount-amt_doccur = T_MWDAT-KAWRT.
modify currencyamount index v_tabix.
curr_li = curr_li + 1.
endif.
endloop.
append LINES OF tax_accountgl to accountgl.
append LINES OF tax_currencyamount to currencyamount.
CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'
EXPORTING
DOCUMENTHEADER = documentheader
TABLES
ACCOUNTGL = accountgl
ACCOUNTRECEIVABLE = t_accountreceivable
CURRENCYAMOUNT = currencyamount
RETURN = return .
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
WAIT = 'X'.
loop at return.
write return-message.
endloop.
Tuesday, 26 August 2014
Getting the Buffer Quality metric from an Oracle System
The requirement was to try and get the “Buffer Quality”
value out of BASIS transaction ST04. The technique for this will vary from
system to system, as it depends on the underlying database.
The field behind this is DBUFF_QUALITY and ST04 is underpinned by program RSDB0004.
A quick look at this tells us that RSDB0004 is just a CASE
Statement that filters the Database System, and calls corresponding
transactions. The one I’m interested in is an Oracle Database:
Going into this, I did a search on “DBUFF_QUALITY” and
found that it was held in function module
C_ORA_MM_GET_DATA_V10.
I ran this in SE37, without any parameters populated, and
in the response, there was a structure called S_ST04N_DATA with parameter DBUFF_QUALITY
which is what I was after.
Nice and Simple!
Friday, 22 August 2014
CSV Files with Commas in the fields....
Okay, so the initial requirement was to load a CSV file
in to SAP and process the content. This all seemed fine, and I processed it as
follows:
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
filename = v_filename_string
filetype = 'DAT'
TABLES
data_tab = itab.
loop
at itab.
split itab-text at ',' into w_input-matnr
w_input-desc w_input-date w_input-demand.
append w_input to t_input.
endloop.
But it became apparent that the users, saving data in
Excel CSV, wanted to include commas in the field values (specifically the
w_input-desc). Obviously the split just takes these as delimiters and messes up
the demand and date values.
To get round this, instead of “GUI Upload”, we’re going
to use
CALL FUNCTION
'KCD_CSV_FILE_TO_INTERN_CONVERT'
EXPORTING
i_filename = l_filename
i_separator =
','
TABLES
e_intern = lt_csv
EXCEPTIONS
upload_csv = 1
upload_filetype = 2
OTHERS = 3.
This results in a slightly awkward table :
Row Col Value
1 0001 0001 40253
2 0001 0002 Crispy Aromatic, Half Duck 20x32
3 0001 0003 14:32
4 0001 0004 40
5 0002 0001 40253
6 0002 0002 Crispy Aromatic, Half Duck 20x32
7 0002 0003 14:33
8 0002 0004 50
But I can loop round this, and create my t_input table
from there…
"Tee up the t_input table.
lt_csv_bluff[] = lt_csv[].
delete ADJACENT DUPLICATES FROM lt_csv_bluff COMPARING row.
loop at lt_csv_bluff into lv_csv_bluff.
append w_input to t_input.
endloop.
loop at lt_csv into lv_csv.
assign COMPONENT lv_csv-col of STRUCTURE w_input to <fs>.
<fs> = lv_csv-value.
MODIFY t_input from w_input INDEX lv_csv-row.
endloop.
"Tee up the t_input table.
lt_csv_bluff[] = lt_csv[].
delete ADJACENT DUPLICATES FROM lt_csv_bluff COMPARING row.
loop at lt_csv_bluff into lv_csv_bluff.
append w_input to t_input.
endloop.
loop at lt_csv into lv_csv.
assign COMPONENT lv_csv-col of STRUCTURE w_input to <fs>.
<fs> = lv_csv-value.
MODIFY t_input from w_input INDEX lv_csv-row.
endloop.
Thursday, 21 August 2014
Infinite Loop for background debugging
I use this all the time for debugging SAP ABAP "background" operations. Sometimes you can't debug straight to a bit of code, as it's operated on by the server, not the a frontend session.
So, what I do, is use this simple bit of code:
data: a, b.
a = 'X'.
do.
if a = b.
exit.
endif.
enddo.
Which, as you can probably tell, sets the program into an infinite loop, which can only be interrupted by debugging.
This is done in transaction SM51 - find the session with ( your / system ) name on it, and hit Program-Debug from the menu
At this point, you can then clear out the "a" variable, which then means that a = b, and so the loop gets exited. You can then debug through the background process.
There are other ways of doing it, but I've found this one to be the simplest and most reliable.
Don't forget to take it out again once you're finished, otherwise you'll paralyse the backend!
Thursday, 26 June 2014
How to create a new SU01 User Parameter ID...
How to create a new SU01 User Parameter ID...
The requirement was to have something against the User Master Record that we could use to differentiate between users when MIGOing stuff. I tried just entering the new value, but I needed to make an SM30 entry in table TPARA first!
Wednesday, 25 June 2014
QR Code Reader in an SAP Personas Screen
This was achieved by Personas calling using an HTML5 BSP with JavaScript library in which employed the camera on an HP Slate. Meanwhile, the Personas screen sent a call to a Web Enabled RFC, which waited for the response from the HTML5 page.
Tuesday, 17 June 2014
Printing a QR Code in a SMARTForm
Here's a great blog from a guy who's managed to get a QR Code output onto a SMARTForm.
Essentially, he:
http://scn.sap.com/docs/DOC-47644
It's so pretty. Again, great work to the author.
Essentially, he:
- uses a Google Charts API to generate the QR Code,
- reads the content of this in using the HTTP_CLASS.
- transfers this content to a nominal bitmap file on SAP
- refers to this file in the SMARTForm
http://scn.sap.com/docs/DOC-47644
It's so pretty. Again, great work to the author.
Generic Object Services - Adding a URL Link to an SAP Document
In this case, a Finance Invoice visible in transaction MIR4.
http://subrc0.wordpress.com/2012/11/13/gos-adding-an-external-link-to-an-object/
Absolutely fantastic work by the author, props.
Nothing really to add to that, the use case is described excellently at the link.
http://subrc0.wordpress.com/2012/11/13/gos-adding-an-external-link-to-an-object/
Absolutely fantastic work by the author, props.
Nothing really to add to that, the use case is described excellently at the link.
Monday, 2 June 2014
Using CSS in SAP UI5
Okay, so it's been a while; as usual! In this post, I explain how to use CSS to affect the screen elements in your UI5 application.
If you're new to UI5, the tutorials here are absolutely invaluable. After much boshing around, I found this one to be the one that I refer back to the most. The "create a ui5 app in 20 seconds" claim is a bit of misdirection in my eyes; true, you are referring to the UI5 library, but you're not talking to a backend, you're not even deploying it anywhere useful (unless you put it in your dropbox folder or some-such). The step between that and the actual application is a little big, and I could have done with a bit more hand-holding, but got there in the end.
I've now developed a few UI5 applications that "do stuff" in SAP.
So, what did I solve today? I'd used the responsive layout container but found that a dropdown in the layout kept on overflowing over the end of where I wanted it to be.
In order not to disrupt the flow of the program, I added in the CSS at the top of the HTML, where one would normally put it in... instead of with the JS declaration.
new sap.ui.layout.form.FormElement({
label: "Status : ",
fields: [ oDropdownBox2 = new sap.ui.commons.DropdownBox({layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),
id: "DropdownBox2",})],
layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})
})
The above is the JS declaration of the screen object. I've highlighted the id, because that gets used in the CSS...
<style type="text/css">
#DropdownBox2 {
width: 100%;
max-width: 200px;
min-width: 60px;
}
</style>
And hey-presto, the dropdown is behaving itself again:
Now I'm sure that there are better ways, but since this works, for now I'll use it until someone corrects me and tells me otherwise! Before anyone asks, I did try changing the weight of the responsiveFlowLayoutData and putting in CSS against the actual declaration, but none of those appeared to have any effect. Try it for yourself!
If you're new to UI5, the tutorials here are absolutely invaluable. After much boshing around, I found this one to be the one that I refer back to the most. The "create a ui5 app in 20 seconds" claim is a bit of misdirection in my eyes; true, you are referring to the UI5 library, but you're not talking to a backend, you're not even deploying it anywhere useful (unless you put it in your dropbox folder or some-such). The step between that and the actual application is a little big, and I could have done with a bit more hand-holding, but got there in the end.
I've now developed a few UI5 applications that "do stuff" in SAP.
So, what did I solve today? I'd used the responsive layout container but found that a dropdown in the layout kept on overflowing over the end of where I wanted it to be.
new sap.ui.layout.form.FormElement({
label: "Status : ",
fields: [ oDropdownBox2 = new sap.ui.commons.DropdownBox({layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),
id: "DropdownBox2",})],
layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})
})
The above is the JS declaration of the screen object. I've highlighted the id, because that gets used in the CSS...
<style type="text/css">
#DropdownBox2 {
width: 100%;
max-width: 200px;
min-width: 60px;
}
</style>
And hey-presto, the dropdown is behaving itself again:
Now I'm sure that there are better ways, but since this works, for now I'll use it until someone corrects me and tells me otherwise! Before anyone asks, I did try changing the weight of the responsiveFlowLayoutData and putting in CSS against the actual declaration, but none of those appeared to have any effect. Try it for yourself!
Subscribe to:
Posts (Atom)