Opens a new session... Just like Word, Outlook, Chrome, Notebook etc etc.
Press Ctrl-N in GUI. Now triggers new session. Useful. 3 of my colleagues hadn't heard about this, so thought it worth broadcasting! SAP starts to behave a bit like other software. Good.
Monday, 23 November 2015
Wednesday, 11 November 2015
WSDL Loading
So my third party gave me a WSDL that needs to be consumed. I was using the wizard in SE80, when I get the following error :
"Proxy Generation : Error Occurred" Incorrect Value: Entity (1/0) Unexpected End of file.
Okay.
Now the WSDL was a text file that was sent to me via e-mail. I'd just saved it from Outlook onto my desktop...
I was able to double check the WSDL using this website:
https://www.wsdl-analyzer.com/service/service/1118547868?version=1
which took a copy of the file and gave me a natty little report on how well formed the file was. It didn't much like my WSDL, and told me the same thing that SAP did... not happy!
I then cut and pasted WSDL content into Eclipse in a new WSDL file, saved that to my desktop. Eclipse seemed to like it. Once that had been saved to the DT, it passed the SAP and WSDL Analyser.
My only summation is that there must be something in notepad / outlook that messes up the WSDL definition...
"Proxy Generation : Error Occurred" Incorrect Value: Entity (1/0) Unexpected End of file.
Okay.
Now the WSDL was a text file that was sent to me via e-mail. I'd just saved it from Outlook onto my desktop...
I was able to double check the WSDL using this website:
https://www.wsdl-analyzer.com/service/service/1118547868?version=1
which took a copy of the file and gave me a natty little report on how well formed the file was. It didn't much like my WSDL, and told me the same thing that SAP did... not happy!
I then cut and pasted WSDL content into Eclipse in a new WSDL file, saved that to my desktop. Eclipse seemed to like it. Once that had been saved to the DT, it passed the SAP and WSDL Analyser.
My only summation is that there must be something in notepad / outlook that messes up the WSDL definition...
Wednesday, 4 November 2015
Creating data on the fly... just like Javascript and Visual Basic!
This blog from Horst (hero!) describes one of the "new" features of the ABAP editor.
http://scn.sap.com/community/abap/blog/2013/05/23/abap-news-for-release-740--inline-declarations
This is ace! No more jumping up to the data declarations or local variable declarations. Just do them on the fly!
http://scn.sap.com/community/abap/blog/2013/05/23/abap-news-for-release-740--inline-declarations
This is ace! No more jumping up to the data declarations or local variable declarations. Just do them on the fly!
Thursday, 29 October 2015
ICT_SERVICE_DESK_API : CRM - Solution Manager - Categorise an Incident without Catalog / CodeGroup / Code combo...
Fully geeking out on CRM at the moment. Present remit is to integrate a third party helpdesk system with our SAP Solution Manager helpdesk... The SAP provided ICT interface is pretty good, but as ever you need to call your friendly neighbourhood ABAPer to finesse it into exactly what you want!
Right now, our config guys have told me that they're reluctant to tie together the Categories to the Catalog / CodeGroup / Code that ICT expects, so I'm having to use an enhancement point to update the Categories on our Helpdesk incidents...
Here's my stub program...
REPORT YPD_INCIDENT_CATEGORISE.
data: i_call type CRMT_OBJECT_ID VALUE '7000000941'.
data: ls_partner type CRMT_PARTNER_COM,
lt_partner type CRMT_PARTNER_COMt,
lt_guid type CRMT_OBJECT_GUID_TAB,
ls_guid type CRMT_OBJECT_GUID,
lt_input_fields type CRMT_INPUT_FIELD_TAB,
ls_input_fields type CRMT_INPUT_FIELD,
ls_field_names type CRMT_INPUT_FIELD_NAMES,
lt_field_names TYPE CRMT_INPUT_FIELD_NAMES_TAB,
lt_orderadm_h TYPE CRMT_ORDERADM_H_COMT,
ls_orderadm_h type crmt_orderadm_h_com,
lt_exception type CRMT_EXCEPTION_T,
lt_sales type CRMT_SALES_COMT,
ls_sales type CRMT_SALES_COM,
lt_service_os type CRMT_SRV_OSSET_COMT,
ls_service_os type CRMT_SRV_OSSET_COM,
ls_osset type CRMT_SRV_OSSET_COM1,
ls_subject type CRMT_SRV_SUBJECT_COM,
LS_GUID16 TYPE guid_16.
CALL FUNCTION 'CRM_ORDERADM_H_GUID_GET_DB'
EXPORTING
IV_OBJECT_ID = i_call
IMPORTING
ET_GUID = lt_guid
EXCEPTIONS
RECORD_NOT_FOUND = 1
OTHERS = 2.
READ TABLE lt_guid into ls_guid INDEX 1.
check ls_guid is not INITIAL.
"Trying to Categorise the call....
ls_service_os-ref_guid = ls_guid.
ls_service_os-ref_kind = 'A'.
CALL FUNCTION 'GUID_CREATE'
IMPORTING
EV_GUID_16 = ls_guid16.
ls_subject-ref_guid = ls_guid16.
ls_subject-asp_id = 'EDENHOUSE SOLUTIONS'.
ls_subject-cat_id = 'AIC_CAT01_03_06'.
ls_subject-katalog_type = 'D'.
INSERT ls_subject into table ls_osset-subject.
CALL FUNCTION 'GUID_CREATE'
IMPORTING
EV_GUID_16 = ls_guid16.
ls_osset-ref_guid = ls_guid16.
ls_osset-profile_type = 'A'.
insert ls_osset into TABLE ls_service_os-osset.
insert ls_service_os INTO TABLE lt_service_os.
"Do the input fields too...
*ls_input_fields-REF_HANDLE
ls_input_fields-REF_GUID = ls_service_os-ref_guid.
ls_input_fields-REF_KIND = 'A'.
ls_input_fields-OBJECTNAME = 'SERVICE_OS'.
ls_field_names-fieldname = 'ASP_ID'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'CAT_ID'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'CODE'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'CODEGRUPPE'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'KATALOGART'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'MODE'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'REF_GUID'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
insert ls_input_fields into TABLE lt_input_fields.
CALL FUNCTION 'CRM_ORDER_MAINTAIN'
EXPORTING
* it_partner = lt_partner
it_service_os = lt_service_os
* it_sales = lt_sales
* it_service_h = lt_service_h
IMPORTING
ET_EXCEPTION = lt_exception
CHANGING
ct_input_fields = lt_input_fields
EXCEPTIONS
error_occurred = 1
document_locked = 2
no_change_allowed = 3
no_authority = 4
OTHERS = 5.
CALL FUNCTION 'CRM_ORDER_SAVE'
EXPORTING
IT_OBJECTS_TO_SAVE = lt_guid
EXCEPTIONS
DOCUMENT_NOT_SAVED = 1
OTHERS = 2
.
IF SY-SUBRC <> 0.
* Implement suitable error handling here
ENDIF.
commit work and wait.
Right now, our config guys have told me that they're reluctant to tie together the Categories to the Catalog / CodeGroup / Code that ICT expects, so I'm having to use an enhancement point to update the Categories on our Helpdesk incidents...
Here's my stub program...
REPORT YPD_INCIDENT_CATEGORISE.
data: i_call type CRMT_OBJECT_ID VALUE '7000000941'.
data: ls_partner type CRMT_PARTNER_COM,
lt_partner type CRMT_PARTNER_COMt,
lt_guid type CRMT_OBJECT_GUID_TAB,
ls_guid type CRMT_OBJECT_GUID,
lt_input_fields type CRMT_INPUT_FIELD_TAB,
ls_input_fields type CRMT_INPUT_FIELD,
ls_field_names type CRMT_INPUT_FIELD_NAMES,
lt_field_names TYPE CRMT_INPUT_FIELD_NAMES_TAB,
lt_orderadm_h TYPE CRMT_ORDERADM_H_COMT,
ls_orderadm_h type crmt_orderadm_h_com,
lt_exception type CRMT_EXCEPTION_T,
lt_sales type CRMT_SALES_COMT,
ls_sales type CRMT_SALES_COM,
lt_service_os type CRMT_SRV_OSSET_COMT,
ls_service_os type CRMT_SRV_OSSET_COM,
ls_osset type CRMT_SRV_OSSET_COM1,
ls_subject type CRMT_SRV_SUBJECT_COM,
LS_GUID16 TYPE guid_16.
CALL FUNCTION 'CRM_ORDERADM_H_GUID_GET_DB'
EXPORTING
IV_OBJECT_ID = i_call
IMPORTING
ET_GUID = lt_guid
EXCEPTIONS
RECORD_NOT_FOUND = 1
OTHERS = 2.
READ TABLE lt_guid into ls_guid INDEX 1.
check ls_guid is not INITIAL.
"Trying to Categorise the call....
ls_service_os-ref_guid = ls_guid.
ls_service_os-ref_kind = 'A'.
CALL FUNCTION 'GUID_CREATE'
IMPORTING
EV_GUID_16 = ls_guid16.
ls_subject-ref_guid = ls_guid16.
ls_subject-asp_id = 'EDENHOUSE SOLUTIONS'.
ls_subject-cat_id = 'AIC_CAT01_03_06'.
ls_subject-katalog_type = 'D'.
INSERT ls_subject into table ls_osset-subject.
CALL FUNCTION 'GUID_CREATE'
IMPORTING
EV_GUID_16 = ls_guid16.
ls_osset-ref_guid = ls_guid16.
ls_osset-profile_type = 'A'.
insert ls_osset into TABLE ls_service_os-osset.
insert ls_service_os INTO TABLE lt_service_os.
"Do the input fields too...
*ls_input_fields-REF_HANDLE
ls_input_fields-REF_GUID = ls_service_os-ref_guid.
ls_input_fields-REF_KIND = 'A'.
ls_input_fields-OBJECTNAME = 'SERVICE_OS'.
ls_field_names-fieldname = 'ASP_ID'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'CAT_ID'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'CODE'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'CODEGRUPPE'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'KATALOGART'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'MODE'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'REF_GUID'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
insert ls_input_fields into TABLE lt_input_fields.
CALL FUNCTION 'CRM_ORDER_MAINTAIN'
EXPORTING
* it_partner = lt_partner
it_service_os = lt_service_os
* it_sales = lt_sales
* it_service_h = lt_service_h
IMPORTING
ET_EXCEPTION = lt_exception
CHANGING
ct_input_fields = lt_input_fields
EXCEPTIONS
error_occurred = 1
document_locked = 2
no_change_allowed = 3
no_authority = 4
OTHERS = 5.
CALL FUNCTION 'CRM_ORDER_SAVE'
EXPORTING
IT_OBJECTS_TO_SAVE = lt_guid
EXCEPTIONS
DOCUMENT_NOT_SAVED = 1
OTHERS = 2
.
IF SY-SUBRC <> 0.
* Implement suitable error handling here
ENDIF.
commit work and wait.
Friday, 23 October 2015
UI5 Product Locator App
Was just putting this baby to bed and realised that I'd not blogged it yet!
Anyway, it was a stack of fun to develop, and if anyone wants something like this on their SAP system, get in touch with EdenhouseSolutions!
Wednesday, 21 October 2015
CRM Add Partner to Incident
The following function can be used to add bespoke partner functions to SAP CRM Incidents - in this case, a "Requester".
The bit that threw me was the need for a BAPI-Commit after the CRM_ORDER_SAVE; it seems SAP have added another layer of flexibility / complexity
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(I_CALL) TYPE CRMT_OBJECT_ID
*" REFERENCE(I_REQUESTER) TYPE CRMT_PARTNER_NO
*" REFERENCE(I_SOLD_TO) TYPE CRMT_PARTNER_NO
*"----------------------------------------------------------------------
data: ls_partner type CRMT_PARTNER_COM,
lt_partner type CRMT_PARTNER_COMt,
lt_guid type CRMT_OBJECT_GUID_TAB,
ls_guid type CRMT_OBJECT_GUID,
lt_input_fields type CRMT_INPUT_FIELD_TAB,
ls_input_fields type CRMT_INPUT_FIELD,
ls_field_names type CRMT_INPUT_FIELD_NAMES,
lt_field_names TYPE CRMT_INPUT_FIELD_NAMES_TAB,
lt_orderadm_h TYPE CRMT_ORDERADM_H_COMT,
ls_orderadm_h type crmt_orderadm_h_com,
lt_exception type CRMT_EXCEPTION_T.
CALL FUNCTION 'CRM_ORDERADM_H_GUID_GET_DB'
EXPORTING
IV_OBJECT_ID = i_call
* IV_OBJECT_TYPE =
IMPORTING
ET_GUID = lt_guid
EXCEPTIONS
RECORD_NOT_FOUND = 1
OTHERS = 2.
READ TABLE lt_guid into ls_guid INDEX 1.
ls_partner-ref_guid = ls_guid.
ls_partner-ref_kind = 'A'.
ls_partner-ref_partner_handle = '0001'.
ls_partner-kind_of_entry = 'C'.
ls_partner-partner_fct = 'Z0000015'.
ls_partner-partner_no = i_requester.
if ls_partner-partner_no(4) ne '0000'.
CONCATENATE '0000' ls_partner-partner_no into ls_partner-partner_no.
endif.
ls_partner-display_type = 'BP'.
ls_partner-no_type = 'BP'.
append ls_partner to lt_partner.
*ls_input_fields-REF_HANDLE
ls_input_fields-REF_GUID = ls_guid.
ls_input_fields-REF_KIND = 'A'.
ls_input_fields-OBJECTNAME = 'PARTNER'.
ls_input_fields-LOGICAL_KEY = '0001'.
ls_field_names-fieldname = 'DISPLAY_TYPE'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'KIND_OF_ENTRY'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'NO_TYPE'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'PARTNER_FCT'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
ls_field_names-fieldname = 'PARTNER_NO'.
INSERT ls_field_names INto table ls_input_fields-FIELD_NAMES.
append ls_input_fields to lt_input_fields.
*ls_orderadm_h-guid = ls_guid.
*append ls_orderadm_h to lt_orderadm_h.
CALL FUNCTION 'CRM_ORDER_MAINTAIN'
EXPORTING
* it_activity_h = lt_activity_h
* it_appointment = lt_appointment
* it_text = lt_text
it_partner = lt_partner
* it_service_os = lt_service_os
* it_status = lt_status
* it_sales = lt_sales
* it_service_h = lt_service_h
IMPORTING
ET_EXCEPTION = lt_exception
CHANGING
* ct_orderadm_h = lt_orderadm_h
ct_input_fields = lt_input_fields
** CV_LOG_HANDLE =
** CT_PARTNER_ATTRIBUTES =
** CT_DOC_FLOW =
EXCEPTIONS
error_occurred = 1
document_locked = 2
no_change_allowed = 3
no_authority = 4
OTHERS = 5.
CALL FUNCTION 'CRM_ORDER_SAVE'
EXPORTING
IT_OBJECTS_TO_SAVE = lt_guid
* IV_UPDATE_TASK_LOCAL = FALSE
* IV_SAVE_FRAME_LOG = FALSE
* IV_NO_BDOC_SEND = FALSE
* IT_ACTIVE_SWITCH =
* IMPORTING
* ET_SAVED_OBJECTS =
* ET_EXCEPTION =
* ET_OBJECTS_NOT_SAVED =
* CHANGING
* CV_LOG_HANDLE =
* CT_NOCHECK_BEFORE_SAVE =
EXCEPTIONS
DOCUMENT_NOT_SAVED = 1
OTHERS = 2
.
IF SY-SUBRC <> 0.
* Implement suitable error handling here
ENDIF.
commit work and wait.
ENDFUNCTION.
Tuesday, 6 October 2015
VB Documentation tool...
I was asked to ensure that the documentation on a program had pseudo-code in it to describe what was going on in...
I had originally cut and pasted the code (lazy, but consistent with what I'd seen from previous documentation on the same project, and also, I got time issues...) which prompted the user to ask for better explanation of what was going on...
The trick for us ABAPers is the balance between the technical and the functional; we have to describe things in English to the Apps guys, and explain things in ABAP to The Computer, and it's often difficult to do both at the same time in a technical spec:
A way of making this easier is to just make sure that every time you output a field name, you output the description as well (and vice versa, but this is less achievable automatically )
The project I'm on is asking for 10 word documents where this is done.
Rather than doing "replace EKPO with EKPO(PO Line Item)" x ten files x 25 different fields, I thought it more prudent to write some code to do it.
Why get a man to do a machine's job?
Anyway, this is some VBScript that will quickly do all the replacements. The fact that it happens slow enough for the eye to see is really satisfying, as it kind of looks like code from films.
Sub Macro2()
'
Dim findandreplace(1, 25) As String
findandreplace(0, 0) = "VBELN"
findandreplace(1, 0) = "VBELN(Sales Document#)"
findandreplace(0, 1) = "posnr"
findandreplace(1, 1) = "POSNR(Line Item#)"
findandreplace(0, 2) = "kunnr"
findandreplace(1, 2) = "KUNNR(Customer#)"
findandreplace(0, 3) = "vkorg"
findandreplace(1, 3) = "VKORG(Sales Org)"
findandreplace(0, 4) = "vtweg"
findandreplace(1, 4) = "VTWEG(Distribution Channel)"
findandreplace(0, 5) = "vbep"
findandreplace(1, 5) = "VBEP(Schedule Line Data)"
findandreplace(0, 6) = "matnr"
findandreplace(1, 6) = "MATNR(Material)"
findandreplace(0, 7) = "lfstk"
findandreplace(1, 7) = "LFSTK(Delivery status)"
findandreplace(0, 8) = "EDATU"
findandreplace(1, 8) = "EDATU(Schedule line date)"
findandreplace(0, 9) = "EZEIT"
findandreplace(1, 9) = "EZEIT(Arrival time)"
findandreplace(0, 10) = "ABGRU"
findandreplace(1, 10) = "ABGRU(Reason for rejection)"
findandreplace(0, 11) = "PARVW"
findandreplace(1, 11) = "PARVW(Partner Function)"
findandreplace(0, 12) = "WERKS"
findandreplace(1, 12) = "WERKS(Plant)"
findandreplace(0, 13) = "VBAP"
findandreplace(1, 13) = "VBAP(SO Line Item)"
findandreplace(0, 14) = "VBAK"
findandreplace(1, 14) = "VBAK(SO Header)"
findandreplace(0, 15) = "LFSTK"
findandreplace(1, 15) = "LFSTK(Delivery Status)"
findandreplace(0, 16) = "WBSTK"
findandreplace(1, 16) = "WBSTK(Total goods movement status)"
findandreplace(0, 17) = "LIFSP"
findandreplace(1, 17) = "LIFSP(Default delivery block)"
findandreplace(0, 18) = "SPRAS"
findandreplace(1, 18) = "SPRAS(Language)"
findandreplace(0, 19) = "VBUK"
findandreplace(1, 19) = "VBUK(Sales Document Admin Data)"
findandreplace(0, 20) = "KNKK"
findandreplace(1, 20) = "KNKK(Customer Credit)"
findandreplace(0, 21) = "LIKP"
findandreplace(1, 21) = "LIKP(SD Document: Delivery Header Data)"
findandreplace(0, 22) = "bolnr"
findandreplace(1, 22) = "BOLNR(Tare/Registration#)"
findandreplace(0, 23) = "makt"
findandreplace(1, 23) = "MAKT(Material Texts)"
findandreplace(0, 24) = "kkber"
findandreplace(1, 24) = "KKBER(Credit Control Area)"
findandreplace(0, 25) = "LFDAT"
findandreplace(1, 25) = "LFDAT(Delivery Date)"
For j = 1 To 25
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = findandreplace(0, j)
.Replacement.Text = findandreplace(1, j)
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Next j
End Sub
I had originally cut and pasted the code (lazy, but consistent with what I'd seen from previous documentation on the same project, and also, I got time issues...) which prompted the user to ask for better explanation of what was going on...
The trick for us ABAPers is the balance between the technical and the functional; we have to describe things in English to the Apps guys, and explain things in ABAP to The Computer, and it's often difficult to do both at the same time in a technical spec:
A way of making this easier is to just make sure that every time you output a field name, you output the description as well (and vice versa, but this is less achievable automatically )
The project I'm on is asking for 10 word documents where this is done.
Rather than doing "replace EKPO with EKPO(PO Line Item)" x ten files x 25 different fields, I thought it more prudent to write some code to do it.
Why get a man to do a machine's job?
Anyway, this is some VBScript that will quickly do all the replacements. The fact that it happens slow enough for the eye to see is really satisfying, as it kind of looks like code from films.
Sub Macro2()
'
Dim findandreplace(1, 25) As String
findandreplace(0, 0) = "VBELN"
findandreplace(1, 0) = "VBELN(Sales Document#)"
findandreplace(0, 1) = "posnr"
findandreplace(1, 1) = "POSNR(Line Item#)"
findandreplace(0, 2) = "kunnr"
findandreplace(1, 2) = "KUNNR(Customer#)"
findandreplace(0, 3) = "vkorg"
findandreplace(1, 3) = "VKORG(Sales Org)"
findandreplace(0, 4) = "vtweg"
findandreplace(1, 4) = "VTWEG(Distribution Channel)"
findandreplace(0, 5) = "vbep"
findandreplace(1, 5) = "VBEP(Schedule Line Data)"
findandreplace(0, 6) = "matnr"
findandreplace(1, 6) = "MATNR(Material)"
findandreplace(0, 7) = "lfstk"
findandreplace(1, 7) = "LFSTK(Delivery status)"
findandreplace(0, 8) = "EDATU"
findandreplace(1, 8) = "EDATU(Schedule line date)"
findandreplace(0, 9) = "EZEIT"
findandreplace(1, 9) = "EZEIT(Arrival time)"
findandreplace(0, 10) = "ABGRU"
findandreplace(1, 10) = "ABGRU(Reason for rejection)"
findandreplace(0, 11) = "PARVW"
findandreplace(1, 11) = "PARVW(Partner Function)"
findandreplace(0, 12) = "WERKS"
findandreplace(1, 12) = "WERKS(Plant)"
findandreplace(0, 13) = "VBAP"
findandreplace(1, 13) = "VBAP(SO Line Item)"
findandreplace(0, 14) = "VBAK"
findandreplace(1, 14) = "VBAK(SO Header)"
findandreplace(0, 15) = "LFSTK"
findandreplace(1, 15) = "LFSTK(Delivery Status)"
findandreplace(0, 16) = "WBSTK"
findandreplace(1, 16) = "WBSTK(Total goods movement status)"
findandreplace(0, 17) = "LIFSP"
findandreplace(1, 17) = "LIFSP(Default delivery block)"
findandreplace(0, 18) = "SPRAS"
findandreplace(1, 18) = "SPRAS(Language)"
findandreplace(0, 19) = "VBUK"
findandreplace(1, 19) = "VBUK(Sales Document Admin Data)"
findandreplace(0, 20) = "KNKK"
findandreplace(1, 20) = "KNKK(Customer Credit)"
findandreplace(0, 21) = "LIKP"
findandreplace(1, 21) = "LIKP(SD Document: Delivery Header Data)"
findandreplace(0, 22) = "bolnr"
findandreplace(1, 22) = "BOLNR(Tare/Registration#)"
findandreplace(0, 23) = "makt"
findandreplace(1, 23) = "MAKT(Material Texts)"
findandreplace(0, 24) = "kkber"
findandreplace(1, 24) = "KKBER(Credit Control Area)"
findandreplace(0, 25) = "LFDAT"
findandreplace(1, 25) = "LFDAT(Delivery Date)"
For j = 1 To 25
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = findandreplace(0, j)
.Replacement.Text = findandreplace(1, j)
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Next j
End Sub
Monday, 5 October 2015
Status from a Network Order
So I had to map this out for someone... quite straightforward, but might be of use to someone out there!
Here we have Network Order 41000000 which has a variety of Statuses against it:
Here we have Network Order 41000000 which has a variety of Statuses against it:
AUFK doesn’t contain the
statuses. To find the statuses, we go via table JEST. JEST is keyed on OBJNR
(Object Number) which is a field in AUFK. It’s basically the order number with
a prefix.
So a search on JEST for OBJNR =
NP000041000000, which yields the following:
Column 3 in this table is
whether the status is inactive or not, so we ignore anything with an X in it.
For the internal statuses, we
can get the text from table TJ02T :
For the external statuses, we
can get the text from table TJ30T.
Wednesday, 16 September 2015
Standing on the shoulders of giants.... [SAPLINK]
Okay, so halfway through looking for xlsx downloads, I came across the following :
SAPLINK : A project / set of programs that allows users to upload+download vast swathes of code, dictionary objects etc outside of the traditional transport methodology:
http://wiki.scn.sap.com/wiki/display/ABAP/SAPlink+User+Documentation
Then once you've got SAPLINK working, you can load in the ZCL_EXCEL* classes, which will do all the Excel work for you...
https://github.com/ivanfemia/abap2xlsx/wiki/Installation-guide
Once again, I'm blown away by the generosity of the community in sharing their code, and generally making life better for their fellow developers! Good work all!
SAPLINK : A project / set of programs that allows users to upload+download vast swathes of code, dictionary objects etc outside of the traditional transport methodology:
http://wiki.scn.sap.com/wiki/display/ABAP/SAPlink+User+Documentation
Then once you've got SAPLINK working, you can load in the ZCL_EXCEL* classes, which will do all the Excel work for you...
https://github.com/ivanfemia/abap2xlsx/wiki/Installation-guide
Once again, I'm blown away by the generosity of the community in sharing their code, and generally making life better for their fellow developers! Good work all!
Monday, 14 September 2015
XSLT Pointer
This is as much for my own future reference as for anyone else's help... but it's been a while since I'd done any XSLT. Since all the examples had the same incoming XML tags as the outgoing mapped structures, it was confusing as to what referred to incoming, and what referred to outgoing :
The rule of thumb I'm following (pragmatic until the last!) is that if it's in quotes and has "ss:" in it, then that's from the source, and any "xml:element" content refers to the outgoing data.
Trying to access the "Attributes" in the source XML is simply a matter of using the "@" symbol.
So the above takes the following xml:
<row r="2" x14ac:dyDescent="0.25" spans="1:5">
<c r="A2" t="s"><v>5</v></c>
<c r="B2" t="s"><v>6</v></c>
<c r="C2" t="s"><v>7</v></c>
<c r="D2" t="s"><v>8</v></c>
<c r="E2" t="s"><v>9</v></c>
</row>
and spits out xml tags without attributes... the "r" attributes have been chucked into "C1" tags:
<sheetData>
<row>
<c>
<c1>A1</c1>
<v>0</v>
</c>
<c>
<c1>B1</c1>
<v>1</v>
</c>
<c>
Thursday, 10 September 2015
XLSX Upload using XSLT
Having been tasked with an upload of xlsx (as well as xls, but hey, there's a quarter-dozen ways of doing that and we all know what they are!) I came across this:
http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/6026d7c0-c716-3010-c8be-ea771ff9d783?QuickLink=index&overridelayout=true&57720065492913
You need to use the XSLT to do the transformation. SAP could really do with writing this into a standardised method, but I daresay someone else might beat them to it!
Good work Manu!
For me, the really interesting thing about this is the way that the xlsx files are structured. I was astonished at the way the shared string file works, but the amount of disk space that gets saved off the back of that could be massive.
Another thing to mention is that the XSLT transformations ARE CASE SENSITVE.
I just spent a cuppla hours having transformations fail on me because I'd not translated to upper case. Eugh. What a day.
http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/6026d7c0-c716-3010-c8be-ea771ff9d783?QuickLink=index&overridelayout=true&57720065492913
You need to use the XSLT to do the transformation. SAP could really do with writing this into a standardised method, but I daresay someone else might beat them to it!
Good work Manu!
For me, the really interesting thing about this is the way that the xlsx files are structured. I was astonished at the way the shared string file works, but the amount of disk space that gets saved off the back of that could be massive.
Another thing to mention is that the XSLT transformations ARE CASE SENSITVE.
I just spent a cuppla hours having transformations fail on me because I'd not translated to upper case. Eugh. What a day.
Thursday, 6 August 2015
How to find which function a UI5 service is calling...
Recently I was asked to investigate why some UI5 transactions were running slowly. Ordinarily, I'd be able to link services seen in the F12 Developer tools in Internet Explorer (in IE tap F12, switch on Network Logging, then do the UI5 f/e transaction, see what services are being called ) to the services defined in SEGW.
For some reason (if I find it, I'll blog it!) there weren't any services defined in SEGW. They were all present and correct in /IWFND/MAINT_SERVICE, but because that doesn't tell you the backend ABAP to look at, it doesn't help here.
What I was able to do was do a search on "odata" in SICF transaction. The odata node has a handler class /IWFND/CL_SODATA_HTTP_HANDLER.
For some reason (if I find it, I'll blog it!) there weren't any services defined in SEGW. They were all present and correct in /IWFND/MAINT_SERVICE, but because that doesn't tell you the backend ABAP to look at, it doesn't help here.
What I was able to do was do a search on "odata" in SICF transaction. The odata node has a handler class /IWFND/CL_SODATA_HTTP_HANDLER.
An external breakpoint in the constructor method of this class will be hit every time ANY odata service is called. From here, a "Breakpoint on Statement : call function" will eventually (about 30 functions later) reach a statement:
call function mv_rfc_name DESTINATION mv_destination
mv_rfc_name will have the name of the function that the service is actually calling.
******************
Okay subsequent EDIT - Just stick the breakpoint in the Constructor of /IWFND/CL_BEC_BOP_COMMON_RFC
This is the constructor of the superclass that all the oData services inherit from.
Should save you about 30 seconds every time you search!
ATB. P.
******************
Another subsequent Edit : 07.09.2017 :
/IWBEP/CL_MGW_BOP_COMMON_RFC also good for this in S4H
******************
Okay subsequent EDIT - Just stick the breakpoint in the Constructor of /IWFND/CL_BEC_BOP_COMMON_RFC
This is the constructor of the superclass that all the oData services inherit from.
Should save you about 30 seconds every time you search!
ATB. P.
******************
Another subsequent Edit : 07.09.2017 :
/IWBEP/CL_MGW_BOP_COMMON_RFC also good for this in S4H
Tuesday, 21 July 2015
UI5 / Gateway Troubleshooting
Brilliant overview of things to do when your UI5 App goes wrong, or you've got to go and fix someone else's, and you don't know where to start:
http://scn.sap.com/community/gateway/blog/2013/08/09/frequent-problems-encountered-in-netweaver-gateway-service-development
Good work Krishna!
http://scn.sap.com/community/gateway/blog/2013/08/09/frequent-problems-encountered-in-netweaver-gateway-service-development
Good work Krishna!
Tuesday, 30 June 2015
ABAP Push Channel
Usual left-field nonsense here... smiley emoji...
Using a combination of the ABAP Push Channel, which sends realtime messages super quick from place to place on your ABAP system, and the Phaser Game Library, I get some realtime graph updates based on what the little dudes on the right hand side are doing.
Just built this as a demo because creating sales orders and sending messages is a bit slow, and I wanted to see how much traffic I could throw at the channel before it started to snarl up.
I can't prove it, but I think it's the graph that's struggling here, not the messaging channel.
SAP have a PONG version, now shipped as standard, with
/sap/bc/apc_test/ping_pong/game
/sap/bc/apc_test/ping_pong/player
One day, I could imagine having 2 terminals, one for each player, which updates a third terminal.
Sorry about the video quality, I guess Youtube are running out of space, but you can basically see what's going on!
Just built this as a demo because creating sales orders and sending messages is a bit slow, and I wanted to see how much traffic I could throw at the channel before it started to snarl up.
I can't prove it, but I think it's the graph that's struggling here, not the messaging channel.
SAP have a PONG version, now shipped as standard, with
/sap/bc/apc_test/ping_pong/game
/sap/bc/apc_test/ping_pong/player
One day, I could imagine having 2 terminals, one for each player, which updates a third terminal.
Sorry about the video quality, I guess Youtube are running out of space, but you can basically see what's going on!
Thursday, 18 June 2015
PI Java Editor - Security Refusal
Ah, security, eh... doing a great job of preventing malicious parties doing stuff to your system. Throwing the baby out with the bathwater, they also prevent ABAP Heroes, such as ABAPGirl and OSSBoy and Mr SMARTForms from doing their thing...
When trying to access the PI Development environment ( Java ) we recently encountered this:
"Your Security Settings have blocked a self-signed application from running"
Which was fixed by lowering security settings (the cavalier approach) or adding the PI server to the exceptions list (the RIGHT way!).
This is done by going to Control Panel - > Java -> Security
When trying to access the PI Development environment ( Java ) we recently encountered this:
"Your Security Settings have blocked a self-signed application from running"
Which was fixed by lowering security settings (the cavalier approach) or adding the PI server to the exceptions list (the RIGHT way!).
This is done by going to Control Panel - > Java -> Security
Nice and easy!
Monday, 18 May 2015
Eastings/Northings to LatLngs conversion
The remit here is to take Eastings/Northings (A UK based Ordnance Survey Gridreferencing system) and convert to LatLngs (the grid-referencing done by most GPS systems, and most importantly, Google Maps).
The algorithms for doing these conversions are here, and the accompanying guide I found really interesting. Basically, it comes down to Eastings/Northings are based on a 2-dimensional grid (assuming that England is roughly flat), but LatLngs are based on a 3-dimensional sphere (I'm looking at you, planet Earth...)
This call for me had the perfect storm of lots of complicated maths, knowledge of 2 programming languages, and the sexy prospect of overlaying the results on Google Maps.
Total trophy moment when I got it to work....
*&---------------------------------------------------------------------*
*& Report YPD_PL1_LATLNG
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT YPD_PL1_LATLNG.
data: pi type f,
radPHI0 type f,
radLAM0 type f,
af0 type f,
bf0 type f,
e2 type f,
Et type f,
phi0 type f,
lam0 type f,
w_deciPhi0 type f,
w_DeciLam0 type f,
o_lat type f,
o_lng type f.
constants: c_a type f value '6377563.396',
c_b type f value '6356256.909',
c_e0 type f value '400000',
c_n0 type f value '100000-',
c_f0 type f value '0.9996012717',
c_deciPhi0 type f value '49.00000000',
c_deciLam0 type f value '2.00000000-',
c_Phi0 type f VALUE '0.855211333',
C_Lam0 type f value '0.034906585-'.
parameters: p_east type int4 default '359536',
p_north type int4 default '403646'.
start-of-selection.
write: 'East:', p_east, ', North', p_north.
perform initialise_vars.
perform E_N_to_LAT using p_east p_north c_n0 c_f0 changing o_lat.
perform E_N_to_LNG using p_east p_north c_n0 c_f0 changing o_lng.
form E_N_to_Lat using p_East type int4
p_North type int4
p_n0 type f
p_f0 type f
changing e_n_to_lat type f.
data: af0 type f,
bf0 type f,
e2 type f,
n type f,
Et type f,
VII type f,
VIII type f,
IX type f,
PHid type f,
nu type f,
rho type f,
eta2 type f.
*'Un-project Transverse Mercator eastings and northings back to latitude.
*'Input: - _
* eastings (East) and northings (North) in meters; _
* ellipsoid axis dimensions (a & b) in meters; _
* eastings (e0) and northings (n0) of false origin in meters; _
* central meridian scale factor (f0) and _
* latitude (PHI0) and longitude (LAM0) of false origin in decimal degrees.
"'REQUIRES THE "Marc" AND "InitialLat" FUNCTIONS
*'Compute af0, bf0, e squared (e2), n and Et
af0 = c_a * p_f0.
bf0 = c_b * p_f0.
e2 = ( ( af0 ** 2 ) - ( bf0 ** 2 ) ) / ( af0 ** 2 ) .
n = ( af0 - bf0 ) / ( af0 + bf0 ).
Et = p_East - c_e0.
*'Compute initial value for latitude (PHI) in radians
perform InitialLat using p_north c_n0 af0 RadPHI0 n bf0 changing PHId.
*'Compute nu, rho and eta2 using value for PHId
nu = af0 / ( Sqrt( 1 - ( e2 * ( ( Sin( PHId ) ) ** 2 ) ) ) ).
rho = ( nu * ( 1 - e2 ) ) / ( 1 - ( e2 * ( SIN( PHId ) ) ** 2 ) ).
eta2 = ( nu / rho ) - 1.
*'Compute Latitude
VII = ( Tan( PHId ) ) / ( 2 * rho * nu ).
VIII = ( ( Tan( PHId ) ) / ( 24 * rho * ( nu ** 3 ) ) ) * ( 5 + ( 3 * ( ( Tan( PHId ) ) ** 2 ) ) + eta2 - ( 9 * eta2 * ( ( Tan( PHId ) ) ** 2 ) ) ).
IX = ( ( Tan( PHId ) ) / ( 720 * rho * ( nu ** 5 ) ) ) * ( 61 + ( 90 * ( ( Tan( PHId ) ) ** 2 ) ) + ( 45 * ( ( Tan( PHId ) ) ** 4 ) ) ).
E_N_to_Lat = ( 180 / Pi ) * ( PHId - ( ( Et ** 2 ) * VII ) + ( ( Et ** 4 ) * VIII ) - ( ( Et ** 6 ) * IX ) ).
WRITE:/ 'Lat Calculation'.
write:/ 'Lat:', e_n_to_lat.
write:/ 'VII', VII.
write:/ 'IX', IX.
endform.
form initialise_vars.
Pi = '3.14159265358979' .
"Convert angle measures to radians
RadPHI0 = c_DeciPhi0 * ( Pi / 180 ).
RadLAM0 = c_DeciLam0 * ( Pi / 180 ).
endform.
form marc using p_bf0 type f
p_n type f
p_phi0 type f
p_phi type f
changing p_marc type f.
data: phi_minus_phi0 type f,
phi_plus_phi0 type f,
phi_minus_phi0_times_2 type f,
phi_plus_phi0_times_2 type f,
phi_minus_phi0_times_3 type f,
phi_plus_phi0_times_3 type f.
data: l_test1 type f,
l_line1 type f,
l_line2 type f,
l_line3 type f,
l_line4 type f.
DATA: L_MARC2 TYPE F.
"Copied from VB Macro Calculation; They can nest function calculations, ABAP can't... stupid ABAP.
phi_minus_phi0 = p_phi - p_phi0.
phi_plus_phi0 = p_phi + p_phi0.
phi_minus_phi0_times_2 = phi_minus_phi0 * 2.
phi_plus_phi0_times_2 = phi_plus_phi0 * 2.
phi_minus_phi0_times_3 = phi_minus_phi0 * 3.
phi_plus_phi0_times_3 = phi_plus_phi0 * 3.
l_test1 = Sin( Phi_minus_phi0 ).
l_line1 = p_bf0.
l_line1 = ( ( ( 1 + p_n + ( ( 5 / 4 ) * ( p_n ** 2 ) ) + ( ( 5 / 4 ) * ( p_n ** 3 ) ) ) * ( p_PHI - p_PHI0 ) ) ).
l_line2 = ( ( ( 3 * p_n ) + ( 3 * ( p_n ** 2 ) ) + ( ( 21 / 8 ) * ( p_n ** 3 ) ) ) * ( Sin( phi_minus_phi0 ) ) * ( COS( phi_plus_phi0 ) ) ).
l_line3 = ( ( ( ( 15 / 8 ) * ( p_n ** 2 ) ) + ( ( 15 / 8 ) * ( p_n ** 3 ) ) ) * ( Sin( phi_minus_phi0_times_2 ) ) * ( Cos( phi_plus_phi0_times_2 ) ) ).
l_line4 = ( ( ( 35 / 24 ) * ( p_n ** 3 ) ) * ( Sin( phi_minus_phi0_times_3 ) ) * ( Cos( phi_plus_phi0_times_3 ) ) ).
* Marc = bf0 * (((1 + n + ((5 / 4) * (n ^ 2)) + ((5 / 4) * (n ^ 3))) * (PHI - PHI0)) _
* - (((3 * n) + (3 * (n ^ 2)) + ((21 / 8) * (n ^ 3))) * (Sin(PHI - PHI0)) * (Cos(PHI + PHI0))) _
* + ((((15 / 8) * (n ^ 2)) + ((15 / 8) * (n ^ 3))) * (Sin(2 * (PHI - PHI0))) * (Cos(2 * (PHI + PHI0)))) _
* - (((35 / 24) * (n ^ 3)) * (Sin(3 * (PHI - PHI0))) * (Cos(3 * (PHI + PHI0)))))
L_MARC2 = p_bf0 * ( l_line1 - l_line2 + l_line3 - l_line4 ).
p_marc = l_marc2.
* p_Marc = p_bf0 * ( ( ( 1 + p_n + ( ( 5 / 4 ) * ( p_n ** 2 ) ) + ( ( 5 / 4 ) * ( p_n ** 3 ) ) ) * ( p_PHI - PHI0 ) )
* - ( ( ( 3 * p_n ) + ( 3 * ( p_n ** 2 ) ) + ( ( 21 / 8 ) * ( p_n ** 3 ) ) ) * ( Sin( phi_minus_phi0 ) ) * ( COS( phi_plus_phi0 ) ) )
* + ( ( ( ( 15 / 8 ) * ( p_n ** 2 ) ) + ( ( 15 / 8 ) * ( p_n ** 3 ) ) ) * ( Sin( phi_minus_phi0_times_2 ) ) * ( Cos( phi_plus_phi0_times_2 ) ) )
* - ( ( ( 35 / 24 ) * ( p_n ** 3 ) ) * ( Sin( phi_minus_phi0_times_3 ) ) * ( Cos( phi_plus_phi0_times_3 ) ) ) ) .
endform.
form InitialLat using p_North type int4
p_n0 type f
P_afo type f
p_PHI0 type f
p_n type f
p_bfo type f
changing p_InitialLat type f.
*'Compute initial value for Latitude (PHI) IN RADIANS.
*'Input: - _
* northing of point (North) and northing of false origin (n0) in meters; _
* semi major axis multiplied by central meridian scale factor (af0) in meters; _
* latitude of false origin (PHI0) IN RADIANS; _
* n (computed from a, b and f0) and _
* ellipsoid semi major axis multiplied by central meridian scale factor (bf0) in meters.
*'REQUIRES THE "Marc" FUNCTION
*'THIS FUNCTION IS CALLED BY THE "E_N_to_Lat", "E_N_to_Long" and "E_N_to_C" FUNCTIONS
*'THIS FUNCTION IS ALSO USED ON IT'S OWN IN THE "Projection and Transformation Calculations.xls" SPREADSHEET
data: l_phi1 type f,
l_phi2 type f,
M type f,
delta type f,
l_myCounter type f.
"First PHI value (PHI1)
l_PHI1 = ( ( p_North - p_n0 ) / p_afo ) + P_PHI0.
*'Calculate M
perform marc using p_bfo
p_n
p_phi0
l_phi1
changing M.
*'Calculate new PHI value (PHI2)
l_PHI2 = ( ( p_North - p_n0 - M ) / p_afo ) + l_PHI1.
*'Iterate to get final value for InitialLat
Do 10000 times. "Prevent Infinity.
delta = p_North - p_n0 - M.
if ABS( delta ) < '0.00001'.
exit.
endif.
l_PHI2 = ( DELTA / P_afo ) + l_PHI1.
perform marc using p_bfo
p_n
p_phi0
l_phi2
changing M.
l_PHI1 = l_PHI2.
l_myCounter = l_myCounter + 1.
enddo.
p_InitialLat = l_PHI2.
endform.
form E_N_to_LNG using p_East type int4
p_North type int4
p_n0 type f
p_f0 type f
changing e_n_to_lng type f.
"Un-project Transverse Mercator eastings and northings back to longitude.
data: af0 type f,
bf0 type f,
e2 type f,
n type f,
Et type f,
VII type f,
VIII type f,
IX type f,
PHid type f,
nu type f,
rho type f,
eta2 type f,
X type f,
XI type f,
XII type f,
XIIA type f.
"Compute af0, bf0, e squared (e2), n and Et
af0 = c_a * p_f0.
bf0 = c_b * p_f0.
e2 = ( ( af0 ** 2 ) - ( bf0 ** 2 ) ) / ( af0 ** 2 ).
n = ( af0 - bf0 ) / ( af0 + bf0 ).
Et = p_East - c_e0.
*'Compute initial value for latitude (PHI) in radians
perform InitialLat using p_north c_n0 af0 RadPHI0 n bf0 changing PHId.
*'Compute nu, rho and eta2 using value for PHId
nu = af0 / ( Sqrt( 1 - ( e2 * ( ( Sin( PHId ) ) ** 2 ) ) ) ).
rho = ( nu * ( 1 - e2 ) ) / ( 1 - ( e2 * ( SIN( PHId ) ) ** 2 ) ).
eta2 = ( nu / rho ) - 1.
" Compute Longitude
X = ( ( Cos( PHId ) ) ** -1 ) / nu.
XI = ( ( ( Cos( PHId ) ) ** -1 ) / ( 6 * ( nu ** 3 ) ) ) * ( ( nu / rho ) + ( 2 * ( ( Tan( PHId ) ) ** 2 ) ) ).
XII = ( ( ( Cos( PHId ) ) ** -1 ) / ( 120 * ( nu ** 5 ) ) ) * ( 5 + ( 28 * ( ( Tan( PHId ) ) ** 2 ) ) + ( 24 * ( ( Tan( PHId ) ) ** 4 ) ) ).
XIIA = ( ( ( Cos( PHId ) ) ** -1 ) / ( 5040 * ( nu ** 7 ) ) ) * ( 61 + ( 662 * ( ( Tan( PHId ) ) ** 2 ) ) + ( 1320 * ( ( Tan( PHId ) ) ** 4 ) ) + ( 720 * ( ( Tan( PHId ) ) ** 6 ) ) ).
E_N_to_Lng = ( 180 / Pi ) * ( RadLAM0 + ( Et * X ) - ( ( Et ** 3 ) * XI ) + ( ( Et ** 5 ) * XII ) - ( ( Et ** 7 ) * XIIA ) ).
WRITE:/ 'Lng Calculation'.
write:/ 'Lat:', e_n_to_lng.
Endform.
The algorithms for doing these conversions are here, and the accompanying guide I found really interesting. Basically, it comes down to Eastings/Northings are based on a 2-dimensional grid (assuming that England is roughly flat), but LatLngs are based on a 3-dimensional sphere (I'm looking at you, planet Earth...)
This call for me had the perfect storm of lots of complicated maths, knowledge of 2 programming languages, and the sexy prospect of overlaying the results on Google Maps.
Total trophy moment when I got it to work....
*&---------------------------------------------------------------------*
*& Report YPD_PL1_LATLNG
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT YPD_PL1_LATLNG.
data: pi type f,
radPHI0 type f,
radLAM0 type f,
af0 type f,
bf0 type f,
e2 type f,
Et type f,
phi0 type f,
lam0 type f,
w_deciPhi0 type f,
w_DeciLam0 type f,
o_lat type f,
o_lng type f.
constants: c_a type f value '6377563.396',
c_b type f value '6356256.909',
c_e0 type f value '400000',
c_n0 type f value '100000-',
c_f0 type f value '0.9996012717',
c_deciPhi0 type f value '49.00000000',
c_deciLam0 type f value '2.00000000-',
c_Phi0 type f VALUE '0.855211333',
C_Lam0 type f value '0.034906585-'.
parameters: p_east type int4 default '359536',
p_north type int4 default '403646'.
start-of-selection.
write: 'East:', p_east, ', North', p_north.
perform initialise_vars.
perform E_N_to_LAT using p_east p_north c_n0 c_f0 changing o_lat.
perform E_N_to_LNG using p_east p_north c_n0 c_f0 changing o_lng.
form E_N_to_Lat using p_East type int4
p_North type int4
p_n0 type f
p_f0 type f
changing e_n_to_lat type f.
data: af0 type f,
bf0 type f,
e2 type f,
n type f,
Et type f,
VII type f,
VIII type f,
IX type f,
PHid type f,
nu type f,
rho type f,
eta2 type f.
*'Un-project Transverse Mercator eastings and northings back to latitude.
*'Input: - _
* eastings (East) and northings (North) in meters; _
* ellipsoid axis dimensions (a & b) in meters; _
* eastings (e0) and northings (n0) of false origin in meters; _
* central meridian scale factor (f0) and _
* latitude (PHI0) and longitude (LAM0) of false origin in decimal degrees.
"'REQUIRES THE "Marc" AND "InitialLat" FUNCTIONS
*'Compute af0, bf0, e squared (e2), n and Et
af0 = c_a * p_f0.
bf0 = c_b * p_f0.
e2 = ( ( af0 ** 2 ) - ( bf0 ** 2 ) ) / ( af0 ** 2 ) .
n = ( af0 - bf0 ) / ( af0 + bf0 ).
Et = p_East - c_e0.
*'Compute initial value for latitude (PHI) in radians
perform InitialLat using p_north c_n0 af0 RadPHI0 n bf0 changing PHId.
*'Compute nu, rho and eta2 using value for PHId
nu = af0 / ( Sqrt( 1 - ( e2 * ( ( Sin( PHId ) ) ** 2 ) ) ) ).
rho = ( nu * ( 1 - e2 ) ) / ( 1 - ( e2 * ( SIN( PHId ) ) ** 2 ) ).
eta2 = ( nu / rho ) - 1.
*'Compute Latitude
VII = ( Tan( PHId ) ) / ( 2 * rho * nu ).
VIII = ( ( Tan( PHId ) ) / ( 24 * rho * ( nu ** 3 ) ) ) * ( 5 + ( 3 * ( ( Tan( PHId ) ) ** 2 ) ) + eta2 - ( 9 * eta2 * ( ( Tan( PHId ) ) ** 2 ) ) ).
IX = ( ( Tan( PHId ) ) / ( 720 * rho * ( nu ** 5 ) ) ) * ( 61 + ( 90 * ( ( Tan( PHId ) ) ** 2 ) ) + ( 45 * ( ( Tan( PHId ) ) ** 4 ) ) ).
E_N_to_Lat = ( 180 / Pi ) * ( PHId - ( ( Et ** 2 ) * VII ) + ( ( Et ** 4 ) * VIII ) - ( ( Et ** 6 ) * IX ) ).
WRITE:/ 'Lat Calculation'.
write:/ 'Lat:', e_n_to_lat.
write:/ 'VII', VII.
write:/ 'IX', IX.
endform.
form initialise_vars.
Pi = '3.14159265358979' .
"Convert angle measures to radians
RadPHI0 = c_DeciPhi0 * ( Pi / 180 ).
RadLAM0 = c_DeciLam0 * ( Pi / 180 ).
endform.
form marc using p_bf0 type f
p_n type f
p_phi0 type f
p_phi type f
changing p_marc type f.
data: phi_minus_phi0 type f,
phi_plus_phi0 type f,
phi_minus_phi0_times_2 type f,
phi_plus_phi0_times_2 type f,
phi_minus_phi0_times_3 type f,
phi_plus_phi0_times_3 type f.
data: l_test1 type f,
l_line1 type f,
l_line2 type f,
l_line3 type f,
l_line4 type f.
DATA: L_MARC2 TYPE F.
"Copied from VB Macro Calculation; They can nest function calculations, ABAP can't... stupid ABAP.
phi_minus_phi0 = p_phi - p_phi0.
phi_plus_phi0 = p_phi + p_phi0.
phi_minus_phi0_times_2 = phi_minus_phi0 * 2.
phi_plus_phi0_times_2 = phi_plus_phi0 * 2.
phi_minus_phi0_times_3 = phi_minus_phi0 * 3.
phi_plus_phi0_times_3 = phi_plus_phi0 * 3.
l_test1 = Sin( Phi_minus_phi0 ).
l_line1 = p_bf0.
l_line1 = ( ( ( 1 + p_n + ( ( 5 / 4 ) * ( p_n ** 2 ) ) + ( ( 5 / 4 ) * ( p_n ** 3 ) ) ) * ( p_PHI - p_PHI0 ) ) ).
l_line2 = ( ( ( 3 * p_n ) + ( 3 * ( p_n ** 2 ) ) + ( ( 21 / 8 ) * ( p_n ** 3 ) ) ) * ( Sin( phi_minus_phi0 ) ) * ( COS( phi_plus_phi0 ) ) ).
l_line3 = ( ( ( ( 15 / 8 ) * ( p_n ** 2 ) ) + ( ( 15 / 8 ) * ( p_n ** 3 ) ) ) * ( Sin( phi_minus_phi0_times_2 ) ) * ( Cos( phi_plus_phi0_times_2 ) ) ).
l_line4 = ( ( ( 35 / 24 ) * ( p_n ** 3 ) ) * ( Sin( phi_minus_phi0_times_3 ) ) * ( Cos( phi_plus_phi0_times_3 ) ) ).
* Marc = bf0 * (((1 + n + ((5 / 4) * (n ^ 2)) + ((5 / 4) * (n ^ 3))) * (PHI - PHI0)) _
* - (((3 * n) + (3 * (n ^ 2)) + ((21 / 8) * (n ^ 3))) * (Sin(PHI - PHI0)) * (Cos(PHI + PHI0))) _
* + ((((15 / 8) * (n ^ 2)) + ((15 / 8) * (n ^ 3))) * (Sin(2 * (PHI - PHI0))) * (Cos(2 * (PHI + PHI0)))) _
* - (((35 / 24) * (n ^ 3)) * (Sin(3 * (PHI - PHI0))) * (Cos(3 * (PHI + PHI0)))))
L_MARC2 = p_bf0 * ( l_line1 - l_line2 + l_line3 - l_line4 ).
p_marc = l_marc2.
* p_Marc = p_bf0 * ( ( ( 1 + p_n + ( ( 5 / 4 ) * ( p_n ** 2 ) ) + ( ( 5 / 4 ) * ( p_n ** 3 ) ) ) * ( p_PHI - PHI0 ) )
* - ( ( ( 3 * p_n ) + ( 3 * ( p_n ** 2 ) ) + ( ( 21 / 8 ) * ( p_n ** 3 ) ) ) * ( Sin( phi_minus_phi0 ) ) * ( COS( phi_plus_phi0 ) ) )
* + ( ( ( ( 15 / 8 ) * ( p_n ** 2 ) ) + ( ( 15 / 8 ) * ( p_n ** 3 ) ) ) * ( Sin( phi_minus_phi0_times_2 ) ) * ( Cos( phi_plus_phi0_times_2 ) ) )
* - ( ( ( 35 / 24 ) * ( p_n ** 3 ) ) * ( Sin( phi_minus_phi0_times_3 ) ) * ( Cos( phi_plus_phi0_times_3 ) ) ) ) .
endform.
form InitialLat using p_North type int4
p_n0 type f
P_afo type f
p_PHI0 type f
p_n type f
p_bfo type f
changing p_InitialLat type f.
*'Compute initial value for Latitude (PHI) IN RADIANS.
*'Input: - _
* northing of point (North) and northing of false origin (n0) in meters; _
* semi major axis multiplied by central meridian scale factor (af0) in meters; _
* latitude of false origin (PHI0) IN RADIANS; _
* n (computed from a, b and f0) and _
* ellipsoid semi major axis multiplied by central meridian scale factor (bf0) in meters.
*'REQUIRES THE "Marc" FUNCTION
*'THIS FUNCTION IS CALLED BY THE "E_N_to_Lat", "E_N_to_Long" and "E_N_to_C" FUNCTIONS
*'THIS FUNCTION IS ALSO USED ON IT'S OWN IN THE "Projection and Transformation Calculations.xls" SPREADSHEET
data: l_phi1 type f,
l_phi2 type f,
M type f,
delta type f,
l_myCounter type f.
"First PHI value (PHI1)
l_PHI1 = ( ( p_North - p_n0 ) / p_afo ) + P_PHI0.
*'Calculate M
perform marc using p_bfo
p_n
p_phi0
l_phi1
changing M.
*'Calculate new PHI value (PHI2)
l_PHI2 = ( ( p_North - p_n0 - M ) / p_afo ) + l_PHI1.
*'Iterate to get final value for InitialLat
Do 10000 times. "Prevent Infinity.
delta = p_North - p_n0 - M.
if ABS( delta ) < '0.00001'.
exit.
endif.
l_PHI2 = ( DELTA / P_afo ) + l_PHI1.
perform marc using p_bfo
p_n
p_phi0
l_phi2
changing M.
l_PHI1 = l_PHI2.
l_myCounter = l_myCounter + 1.
enddo.
p_InitialLat = l_PHI2.
endform.
form E_N_to_LNG using p_East type int4
p_North type int4
p_n0 type f
p_f0 type f
changing e_n_to_lng type f.
"Un-project Transverse Mercator eastings and northings back to longitude.
data: af0 type f,
bf0 type f,
e2 type f,
n type f,
Et type f,
VII type f,
VIII type f,
IX type f,
PHid type f,
nu type f,
rho type f,
eta2 type f,
X type f,
XI type f,
XII type f,
XIIA type f.
"Compute af0, bf0, e squared (e2), n and Et
af0 = c_a * p_f0.
bf0 = c_b * p_f0.
e2 = ( ( af0 ** 2 ) - ( bf0 ** 2 ) ) / ( af0 ** 2 ).
n = ( af0 - bf0 ) / ( af0 + bf0 ).
Et = p_East - c_e0.
*'Compute initial value for latitude (PHI) in radians
perform InitialLat using p_north c_n0 af0 RadPHI0 n bf0 changing PHId.
*'Compute nu, rho and eta2 using value for PHId
nu = af0 / ( Sqrt( 1 - ( e2 * ( ( Sin( PHId ) ) ** 2 ) ) ) ).
rho = ( nu * ( 1 - e2 ) ) / ( 1 - ( e2 * ( SIN( PHId ) ) ** 2 ) ).
eta2 = ( nu / rho ) - 1.
" Compute Longitude
X = ( ( Cos( PHId ) ) ** -1 ) / nu.
XI = ( ( ( Cos( PHId ) ) ** -1 ) / ( 6 * ( nu ** 3 ) ) ) * ( ( nu / rho ) + ( 2 * ( ( Tan( PHId ) ) ** 2 ) ) ).
XII = ( ( ( Cos( PHId ) ) ** -1 ) / ( 120 * ( nu ** 5 ) ) ) * ( 5 + ( 28 * ( ( Tan( PHId ) ) ** 2 ) ) + ( 24 * ( ( Tan( PHId ) ) ** 4 ) ) ).
XIIA = ( ( ( Cos( PHId ) ) ** -1 ) / ( 5040 * ( nu ** 7 ) ) ) * ( 61 + ( 662 * ( ( Tan( PHId ) ) ** 2 ) ) + ( 1320 * ( ( Tan( PHId ) ) ** 4 ) ) + ( 720 * ( ( Tan( PHId ) ) ** 6 ) ) ).
E_N_to_Lng = ( 180 / Pi ) * ( RadLAM0 + ( Et * X ) - ( ( Et ** 3 ) * XI ) + ( ( Et ** 5 ) * XII ) - ( ( Et ** 7 ) * XIIA ) ).
WRITE:/ 'Lng Calculation'.
write:/ 'Lat:', e_n_to_lng.
Endform.
Subscribe to:
Posts (Atom)