As may already know (As I have said this a thousand times) I love R -:) And of course...I love Shiny -;)
Today I had the opportunity to read a nice little book called Web Application Development with R using Shiny.
This book starts of course with a small introduction to R, which is more than enough to get started as Shiny will have you coding in no time. Shiny makes it really easy to create web applications using R as its backend.
The explanation of Shiny and its components is pretty well detailed with easy to medium to hard examples...and even when I'm myself a seasoned Shiny developer...there were a lot of things for me to learn...which is always something cool -;)
For example...although I suspect about this...I never tried it and this book just confirm that we can indeed use custom HTML, JavaScript and even JQuery in interaction with Shiny...which for sure open a new way of possibility when developing web applications with R.
Well...let's see a couple of examples shown in the book, so you can get an idea of what Shiny can do...
For sure, a book covering a single package can't be too long...that's why I call this a "nice little book"...but in the end...I'm surprise that the author managed to actually make a book out of it...with examples and lots of code to give us a full overview of Shiny and more than a better starting point to make us start developing our own applications...
If you haven't used R before or you have use it but have never deal with Shiny...this book is totally for you...go ahead and buy it! It's even on sale -;)
Greetings,
Blag.
My Rants related to SAP, Scripting Languages, Technologies and everything else I wanted to talk about...
miércoles, 27 de noviembre de 2013
martes, 19 de noviembre de 2013
Calling R from the ERP - A dirty little hack
Since I joined SAP around 2 years ago, I simply stopped using ABAP…even when I use it for almost 11 years when I was a consultant…
A week ago, I was thinking about writing a new blog…something nice…some hacky…something that would allow me to just rest and don’t blog for the rest of the year…
I thought about ERP and R…while some things have been done already like Analytics with SAP and R from Piers Harding. I wanted to actually call R from the ERP instead of the ERP from R -;)
While thinking about this…I thought the best way to do it would be to reuse something that I before on my blog Consuming R from SAP Mobile Platform where I used Rook on Heroku to create a REST page that could be consumable…
So…for this particular blog…I wanted to something simple…call R, generate a graphic and show it on my ABAP program…here’s a small diagram to get things a little bit more clear…
Here's the code for the installR.sh script...
With that…you will have a full R installation with graphic capabilities…of course…you will need to delete all the garbage generated…but we will get there later…
Now…we need to install Rook…but we need version 1.0-2 so we need to download it and install it from the source…
Then launch R…simply call it by saying…
As it will launch the R environment…
As I was lazy to work more on the script to delete those files automatically…basically…the “bin” folder should look like this…
Once we’re done…we need to pack our stuff and sent it somewhere else, as Heroku is read only…once we log off…we lost everything…
Once we have everything saved…we can close the Heroku session and keep going…we can use WinSCP to copy our packed folders from our AWS server into our local project folder…uncompressed them and copy the following files from rookonheroku…
Of course…this is a lot of work…and I mean it…lot
So…I have upload the final compiled version to GitHub -;) To get it…simply do this…
Create the code for the Rook application
On last thing we need to do…is to create the Rook application that it’s going to work on our Rook server…
In a few words what is happening here is simple...we receive the parameters "carrid" and "seats"...both came as a string with "," so we use strsplit to separate them and then create a factor with the values. In the case of "seats" we need it to be numeric so we use the as.numeric function. Finally we create a data.frame combining "carrid" and "seats". Using "Cairo" (That's why we needed graphic capabilities on R) we create a Bitmap file which is going to be the result of creating a dotchart. Once it has been created, we read it, using the readBin function we get it's Hexadecimal representation. Using the function paste and its collapse method, we put everything on a big string and send it back...easy as pie -;)
I’m sure that you will wonder how I came out with the number 231488 on the readBin line…well…I download a nice Hexadecimal Editor called HxD then I create the graphic on my local R and load it…the I went to the last line and took the Hex number…
Using the calculator I simply changed the Hex value 38830 to decimal, multiply it by 16 and then add 16 more as the first line doesn’t count…simply and easy -;)
Create the function module ZUPLOAD_GRAPHICS_TABLE
This function module will allow us to upload the generated graphic into SE78.
Create the ABAP program to make it all happen…
When we run our program…we will call our Rook application on Heroku, which will receive the sum of seats for three carriers and then create a graphic, read it’s hexadecimal representation, give back to ABAP which will in turn create it on SE78 and then read it to show it on screen…now…you will not get the best resolution ever…and will assume it’s because “Cairo” doesn’t really support bmp files, or because the graphic is getting transported and changed all the way…so…it doesn't look good…but heck! We’re calling R from the ERP…what else do you want? -:D
A week ago, I was thinking about writing a new blog…something nice…some hacky…something that would allow me to just rest and don’t blog for the rest of the year…
I thought about ERP and R…while some things have been done already like Analytics with SAP and R from Piers Harding. I wanted to actually call R from the ERP instead of the ERP from R -;)
While thinking about this…I thought the best way to do it would be to reuse something that I before on my blog Consuming R from SAP Mobile Platform where I used Rook on Heroku to create a REST page that could be consumable…
So…for this particular blog…I wanted to something simple…call R, generate a graphic and show it on my ABAP program…here’s a small diagram to get things a little bit more clear…
Of course, when I tried this the first time…it failed…miserably…simply because the current implementation of Rook on Heroku doesn't have graphic capabilities on it…so it was impossible to actually generate a graphic…
Let’s get our hands dirty and let’s separate this blogs into steps so it become easier to handle -:)
Compile R with graphic capabilities on Heroku
This step was really a pain…it took me almost a week to get it done…and funny enough the rest of the steps took me about 6 hours…anyway…let’s keep going…
I started by looking at this two awesome projects on Github…rookonheroku and heroku-buildpack-r-build-r I took some chips from both and then create my own script and steps…
If you don’t have Heroku Tool Belt installed…go ahead and grab it…Log into Heroku and do the following…
Steps to install R on Heroku with graphic capabilities |
---|
mkdir myproject && cd myproject mkdir bin echo "puts 'OK'" > config.ru echo "source 'http://rubygems.org'\n gem 'rack'" > Gemfile #Open your project folder and modify the Gemfile in Notepad…replace the "\n" by an actual line break. bundle install git init . && git add . && git commit -m "Init" heroku apps:create myproject --stack=cedar git push heroku master #Copy and paste the content of my installR.sh file into your project folder, #also copy the files features.h #and features-orig.h from heroku-buildpack-r-build-r) git add . && git commit -am "message" && git push heroku master heroku ps:scale web=0 heroku run bash cd bin/ ./installR.sh |
Here's the code for the installR.sh script...
installR.sh |
---|
#!/bin/bash # NOTE: Heroku Cedar Stack # gcc needs to be 4.3 # See http://cran.r-project.org/doc/manuals/R-admin.html for details on building R ## HELPERS function download() { if [ ! -f "$2" ]; then echo Downloading $2... curl $1 -o $2 else echo Got $2... fi } function build() { echo ---------------------------------------------------------------------- echo Building $@... echo ---------------------------------------------------------------------- echo pushd $1 ./configure --prefix=$vendordir/$2 ${@:3} && make && make install && make clean popd > /dev/null echo echo # add to libraries and pkg-config export LD_LIBRARY_PATH="$vendordir/$2:$LD_LIBRARY_PATH" export PKG_CONFIG_PATH="$vendordir/$2/lib/pkgconfig:$PKG_CONFIG_PATH" } ## SCRIPT set -e r_version="${1:-2.13.1}" r_version_major=${r_version:0:1} if [ -z "$r_version" ]; then echo "USAGE: $0 VERSION" exit 1 fi basedir="$( cd -P "$( dirname "$0" )" && pwd )" # create output directory vendordir=/app/vendor mkdir -p $vendordir echo ====================================================================== echo Downloading and unpacking dependancies... echo ====================================================================== # We need to install xz to be able to unzip the gcc package we're going to download in a minute curl http://gfortran.com/download/x86_64/xz.tar.gz -o xz.tar.gz tar xzvf xz.tar.gz # Get and unpack gcc-4.3 binary, including gfortran curl http://gfortran.com/download/x86_64/snapshots/gcc-4.3.tar.xz -o gcc-4.3.tar.xz ./usr/bin/unxz gcc-4.3.tar.xz tar xvf gcc-4.3.tar # http://www.freetype.org/freetype2/ freetype_version=2.5.0 download http://www.mirrorservice.org/sites/download.savannah.gnu.org/releases/freetype/freetype-$freetype_version.tar.gz freetype-$freetype_version.tar.gz tar xzf freetype-$freetype_version.tar.gz # http://directfb.org/ directfb_version=1.2.9 directfb_ver_major=${directfb_version:0:3} download http://directfb.org/downloads/Core/DirectFB-$directfb_ver_major/DirectFB-$directfb_version.tar.gz DirectFB-$directfb_version.tar.gz tar xzf DirectFB-$directfb_version.tar.gz # http://www.libpng.org/pub/png/libpng.html libpng_version=1.2.50 download ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng12/libpng-$libpng_version.tar.gz libpng-$libpng_version.tar.gz tar xzf libpng-$libpng_version.tar.gz # http://www.cairographics.org pixman_version=0.29.4 download http://www.cairographics.org/snapshots/pixman-$pixman_version.tar.gz pixman-$pixman_version.tar.gz tar xzf $basedir/pixman-$pixman_version.tar.gz # http://www.freedesktop.org/software/fontconfig fontconfig_version=2.9.0 download http://www.freedesktop.org/software/fontconfig/release/fontconfig-$fontconfig_version.tar.gz fontconfig-$fontconfig_version.tar.gz tar xzf $basedir/fontconfig-$fontconfig_version.tar.gz # http://www.cairographics.org cairo_version=1.9.14 download http://www.cairographics.org/snapshots/cairo-$cairo_version.tar.gz cairo-$cairo_version.tar.gz tar xzf $basedir/cairo-$cairo_version.tar.gz # http://www.pango.org #pango_ver=1.35 #pango_version=$pango_ver.0 #download http://ftp.gnome.org/pub/GNOME/sources/pango/$pango_ver/pango-$pango_version.tar.xz #pango-$pango_version.tar.xz #tar xJf $basedir/pango-$pango_version.tar.xz # R download http://cran.r-project.org/src/base/R-$r_version_major/R-$r_version.tar.gz R-$r_version.tar.gz tar xzf R-$r_version.tar.gz # http://gcc.gnu.org/wiki/GFortran gcc_version=4.3 download http://gfortran.com/download/x86_64/snapshots/gcc-$gcc_version.tar.xz gcc-$gcc_version.tar.xz tar xJf $basedir/gcc-$gcc_version.tar.xz -C $vendordir # patch gcc features.h file # see http://permalink.gmane.org/gmane.comp.gcc.help/40166 mkdir -p $vendordir/gcc-$gcc_version/lib/gcc/x86_64-unknown-linux-gnu/$gcc_version/include-fixed cp $basedir/features.h $vendordir/gcc-$gcc_version/lib/gcc/x86_64-unknown-linux-gnu/$gcc_version/include-fixed/features.h # https://www.gnu.org/software/libc/ glibc_version=2.7 glibc_version_x=2.7ds1 download ftp://ftp.gunadarma.ac.id/linux/debian/pool/main/g/glibc/glibc_2.7.orig.tar.gz glibc_$glibc_version.tar.gz tar xzf $basedir/glibc_$glibc_version.tar.gz -C $vendordir tar xjf $vendordir/glibc-$glibc_version/glibc-$glibc_version_x.tar.bz2 -C $vendordir echo ============================================================ echo Building dependencies... echo ====================================================================== build "$basedir/freetype-$freetype_version" freetype build "$basedir/DirectFB-$directfb_version" DirectFB build "$basedir/libpng-$libpng_version" libpng build "$basedir/pixman-$pixman_version" pixman build "$basedir/fontconfig-$fontconfig_version" fontconfig build "$basedir/cairo-$cairo_version" cairo # copy over missing header files cp $basedir/cairo-$cairo_version/src/*.h $vendordir/cairo/include #build $basedir/pango-$pango_version pango # build R echo ============================================================ echo Building R echo ============================================================ cd $basedir/R-$r_version/ export LDFLAGS="-L$vendordir/gcc-$gcc_version/lib64" export CPPFLAGS="-I$vendordir/glibc-$glibc_version/string/ -I$vendordir/glibc-$glibc_version/time" export PATH="$vendordir/gcc-$gcc_version/bin:$PATH" echo ---------------------------------------------------------------------- echo LD_LIBRARY_PATH=$LD_LIBRARY_PATH echo PKG_CONFIG_PATH=$PKG_CONFIG_PATH echo ---------------------------------------------------------------------- ./configure --prefix=$vendordir/R --enable-R-shlib --with-readline=no --with-x=yes make cd /app/bin #ln -s R-2.15-1/bin/R ln -s R-2.13.1/bin/R rm gcc-4.3.tar rm glibc_2.7.orig.tar.gz rm R.tar.gz rm xz.tar.gz rm -rf usr/ rm -rf gcc-4.3/bin rm -rf gcc-4.3/lib rm -rf gcc-4.3/libexec rm -rf gcc-4.3/info rm -rf gcc-4.3/man rm -rf gcc-4.3/share rm -rf gcc-4.3/include rm glibc-2.7/*.tar.bz cd bin/glibc-2.7/ rm -rf abilist/ abi-tags aclocal.m4 argp assert/ b* BUGS C* c* d* e* F* g* h* i* I* l* m* M* N* aout/ rm -rf LICENSES n* o* p* P* R* r* scripts/ setjmp/ shadow/ shlib-versions signal/ socket/ soft-fp/ rm -rf stdio-common/ stdlib/ streams/ sunrpc/ sysdeps/ sysvipc/ termios/ test-skeleton.c timezone rm -rf tls.make.c version.h Versions.def wcsmbs/ wctype/ WUR-REPORT cd ../R-2.13.1 rm -rf src rm Make* rm -rf doc rm NEWS* rm -rf test rm config* rm O* README ChangeLog COPYING INSTALL SVN-REVISION VERSION NEED etc |
With that…you will have a full R installation with graphic capabilities…of course…you will need to delete all the garbage generated…but we will get there later…
Now…we need to install Rook…but we need version 1.0-2 so we need to download it and install it from the source…
Download Rook 1.0-2 |
---|
Wget http://cran.r-project.org/src/contrib/Archive/Rook/Rook_1.0-2.tar.gz -o Rook_1.0-2.tar.gz |
Then launch R…simply call it by saying…
Calling R |
---|
R |
As it will launch the R environment…
Installing Rook |
---|
install.packages(/Rook_1.0-2.tar.gz, repos = NULL, type="source") #Now we can simply quit R q() |
As I was lazy to work more on the script to delete those files automatically…basically…the “bin” folder should look like this…
And the “vendor” folder like this…
Please remove the folders by using…
Removing folders |
---|
rm –rf name_of_folder |
Once we’re done…we need to pack our stuff and sent it somewhere else, as Heroku is read only…once we log off…we lost everything…
Backup your work |
---|
tar -cvzf bin.tar.gz bin tar -cvzf vendor.tar.gz vendor scp bin.tar.gz me@myserver.com:/myproject/bin.tar.gz scp vendor.tar.gz me@myserver.com:/myproject/vendor.tar.gz #For scp you actually need a server…and I had my R on AWS…so I did used that…it might look like this… scp -i XXX_X.pem bin.tar.gz root@XX.XX.XXX.XXX:/Blag/bin.tar.gz |
Once we have everything saved…we can close the Heroku session and keep going…we can use WinSCP to copy our packed folders from our AWS server into our local project folder…uncompressed them and copy the following files from rookonheroku…
- config.ru
- demo.R
- Procfile
Last push on Heroku |
---|
git add . && git commit -am "message" && git push heroku master heroku ps:scale web=1 |
Of course…this is a lot of work…and I mean it…lot
So…I have upload the final compiled version to GitHub -;) To get it…simply do this…
Getting Blagrook |
---|
git clone git:// github.com/atejada/BlagRook.git yourproject #(This will clone my Github and create a folder called yourproject to store the codes) heroku create myapp #(Create an application for the Rook script) git push heroku master #(This allows to pass everything from my yourproject folder to your Heroku account) |
Create the code for the Rook application
On last thing we need to do…is to create the Rook application that it’s going to work on our Rook server…
demo.R |
---|
library(Rook) newapp<-function(env){ req<-Rook::Request$new(env) res<-Rook::Response$new() carrid_param<-c(req$params()$carrid) seats_param<-c(req$params()$seats) carrid_param<-strsplit(carrid_param,",") carrid_param<-c(carrid_param[[1]][1],carrid_param[[1]][2], carrid_param[[1]][3]) seats_param<-strsplit(seats_param,",") seats_param<-c(as.numeric(seats_param[[1]][1]),as.numeric(seats_param[[1]][2]), as.numeric(seats_param[[1]][3])) params<-data.frame(carrid_param,seats_param) bmp("R_Plot.bmp",type=c("cairo")) dotchart(params$seats_param,labels=params$carrid_param, xlab="Number of seats",ylab="Carriers") dev.off() to.read = file("R_Plot.bmp", "rb") x<-readBin(to.read, raw(),n=231488) hex<-paste(x, collapse = "") res$write(hex) res$finish() } server = Rhttpd$new() server$add(app = newapp, name = "summarize") server$start(listen="0.0.0.0", port=as.numeric(Sys.getenv("PORT"))) while(T) { Sys.sleep(10000) } |
In a few words what is happening here is simple...we receive the parameters "carrid" and "seats"...both came as a string with "," so we use strsplit to separate them and then create a factor with the values. In the case of "seats" we need it to be numeric so we use the as.numeric function. Finally we create a data.frame combining "carrid" and "seats". Using "Cairo" (That's why we needed graphic capabilities on R) we create a Bitmap file which is going to be the result of creating a dotchart. Once it has been created, we read it, using the readBin function we get it's Hexadecimal representation. Using the function paste and its collapse method, we put everything on a big string and send it back...easy as pie -;)
I’m sure that you will wonder how I came out with the number 231488 on the readBin line…well…I download a nice Hexadecimal Editor called HxD then I create the graphic on my local R and load it…the I went to the last line and took the Hex number…
Using the calculator I simply changed the Hex value 38830 to decimal, multiply it by 16 and then add 16 more as the first line doesn’t count…simply and easy -;)
Create the function module ZUPLOAD_GRAPHICS_TABLE
This function module will allow us to upload the generated graphic into SE78.
ZUPLOAD_GRAPHICS_TABLE |
---|
FUNCTION ZUPLOAD_GRAPHICS_TABLE. *"---------------------------------------------------------------------- *"*"Local Interface: *" IMPORTING *" REFERENCE(OBJECT) TYPE TDOBJECT DEFAULT 'GRAPHICS' *" REFERENCE(NAME) TYPE TDOBNAME *" REFERENCE(BTYPE) TYPE TDBTYPE *" REFERENCE(ID) TYPE TDID DEFAULT 'BMAP' *" REFERENCE(RESOLUTION) TYPE TDRESIDENT OPTIONAL *" REFERENCE(RESIDENT) TYPE TDRESIDENT OPTIONAL *" REFERENCE(AUTOHEIGHT) TYPE TDAUTOHGHT OPTIONAL *" TABLES *" T_BITMAP OPTIONAL *"---------------------------------------------------------------------- TYPES: TY_BOOLEAN(1) TYPE C. TYPES: BEGIN OF TY_SBDST_CONTENT. INCLUDE STRUCTURE BAPICONTEN. TYPES: END OF TY_SBDST_CONTENT. TYPES: SBDST_COMPONENTS LIKE BAPICOMPON OCCURS 1, SBDST_PROPERTIES LIKE BAPIPROPER OCCURS 1, SBDST_SIGNATURE LIKE BAPISIGNAT OCCURS 1, SBDST_CONTENT LIKE BAPICONTEN OCCURS 1. DATA: T_BDS_CONTENT TYPE STANDARD TABLE OF TY_SBDST_CONTENT, WA_BDS_COMPONENTS TYPE LINE OF SBDST_COMPONENTS, L_BDS_PROPERTIES TYPE SBDST_PROPERTIES, L_BDS_COMPONENTS TYPE SBDST_COMPONENTS, T_STXBITMAPS TYPE STANDARD TABLE OF STXBITMAPS WITH HEADER LINE, WA_BDS_SIGNATURE TYPE LINE OF SBDST_SIGNATURE, L_BDS_SIGNATURE TYPE SBDST_SIGNATURE, L_BDS_CONTENT TYPE SBDST_CONTENT, WA_STXBITMAPS TYPE STXBITMAPS, WA_BDS_PROPERTIES TYPE LINE OF SBDST_PROPERTIES. DATA: W_BYTECOUNT TYPE I, W_COLOR(1) TYPE C, W_WIDTH_TW TYPE STXBITMAPS-WIDTHTW, W_HEIGHT_TW TYPE STXBITMAPS-HEIGHTTW, W_WIDTH_PIX TYPE STXBITMAPS-WIDTHPIX, W_HEIGHT_PIX TYPE STXBITMAPS-HEIGHTPIX, W_RESOLUTION TYPE STXBITMAPS-RESOLUTION, W_BDS_BYTECOUNT TYPE I, W_TYPE TYPE STXBITMAPS-TDBTYPE, W_DOCID TYPE STXBITMAPS-DOCID. DATA: L_BDS_OBJECT TYPE REF TO CL_BDS_DOCUMENT_SET. CONSTANTS: C_TRUE TYPE TY_BOOLEAN VALUE 'X', C_FALSE TYPE TY_BOOLEAN VALUE SPACE, C_BDS_MIMETYPE TYPE BDS_MIMETP VALUE 'application/octet-stream', C_BDS_CLASSNAME TYPE SBDST_CLASSNAME VALUE 'DEVC_STXD_BITMAP', C_BDS_CLASSTYPE TYPE SBDST_CLASSTYPE VALUE 'OT'. IF BTYPE = 'BMON'. W_COLOR = C_FALSE. ELSE. W_COLOR = C_TRUE. ENDIF. CALL FUNCTION 'SAPSCRIPT_CONVERT_BITMAP_BDS' EXPORTING COLOR = W_COLOR FORMAT = 'BMP' BITMAP_BYTECOUNT = W_BYTECOUNT compress_bitmap = 'X' IMPORTING WIDTH_TW = W_WIDTH_TW HEIGHT_TW = W_HEIGHT_TW WIDTH_PIX = W_WIDTH_PIX HEIGHT_PIX = W_HEIGHT_PIX DPI = W_RESOLUTION BDS_BYTECOUNT = W_BDS_BYTECOUNT TABLES BITMAP_FILE = T_BITMAP BITMAP_FILE_BDS = T_BDS_CONTENT EXCEPTIONS FORMAT_NOT_SUPPORTED = 1 NO_BMP_FILE = 2 BMPERR_INVALID_FORMAT = 3 BMPERR_NO_COLORTABLE = 4 BMPERR_UNSUP_COMPRESSION = 5 BMPERR_CORRUPT_RLE_DATA = 6 OTHERS = 7. CREATE OBJECT L_BDS_OBJECT. WA_BDS_COMPONENTS-DOC_COUNT = '1'. WA_BDS_COMPONENTS-COMP_COUNT = '1'. WA_BDS_COMPONENTS-MIMETYPE = C_BDS_MIMETYPE. WA_BDS_COMPONENTS-COMP_SIZE = W_BYTECOUNT. APPEND WA_BDS_COMPONENTS TO L_BDS_COMPONENTS. W_TYPE = 'BSD'. SELECT SINGLE * INTO T_STXBITMAPS FROM STXBITMAPS WHERE TDOBJECT = OBJECT AND TDNAME = NAME AND TDID = ID AND TDBTYPE = BTYPE. IF SY-SUBRC = 0. READ TABLE T_STXBITMAPS INDEX 1. W_DOCID = T_STXBITMAPS-DOCID. ELSE. CLEAR W_DOCID. ENDIF. IF W_DOCID IS INITIAL. WA_BDS_SIGNATURE-DOC_COUNT = '1'. APPEND WA_BDS_SIGNATURE TO L_BDS_SIGNATURE. CALL METHOD L_BDS_OBJECT->CREATE_WITH_TABLE EXPORTING CLASSNAME = C_BDS_CLASSNAME CLASSTYPE = C_BDS_CLASSTYPE COMPONENTS = L_BDS_COMPONENTS CONTENT = T_BDS_CONTENT CHANGING SIGNATURE = L_BDS_SIGNATURE EXCEPTIONS OTHERS = 1. READ TABLE L_BDS_SIGNATURE INDEX 1 INTO WA_BDS_SIGNATURE TRANSPORTING DOC_ID. IF SY-SUBRC = 0. W_DOCID = WA_BDS_SIGNATURE-DOC_ID. ENDIF. ELSE. CALL METHOD L_BDS_OBJECT->UPDATE_WITH_TABLE EXPORTING CLASSNAME = C_BDS_CLASSNAME CLASSTYPE = C_BDS_CLASSTYPE DOC_ID = W_DOCID DOC_VER_NO = '1' DOC_VAR_ID = '1' CHANGING COMPONENTS = L_BDS_COMPONENTS CONTENT = T_BDS_CONTENT EXCEPTIONS NOTHING_FOUND = 1 OTHERS = 2. ENDIF. WA_STXBITMAPS-TDNAME = NAME. WA_STXBITMAPS-TDOBJECT = OBJECT. WA_STXBITMAPS-TDID = ID. WA_STXBITMAPS-TDBTYPE = BTYPE. WA_STXBITMAPS-DOCID = W_DOCID. WA_STXBITMAPS-WIDTHPIX = W_WIDTH_PIX. WA_STXBITMAPS-HEIGHTPIX = W_HEIGHT_PIX. WA_STXBITMAPS-WIDTHTW = W_WIDTH_TW. WA_STXBITMAPS-HEIGHTTW = W_HEIGHT_TW. WA_STXBITMAPS-RESOLUTION = RESOLUTION. WA_STXBITMAPS-RESIDENT = RESIDENT. WA_STXBITMAPS-AUTOHEIGHT = AUTOHEIGHT. WA_STXBITMAPS-BMCOMP = 'X'. INSERT INTO STXBITMAPS VALUES WA_STXBITMAPS. ENDFUNCTION. |
Create the ABAP program to make it all happen…
ZROOK |
---|
*&--------------------------------------------------------------------&* *& Report ZROOK &* *&--------------------------------------------------------------------&* *& Author: Alvaro "Blag" Tejada Galindo &* *& Company: SAP Labs Palo Alto &* *& Date: November 11, 2013 &* *& Modified on: November 18, 2013 &* *& Reason: Finish the code -;) &* *&********************************************************************&* REPORT ZROOK NO STANDARD PAGE HEADING. TYPES : BEGIN OF ty_bitmap, l(64) TYPE x, END OF ty_bitmap. TYPES: BEGIN OF TY_GRAPHIC_TABLE, LINE(255) TYPE X, END OF TY_GRAPHIC_TABLE. types: begin of ty_flights, carrid type sflight-carrid, seatsocc type sflights-seatsocc, end of ty_flights. DATA: it_bitmap TYPE STANDARD TABLE OF ty_bitmap, i_po_data TYPE STANDARD TABLE OF string, i_bitmap TYPE STANDARD TABLE OF string, T_GRAPHIC_TABLE TYPE STANDARD TABLE OF TY_GRAPHIC_TABLE, t_flights type STANDARD TABLE OF ty_flights, bitmap type string, client TYPE REF TO if_http_client, container TYPE REF TO cl_gui_custom_container, lv_length TYPE i, lv_content TYPE xstring, lr_mime_rep TYPE REF TO if_mr_api, OUTXSTRING type xstring, URL(255) TYPE C, PICTURE TYPE REF TO CL_GUI_PICTURE, L_BYTECOUNT TYPE I, L_CONTENT TYPE STANDARD TABLE OF BAPICONTEN, GRAPHIC_SIZE TYPE I, bin TYPE xstring, conv TYPE REF TO cl_abap_conv_in_ce, response TYPE string, carrid type string, seats type string, seatsocc type string, param type string. FIELD-SYMBOLS: <fs_bitmap> like line of i_bitmap, <fs_itbitmap> like line of it_bitmap, <fs_po_data> like line of i_po_data, <fs_flight> like line of t_flights. START-OF-SELECTION. perform get_data. perform call_rook. perform create_graphic. perform show_graphic. *&---------------------------------------------------------------------* *& Form GET_DATA *&---------------------------------------------------------------------* FORM GET_DATA. select carrid sum( seatsocc ) into table t_flights from sflights group by carrid. loop at t_flights ASSIGNING <fs_flight>. seatsocc = <fs_flight>-seatsocc. CONDENSE seatsocc NO-GAPS. CONCATENATE carrid <fs_flight>-carrid into carrid SEPARATED BY ','. CONCATENATE seats seatsocc into seats SEPARATED BY ','. ENDLOOP. replace regex '\A,' in carrid with space. replace regex '\A,' in seats with space. CONCATENATE '/custom/summarize?carrid=''' carrid '''&seats=' seats into param. ENDFORM. " GET_DATA *&---------------------------------------------------------------------* *& Form CALL_ROOK *&---------------------------------------------------------------------* FORM CALL_ROOK. CALL METHOD cl_http_client=>create EXPORTING host = 'blagrook.herokuapp.com' scheme = 1 IMPORTING client = client. client->request->set_method( if_http_request=>co_request_method_get ). cl_http_utility=>set_request_uri( request = client->request uri = param ). client->send( ). client->receive( ). bin = client->response->get_data( ). conv = cl_abap_conv_in_ce=>create( input = bin ). conv->read( IMPORTING data = response ). client->close( ). ENDFORM. " CALL_ROOK *&---------------------------------------------------------------------* *& Form CREATE_GRAPHIC *&---------------------------------------------------------------------* FORM CREATE_GRAPHIC. bitmap = response. TRANSLATE bitmap TO UPPER CASE. CALL FUNCTION 'SOTR_SERV_STRING_TO_TABLE' EXPORTING TEXT = bitmap LINE_LENGTH = 128 TABLES TEXT_TAB = i_bitmap. loop at i_bitmap ASSIGNING <fs_bitmap>. APPEND INITIAL LINE TO it_bitmap ASSIGNING <fs_itbitmap>. <fs_itbitmap>-l = <fs_bitmap>. ENDLOOP. CALL FUNCTION 'ZUPLOAD_GRAPHICS_TABLE' EXPORTING OBJECT = 'GRAPHICS' NAME = 'BLAG' BTYPE = 'BMON' ID = 'BMAP' TABLES T_BITMAP = it_bitmap. ENDFORM. " CREATE_GRAPHIC *&---------------------------------------------------------------------* *& Form SHOW_GRAPHIC *&---------------------------------------------------------------------* FORM SHOW_GRAPHIC. CALL FUNCTION 'SAPSCRIPT_GET_GRAPHIC_BDS' EXPORTING I_OBJECT = 'GRAPHICS' I_NAME = 'BLAG' I_ID = 'BMAP' I_BTYPE = 'BMON' IMPORTING E_BYTECOUNT = L_BYTECOUNT TABLES CONTENT = L_CONTENT EXCEPTIONS NOT_FOUND = 1 BDS_GET_FAILED = 2 BDS_NO_CONTENT = 3 OTHERS = 4. CALL FUNCTION 'SAPSCRIPT_CONVERT_BITMAP' EXPORTING OLD_FORMAT = 'BDS' NEW_FORMAT = 'BMP' BITMAP_FILE_BYTECOUNT_IN = L_BYTECOUNT IMPORTING BITMAP_FILE_BYTECOUNT = GRAPHIC_SIZE TABLES BDS_BITMAP_FILE = L_CONTENT BITMAP_FILE = T_GRAPHIC_TABLE EXCEPTIONS OTHERS = 1. CALL FUNCTION 'DP_CREATE_URL' EXPORTING TYPE = 'IMAGE' SUBTYPE = 'BMP' TABLES DATA = T_GRAPHIC_TABLE CHANGING URL = URL. CREATE OBJECT container EXPORTING container_name = '' repid = 'SAPMSSY0' dynnr = '0120'. container->set_top( -85 ). container->set_left( 120 ). container->set_width( 580 ). container->set_height( 580 ). CREATE OBJECT PICTURE EXPORTING PARENT = container. CALL METHOD PICTURE->LOAD_PICTURE_FROM_URL EXPORTING URL = URL. CALL METHOD PICTURE->SET_DISPLAY_MODE EXPORTING DISPLAY_MODE = PICTURE->DISPLAY_MODE_FIT_CENTER. WRITE ''. ENDFORM. " SHOW_GRAPHIC |
When we run our program…we will call our Rook application on Heroku, which will receive the sum of seats for three carriers and then create a graphic, read it’s hexadecimal representation, give back to ABAP which will in turn create it on SE78 and then read it to show it on screen…now…you will not get the best resolution ever…and will assume it’s because “Cairo” doesn’t really support bmp files, or because the graphic is getting transported and changed all the way…so…it doesn't look good…but heck! We’re calling R from the ERP…what else do you want? -:D
It was really fun…so see you next year -;)
Greetings,
Blag.
Developer Experience.
Suscribirse a:
Entradas (Atom)