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