Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added the ability to specify codeset switches manually in a Code128 barcode. #1

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion BarcodeLib/BarcodeLib.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions BarcodeLib/BarcodeLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
<Compile Include="Symbologies\Codabar.cs" />
<Compile Include="Symbologies\Code11.cs" />
<Compile Include="Symbologies\Code128.cs" />
<Compile Include="Symbologies\Code128CustomBuilder.cs" />
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Custom can be removed from this title since its really just building a Code128 string to be encoded.

<Compile Include="Symbologies\Code39.cs" />
<Compile Include="Symbologies\Code93.cs" />
<Compile Include="Symbologies\Pharmacode.cs" />
Expand Down
151 changes: 130 additions & 21 deletions BarcodeLib/Symbologies/Code128.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
Expand All @@ -11,7 +12,7 @@ namespace BarcodeLib.Symbologies
/// </summary>
class Code128 : BarcodeCommon, IBarcode
{
public enum TYPES:int { DYNAMIC, A, B, C };
public enum TYPES : int {DYNAMIC , A , B , C , CUSTOM };
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra spaces added here

private DataTable C128_Code = new DataTable("C128");
private List<string> _FormattedData = new List<string>();
private List<string> _EncodedData = new List<string>();
Expand Down Expand Up @@ -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 = "";
Expand Down Expand Up @@ -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
Expand All @@ -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());
Expand Down
34 changes: 34 additions & 0 deletions BarcodeLib/Symbologies/Code128CustomBuilder.cs
Original file line number Diff line number Diff line change
@@ -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)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unnecessary wrapping

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bbarnhill I think that wrapping on lines 14–17 is just what VS automatically does. No point in trying to override VS because whenever you edit near that it’ll just reperform that same whitespace change again.

Line 25 is so long maybe it needs to be split up more ;-).

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its probably fine in length ... just wrapped for some reason

};
}

public string GetBarcodeString()
{
return Code128String;
}
}
}
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
```