diff --git a/BarcodeLib/BarcodeLib.cs b/BarcodeLib/BarcodeLib.cs index c233c8c..dcb89ad 100644 --- a/BarcodeLib/BarcodeLib.cs +++ b/BarcodeLib/BarcodeLib.cs @@ -25,7 +25,7 @@ namespace BarcodeLib { #region Enums - public enum TYPE : int { UNSPECIFIED, UPCA, UPCE, UPC_SUPPLEMENTAL_2DIGIT, UPC_SUPPLEMENTAL_5DIGIT, EAN13, EAN8, Interleaved2of5, Standard2of5, Industrial2of5, CODE39, CODE39Extended, CODE39_Mod43, Codabar, PostNet, BOOKLAND, ISBN, JAN13, MSI_Mod10, MSI_2Mod10, MSI_Mod11, MSI_Mod11_Mod10, Modified_Plessey, CODE11, USD8, UCC12, UCC13, LOGMARS, CODE128, CODE128A, CODE128B, CODE128C, ITF14, CODE93, TELEPEN, FIM, PHARMACODE }; + public enum TYPE : int { UNSPECIFIED, UPCA, UPCE, UPC_SUPPLEMENTAL_2DIGIT, UPC_SUPPLEMENTAL_5DIGIT, EAN13, EAN8, Interleaved2of5, Standard2of5, Industrial2of5, CODE39, CODE39Extended, CODE39_Mod43, Codabar, PostNet, BOOKLAND, ISBN, JAN13, MSI_Mod10, MSI_2Mod10, MSI_Mod11, MSI_Mod11_Mod10, Modified_Plessey, CODE11, USD8, UCC12, UCC13, LOGMARS, CODE128, CODE128A, CODE128B, CODE128C, CODE128CUSTOM, ITF14, CODE93, TELEPEN, FIM, PHARMACODE }; public enum SaveTypes : int { JPG, BMP, PNG, GIF, TIFF, UNSPECIFIED }; public enum AlignmentPositions : int { CENTER, LEFT, RIGHT}; public enum LabelPositions : int { TOPLEFT, TOPCENTER, TOPRIGHT, BOTTOMLEFT, BOTTOMCENTER, BOTTOMRIGHT }; @@ -434,6 +434,9 @@ internal Image Encode() case TYPE.CODE128C: ibarcode = new Code128(Raw_Data, Code128.TYPES.C); break; + case TYPE.CODE128CUSTOM: + ibarcode = new Code128(Raw_Data,Code128.TYPES.CUSTOM); + break; case TYPE.ITF14: ibarcode = new ITF14(Raw_Data); break; diff --git a/BarcodeLib/BarcodeLib.csproj b/BarcodeLib/BarcodeLib.csproj index 531b08c..5c8c82b 100644 --- a/BarcodeLib/BarcodeLib.csproj +++ b/BarcodeLib/BarcodeLib.csproj @@ -89,6 +89,7 @@ + diff --git a/BarcodeLib/Symbologies/Code128.cs b/BarcodeLib/Symbologies/Code128.cs index 12ea28a..62e6807 100644 --- a/BarcodeLib/Symbologies/Code128.cs +++ b/BarcodeLib/Symbologies/Code128.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Text; using System.Data; @@ -11,7 +12,7 @@ namespace BarcodeLib.Symbologies /// class Code128 : BarcodeCommon, IBarcode { - public enum TYPES:int { DYNAMIC, A, B, C }; + public enum TYPES : int {DYNAMIC , A , B , C , CUSTOM }; private DataTable C128_Code = new DataTable("C128"); private List _FormattedData = new List(); private List _EncodedData = new List(); @@ -265,6 +266,86 @@ private string CalculateCheckDigit() DataRow[] RetRows = this.C128_Code.Select("Value = '" + Remainder.ToString() + "'"); return RetRows[0]["Encoding"].ToString(); } + + private void BreakUpAndInsertCodeCharacters() + { + string temp = ""; + string tempRawData = Raw_Data; + var currentType = Code128.TYPES.DYNAMIC; + var starting = true; + + if (tempRawData[0] != Convert.ToChar(140)) + Error("EC128-7: Custom CODE 128 string does not start with a specified code."); + + var codeBlocks = tempRawData.Split(Convert.ToChar(140)); + foreach (var codeBlock in codeBlocks) + { + if (String.IsNullOrEmpty(codeBlock)) + continue; + + var startCodeVal = codeBlock[0]; + switch (startCodeVal) + { + case 'A': + if (starting) + { + _FormattedData.Add("START_A"); + starting = false; + } + else + { + _FormattedData.Add("CODE_A"); + } + currentType = TYPES.A; + break; + case 'B': + if (starting) + { + _FormattedData.Add("START_B"); + starting = false; + } + else + { + _FormattedData.Add("CODE_B"); + } + currentType = TYPES.B; + break; + case 'C': + if (starting) + { + _FormattedData.Add("START_C"); + starting = false; + } + else + { + _FormattedData.Add("CODE_C"); + } + currentType = TYPES.C; + break; + default: + Error("EC128-8: Attempting to use unsuported code in custom CODE 128 barcode."); + break; + } + var dataToAdd = codeBlock.Substring(1); + if (currentType == TYPES.A || currentType == TYPES.B) + { + foreach (var c in dataToAdd) + { + _FormattedData.Add(c.ToString()); + } + } + else + { + if (dataToAdd.Length % 2 != 0) + Error("EC128-9: Attempting to encode a CODE 128 C block with odd number of digits"); + for (int i = 0; i < dataToAdd.Length; i += 2) + { + var toAdd = string.Format("{0}{1}", dataToAdd[i], dataToAdd[i + 1]); + _FormattedData.Add(toAdd); + } + } + } + } private void BreakUpDataForEncoding() { string temp = ""; @@ -396,15 +477,26 @@ private void InsertStartandCodeCharacters() } private string GetEncoding() { - //break up data for encoding - BreakUpDataForEncoding(); + if (type == TYPES.CUSTOM) + { + BreakUpAndInsertCodeCharacters(); + } + else + { + + //break up data for encoding + BreakUpDataForEncoding(); - //insert the start characters - InsertStartandCodeCharacters(); + //insert the start characters + InsertStartandCodeCharacters(); + } string CheckDigit = CalculateCheckDigit(); string Encoded_Data = ""; + + var encodingType = TYPES.A; //Always start with code A + foreach (string s in _FormattedData) { //handle exception with apostrophes in select statements @@ -414,27 +506,44 @@ private string GetEncoding() //select encoding only for type selected switch (this.type) { - case TYPES.A: E_Row = this.C128_Code.Select("A = '" + s1 + "'"); + case TYPES.A: + E_Row = this.C128_Code.Select("A = '" + s1 + "'"); break; - case TYPES.B: E_Row = this.C128_Code.Select("B = '" + s1 + "'"); + case TYPES.B: + E_Row = this.C128_Code.Select("B = '" + s1 + "'"); break; - case TYPES.C: E_Row = this.C128_Code.Select("C = '" + s1 + "'"); + case TYPES.C: + E_Row = this.C128_Code.Select("C = '" + s1 + "'"); break; - case TYPES.DYNAMIC: E_Row = this.C128_Code.Select("A = '" + s1 + "'"); - - if (E_Row.Length <= 0) - { - E_Row = this.C128_Code.Select("B = '" + s1 + "'"); - - if (E_Row.Length <= 0) - { - E_Row = this.C128_Code.Select("C = '" + s1 + "'"); - }//if - }//if + case TYPES.DYNAMIC: + case TYPES.CUSTOM: + //Always use value from current encoding + E_Row = this.C128_Code.Select(encodingType.ToString() + " = '" + s1 + "'"); + //If we have a START or CODE element then determine which encoding to switch to. + if (s1.StartsWith("START") || s1.StartsWith("CODE")) + { + var typeSplit = s1.Split('_'); + switch (typeSplit[1]) + { + case "A": + encodingType = TYPES.A; + break; + case "B": + encodingType = TYPES.B; + break; + case "C": + encodingType = TYPES.C; + break; + default: + Error("EC128-8: Attempting to use unsuported code in custom CODE 128 barcode."); + break; + } + } break; - default: E_Row = null; + default: + E_Row = null; break; - }//switch + } //switch if (E_Row == null || E_Row.Length <= 0) Error("EC128-5: Could not find encoding of a value( " + s1 + " ) in C128 type " + this.type.ToString()); diff --git a/BarcodeLib/Symbologies/Code128CustomBuilder.cs b/BarcodeLib/Symbologies/Code128CustomBuilder.cs new file mode 100644 index 0000000..79db282 --- /dev/null +++ b/BarcodeLib/Symbologies/Code128CustomBuilder.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace BarcodeLib.Symbologies +{ + public class Code128CustomBuilder + { + public enum Code128Type { A, B, C }; + private string Code128String { get; set; } + + public static Code128CustomBuilder Start(Code128Type type, string barcodePart) + { + return new Code128CustomBuilder() + { + Code128String = String.Format("{0}{1}{2}", char.ConvertFromUtf32(140), type.ToString(), barcodePart) + }; + } + + public Code128CustomBuilder AddPart(Code128Type type, string barcodePart) + { + return new Code128CustomBuilder() + { + Code128String = + string.Format("{0}{1}{2}{3}", Code128String, char.ConvertFromUtf32(140), type.ToString(), barcodePart) + }; + } + + public string GetBarcodeString() + { + return Code128String; + } + } +} diff --git a/README.md b/README.md index ab04fe3..ed43b47 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,35 @@ If you decide to create an instance with parameters, the parameters are as follo BarCodeLib.Barcode b = new BarCodeLib.Barcode(BarCodeLib.TYPE.UPCA, "038000356216", Color.Black, Color.White, 300, 150); ``` -### Example ### +#### Example #### ``` BarCodeLib.Barcode b = new BarCodeLib.Barcode(BarCodeLib.TYPE.UPCA, "038000356216", Color.Black, Color.White, 300, 150); Image img = b.Encode(); ``` + +### Code 128 Barcodes ### + +A Code 128 Barcode may contain any combination of 3 different codesets, Code A, Code B and Code C. + +Using the library it is possible to generate a Code 128 barcode in a number of ways: + + - Either entirely of a single codeset (using types CODE128A, CODE128B or CODE128C) + - Letting the generator decide which codeset to use for each character (or character pair) (using type CODE128) + - Specifiying the codesets required for each portion of the barcode (using type CODE128CUSTOM) + +To specify the codesets required for each portion of the barcode there is a Code128CustomBuilder class with the below methods. +``` +Code128CustomBuilder.Start(Code128Type, string); //Static constructor +AddPart(Code128Type, string); +GetBarcodeString(); +``` +#### Example #### +``` +BarCodeLib.Barcode b = new BarCodeLib.Barcode(); +string barcodeString = + Code128Builder.Start(Code128Builder.Code128Type.B, "%0S23413S") + .AddPart(Code128Builder.Code128Type.C, "15976911000231151826") + .GetBarcodeString(); +Image barcodeImage = b.Encode(TYPE.CODE128CUSTOM, barcodeString); +``` \ No newline at end of file