MiBarcodeでも充分満足なのだが、スピードを言われてしまうと、自分のやり方では弱い。
別のライブラリを探したところ、「Barcode Image Generation Library」があったため、それに関するメモ。
調査
Code128に対応する、よさそうなバーコードライブラリがないかを探したところ、stackoverflowに情報が。
stackoverflow - C# : Generating Code 128 Barcode (width of bars/spaces)
その中のCode Projectのものがメンテナンスが続けられていて良さそうだったので、そちらを利用してみることに。
THE CODE PROJECT - Barcode Image Generation Library よりダウンロード。バージョンは「June 12, 2012 (1.0.0.13)」。
Barcode Image Generation Library のライセンス表記
記事のURL | http://www.codeproject.com/Articles/20823/Barcode-Image-Generation-Library |
著者 | Brad Barnhill |
参照記事バージョン | 12 Jun 2012 |
ライセンス | The Code Project Open License (CPOL) 1.02 |
利用してみての所感
- MiBarcodeに比べると、GUIが出てこない分、速い。
- クリップボード経由でのExcel2003へのデータ貼り付けが難しい。
- 追加コメントをバーコードにつけることができない。
- 追加コメントだけをバーコードにつけることができない。
いろいろとできそうだけれど、自分の希望の仕様(3,4を満たす)まであと少し。
ソースが公開されているのでソースを眺め、強引に手を加えることにした。
手を加えたところとソース
対象のクラスは「BarcodeLib.Barcode」のみであり、非常にやりやすかった。
プロパティを2つ追加。「追加コメント」と「追加コメントだけかどうかのbool」。
public string Comment { get; set; } public bool CommentOnly { get; set; }
Encodeメソッドのオーバーロードを追加し、上記で追加したプロパティ2つ分を引数に加えて実装
public Image Encode(TYPE iType, string StringToEncode, int Width, int Height, string comment, bool commentOnly) { this.Comment = comment; this.CommentOnly = commentOnly; return Encode(iType, StringToEncode, Width, Height); }
Encodeメソッド(引数なし版)に、追加コメントを引き渡す処理を追加(以下の★Add Start 〜 ★Add Endで囲んだ部分)。
this.Encoded_Value = ibarcode.Encoded_Value; this.Raw_Data = ibarcode.RawData; // ★Add Start if (CommentOnly) { this.RawData = Comment; } else { this.RawData += " " + Comment; } // ★Add End _Encoded_Image = (Image)Generate_Image();
結果
ビルドしてできたdllを参照・使用したところ、希望のモノができた。
使用してみたコード
仕様はMiBarcode版と同じだが、クリップボード経由でないため、
PNGファイルをローカル出力→PNGファイルを読込→Excel貼り付けとした。
public class Contents { public string BarcodeValue { get; set; } public string Comment { get; set; } } /// <summary> /// Excelへと出力 /// </summary> /// <param name="contents">出力する内容</param> /// <param name="commentOnly">コメントだけか</param> /// <returns></returns> private bool Export(List<Contents> contents, bool commentOnly) { // Excelへの出力判定 bool exported = false; // Excelファイルが存在する場合、以前のデータは不要なため削除する if (System.IO.File.Exists(BarcodeSheetFullPath)) { System.IO.File.Delete(BarcodeSheetFullPath); } Excel.Application app = new Excel.Application(); Excel.Workbook workbook = app.Workbooks.Add(); Excel.Worksheet sheet = (Excel.Worksheet)workbook.Sheets[1]; Excel.Range cells = sheet.Cells; int rowIndex = 1; int printCount = 1; foreach (var content in contents) { // Excel出力位置の調整 // Excelが横3列、縦13行で一ページであるため、 // セルを調整してバーコードを貼り付けていく Excel.Range range; int mod = printCount % 3; switch (printCount % 3) { case 1: range = (Excel.Range)cells[rowIndex, 1]; break; case 2: range = (Excel.Range)cells[rowIndex, 4]; break; case 0: range = (Excel.Range)cells[rowIndex, 7]; if (rowIndex % 53 != 0) { rowIndex = rowIndex + 4; } else { // 改ページが必要な場合の設定 rowIndex = rowIndex + 7; } break; default: range = null; break; } printCount++; // COMへの参照をなるべく早く解放したいため、 // ここでセルの位置を取得してしまう float fx = float.Parse(range.Left.ToString()); float fy = float.Parse(range.Top.ToString()); System.Runtime.InteropServices.Marshal.ReleaseComObject(range); range = null; // バーコード出力するものがなければ、Excelの位置だけ調整して次のレコードへ // *空白を設定する場合に使用する if (string.IsNullOrWhiteSpace(content.BarcodeValue)) { continue; } // バーコードシートに空白を設定することもあるため、 // バーコード出力するものがなければ、印刷処理はしない if (string.IsNullOrWhiteSpace(content.BarcodeValue)) { } else { SavePNGImageByBarcodeLib(content.BarcodeValue, content.Comment, commentOnly); // Pictures.Insertは、Excel2010ではKB2396509 のような不具合があるため、 // Shapes.Addメソッドを使うしかないと思われる Excel.Shapes shapes = sheet.Shapes; Excel.Shape shape = shapes.AddPicture(PNGFullPath, Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoTrue, fx, fy, 200, 70); // サイズを戻す shape.ScaleHeight(1, Microsoft.Office.Core.MsoTriState.msoTrue); shape.ScaleWidth(1, Microsoft.Office.Core.MsoTriState.msoTrue); // 使用したCOMオブジェクトを解放 System.Runtime.InteropServices.Marshal.ReleaseComObject(shape); shape = null; System.Runtime.InteropServices.Marshal.ReleaseComObject(shapes); shapes = null; } } // 保存するときはファイルフォーマットを指定すること // 指定しないと、正しいファイル定義ではない旨のエラーでExcelファイルを開けなくなる // 「いいえ」「キャンセル」の場合は例外を出してしまうため、try-catchしておく // →例外であれば、キャンセルなどが選択されたとみなして、処理しない try { workbook.SaveAs(Filename: BarcodeSheetFullPath, FileFormat: 56); // ここまででエラーが発生していないのであれば、 // 出力はできたものと考える exported = true; } catch (System.Runtime.InteropServices.COMException) { // ここでのエラーは、保存上書きで「いいえ」「キャンセル」を選択した時のものと考えられる // そのため、続行して問題ない // ただし、印刷していないことを知らせる exported = false; } catch (Exception) { // 上記以外の場合は原因を知りたいため、例外を飛ばす throw; } workbook.Close(); app.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(cells); cells = null; System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet); sheet = null; System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook); workbook = null; System.Runtime.InteropServices.Marshal.ReleaseComObject(app); app = null; GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); return exported; } /// <summary> /// バーコードデータイメージ(PNG)の作成 /// </summary> /// <param name="barcodeValue"></param> /// <param name="comment"></param> private void SavePNGImageByBarcodeLib(string barcodeValue, string comment, bool commentOnly) { BarcodeLib.Barcode lib = new BarcodeLib.Barcode(); lib.IncludeLabel = true; if (string.IsNullOrWhiteSpace(comment)) { lib.Encode(BarcodeLib.TYPE.CODE128A, barcodeValue, 202, 70); } else { lib.Encode(BarcodeLib.TYPE.CODE128A, barcodeValue, 202, 70, comment, commentOnly); } lib.SaveImage(PNGFullPath, BarcodeLib.SaveTypes.PNG); }
最後に
作者のBrad Barnhillさんには本当に感謝です。ありがとうございます。