Skip to Content
Technical Articles

Asynchronous Posting & Dumping of production versions XL Data


In this blog post, we’ll come to know that posting and downloading of production versions of material XL Data.

Posting the XL data into SAP was done using a Start immediately Update Function module CM_FV_PROD_VERS_DB_UPDATE from presentation layer and dumping the XL data from SAP into Presentation layer was done using a normal function module GUI_DOWNLOAD.



Step 1:

Go to Transaction SE38.

Enter the name of the program and click on create button as shown below.

The below Screen will appear give the program type as executable.

Click on save button


Step 2:

Designed a selection screen for Uploading, Downloading and ALV Output Functionalities.

When we Un-Check the Upload check box it will work for download and if we check the check box it will work for upload.

Check Upload Check-Box:

Uncheck Upload Check-Box:          

Value request and help request logic was handled to load the XL data from Presentation layer. Enabling and disabling the Selection screen fields are handled at selection-screen output event.

Step 3:

When the upload check box is Unchecked, data displayed in ALV format for download using REUSE_ALV_GRID_DISPLAY Function module.

Pass the filled field-catalogs, PF Status Event, User-command event to ALV Function module to display the output.

Test Case:


Execute the report it will display the ALV output.


In the application tool bar you will find the download button to download data into Presentation layer in XL Format.

Step 4 :

If we press the download button an XL File got downloaded into presentation layer.

Note: Please maintain .XLS at the end of the file name.

Dumped XL Data:

Step 5 :

If checkbox was checked to load the XL data from presentation layer to SAP.

Presentation layer XL Data:

Test Case:

Selection screen :

Execute the report it will update the Production data into SAP.

Function module used to arrange the XL Data is ALSM_EXCEL_TO_INTERNAL_TABLE .

Function module used to update the production vertions data into sap Table MKAL is CM_FV_PROD_VERS_DB_UPDATE in UPDATE TASK Mode.

Step 6 :

Please find the logic to dump and posting the production versions data.

**– Types Declaration
TYPES: BEGIN OF ty_mkal,            ” internal table as per flat file strucre
werks TYPE mkal-werks,     ” Plant
matnr TYPE mkal-matnr,     ” Material Number
verid TYPE mkal-verid,     ” Production Version
text1 TYPE mkal-text1,     ” Short text on the production version
adatu TYPE mkal-adatu,     ” Valid-from date of production version
bdatu TYPE mkal-bdatu,     ” Run-time end: production version
bstmi TYPE mkal-bstmi,     ” Lower value of the lot-size interval
bstma TYPE mkal-bstma,     ” Upper value of the lot-size interval
stlal TYPE mkal-stlal,     ” Alternative BOM
stlan TYPE mkal-stlan,     ” BOM Usage
plnnr TYPE mkal-plnnr,     ” Key for Task List Group
alnal TYPE mkal-alnal,     ” Group Counter
plnty TYPE mkal-plnty,     ” Task List Type
END OF ty_mkal,
BEGIN OF ty_mkal1.

TYPES END OF ty_mkal1.

TYPES : BEGIN OF ty_fname,
fname(20) TYPE c,
END OF ty_fname.

**– Global Variables
DATA : v1      TYPE mkal-werks,
v2      TYPE mkal-matnr,
lv_file TYPE string,
r_comm  TYPE string,
v_matnr TYPE matnr,
v_werks TYPE werks_d.

**– Work Areas & Inernal Tables
DATA : it_mkal        TYPE alsmex_tabline OCCURS 0 WITH HEADER LINE,
ls_fieldcat    TYPE slis_fieldcat_alv,
t_fieldcatelog TYPE TABLE OF slis_fieldcat_alv,
it_it_mkal_i   TYPE STANDARD TABLE OF ty_mkal1,
wa_it_mkal_i   LIKE LINE OF it_it_mkal_i,
it_mkal2       TYPE TABLE OF ty_mkal WITH HEADER LINE,
wa_mkal2       TYPE ty_mkal,
ls_fname       TYPE ty_fname,
lt_fname       TYPE STANDARD TABLE OF ty_fname,
c              TYPE slis_selfield,
a              TYPE slis_t_extab,
it_event       TYPE slis_t_event,
wa_event       LIKE LINE OF it_event.
**– Selection screen Design
s_matnr FOR v2 MODIF ID m1.
PARAMETERS p_file TYPE ibipparms-path MODIF ID m2 .

werks FROM mkal
INTO ( v_matnr , v_werks )
WHERE matnr IN s_matnr
AND werks IN s_plant.
IF sy-subrc NE 0.

IF screen-group1 = ‘M1’.
screen-input = 0.
ELSEIF screen-group1 = ‘M2’.
screen-input = 1.
IF screen-group1 = ‘M1’.
screen-input = 1.
ELSEIF screen-group1 = ‘M2’.
screen-input = 0.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file. ” f4 help for file input
PERFORM file_help.
AT SELECTION-SCREEN ON HELP-REQUEST FOR p_file. ” F1 help for file input
MESSAGE ‘Please press f4 to upload the file’ TYPE ‘I’.


IF p_upload IS INITIAL.
IF ( s_plant-low IS NOT INITIAL OR s_plant-high IS NOT INITIAL ) AND
( s_matnr-low IS NOT INITIAL OR s_matnr-high IS NOT INITIAL ).

SELECT matnr
plnty FROM mkal INTO CORRESPONDING FIELDS OF TABLE it_mkal2 WHERE werks IN                                                                                                              s_plant AND matnr IN s_matnr.

IF sy-subrc NE 0.
*       Filling of Fieldcatalog
ls_fieldcat-col_pos  = 1.
ls_fieldcat-fieldname = ‘WERKS’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘PLANT’.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname = ls_fieldcat-seltext_m.
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

ls_fieldcat-col_pos  = 2.
ls_fieldcat-fieldname = ‘MATNR’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘MATERIAL’.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname = ls_fieldcat-seltext_m .
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

ls_fieldcat-col_pos  = 3.
ls_fieldcat-fieldname = ‘VERID’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘VESION ID’.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname = ls_fieldcat-seltext_m .
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

ls_fieldcat-col_pos  = 4.
ls_fieldcat-fieldname = ‘TEXTL’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘TEXT’.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname = ls_fieldcat-seltext_m .
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

ls_fieldcat-col_pos  = 5.
ls_fieldcat-fieldname = ‘ADATU’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘VALID FROM’.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname = ls_fieldcat-seltext_m .
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

ls_fieldcat-col_pos  = 6.
ls_fieldcat-fieldname = ‘BDATU’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘VALID TO’.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname =  ls_fieldcat-seltext_m.
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

ls_fieldcat-col_pos  = 7.
ls_fieldcat-fieldname = ‘BSTMI’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘LOWER LOT SIZE’.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname = ls_fieldcat-seltext_m .
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

ls_fieldcat-col_pos  = 8.
ls_fieldcat-fieldname = ‘BSTMA’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘UPPER LOT SIZE’.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname = ls_fieldcat-seltext_m .
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

ls_fieldcat-col_pos  = 9.
ls_fieldcat-fieldname = ‘STLAL’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘ALT BOM’.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname = ls_fieldcat-seltext_m .
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

ls_fieldcat-col_pos  = 10.
ls_fieldcat-fieldname = ‘STLAN’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘BOM’.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname = ls_fieldcat-seltext_m .
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

ls_fieldcat-col_pos  = 11.
ls_fieldcat-fieldname = ‘PLNNR’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘GROUP KEY’.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname = ls_fieldcat-seltext_m .
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

ls_fieldcat-col_pos  = 12.
ls_fieldcat-fieldname = ‘ALNAL’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘GROUP COUNTER ‘.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname = ls_fieldcat-seltext_m .
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

ls_fieldcat-col_pos  = 13.
ls_fieldcat-fieldname = ‘PLNTY’.
ls_fieldcat-tabname = ‘IT_MKAL2’.
ls_fieldcat-seltext_m = ‘TASK LIST TYPE’.
APPEND ls_fieldcat TO t_fieldcatelog.
ls_fname-fname = ls_fieldcat-seltext_m .
APPEND ls_fname TO lt_fname.
CLEAR: ls_fieldcat,ls_fname.

wa_event-name = ‘PF_STATUS_SET’.
wa_event-form = ‘ZGUI’.

APPEND wa_event TO it_event.

wa_event-name = ‘USER_COMMAND’.
wa_event-form = ‘UC’.

PERFORM uc USING sy-ucomm  c.
APPEND wa_event TO it_event.

i_callback_program = sy-repid
i_structure_name   = ‘WA_MKAL’
it_fieldcat        = t_fieldcatelog[]
it_events          = it_event
t_outtab           = it_mkal2
program_error      = 1
OTHERS             = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.                             ” SET_PF_STATUS


filename                = p_file
i_begin_col             = 1
i_begin_row             = 1
i_end_col               = 13
i_end_row               = 99
intern                  = it_mkal
inconsistent_parameters = 1
upload_ole              = 2
OTHERS                  = 3.
IF sy-subrc <> 0.
* Implement suitable error handling here
DATA l_index TYPE i.
IF  it_mkal[] IS INITIAL.
MESSAGE ‘No data uploaded!’ TYPE ‘E’.
SORT  it_mkal BY row col.
LOOP AT it_mkal.
MOVE  it_mkal-col TO l_index.
IF sy-subrc = 0. ” Incase there are more xls columns than fields
MOVE it_mkal-value TO <fs>.
AT END OF row.
APPEND it_mkal2.
CLEAR  it_mkal2.

” populate fields of struture and append to itab
LOOP AT it_mkal2.
wa_it_mkal_i-mandt = sy-mandt.

input  = it_mkal2-matnr
output = it_mkal2-matnr.
MOVE-CORRESPONDING it_mkal2 TO wa_it_mkal_i.
APPEND wa_it_mkal_i TO it_it_mkal_i.
CLEAR : wa_it_mkal_i.

LOOP AT  it_mkal2.
it_m_aend-matnr = it_mkal2-matnr.
it_m_aend-werks = it_mkal2-werks.
it_m_aend-verid = it_mkal2-verid.
it_m_aend-zaehl = ‘0001’.
APPEND it_m_aend.
CLEAR it_m_aend.

IF it_it_mkal_i IS NOT INITIAL.
it_mkal_i = it_it_mkal_i.
IF sy-subrc EQ 0.

FORM file_help .
program_name  = syst-cprog
dynpro_number = syst-dynnr
field_name    = ‘P_FILE’
file_name     = p_file.
ENDFORM.                    ” FILE_HELP
*&      Form  ZGUI
*       text
*      –>P_A  text
FORM zgui  USING    p_a TYPE slis_t_extab.
*&      Form  UC
*       text
*      –>P_SY_UCOMM  text
*      –>P_SLIS_SELFIELD  text
*&      Form  UC
*       text
*      –>P_SY_UCOMM  text
*      –>P_C  text
FORM uc  USING   a LIKE sy-ucomm
b TYPE  slis_selfield.

IF a = ‘DOWN’.
DATA p_fname TYPE ibipparms-path.
program_name  = syst-cprog
dynpro_number = syst-dynnr
field_name    = ‘P_FNAME’
file_name     = p_fname.
DATA p_name TYPE string.
p_name = p_fname.
*       BIN_FILESIZE            =
filename                = p_name
filetype                = ‘ASC’
append                  = ‘X’
write_field_separator   = ‘X’
*       HEADER                  = ’00’
*       WRITE_LF                = ‘X’
*       COL_SELECT              = ‘ ‘
*       COL_SELECT_MASK         = ‘ ‘
*       DAT_MODE                = ‘ ‘
*       CONFIRM_OVERWRITE       = ‘ ‘
*       NO_AUTH_CHECK           = ‘ ‘
*       CODEPAGE                = ‘ ‘
*       IGNORE_CERR             = ABAP_TRUE
*       REPLACEMENT             = ‘#’
*       WRITE_BOM               = ‘ ‘
*       WK1_N_FORMAT            = ‘ ‘
*       WK1_N_SIZE              = ‘ ‘
*       WK1_T_FORMAT            = ‘ ‘
*       WK1_T_SIZE              = ‘ ‘
*       FILELENGTH              =
data_tab                = it_mkal2
fieldnames              = lt_fname
file_write_error        = 1
no_batch                = 2
gui_refuse_filetransfer = 3
invalid_type            = 4
no_authority            = 5
unknown_error           = 6
header_not_allowed      = 7
separator_not_allowed   = 8
filesize_not_allowed    = 9
header_too_long         = 10
dp_error_create         = 11
dp_error_send           = 12
dp_error_write          = 13
unknown_dp_error        = 14
access_denied           = 15
dp_out_of_memory        = 16
disk_full               = 17
dp_timeout              = 18
file_not_found          = 19
dataprovider_exception  = 20

control_flush_error = 21
OTHERS = 22.
IF sy-subrc <> 0.
* Implement suitable error handling here





Using this report we can update Productions Versions of material table data with XL Data using ‘CM_FV_PROD_VERS_DB_UPDATE‘ Function module and download the updated XL Data to Presentation layer.

Thanks for reading.

Hope this post would be helpful.


You must be Logged on to comment or reply to a post.
  • Have you look at abap2xlsx?  It has some amazing capabilities including uploading Excel sheets.  It saves a lot of work.

    I'm not sure what version you are on, but using classes is always a good options.  First to get rid of your performs.  The class CL_GUI_FRONTEND_SERVICES is a nice one to use.

    Now for the positive comments:

    • This will work for uploading
    • I've never used CM_FV_PROD_VERS_DB_UPDATE and I'll have to look into it.
    • I really love the way you broke this apart in snippets to explain each one.
    • Someone just starting in ABAP could follow this.  It even starts with the SE38 screen.  (SE80, Eclipse or whatever)  They all take you to the same place.
    • It uses patterns that could be used in a dynamic program.  Such as filling the field catalog.

    Nice blog.   Just some changes to upgrade the code.  It's hard to write blogs like this with a ton of code reviews looking at your code.

  • Sorry, I feel Michelle Crapo is being very generous calling this "nice blog". Personally, I'm terrified that someone would read this and think this is a good example of an SCN blog or even a good ABAP example. This post wants me go full-on Gordon Ramsay and start screaming profanities. But that would not be very professional or community-friendly. So to borrow OJ Simpson's "if I did it, that's how I would've done it" format, if I were to write such blog, I would've done the following.

    1. Decided what would be the main focus of my blog post. Do I want to show an example of how to upload/download files, how to create an ALV report with a custom function, or do I want to show how to update production versions in SAP? And if I decided to describe a complex program then I would try to "modularize" the blog by referring to other blogs or SAP documentation for parts of it, so that I can focus on bigger picture.
    2. Decided what would be the target audience. If it's the complete beginners then I'd have a lot more explaining to do. If it's the experienced ABAPers then I don't need to explain how to create a program.
    3. I would've spent time to choose an accurate and descriptive title. Title is the face of the blog, the first impression. If it's inaccurate then the readers will be disappointed by a "clickbait" or won't even open the blog.
    4. Used standard SAP terminology and accurate product names because I want the readers to understand exactly what I'm talking about (XL?) and to be able find my post in Google easily. I would also choose language appropriate for a written article, such as "download" instead of "dump" and tried to avoid jargon.
    5. I would've started by explaining to the readers (mostly ABAPers) what "production versions" is and linked SAP documentation for reference. Also, I would have explained briefly what is the context of the story and why I've chosen to show how to use an FM that is not released by SAP.
    6. I'd explain why this particular design was chosen for the program, what pros/cons it has compared to other possible solutions, and what business challenge it solves. Why would the business users prefer to use old xls instead of xlsx format? Must be some explanation there.
    7. I would've searched for the modern ABAP functionality and would've used, for example, CL_GUI... class (mentioned by Michelle) to manage the file operations, and SALV for ALV functionality.
    8. In the code examples, I would've followed the current guidelines and would not use Hungarian Notation or any obsolete commands or techinques. I would've offered full program code in text form (probably also posted on GitHub) or shared the relevant fragments (in case of a "modularized" blog, see p. 1) with a clear explanation how the readers can "connect the dots". I would offer not just "how" but also "why" explanation for each step.
    9. I would've made an effort to note how the code could be different based on ABAP version available. (Posting on Github would've made it simpler.)
    10. I would've ensured that my screenshots are accurate, consistent, and match the blog text.
    11. Before publishing, I would've previewed and edited the blog post several times to make sure grammar and capitalization is correct to the best of my knowledge, and formatting is neat and appropriate (e.g. format code as code).
    12. Lastly, I would've promptly acknowledged the blog comments with a personal reply or at least a click on "Like" button.
    • I think a lot of it is around what version of SAP that you are on.  Sometimes you don't have an option to use something else.   I didn't notice the name/description differences - good catch.

      I do like the format of the blog.  A snippet of the code and then the explanation.  I think that if you've never written a program - those early steps would help.  But again it depends on your version of SAP.  SE38 or SE80 isn't a good start point for people starting their programming careers.  I would start them with Eclipse.

      😉  Nice blog is in the eyes of the beholder.  Again I liked the format - snippet and explanation.  I would be upset as a code reviewer if I saw this in my company.  However, we use on-premise HANA.  So I would expect upgraded code.

      I also like that he put the code out there.  Even I have a hard time doing that.

      • Michelle, with all due respect I believe at this point we can safely assume that vast majority of the SAP systems have SALV functionality. As far as ABAP is concerned, this blog could’ve been just mediocre 10 years ago. But it’s 2020 now and it’s time to stop pretending that it’s still OK to code like that.

        And while the explanation exists, it’s actually not clear. Our DEV system was down yesterday, so I had time to read this carefully. ? Quite honestly, I could just go sentence by sentence and have lots of questions on each one. For example, the button doesn’t just magically appear in ALV toolbar, it requires a special GUI status. This is mentioned nowhere in the blog. How would this be helpful to the beginners?

        I understand there must be certain pressure on the Champions to make everyone feel warm and fuzzy on SCN and stuff. But after finding another blog (linked in my other comment) where the author copied the screenshots from and which has the same exact format I suspect this is just the SCN variation of SDN point hunting.


        • I love debating with you.  It's so much fun, because you have valid points.  There isn't any pressure on SAP Champions to give warm and fuzzy comments out.  Personally I like to encourage people.  My comments will be improved by what you have typed.  Yes encourage, but also point out the coding technique.

          Yes, almost all systems have SALV.  So yes, totally agree that it would have made the coding easier.  Again you are correct, I did not go line by line through this one and verify everything.

          Perhaps this blog is valuable because of the comments that it is generating?  I don't know.  The screen shots - that's pretty bad, and I didn't comment after you, because I totally agree with your comment.  I did "like" it.  Totally surprised you even found the other blog.  Amazing.

          Well there really isn't anything that would be of value for posting any blog - I don't think.  I guess you get to go on a list.  But I don't know what else would motivate you except your own desire to share and build a good community.

          My reasoning and we can agree to disagree:

          1.  It was his first blog - does not make it OK to copy or give bad information.  But I do like the format.  Of both blogs.
          2. He showed code here.  I practically shake when I do that.  And I double, triple...  check my code.  I applaud anyone brave enough to put actual code in our community.  There are 100 different ways to do something.  So it's very scary.  I like that the comments may help me in my future code...  And so I do publish some of my code.  Sadly the code in this blog is not something you or I would like to see in our system.   But it will work - I believe.  I haven't cut and pasted it.  Perhaps I should have stated that better.

          So is this blog worth posting?  Perhaps not.  Why?  Because you have changed my mind.  I really wouldn't want someone to think it was fine to code like this.

          Do I wish someone had taken a quick look at it before it was published? Yes, someone could have let him know he was using old coding techniques.

          Do I think any coping from other blogs is OK?  NO.  I had no idea he had copied the screens.  Nor did I look at them close enough to notice they were different than the blog.  If I had, I would probably have assumed, he just messed up on his screenshots.

          • In my opinion, it would be better if at least the very first blogs were reviewed by a moderator or someone. SCN is held in higher regard in the community, so the expectations for the content are higher too. (I had quite a bit of prior writing experience before venturing out on SCN.) It's not the best place for the very first blogging experiment IMHO. Just like in skiing, you start with a beginner slope (e.g. a personal blog or internal for a company) and then slowly graduate to more complex ones.

            I also hesitate to share code on SCN, it's not hard to notice that none of my blogs are technical. 🙂 But it's mostly because we have so many excellent ABAP bloggers who are much better than me in that area. I do sometimes post code in the answers though.

            P.S. It feels like we have material for at least 5 blogs in the comments here already. 🙂

          • 🙂  Yes at least 5.  Maybe even more.

            Actually, my first blog was here.  If I had received a lot of negatives without any positive feedback, it would have been my last.

            Yes, there are so many better people than I am.  BUT I try ever once and a while to write something.  Then if there are better way to do things, I usually find out.


  • I just looked at CM_FV_PROD_VERS_DB_UPDATE. Never ever use it, it's like direct update to database tables, without any data integrity check!

      • I have a hard time agreeing that unreleased function modules should not be used.  I do  really check the code prior to using them.  CS_BOM_EXPL_MAT_V2 is an example of a function module that I've used for years.   Perhaps I should look for a BAPI.  (It's been YEARS since I've used it)

        I have other examples as well.

          • So true!!!  It just can be frustrating finding what you want and then it not being released.   It can drive me a little crazy when looking for things.

            And before I use them for the first time I do look at the code, even if it is released to the customer.

  • I thought some of the screenshots looked odd (showing different program name and description) but now I realize they were simply taken from a blog by another author:

    Care to explain how this happened?