Friday, December 31, 2010

SAP: Generate Barcodes with a web service to use in Excel.....demo

Ok I am in the middle of a post to the SAP SDN site covering my recent activity with the Barcode Writer in Pure Postscript and SAP. Its not complete yet and I will see when I submit it...

This Excel demo will not be in the SDN post however how its done in SAP will be covered.
Anyway its not complicated and its still in demo stages as I still want to cover a bit more in the conversion from postscript to the image used in SAP/Excel.

Any comments welcome and any ideas about postscript to gif/bmp/jpg conversion also appreciated!

The video shows how to get the barcode into excel depending on cell values. I then change the scale in the backend BSP to increase the size of the barcode, the video was done with camstudio and directly uploaded to YouTube. No soundtrack on this video as its only a demo. Also sorry to shout but you will need to view it in FULL SCREEN - the icon bottom right of the video.

I will be posting more later but off for a holiday so will pick it all up later. Happy New Year.

Sunday, December 19, 2010

SAP: Configure CutePDF writer to permanently include Barcode Writer in Pure Postscript

CutePDF's part in Barcodes in SAP with the Barcode writer in Pure Postscript.

Previously I had blogged about 26 barcodes on one page with scripts based around Redmon, Microsoft services for Unix and Ghostscript.

Well Cutepdf allows the PDF call to be configured in a setup.ini file, so I can bypass Redmon and Microsoft services for Unix in the following way.

The install directory for CutePDF on my XP system  (my ghostscript version is 8.64)

C:\Program Files\Acro Software\CutePDF Writer

Here create a setup.ini file with the following contents
[Parameters]
Command="C:\Program Files\gs\gs8.64\bin\gswin32c.exe"
Arguments=-q -dSAFER -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile="%1" "C:\Program Files\Acro Software\CutePDF Writer\barcode.ps" -
(as its blogger again with formatting code sections, the Arguments parameter is ONE line and ends with - character)

The arguments line includes the barcode.ps postscript so this file needs to be placed in the same directory. This does mean that every call to the cutepdf printer would merge barcode.ps with every printout.

Here is a screen shot of my setup.



I have not tested all parts only the ABAP list and sapscript. My previous experience of trying to merge postscript files was not so successful. However, so far it works every time.

Saturday, December 18, 2010

SAP: 26 different barcodes on a page with 1 ABAP report for FREE

So why have 26 different barcodes on one page with one ABAP report?

It's basically to demonstrate another way to use the Barcode Writer in Pure Postscript with SAP. Check out the BWIPP to see all the barcodes it supports.

My previous blogs have demonstrated integrating the BWIPP code for one barcode into a device type. This link demonstrates the approach using QR codes. Check out my SDN blog covering the technical detail.

However the method I will cover here requires some simple scripting to integrate the BWIPP into the SAP output stream for further processing at the desktop/printer. The following screen shot is the final result.



Windows XP Desktop Method - PDF


Steps involved
1) Download the BWIPP here
2) SAP Device types/output device and ABAP code 
3) Ghostscript ( I used version 8.64 for this demo)
4) Redmon (it can be found on the general ghostscript link above aswell)
5) Microsoft Service for Unix*
6) Final step run the ABAP code.


*As I used Solaris to develop the scripts on a Unix system I use the Unix based commands to integrate the BWIPP on windows. After reading the detail you may be able to help me out and suggest another method, I would like to hear about any other suggestions.


1) BWIPP
Extract the zipfile and the barode.ps file should be placed in the ghostscript bin directory that is covered later.


2) SAP Device type
The SAP Device type this time only sets up the postscript code to call the barcode. Therefore the insertion of the barcode.ps at the desktop/printer is essential.

SAP Device Type here ZBWIPP  (Filename = ZBWIPP.PRI)
SAP Output Device ZBWIPP_ALL (Filename = ZBWIPP_ALL)
SAP ABAP Code ZBWIPP_PRINT (Filename = ZBWIPP_PRINT.TXT)

Download all 3 files in a zip file here

Follow the QRcode guide but import the above files into SAP at the appropriate place.

The Output device will be ZBWIPP_ALL
The device type will be ZBWIPP
and the ABAP code is called ZBWIPP_PRINT
#######################################################################
### 17-Jan-2011 update
### Due to a change in the barcode writer in pure postscript then the ZBWIPP device type
### needs to be updated. Read about the BWIPP change in the link to the BWIPP mailing list
So the following printer controls need to be changed ZBW26 ZBW27 and ZBW28
text for the 3 barcodes below starting from ZBW26
zbst\n/zzbc (databaromni) def\nbct sqrd\nzben\n
zbst\n/zzbc (databarexpanded) def\nbct sqrd\nzben\n
zbst\n/zzbc (databarlimited) def\nbct sqrd\nzben\n
###
###
#######################################################################


3) Ghostscript is required to process the postscript file and create the PDF. The rest of the scripts will be placed in the bin directory of the ghostscript install.

4) REDMON is required for XP to create a printer in XP that SAPLPD can use. The scripts run with REDMON will integrate the BWIPP into the SAP output stream and call ghostscript to produce the final PDF.

This is the guide for a virtual postscript printer that I modified in the following way

Its IMPORTANT again to match the SAP printer name with the desktop printer. The name has to be the following "qrcodeport" (obviously if you know what your doing you can change it and you can see the qrcode origins of all of this :)



Basically the call to the printer is not made, so only one REDMON printer port is setup and the script called is PBWIPP.BAT as shown here


Script for REDMON

PBWIPP.BAT

cat - > "C:\Program Files\gs\gs8.64\bin\temp.ps"
cd "C:\Program Files\gs\gs8.64\bin\"
bwipp.ksh temp.ps



5) Microsoft Services for UNIX.
Now as my background is in UNIX then I used UNIX scripts for the Windows install. If you think there could be a better way then I would be happy to hear about any suggestions.
* I have found another way that bypasses both Redmon and Microsoft Service for Unix here.
barcode.ps needs to exist in the bin directory, its best to remove the very first line.

Script should be placed again in the ghostscript bin directory.
BWIPP.KSH
#!/bin/ksh

export PATH=$PATH:/dev/fs/C/"Program Files"/gs/gs8.64/bin/:/dev/fs/C/"Program Files"/gs/gs8.64/lib/

cd /dev/fs/C/"Program Files"/gs/gs8.64/bin

#move the SAP postscript input to one side
cat $1 >$$sap.ps

#insert Postscript
sed '/INSERTBARCODE/ r barcode.ps' <$$sap.ps >     $$sap1.ps
mv $$sap1.ps $$sap.ps

gswin32c.exe -q -dSAFER -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=ghost$$.pdf  $$sap.ps

runwin32  start acrord32.exe "c:\program files\gs\gs8.64\bin\ghost$$.pdf"

rm -f $$sap.ps
rm -f temp.ps


6) Final step run the ABAP code.
From transaction se38 run the ABAP code created earlier.
Its IMPORTANT to select the following options for page format X_65_80 and print immediately.


and the final PDF should appear in the bin directory.

NOW as it is all based on device type print controls then all the above can be used in SMARTFORMS or SAPSCRIPT.
As per the following youtube video but there is no need to change printers if the above method is used...



Printer Control Barcode Postscript code
ZBW01 MANDATORY at the START of every BARCODE
ZBW02 qrcode
ZBW03 datamatrix
ZBW04 azteccode
ZBW05 maxicode
ZBW06 auspost
ZBW07 code11
ZBW08 code128
ZBW09 code2of5
ZBW10 code39
ZBW11 code93
ZBW12 ean13
ZBW13 ean8
ZBW14 interleaved2of5
ZBW15 isbn
ZBW16 japanpost
ZBW17 kix
ZBW18 msi
ZBW19 onecode
ZBW20 pdf417
ZBW21 pharmacode
ZBW22 plessey
ZBW23 postnet
ZBW24 rationalizedCodabar
ZBW25 royalmail
ZBW26 rss14
ZBW27 rssexpanded
ZBW28 rsslimited
ZBW29 upca
ZBW30 upce
ZBW31 leitcode
ZBW32 hibccode128
ZBW33 hibccode39
ZOP01 /bcopt (parse) def\n
ZOP02 /bcopt (raw) def\n
ZOP03 /bcopt (includetext) def\n
ZOP04 /bcopt (includecheck includetext) def\n
ZOP05 /bcopt (format=truncated) def\n
ZOP06 /bcopt (format=stacked) def\n

Sunday, December 12, 2010

Free: Countries of the world in a Polygon KML file

Countries of the world KML file, download for free and it can be use for any purpose, the file is a KML polygon file of  the countries in the world in the Natural Earth datasets.

Download : WorldPoly file

I generated the file with SAP ABAP which reads the Natural Earth country shapefile in my geoserver in the clouds. More about this later.

The country ISO codes were used to colour by region  from the UN site here

*The Natural Earth Dataset has French Guiana  with the ISO code for France. The ABAP code reads the ISO code to determine the colour of the polygon. More thematic mapping to come.

Looks  like this in Google Earth



and looks like this in arcgis explorer



RAW Version

I used geoserver to produce the KML shown above.

A blog about my adventures into GEO/KML and SAP can be found on the SDN site here.

The raw file is shown in Google maps below and can be downloaded here

The main difference between the world poly file and the raw file is in the XML markup and colours found in the KML.

The RAW kml file is produced by geoserver containing the ISO codes of the countries. My ABAP program generated the polygon colours based on UN data for the world poly KML file.

Google maps will stop supporting external KML in February 2015
https://support.google.com/maps/answer/41136?p=kml&hl=en&rd=1


So I have taken a static screen shot to show the differences between the two KML files below.



Saturday, December 11, 2010

SAP: cURLing a BSP through GuiXT

Following on from my post about cURLing a google static map then I did follow up with a yahoo based method.

The reasons to try another way to get a map onto a SAP screen was to test out BSP, REST based Yahoo service and to learn more about SAP.

Why Yahoo and not Google? In my opnion Google does have better maps particularly Japan, however reading "terms of use" and at one time it appeared that Yahoo would allow free use. I have not studied the terms of use in detail recently however its not as free as I would like! However I completed the Yahoo based way.

cURLing through a proxy
cURL does allow you to follow redirection (-L option) however I hit a proxy issue where the local SAP server was accessible with a direct connection but the yahoo service required a proxy connection. This is were I failed to get cURL to work.

So I found my work around

Setup the BSP to cache the yahoo image in SAP, to allow direct cURL download.

BSP to Use Yahoo's Static Map API

I created a BSP in se80 called ZJZIP and eventually ended up with these page attributes for the main map.htm page.



Error Handling

The google static map example I posted earlier does not allow much error checking for the image. As this example is a BSP I checked the Yahoo API xml for any errors. The simple transformation used, which appears later, returns either the URL for the image or an error code. Therefore I added an error.gif to the MIME section of the BSP.







The layout of the BSP would appear in se80 as follows.


















So onto the Event Handler OnInitilization code

navigation->set_parameter( 'postcode' ).
navigation->set_parameter( 'height' ).
navigation->set_parameter( 'width' ).
navigation->set_parameter( 'zoom' ).
navigation->set_parameter( 'out' ).
if postcode is initial.
  postcode = 'b904su'.
endif.
if height is initial.
  height = '200'.
endif.
if width is initial.
  width = '200'.
endif.
if zoom is initial.
  zoom = '5'.
endif.
if out is initial.
  out = 'gif'.
endif.
DATA: pict_url type string,
      error_msg type string.
DATA err_url type string.
DATA: urlget TYPE STRING,
      urlstub TYPE STRING,
      urlstub1 type string,
      urlstub2 type string,
      urlstub3 type string,
      urlstub4 type string,
      urlstub5 type string,
      http_client TYPE REF TO IF_HTTP_CLIENT,
      return_code TYPE I,
       p_filnam type string,
      content TYPE STRING.
urlstub = 'http://local.yahooapis.com/MapsService/V1/mapImage?appid=ENTER-YOUR-OWN-YAHOO-APP-ID'.
urlstub1 = '&image_type='.
urlstub2 = '&image_height='.
urlstub3 = '&image_width='.
urlstub4 = '&zoom='.
urlstub5 = '&zip='.
concatenate urlstub urlstub1 out urlstub2 height urlstub3 width urlstub4 zoom urlstub5 postcode into urlget.
cl_http_client=>create_by_url(
  EXPORTING url = urlget
  proxy_host = 'PROXY.SERVER.ADDRESS'
  proxy_service = 'PROXY_PORT'
  IMPORTING client = http_client ).
http_client->send( ).
http_client->receive( ).
http_client->response->get_status( IMPORTING code = return_code ).
content = http_client->response->get_cdata( ).
http_client->close( ).
data: xml_string type xstring.
DATA: gs_rif_ex     TYPE REF TO cx_root,
      gs_var_text   TYPE string.
TRY.
    CALL TRANSFORMATION  ZJ_YAH_geopict
        SOURCE XML  content
        RESULT ROOT = pict_url
              EROOT = error_msg.
  CATCH cx_root INTO gs_rif_ex.
    gs_var_text = gs_rif_ex->get_text( ).
    MESSAGE gs_var_text TYPE 'E'.
ENDTRY.
if proxy <> 'y'.
if pict_url is initial.
  d_pc = 'ERROR: could not process address'.
err_url = 'http://F.Q.D.N.HERE:8000/sap/bc/bsp/zjzip/error.gif'.
  navigation->goto_page( err_url ).
else.
  DATA URL1 type string.
  url1 =   pict_url.
  d_pc = pict_url.
data:   file_length    TYPE  STRING,
  file_mime_type TYPE  STRING,
  file_name      TYPE  STRING,
  file_content   TYPE  XSTRING,
  display_type   TYPE  STRING.
cl_http_client=>create_by_url(
  EXPORTING url = d_pc
  proxy_host = 'PROXY.SERVER.ADDRESS'
  proxy_service = 'PROXY_PORT'
  IMPORTING client = http_client ).
http_client->send( ).
http_client->receive( ).
http_client->response->get_status( IMPORTING code = return_code ).
bit = http_client->response->get_data( ).
http_client->close( ).
postcode = XSTRLEN( bit ).
IF  XSTRLEN( bit ) > 0.
  DATA: cached_response TYPE REF TO if_http_response.
  CREATE OBJECT cached_response TYPE CL_HTTP_RESPONSE EXPORTING add_c_msg = 1.
  cached_response->set_data( bit ).
   cached_response->set_header_field( name  = if_http_header_fields=>content_type
                                       value = 'image/gif' ).
    cached_response->set_status( code = 200 reason = 'OK' ).
    cached_response->server_cache_expire_rel( expires_rel = 180 ).
    DATA: guid TYPE guid_32.
    CALL FUNCTION 'GUID_CREATE' IMPORTING ev_guid_32 = guid.
    CONCATENATE runtime->application_url '/' guid '.gif' INTO display_url.
    cl_http_server=>server_cache_upload( url      = display_url
                                         response = cached_response ).
response->redirect( display_url ).
else.
display_url = runtime->application_url.
  ENDIF.
endif.
endif.


Use transaction xlst_tool for the...(not so)
Simple Transformations

<?sap.transform simple?>
<tt:transform xmlns:tt="http://www.sap.com/transformation-templates" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <tt:root name="ROOT"/>
  <tt:root name="EROOT"/>
  <tt:template>
    <tt:d-cond>
      <Result>
        <tt:value ref="ROOT"/>
      </Result>
    </tt:d-cond>
    <tt:d-cond>
      <Error>
          <Message><tt:value ref="EROOT"/></Message>
      </Error>
    </tt:d-cond>
  </tt:template>
</tt:transform>



Testing it.....

Refer to the post cURLing a google static map

The following changes would be required for the BSP controlled Yahoo image.

In STEP THREE
Change the jpg format to gif


In STEP FIVE
Add the option -L to allow redirection and the F.Q.D.N is the SAP server fully qualified domain name. The PORT needs to be changed to the appropriate value.

c:\guixt\curlbin\curl -L http://F.Q.D.N.:PORT/sap/bc/bsp/sap/zjzip/map.htm? -d "postcode=%1,%2"  -d width=200 -d height=200 -d zoom=5   -G >c:\GuiXT\img\%1.gif

The END Result.











More to come on the geocode side of things.....

Wednesday, December 8, 2010

Visualising Wikipedia data with Tableau, sparql and dbpedia



Geocodes and thematic mapping in SAP will be blogged later. However here as a starting point is a very quick summary of thematic mapping Japan's population by prefecture in Tableau.


Sparqling DBpedia for Japan's Population Statistics.

Check out sparql on wikipedia
Check out dbpedia on wikipedia

So DBpedia has a sparql endpoint that allowed me to extract the total population and density with the following query.

**15/03/2013 Tableau informed me that my "vizzes" will be on my own profile page very soon. So I thought I would revisit my experiment with querying Wikipedia data with SPARQL and presenting the results with tableau.

I found that I needed to change the SPARQL query as follows.
*************

PREFIX dcterms: <http://purl.org/dc/terms/>

PREFIX skos: <http://www.w3.org/2004/02/skos/core#>

PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>

PREFIX dbpedia2: <http://dbpedia.org/property/>

SELECT ?prefecture ?lat ?long ?pop ?popt ?den ?denp

WHERE {

?prefecture dcterms:subject <http://dbpedia.org/resource/Category:Prefectures_of_Japan> .

?prefecture geo:lat ?lat .

?prefecture geo:long ?long.

OPTIONAL { ?prefecture dbpedia2:population ?pop }

OPTIONAL { ?prefecture dbpedia2:populationTotal ?popt }

OPTIONAL { ?prefecture dbpedia2:density ?den }

OPTIONAL { ?prefecture dbpedia2:populationDensityKm ?denp }

FILTER (xsd:double(?lat)).

FILTER (xsd:double(?long)).

}
**************

*original query in 2010 below will now fail to select any data.


PREFIX skos: <http://www.w3.org/2004/02/skos/core#>

PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>

PREFIX dbpedia2: <http://dbpedia.org/property/>

SELECT ?prefecture ?lat ?long ?pop ?popt ?den ?denp

WHERE {

?prefecture skos:subject <http://dbpedia.org/resource/Category:Prefectures_of_Japan> .

?prefecture geo:lat ?lat .

?prefecture geo:long ?long.

OPTIONAL { ?prefecture dbpedia2:population ?pop }

OPTIONAL { ?prefecture dbpedia2:populationTotal ?popt }

OPTIONAL { ?prefecture dbpedia2:density ?den }

OPTIONAL { ?prefecture dbpedia2:populationDensityKm ?denp }

FILTER (xsd:double(?lat)).

FILTER (xsd:double(?long)).

}






*2013 edit
Enter the first query above in DBpedia Virtuoso SPARQL Query From

The data needs to be tidied up (and I still have to update the prefecture names!) due to some changes of data names in the property section.

Using the SHOW ME! button in Tableau 

OK, so Tableau public is free and I can embed the data in this blog. I registered for an account cut and pasted my data above after a tidy up in Excel (you can download the data I used in the presentation). Then I hit the Show Me! button and the final presentation is here. So simple.......maybe.




Thursday, November 18, 2010

More 2d Barcode Device Types for SAP

The datamatrix and Aztec code Device Types can be seen in use in the YouTube video.

I have just created the MaxiCode device type.

The same printer controls work in the same way for each device type but each one generates its intended 2d barcode. As per the video.

Datamatrix here

Aztec Code here

MaxiCode here


SAP SDN blog page for BWIPP here

Thursday, November 11, 2010

Windows: printing postscript on modern networked HP printers

As I am working on Unix systems with SAP I do not have to deal with HP printer drivers on windows. We do have HP printers and the Unix systems work well without any HP drivers. I have HP printers setup on my desktop which someone else setup. All standard HP drivers as we do not have postscript printers.

However......

I finally took a trip to HP website for the 2 particular printers in the office, HP 4250 and 4700.

I found postscript drivers for both printers so....


BWIPP device types in SAP can now print directly to these printers, without any scripting.

Check the config page of any HP printer and if it supports postscript then most likely there will be a postscript driver (probably :)

I was using Redmon as part of another method to generate pdfs without cute pdf writer. I am still going to use Redmon for this but I had found another method to print postscript to non-postscript printers using Redmon. I wont be following that method now.


Tuesday, October 5, 2010

QRcodes in SAP transactions with a Zebra Crossing (ZXing) Part 1


Following up to my post on QRcodes in smartforms and sapscript which can be found here

Ever since coming across a QR code in my passport I have wanted to integrate them into SAP. I like the idea of a "quick response" of data into a mobile device as I hate typing on mobile phones. Now this is a technical solution and a demonstration of using QR codes in an ABAP transaction. The solution requires a SAP system with a java stack. The QR codes can generated and used in any web application or custom ABAP transaction. No need to rely on external web sites to generate the codes.

If your still unsure about QR codes, then try the wikipedia link
Or download The Weather Channel Android App from TV!

I am more of an system administrator/integrator than a developer so I found,
*) a Zebra crossing to do the actual QR code generation, ZXing (Zebra Crossing) (later versions now exist than the one I use)
*) the custom ABAP code is based on SAP program "SAPHTML_DEMO1"
*) GuiXT is used to link standard SAP transactions to the custom code.

The purpose of the ABAP transaction is to map the location of any customer/contact and provide a "quick response" of the map url to a mobile phone via the QR code. I made some attempts to use vCard and MEcard formats to send contact details via QR codes. However from my experience the actual applications that scan QR codes vary widely in their adoption of formats for contact information. So here I will just focus on URL's for mapping a customer's location.

ZXing


So first things first we need the QR code and to get it I made a journey into the world of Java/JSP/servlets and the SAP Java engine.

To get to my Zebra Crossing I had to use an Ant. So after a trip to Apache Ant I managed to build the key component of ZXing "core" I needed. The getting started section at the ZXing website is here. Within the ZXing "core" component is the base QR code used to generate the QR code in for my ABAP transaction. ZXing has many options/sections and platforms but all I needed was the core component to generate the QR code as I was not going to decode/scan anything.

Now as stated previously I am not a developer so I needed some clues in how to use my newly aquired core.jar file. Now searching the web provided so many options that it took some time to actually get to a working version.

Java images: JSP vs Servlet

Now I had for a long time a working version based purely in JSP. There are many examples "out there" where the image is done via pure JSP. Now this works however in the SAP java engine a warning message about output streams is generated. So checking further into the information available and the way forward was to split the actual image generation into a servlet.

With the SAP Netweaver Developer Studio I built the following into an application.

To get started with the NWDS I used this SDN blog. For this application I did not follow the authorisation part in the blog as this service is for anyone to use (anonymous user).

I am not a Java developer so I needed some help to get started and complete the process.

So I found on the web,
getting started: - initial start to the QRCodeWriter.java in ZXing here
Help splitting the code into a JSP and Servlet:- SAP note 1218520



JSP (at last I found somewhere that lets me format code to cut n paste into blogger)

<%@ page language="java" %>
<%response.sendRedirect( "/QRplutus/servlet/QRimg?" + request.getQueryString());
%>

Servlet

package servlet;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.zxing.*;
import com.google.zxing.common.ByteMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
public class QRimg extends HttpServlet {
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
String pw = request.getParameter ("w");
String ph = request.getParameter ("h");
int width;
int height;
if ( pw == null ) {
width = 200;
}
else
{
width = Integer.parseInt(pw);
}
if ( ph == null ) {
height = 200;
}
else
{
height = Integer.parseInt(ph);
}
String text = request.getParameter ("t");
if ( text == null ) {
text = "**ERROR No text passed to encode";
}
QRCodeWriter writer = new QRCodeWriter();
ByteMatrix matrix = null;
try {
matrix = writer.encode(text, BarcodeFormat.QR_CODE, width, height);
} catch (WriterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[][] matrixByte = matrix.getArray();
BufferedImage bimg = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);
byte[] linearbuffer = new byte[width*height];
int i=0;
for(int y=0;y<height;y++)
for(int x=0;x<width;x++)
linearbuffer[i++]=matrixByte[y][x];
bimg.getRaster().setDataElements(0, 0, width, height, linearbuffer);
response.setContentType("image/jpeg");
ImageIO.write(bimg, "jpeg", response.getOutputStream());
}
}

JSP & Servlet can be found here text file can be downloaded which contains the above code.

To generate the QR code, once deployed, then the following url can be used based on the above example.

http://hostname:5xx00/QRplutus/QRcode.jsp?t=test+QRcode&w=300&h=300


Obviously hostname is the hostname of the SAP server
5xx00 should match the instance number of the SAP java engine, e.g. 50000
t= is the text to encode
w= and h= control the height and width of the QR code.


You can find the whole SAP EAR file here, which you could deploy to a SAP java engine via SDM install tool.
End of part One,

Link to part Two will appear later..........

Monday, October 4, 2010

Solaris: printing postscript on modern networked HP printers

My first attempts at using the Barcode Writer In Pure Postscript involved a unix script and direct printing on networked HP printers.

While the Unix scripts will be dusted off soon, the postscript file printing to HP printers is documented here.

I am fairly used to creating standard HP print queues in Solaris for SAP printing, however as my interest was in postscript I wanted a simple way to print postscript output. Unix printing is covered in great detail on the web and openprinting.org is the way to go to set it up properly.

However I like to keep things as simple as possible.

I still need to do more investigation as to why "low level postscript" is accepted on HP printers and the future of print device pswrite in ghostscript is unclear to me.

However my simple approach was to basically print postscript files to our office jetdirect HP printers using one common print filter/device pswrite in ghostscript

1) Create a printer

lpadmin -p {printer name} -v /dev/null -m netstandard -o dest={IP address}:9100 -o protocol=tcp -o banner=never -T PS -I postscript


2) Use pswrite as the Ghostscript DEVICE option


Edit file /etc/lp/interfaces/{printer name} and change the following lines

if [ -z "${FILTER}" ]
...
..
...
fi

Change to a one liner


FILTER="/usr/sfw/bin/gs -q -dSAFER -dBATCH -dNOPAUSE -sDEVICE=pswrite -sOutputFile=- -"

then
enable print_queue
accept print_queue

Set the printer up in SAP and BWIPP device type can now print directly to HP printers.....

The same standard filter works for our HP office printers, a colour HP LaserJet 4700 and black and white HP LaserJet 4250.



Tuesday, September 28, 2010

How to Print(PDF) QR Codes in standard SAP

QR Code SAP Device Type using Barcode Writer in Pure Postscript

Ever since coming across a QR code in my passport I have wanted to integrate them into SAP. I like the idea of a "quick response" of data into a mobile device as I hate typing on mobile phone keyboards. Now this is a technical solution and no business case is provided, however the flight demo SAP sapscript and smartforms which will be covered later offer an interesting use of QR codes (in my opinion).

Still unsure about QR codes, then try the Wikipedia link
See them in action here with Google's favourite places advert

I am more of an system integrator/administrator than a developer so I found,
*) the application to do the actual QR code generation, Terry Burton's Barcode Writer in Pure Postscript, here
*) For simplicity I use the Cute PDF writer to generate the PDF via SAPlpd. A mention must go out to Ghostscript as this is used to do the actual QR Code PDF conversion. So this needs to be installed as per the instructions for Cute PDF writer.
*) Configure ABAP list program/SAPSCRIPT/SMARTFORMS to use the device type printer controls to generate the QR Codes.

Here is how to generate QR codes in SAP.


1) SPAD - Import device type FILE=ZBWIPPQR.PRI
You can download the ZBWIPPQR device type here
On the next screen enter ZBWIPPQR as the device type name


The ZBWIPPQR.PRI is a plain text file which you can open with any text editor to check it out.

2) Import output device FILE = zbwipp.txt
Download text file ZBWIPP.TXT for import here


next screen enter ZBWIPP.txt as the file name (use the directory where you downloaded the file)


3) Install Cute PDF writer from here
(direct download here http://www.cutepdf.com/download/CuteWriter.exe )
It is important to install with the PS2PDF option, so answer yes at the following prompt.



RENAME Cute PDF Writer printer to qrcodes as shown here.
Before


After



Why rename the printer to qrcodes?
This must be renamed to qrcodes to match the imported output device as shown below in the SPAD output screen. (SAPLPD will now use the printer qrcodes, in this way it does NOT interfere with any other SAP frontend printer settings you may have).



5) To enable frontend printing please ensure the user settings for spool control are set to "output immediately" in SU01.

Defaults TAB screen shot of the setting required. (make sure it is set, log off and check it again :)




6) Import the following example ABAP code to test QR codes in SAP.
From transaction SE38 create ABAP report ZQR_PRINT.
Cut and paste the text from this file found here ZQR_PRINT

Ignore any warning only messages relating to NEW-PAGE PRINT ON, this is purely used as a simple method to allow the ABAP code to use the printer controls in the device type.

Activate the program as the message is only a warning. This is only a test for ABAP list prints.


Now run the ZQR_PRINT report

Select ZBWIPP as the output device in the following print parameter screen.

*please note that the options shown here purely depend on the options you have active in the user settings. So its important, as previously stated, to have already set print immediately as one of the options.



After selecting the green tick mark, then after a short while you should have a prompt to save a PDF file.


7) The actual QR Code PDF document should look something like this....



8)... to be continued and the simple next step to use the printer controls in SAPSCRIPT and SMARTFORMS.
The YouTube videos for smartforms and sapscript now below....
*the video also shows other barcode examples.
1) The DataMatrix device type can be downloaded here
2) The Aztec Code device type can be downloaded here
*Not shown in the video but also available
3) The MaxiCode device type can be downloaded here


If you use these SAP barcodes and think that it is worthy of a donation, consider making a contribution to support the ongoing development. Making a donation in no way constitutes a purchase payment for the device types/software. 



SMARTFORMS Video



*Check out the general page for more information in regards to barcode printing in SAP with the Barcode Writer in Pure Postscript


Check out my SCN blogs here.



 SAPSCRIPT Video




If you are interested in the following screenshot, then follow this link.




Monday, June 7, 2010

SAP: How to get a Google Static Map onto a Standard SAP screen

A short and simple guide to get a Google Static Map image onto a standard Windows SAPGUI screen.





Normal GuiXT will not allow image files to be viewed via HTTP. The basic Guixt is free with standard Windows SAPGUI. Paying Synactive some cash will allow all the good things found here

*1 As its a static map the location of the customer is based on post code only
*2 As its a Google API, then you should read the terms of use, to ensure you comply

What you need is
1) Windows SAPGUI
2) GuiXT activated and knowledge of the default script directory. (normal example GuiXT directory is C:/GuiXT/, and these examples will use this directory)
3) Follow this link to get cURL


Step ONE
Setup the Windows directories.
create
C:/GuiXT/img
C:/GuiXT/curlbin


Step TWO
Extract cURL into C:/GuiXT/curlbin

Step THREE
Create GuiXT script named "SAPLBUS_LOCATOR.e3000.txt" in C:/GuiXT/ for transaction BP (business partner)

The contents of SAPLBUS_LOCATOR.e3000.txt


if Q[Page=Address]

Pushbutton (toolbar) "Refresh Google Map Image" image (14,95) "c:\GuiXT\img\&F[ADDR2_DATA-POST_CODE1].jpg" "-NoBuffer" "-Transparent" "-Plain"


image (14,95) "c:\GuiXT\img\&F[ADDR2_DATA-POST_CODE1].jpg" "-NoBuffer" "-Transparent" "-Plain" exe="C:\GuiXT\startstatic.bat &F[ADDR2_DATA-POST_CODE1] ""&F[T005T-LANDX]"""

endif


*Note the image (14,95) is ONE line and requires all those quotes. This script passes the post code and country to a BAT file.

Step FOUR
Create BAT file C:\GuiXT\startstatic.bat

The contents of C:\GuiXT\startstatic.bat

@ECHO OFF

cd c:\guixt

IF EXIST c:\guixt\img\%1.jpg GOTO EXfile

set LAND=%2
set LAND=%LAND: =+%

start /min c:\GuiXT\staticnew.bat %1 %LAND%

:EXfile

exit


This script checks if the post code exists and simple exits if it does. If the image does not exist then it does a simple string replace, in replacing " " (space) for a plus. This is for URL encoding in the next script. The script is split so the START command can be used to minimise the next cURL script.

Step FIVE
Create BAT file c:\GuiXT\staticnew.bat

The contents of c:\GuiXT\staticnew.bat

c:\guixt\curlbin\curl http://maps.google.com/maps/api/staticmap? -d "center=%1,%2" -d size=200x200 -d zoom=12 -d format=jpg -d sensor=false -d "markers=color:blue|label:H|%1,%2" -G >c:\GuiXT\img\%1.jpg


exit



This script uses cURL to download the static map image in jpg format. The curl command is one line. It uses the post code and country to geo code the location via the google api.

The END Result





Final Note
As its google its not free, but cURL can be used to download static images of which I will attempt to cover with later blogs.
*The post code is used to save the downloaded image. If the countries used share the same postcode format then the country name is needed in the filename to make it unique.

Monday, May 17, 2010

Rename Digital Camera files with the Date and Time using a 7 line KSH script

I hate the way digital cameras name files. Both the Sony and Casio cameras we have owned use an incremental file naming convention. This name is not connected to the date and time of the photo.

When I want to collect photos from a particular date of the year, ( e.g for my son or daughters birthdays) its pretty labour intensive to do this manually.

Now I have got a Unix based Mac I can revert to a scripting language I learnt many years ago to do the job for me. (Well using iPhoto is NOT the point :) and other examples are out there for that particular program.)

I DO not use on this on the original files, but copy into another directory, here $HOME/Documents/pictures/

The 7 Line Script
ls *JPG|while read i
do
echo $i
d=`strings $i |egrep "[1-2][0-9][0-9][0-9]:"|head -1|sed "s/ /-/g
s#:#-#g"`
cp $i $HOME/Documents/pictures/$d.jpg
done

*The strings bit converts the binary file into a readable file for the egrep and sed commands.

Running the strings command on a photo file on its own.
2009:10:13 19:05:29
2009:10:13 19:05:29
2009:10:13 19:05:29


We dont use any cyber shot - mult shot camera function so I can safely use the time to the second for the filename.

Then a simple ls command to list the dates for the yearly events.

ls $HOME/Documents/pictures/20[0-9][0-9]-10-13* - every 13th October for the year 2000 onwards.

Then copy them into a temporary directory with a simple cp after creating the temp directory.

cp $HOME/Documents/pictures/20[0-9][0-9]-10-13* $HOME/temp

Friday, March 12, 2010

64 bit or not

Amazing! my mac is not 64 bit enabled by default.


The technical details are here.


I need 64 bit for my solaris install in virtual box for some extra sleepless nights.


However, just changing the virtual box setting for version will boot Solaris into 64bit mode. Great.... no sleep











Google +