1
votes

I need to trigger a subroutine when a serial number of a product has been scanned in with a barcode scanner. The serial number looks like this: 11NNNN22334. I then need to use the scanned in serial number as a variable.

I tried dynamic regular expression hotstrings library which I include below, but I can't make it work reliably using a barcode scanner (it's too fast). I don't want to slow down the barcode scanner. It either does not trigger the subroutine at all or leaves the first digit of the serial number behind after the subroutine been triggered. Any ideas?

Test:
MsgBox, %$1% ; THIS IS THE STRING THAT TRIGGERED THE SUBROUTINE
return

hotstrings("([0-9][0-9]NNNN[0-9][0-9][0-9][0-9][0-9])", "Test")

/*
    Function: HotStrings
        Dynamically adds regular expression hotstrings.

    Parameters:
        c - regular expression hotstring
        a - (optional) text to replace hotstring with or a label to goto,
            leave blank to remove hotstring definition from triggering an action

    Examples:
> hotstrings("(B|b)tw\s", "%$1%y the way") ; type 'btw' followed by space, tab or return
> hotstrings("i)omg", "oh my god!") ; type 'OMG' in any case, upper, lower or mixed
> hotstrings("\bcolou?r", "rgb(128, 255, 0);") ; '\b' prevents matching with anything before the word, e.g. 'multicololoured'

    License:
        - RegEx Dynamic Hotstrings: Modified version by Edd  
        - Original: <http://www.autohotkey.net/~polyethene/#hotstrings>
        - Dedicated to the public domain (CC0 1.0) <http://creativecommons.org/publicdomain/zero/1.0/>
*/

hotstrings(k, a = "", Options:="")
{
    static z, m = "~$", m_ = "*~$", s, t, w = 2000, sd, d = "Left,Right,Up,Down,Home,End,RButton,LButton", f = "!,+,^,#", f_="{,}"
    global $
    If z = ; init
    {
        RegRead, sd, HKCU, Control Panel\International, sDecimal
        Loop, 94
        {
            c := Chr(A_Index + 32)
            If A_Index between 33 and 58
                Hotkey, %m_%%c%, __hs
            else If A_Index not between 65 and 90
                Hotkey, %m%%c%, __hs
        }
        e = 0,1,2,3,4,5,6,7,8,9,Dot,Div,Mult,Add,Sub,Enter
        Loop, Parse, e, `,
            Hotkey, %m%Numpad%A_LoopField%, __hs
        e = BS,Shift,Space,Enter,Return,Tab,%d%
        Loop, Parse, e, `,
            Hotkey, %m%%A_LoopField%, __hs
        z = 1
    }
    If (a == "" and k == "") ; poll
    {
        q:=RegExReplace(A_ThisHotkey, "\*\~\$(.*)", "$1")
        q:=RegExReplace(q, "\~\$(.*)", "$1")
        If q = BS
        {
            If (SubStr(s, 0) != "}")
                StringTrimRight, s, s, 1
        }
        Else If q in %d%
            s =
        Else
        {
            If q = Shift
            return
            Else If q = Space
                q := " "
            Else If q = Tab
                q := "`t"
            Else If q in Enter,Return,NumpadEnter
                q := "`n"
            Else If (RegExMatch(q, "Numpad(.+)", n))
            {
                q := n1 == "Div" ? "/" : n1 == "Mult" ? "*" : n1 == "Add" ? "+" : n1 == "Sub" ? "-" : n1 == "Dot" ? sd : ""
                If n1 is digit
                    q = %n1%
            }
            Else If (GetKeyState("Shift") ^ !GetKeyState("CapsLock", "T"))
                StringLower, q, q
            s .= q
        }
        Loop, Parse, t, `n ; check
        {
            StringSplit, x, A_LoopField, `r
            If (RegExMatch(s, x1 . "$", $)) ; match
            {
                StringLen, l, $
                StringTrimRight, s, s, l
                if !(x3~="i)\bNB\b")        ; if No Backspce "NB"
                    SendInput, {BS %l%}
                If (IsLabel(x2))
                    Gosub, %x2%
                Else
                {
                    Transform, x0, Deref, %x2%
                    Loop, Parse, f_, `,
                        StringReplace, x0, x0, %A_LoopField%, ¥%A_LoopField%¥, All
                    Loop, Parse, f_, `,
                        StringReplace, x0, x0, ¥%A_LoopField%¥, {%A_LoopField%}, All
                    Loop, Parse, f, `,
                        StringReplace, x0, x0, %A_LoopField%, {%A_LoopField%}, All
                    SendInput, %x0%
                }
            }
        }
        If (StrLen(s) > w)
            StringTrimLeft, s, s, w // 2
    }
    Else ; assert
    {
        StringReplace, k, k, `n, \n, All ; normalize
        StringReplace, k, k, `r, \r, All
        Loop, Parse, t, `n
        {
            l = %A_LoopField%
            If (SubStr(l, 1, InStr(l, "`r") - 1) == k)
                StringReplace, t, t, `n%l%
        }
        If a !=
            t = %t%`n%k%`r%a%`r%Options%
    }
    Return
    __hs: ; event
    hotstrings("", "", Options)
    Return
}
4

4 Answers

0
votes

You can try to speed up the hotkeys function by fiddling with SetBatchLines:

hotstrings(k, a = "", Options:="")
{
    prevBatchlines := A_BatchLines
    SetBatchLines, -1


    ... ; rest of function here


    }

    ; reset to whatever it was 
    SetBatchLines, %prevBatchlines%

    Return

    __hs: ; event
        hotstrings("", "", Options)
    Return
}

Although usually not recommended (it's nonzero by default for a reason), sometimes it is the only way.

0
votes

Maybe give this a shot, it's setup to wait for your required syntax:

code:=
for k, v in StrSplit("QWERTYUIOPASDFGHJKLZXCVBNM")
    Hotkey, % "~" v, WaitForBarcode 
Loop 10 {
    Hotkey, % "~" (10-A_Index) "", WaitForBarcode 
    Hotkey, % "~Numpad" (10-A_Index) "", WaitForBarcode  
}
return

FoundCode(var) {
    MsgBox % "Caught code: " var
}

WaitForBarcode(){
    global code
    k:=SubStr(A_ThisHotkey,0)
    code.=k
    code:=(is(SubStr(code,1,2))=1)?k:(is(SubStr(code,3,4))=2)?k:(is(SubStr(code,7,5))=1)?k:(StrLen(code)=11)?FoundCode(code):code
}

is(var) {
    if var is not digit
        return 1
    if var is not alpha
        return 2
}

I have no way of testing it with any input device other than keyboard, maybe it will work, maybe not.

Alternative for looping through keys would be:

Loop 43
  Hotkey, % "~" Chr(A_Index+47), Bar 
0
votes

At work we have a lot of USB barcode scanners that type the scan results to the keyboard buffer.

If you have access to the barcode scanner and it's a hardware scanner, you usually can definde a prefix/postfix code the scanner has to send before the scan. Check your scanner manual, to set it you normally just scan a few barcodes.

If you define the prefix code as a hotkey you can then run code to capture the letters until the post fix.

A simple example on key capture is

Loop {
    Input, key, I L1 V
    log = %log%%key%
}

#s::MsgBox, 64, Key History, %log%

It should be easy to change this to stop looping after the postfix key of your choice.

source here

0
votes

Although it's not a solution, I managed to find a workaround by changing the scanner's suffix from carriage return to tab and using the original method I posted.