Terry Burton
Terry Burton

Reputation: 3030

How to convert a UPC-E barcode to a UPC-A barcode?

What is the algorithm for converting a zero-suppressed, eight-digit GTIN-12 identifier (represented as a UPC-E barcode) into the full, twelve-digit version as shown in a UPC-A barcode?

Upvotes: 5

Views: 8012

Answers (5)

Antiz
Antiz

Reputation: 11

This was VERY helpful.

My contribution (what I needed) was a SQLite3 CASE statement that would do the conversion on the fly:

CASE 
WHEN LENGTH(table.upc) = 8 THEN 
    CASE 
    WHEN SUBSTR(TRIM(table.upc, '|'), 7, 1) IN ('0', '1', '2') THEN 
        SUBSTR(TRIM(table.upc, '|'), 1, 3) || SUBSTR(TRIM(table.upc, '|'), 7, 1) || '0000' || SUBSTR(TRIM(table.upc, '|'), 4, 3) || SUBSTR(TRIM(table.upc, '|'), 8, 1)
    WHEN SUBSTR(TRIM(table.upc, '|'), 7, 1) = '3' THEN 
        SUBSTR(TRIM(table.upc, '|'), 1, 4) || '00000' || SUBSTR(TRIM(table.upc, '|'), 5, 2) || SUBSTR(TRIM(table.upc, '|'), 8, 1)
    WHEN SUBSTR(TRIM(table.upc, '|'), 7, 1) = '4' THEN 
        SUBSTR(TRIM(table.upc, '|'), 1, 5) || '00000' || SUBSTR(TRIM(table.upc, '|'), 6, 1) || SUBSTR(TRIM(table.upc, '|'), 8, 1)
    WHEN SUBSTR(TRIM(table.upc, '|'), 7, 1) BETWEEN '5' AND '9' THEN 
        SUBSTR(TRIM(table.upc, '|'), 1, 6) || '0000' || SUBSTR(TRIM(table.upc, '|'), 7, 1) || SUBSTR(TRIM(table.upc, '|'), 8, 1)
    ELSE TRIM(table.upc, '|')
    END
ELSE table.upc

END

Upvotes: 1

Ethan Allen
Ethan Allen

Reputation: 14835

Answer in Swift 5. Beware that this returns 0 if a conversion is not possible, so you'll need to change the code if you don't want that result. Extensions are included to make String index ranges much easier to use:

static func convertUPCEtoUPCA(code: String) -> String {
    if code.isNumber && code.length == 8
    {
        switch code[6] {
        case "0", "1", "2":
            return "\(code.prefix(3))\(String(code[6]))0000\(code[3..<6])\(String(code[7]))"
        case "3":
            return "\(code.prefix(4))00000\(code[4..<6])\(String(code[7]))"
        case "4":
            return "\(code.prefix(5))00000\(String(code[5]))\(String(code[7]))"
        case "5", "6", "7", "8", "9":
            return "\(code.prefix(6))0000\(code.suffix(2))"
        default:
            return "0"
        }
    } else {
        return "0"
    }
}

extension String {
    subscript(_ range: CountableRange<Int>) -> String {
        let start = index(startIndex, offsetBy: max(0, range.lowerBound))
        let end = index(start, offsetBy: min(self.count - range.lowerBound,
                                             range.upperBound - range.lowerBound))
        return String(self[start..<end])
    }
    
    subscript(_ range: CountablePartialRangeFrom<Int>) -> String {
        let start = index(startIndex, offsetBy: max(0, range.lowerBound))
        return String(self[start...])
    }
}

extension StringProtocol {
    subscript(offset: Int) -> Character {
        self[index(startIndex, offsetBy: offset)]
    }
}

Answer also in Kotlin:

fun convertUPCEtoUPCA(barcode: String): String {
    var data = barcode

    if (isNumericToX(barcode) && barcode.length == 8) {
        when (data[6]) {
            '0', '1', '2' -> {
                data = data.substring(0, 3) + data[6].toString() + "0000" + data.substring(3, 6) + data[7]
            }
            '3' -> {
                data = data.substring(0, 4).toString() + "00000" + data.substring(4, 6) + data[7]
            }
            '4' -> {
                data = data.substring(0, 5).toString() + "00000" + data[5] + data[7]
            }
            '5', '6', '7', '8', '9' -> {
                data = data.substring(0, 6).toString() + "0000" + data[6] + data[7]
            }
        }
        return data
    } else if (isNumericToX(barcode)) {
        return barcode
    } else {
        return "0"
    }
}

Upvotes: 2

psyklopz
psyklopz

Reputation: 2391

This duplicates the algorithm in @Terry Burton's answer, written in Java.


switch (data.charAt(6)) {
    case '0':
    case '1':
    case '2': {
        data = data.substring(0, 3) + data.charAt(6) + "0000" + data.substring(3, 6) + data.charAt(7);
        break;
    }
    case '3': {
        data = data.substring(0, 4) + "00000" + data.substring(4, 6) + data.charAt(7);
        break;
    }
    case '4': {
        data = data.substring(0, 5) + "00000" + data.charAt(5) + data.charAt(7);
        break;
    }
    case '5':
    case '6':
    case '7':
    case '8':
    case '9': {
        data = data.substring(0, 6) + "0000" + data.charAt(6) + data.charAt(7);
        break;
    }
}

Upvotes: 3

Trevor Kennedy
Trevor Kennedy

Reputation: 31

Here is a C# version that is corrected. As well as some test cases.

public string Expand_UPCE_to_UPCA_GTIN12(string upce)
{
    return upce[6] switch
    {
        '0' or '1' or '2' => $"{upce[..3]}{upce[6]}0000{upce[3..6]}{upce[7]}",
        '3' => $"{upce[..4]}00000{upce[4..6]}{upce[7]}",
        '4' => $"{upce[..5]}00000{upce[5]}{upce[7]}",
        _ => $"{upce[..6]}0000{upce[6..]}",
    };
}

Console.WriteLine($"Test A: {Expand_UPCE_to_UPCA_GTIN12("02345673")} becomes 023456000073");
Console.WriteLine($"Test B: {Expand_UPCE_to_UPCA_GTIN12("02345147")} becomes 023450000017");
Console.WriteLine($"Test C: {Expand_UPCE_to_UPCA_GTIN12("08679339")} becomes 086700000939");
Console.WriteLine($"Test D: {Expand_UPCE_to_UPCA_GTIN12("06397126")} becomes 063200009716");
Console.WriteLine($"Test E: {Expand_UPCE_to_UPCA_GTIN12("07832309")} becomes 078000003239"); // Diet Dr Pepper 12 fl oz can 

Upvotes: 3

Terry Burton
Terry Burton

Reputation: 3030

The algorithm for converting a GTIN-12 identifier between UPC-E and UPC-A representation can be most clearly seen from the following pattern mapping:

SabcdeNX ⟺ SabN0000cdeX  :  0≤N≤2
Sabcde3X ⟺ Sabc00000deX
Sabcde4X ⟺ Sabcd00000eX
SabcdeNX ⟺ Sabcde0000NX  :  5≤N≤9

In the above S is the number system (either 0 or 1) and X is the check digit.

In pseudo-code it looks like this:

Input:  A valid eight-digit UPC-E: Assigned to E[]. 
Output: PASS: Twelve-digit UPC-A representing the UPC-E.
        FAIL: Reason.

if E[0] != {0-1} then FAIL: Invalid number system.

if E[6] == {0-2} then PASS: E[0..2] . E[6] . "0000"  . E[3..5] . E[7]
if E[6] == "3"   then PASS: E[0..3] .        "00000" . E[4..5] . E[7]
if E[6] == "4"   then PASS: E[0..4] .        "00000" . E[5]    . E[7]    
if E[6] == {5-9} then PASS: E[0..5] .        "0000"  . E[6]    . E[7]

Upvotes: 16

Related Questions