Monday 23 November 2015

CTRL-N

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.

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...

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!

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.

datai_call type CRMT_OBJECT_ID VALUE '7000000941'.

datals_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


FUNCTION 
ZSHA_ORDER_MAINTAIN_ADD.
*"----------------------------------------------------------------------
*"*"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
*"----------------------------------------------------------------------

datals_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(4ne '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

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:


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!



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.

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.


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

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!

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!

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



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.


datapi 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.


constantsc_a type value '6377563.396',
           c_b type value '6356256.909',
           c_e0 type value '400000',
           c_n0 type value '100000-',
           c_f0 type value '0.9996012717',
           c_deciPhi0 type value '49.00000000',
           c_deciLam0 type value '2.00000000-',
           c_Phi0 type VALUE '0.855211333',
           C_Lam0 type value '0.034906585-'.

parametersp_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.

dataaf0 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 ** bf0 ** af0 ** .
    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 / Sqrte2 * SinPHId )  ** ).
    rho nu * e2 )  e2 * SINPHId ** ).
    eta2 nu / rho 1.

*'Compute Latitude
    VII TanPHId * rho * nu ).
    VIII TanPHId 24 * rho * nu ** TanPHId ** + eta2 * eta2 * TanPHId ** ).
    IX TanPHId )  720 * rho * nu ** 61 90 TanPHId )  ** 45 TanPHId ** ).

    E_N_to_Lat 180 / Pi PHId Et ** * VII Et ** * VIII Et ** * 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.

  dataphi_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.

  datal_test1 type f,
        l_line1 type f,
        l_line2 type f,
        l_line3 type f,
        l_line4 type f.

  DATAL_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 SinPhi_minus_phi0 ).

    l_line1 p_bf0.
    l_line1 + p_n + p_n ** p_n ** p_PHI p_PHI0 ).
    l_line2 * p_n p_n ** 21 p_n ** Sinphi_minus_phi0 COSphi_plus_phi0 ).
    l_line3 15 p_n ** 15 p_n ** Sinphi_minus_phi0_times_2 Cosphi_plus_phi0_times_2 ).
    l_line4 35 24 p_n ** Sinphi_minus_phi0_times_3 )  Cosphi_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

datal_phi1 type f,
      l_phi2 type f,
      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 / p_afo + l_PHI1.

*'Iterate to get final value for InitialLat

    Do 10000 times.       "Prevent Infinity.
      delta p_North p_n0 M.
      if ABSdelta '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.

dataaf0 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,
      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 ** bf0 ** af0 ** ).
    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 / Sqrte2 * SinPHId )  ** ).
    rho nu * e2 )  e2 * SINPHId ** ).
    eta2 nu / rho 1.

" Compute Longitude
    CosPHId ** -/ nu.
    XI CosPHId ** -nu ** nu / rho TanPHId ** ).
    XII CosPHId ** -120 nu ** 28 TanPHId ** 24 TanPHId ** ).
    XIIA CosPHId ** -5040 nu ** 61 662 TanPHId ** 1320 TanPHId ** 720 TanPHId ** ).

    E_N_to_Lng 180 / Pi RadLAM0 + Et * Et ** * XI Et ** * XII Et ** * XIIA ).

  WRITE:'Lng Calculation'.
  write:'Lat:'e_n_to_lng.

Endform.