Ziel
Sie möchten eine S10 Anwendung erstellen, mit der der Benutzer Codes (Barcodes, QR-Codes etc.) einscannen kann. Die erkannten Daten aus dem Code sollen automatisch weiterverabreitet werden.

Mobile Geräte bieten eine Reihe an neuen Anwendungsmöglichkeiten durch den Zugriff auf die Kamera, Sensoren und so weiter. Zum Scannen von Barcodes existieren JavaScript Bibliotheken, die Sie sehr einfach einbinden und verwenden können.



Implementierung
In der Regel wird in einem bestimmten S10-View im HTML Code die JavaScript-Bibliothek eingebunden, die das Scannen von Barcodes implementiert. Wir verwenden im folgenden Beispiel den HTML5 QR Code scanner , den wir mit folgender Zeile einbinden:

    <!-- Open-source library for scanning barcodes/qrcodes -->
    <!--  https://github.com/mebjas/html5-qrcode -->
    <script src='../../../scripts/html5-qrcode.min.js'> </script>

Es wird nun zunächst ein neues Objekt erstellt und der Scanner gestartet. Zudem wird definiert was passieren soll, wenn der Scanner erfolgreich einen Code erkannt hat. In diesem Fall wird der erkannte Text in ein Eingabefeld gesetzt. Dies kann ein S10 InputField sein, das heißt, der Inhalt der Variablen steht dann auch in der ABAP Klasse zur Verfügung.

    // Start the scanner
    var html5QrcodeScanner = new Html5QrcodeScanner(
        "reader", { fps: 10, qrbox: 250 });
    html5QrcodeScanner.render(onScanSuccess);

    // The scanner recognized a code
    function onScanSuccess(decodedText, decodedResult) {

        // Put the recognized text of the code in an input field
        document.getElementById('scan_result').value = decodedText;

        // Needed to synchronize the data
        S10Enter();
    }


Die weitere Verarbeitung der Daten kann auf unterschiedliche Weise erfolgen:
 
1. Die erkannten Daten aus dem Code werdem dem Benutzer nur angezeigt und nicht weiter verabreitet
2. Die Daten werden automatisch durch eine JavaScript Methode verarbeitet, z.B. das Aufteilen in einzelne Felder aus einem Gesamttext
3. Die Verarbeitung findet in einer ABAP Methode statt.

<!-- Target area for the scanner-->
<div style="width:100%;height:35%;" id="reader"></div>

<!-- Normal S10 input field-->
<input class="input" id="scan_result" name="scan_result" type="text">

<!-- Hidden s10 field triggering JavaScript method on value change-->
<input class="input" name="scan_result" type="hidden"
   onchange="parse_scan_result(this.value);">

<!-- Hidden s10 field triggering ABAP method on value change-->
<input class="input" name="scan_result" type="hidden"
onchange="S10Apply('parse_scan_result'); ">

Beispiel: Warenausgang buchen
Mit dieser S10 Anwendung kann ein Anwendunger mit seinem mobilen Gerät einen QR-Code scannen der folgende Daten enthält:
Belegnummer einer Ausliferung, Materialnummer, Position in Lieferung und Liefermenge.
Wird ein Code erkannt und die Daten eingelesen, kann er anschließend direkt die Buchung des Warenausgangs im SAP System anstoßen.



ABAP Programm: /S10/BARCODE_EXAMPLE

program /s10/barcode_example.

class barcode_class definition inheriting from /s10/any.

  public section.

* project path (textpool, screens)
    constants:
        projectpath type string value 'sap/bc/bsp/s10/barcode'.

    data:
      vbeln type vbkok-vbeln,
      posnr type vbpok-posnr_vl,
      lfimg type vbpok-lfimg,
      matnr type mara-matnr,
      maktx type makt-maktx.

    methods:

* Method to book outgoing goods
      update_delivery,

* Build the description for a material
      build_maktx
        importing
          matnr type mara-matnr
        exporting
          maktx type makt-maktx.

endclass.

class barcode_class implementation.

  method build_maktx.

* read maktx
    select single maktx from makt into maktx
            where matnr = matnr and spras = sy-langu.
  endmethod.

  method update_delivery.

* Use a self defined authority object
    authority-check object 'Z_S10_BARC'
      id 'ACTVT' field '10'.

* not authorized -> message to user and stop processing
    if sy-subrc <> 0.
      s10errormessage(
         exporting
          msgid             =     'CACSIB'
          msgno             =      503
      ).
    endif.

    data: ps_vbkok type vbkok.
    data: lw_vbpok type vbpok.
    data: pt_vbpok type table of vbpok.
    data: lt_prot type table of prott.
    data: lw_prot type  prott.

    clear ps_vbkok.

    ps_vbkok-vbeln_vl        = vbeln.
    ps_vbkok-vbtyp_vl        = 'J'.
    ps_vbkok-wabuc         = 'X'.
    ps_vbkok-wadat_ist     = sy-datum.

    lw_vbpok-vbeln_vl  = vbeln.
    lw_vbpok-posnr_vl  = posnr.
    lw_vbpok-lfimg       = lfimg.
    lw_vbpok-umvkz    = 1.
    lw_vbpok-umvkn    = 1.
    append lw_vbpok to pt_vbpok. clear lw_vbpok.

    call function 'WS_DELIVERY_UPDATE_2'
      exporting
        vbkok_wa               = ps_vbkok
        synchron               = 'X'
        commit                 = 'X'
        delivery               = vbeln
        if_error_messages_send = 'X'
      tables
        vbpok_tab              = pt_vbpok
        prot                   = lt_prot
      exceptions
        error_message          = 4
        others                 = 2.

    if sy-subrc = 0.

      s10infomessage( s10localize( id = 'booking_success' ) ).

    endif.

* Error occured
    if sy-subrc <> 0.

      s10errormessage(
        exporting
          msgid             =     sy-msgid
          msgno             =    sy-msgno
      ).

    endif.

* Error messages ?
    loop at lt_prot into lw_prot where msgty = 'E' or msgty = 'A'.

      data: msgno type syst_msgno.
      msgno = lw_prot-msgno.

      s10errormessage(
       exporting
         msgid             =     lw_prot-msgid
         msgno             =   msgno
           ).

    endloop.
  endmethod.
  
endclass.

* main class for this application
class main definition inheriting from /s10/any.

  public section.

    data:   mybarcode_class type ref to barcode_class.

    methods:
      logon.

endclass.


class main implementation.

* logon user
  method logon.

* set S10 license
    s10setlicense( 'Synactive GmbH demo license number=100 role=s10demo_role 
maxusers=10 signature=821.126.87.7'
). * create manager object create object mybarcode_class. * start list display mybarcode_class->s10nextscreen( 'start'). endmethod. endclass.

Der HTML View: barcode_class.start.html

<!DOCTYPE html>
<html>

<head>
    <!-- Default header for S10 applications-->
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=400">
    <link rel='stylesheet' type='text/css' href='../../../style/s10.style.css'>
    <link rel='stylesheet' type='text/css' href='../../../style/custom.style.css'>
    <script src='../../synactiveS10/synactiveS10.java.js'></script>

    <!-- Open-source library for scanning barcodes/qrcodes -->
          https://github.com/mebjas/html5-qrcode -->
    <script src='../../../scripts/html5-qrcode.min.js'></script>

    <!-- Open source library for generating barcodes/qrcodes   -->
    <script src='../../../scripts/qrcode_generator.js'></script>

    <title>Warenausgang buchen</title>

</head>


<body style="width: 100%; margin: 0px; padding: 0px;" onload='init();' class="colorscheme9">

    <div class="headerarea" style="width: 100%; padding: 10px;">
        <b>Warenausgang buchen</b>
    </div>

    <!-- Toolbar definition with navigation-->
    <div class="toolbar">

        <button id="new_scan_button" type="button" class="toolbarbutton" onclick="new_scan()">
            Neuer Scan
        </button>

        <button type="button" class="toolbarbutton" style="float: right;" onclick="S10Logoff();">
            Abmelden
        </button>

    </div>

    <!-- Tabs definition-->
    <table class="tabstrip">
        <tr>
            <td id="scan" class="tabactive" onclick="S10ActivateTab(this);">
                Scannen
            </td>
            <td id="generate" class="tab" onclick="S10ActivateTab(this);">
                QR-Code generieren
            </td>
    </table>

    <!-- Area for tab 1 (scan) -->
    <div class="tabpageactive" id="scan.area">

        <div style="width:100%;height:35%;" id="reader"></div>

        <table id="confirmation_area"
            style="display:none;width: 100%; padding: 15px; 
            border-radius: 12px; background: #f1f5fb;">
            <tr>
                <td>
                    <div>
                        <span style="font-weight:bold">Kontrolle</span>
                    </div>
                </td>
            </tr>
            <tr>
                <td>
                    <label class="label" for="vbeln">Belegnummer</label><br>
                    <span class="output" name="vbeln"></span>
                    <input class="input" id="vbeln" name="vbeln" type="hidden">
                    <br>

                    <label class="label" for="matnr">Material</label><br>
                    <span class="output" name="matnr"></span>
                    <span class="output" name="maktx"></span>
                    <input class="input" id="matnr" name="matnr" type="hidden">
                    <br>

                    <label class="label" for="posnr">Position</label><br>
                    <span class="output" name="posnr"></span>
                    <input class="input" id="posnr" name="posnr" type="hidden">
                    <br>

                    <label class="label" for="lfimg">Menge</label><br>
                    <span class="output" name="lfimg"></span>
                    <input class="input" id="lfimg" name="lfimg" type="hidden">
                    <br>
                    <br>
                    <button style="margin:0px;width:100%;border-radius:3px;height:75px;" 
                            type="button" class="button"
                        onclick="S10Apply('update_delivery');">
                        Warenausgang buchen
                    </button>

                </td>
            </tr>
        </table>
    </div>

    <!-- Area for tab 2 (generate) -->
    <div class="tabpage" id="generate.area">

        <table style="width: 100%; padding: 15px; 
                    border-radius: 12px; background: #f1f5fb;">

            <tr>
                <td style="width:220px;">
                    <label class="label" for="vbeln_in">Belegnummer</label><br>
                    <input class="input" id="vbeln_in" type="text">
                    <br>

                    <label class="label" for="matnr_in">Material</label><br>
                    <input class="input" id="matnr_in" type="text">
                    <br>

                    <label class="label" for="posnr_in">Position</label><br>
                    <input class="input" id="posnr_in" type="text">
                    <br>

                    <label class="label" for="lfimg_in">Menge</label><br>
                    <input class="input" id="lfimg_in" type="text">
                    <br>
                    <br>

                    <button style="margin:0px;width:100%;border-radius:3px;height:75px;" 
                            type="button" class="button"
                        onclick="make_qr_code();">
                        QR-Code generieren
                    </button>
                </td>

                <td style="vertical-align:top;">
                    <input syle="width:100%;" type="text" class="output" id="qrode_text_input"> </input>
                    <div id="generated_qrcode" style="width:150px; height:15px; margin-top:5px;"></div>

                </td>
            </tr>
        </table>
    </div>

    <script>

        // The scanner recognized a code
        function onScanSuccess(decodedText, decodedResult) {

            // Handle on success condition with the decoded text or result.
            var a = decodedText.split(";"), i;

            // Parse the text of the scanned code and put
            // the values in inputfield 
            for (i = 0; i < a.length; i++) {
                var key = a[i].split(":")[0];
                var val = a[i].split(":")[1];

                if (document.getElementById(key) != null) {
                    document.getElementById(key).value = val;
                }
            }

            html5QrcodeScanner.clear();
            // ^ this will stop the scanner (video feed) and clear the scan area.

            // Make the area with the results visible
            document.getElementById("confirmation_area").style.display = "inline-block";

            S10Enter();
        }

        // Start the scanner
        var html5QrcodeScanner = new Html5QrcodeScanner(
            "reader", { fps: 10, qrbox: 250 });
        html5QrcodeScanner.render(onScanSuccess);

        // Start a new scanner
        function new_scan() {

            document.getElementById("confirmation_area").style.display = "none";

            html5QrcodeScanner = new Html5QrcodeScanner(
                "reader", { fps: 10, qrbox: 250 });
            html5QrcodeScanner.render(onScanSuccess);
        }

        var qrcode = new QRCode(document.getElementById("generated_qrcode"), {
            width: 100,
            height: 100
        });

        // Generate a new QR code according to the values in inputfields        
        function make_qr_code() {

            var text = "";
            text += "vbeln:" + document.getElementById("vbeln_in").value + ";";
            text += "matnr:" + document.getElementById("matnr_in").value + ";";
            text += "posnr:" + document.getElementById("posnr_in").value + ";";
            text += "lfimg:" + document.getElementById("lfimg_in").value;

            document.getElementById("qrode_text_input").value = text;
            qrcode.makeCode(text);
        }

    </script>
</body>

</html>

Komponente S10 Framework