久々のプログラム制作
今さら感あるバーコードですが、JAN(EAN)とCODE39を印字しようと調べるとブラザーのラベルプリンターが他社の1/10程の低価格。またB-PACと言うSDKがあり自プログラムから印刷可能。早々PT-9700PCを購入し、そのB-PACを使ってみると・・・
嵌る・・・。プリンターが全くうんともすんとも言わない。
環境はWindows7の64bitとWindows8.1の64bit+VS2010、VS2012、VS2013、の6通り。
全て試したがエラー発生せず。エラーが発生しない=こう言うのが一番困ります。
ちなみにブラザーのラベルプリンターの価格は・・
「今どきUSB接続しか出来ないPT-9700PCが約2万、LAN接続できるPT-9800PCNは何と倍の4万強」高過ぎですね。
一応プリンターやSDKが外れの可能性もあるので安い方、PT-9700PCを購入。
エラーその1
「相互運用型 ‘bpac.DocumentClass’ を埋め込むことができません。代わりに適用可能なインターフェイスを使用してください」。
<対処方法>
これはググると答えが沢山出てくる。「b-pac エラー」などで。
このサイトから情報登録するとSDKをDL出来るが、ここでDLしたSDKをインストール。
(私はVer3.1.003の64bitバージョンDL ← これも間違いの原因=その2で悩んだエラーの原因)
するとVisualStudioのプロジェクトにCOMの参照を追加できるのだが・・。
現実には参照で、Brother b-PAC 3.1 Type Library(ver1.3、なんで1.3なの?)を追加するとbpacと言う参照が出来、これをクリックすると「相互運用機能型の埋め込み」と言うプロパティーがあり、これがTrueになってるからFalseにする。
この問題は5分で解決。
エラーその2
上記対処してもプリンターは全くうんともすんとも言わない。プリンターを購入するとラベルをデザインできるP-touch Editor 5.1と言うのが付いており、このソフトからは問題なく印刷できる。
<エラー内容>
なし。そう、エラーにならないのです、自プロから印刷ボタンをクリックしても何の応答もなし。テンプレートのオープン、StartPrint、PrintOut、EndPrint、クローズ、何のエラーも起こらずスルーしてしまいます。
結局半日ほど悩み・・こういう時はホボ凡ミスが原因が多い・・と、初心に戻り最初から抜けがないか手順を追ってみと発見!原因は・・・やはりクダラナイ・・
<原因>
PT-9700PC(PT-9800PCN)に適合しているSDKが何と!!32ビット版のみ!
※私は64bit windowsなので気にせず64bit版をインストールしていた。
流石元が古いプリンターとSDKです。答えはブラザーのサイトにありましたが、もっと分かり易い所に書け!と言いたくなります。
b-PACトップ → 動作環境の下の方
<対処方法>
1.b-PAC、64bitSDKをアンインストール(私の場合)
2.b-PAC、32bitSDKをDLしてインストール
上記行うと、32bit版SDKが、ちゃんとx86フォルダへインストールされます。

余談)
Brotherのサンプルプログラムが使うラベルのテンプレートフォルダは64bit版sdkをインストールしたと仮定しているようで、要注意!!
素直にサンプルに従い、プログラムで読み込むテンプレートフォルダ先を間違えるとまた変なエラーが発生し悩むでしょう
これで大丈夫だろうと思っていたら、今度はCOMエラーが発生。今更COMですか?めんどくさい・・・
エラーその3へ進む・・・
エラーその3
テンプレートのOPENで下記エラー発生。
<エラー内容>
------------------------------------
COMException
------------------------------------
CLSID {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} を含むコンポーネントの COM クラス ファクトリを取得中に、次のエラーが発生しました: 80040154
クラスが登録されていません (HRESULT からの例外:0x80040154 (REGDB_E_CLASSNOTREG))。
------------------------------------
こういう濃いエラーは、ググれば絶対誰かがUPしている筈!とググったら素晴らしい方が記事を残してくれていました!
こちらの素晴らしい方のおかげで即解決 → こちらのお方
自己解決ではありませんが、最近はnetデバッグありですから。
※余談だが、最近netを見ていると2/3程のブログは嘘を書いている=本人自身が嘘を書いている事に気付いていない。かなりレベルの低い自称SEがいるのでご注意!こういう方々を雇ってしまったら爆弾抱えている状態=かなり怖ろしい・・しかも60-70%がこう言う方々。今後は面接よりペーパーテストを強烈に重視したいと思います。
<原因>
32bit版COMなので(何だか知らんがSDKが32bitだからそうだろうと勝手に解釈)、
プロジェクトのターゲットプラットフォームも32bitにしないとCOMエラーが発生する。
<対処>
プロジェクトのプロパティーにあるターゲットプラットホームをx86にする。
これ等、エラー3点の対処を行うと、バーコードが印刷された!祝
余談、最初から滞りなくやれたら「なんだこれ?こんな簡単なんだ」となるのでしょうが、システム開発ってクダラナイ事に時間取られすぎます。それがノウハウになりますが、でもそもそも論から言えば、それって違うのでは?ですね。早く明るい業界になって欲しいものです。
以上で、C#、.NET Framework4(2~4、OK!)を使い、自プロからBrotherラベルプリンターへの出力印刷が完了です。
ちなみに制作しているモノはシリアルNo+製造番号ロットNo自動採番+バーコード出力プログラムです。
<その他の注意点:別のエラー>
これも1度引っかかったので解説。
・サンプルプログラム実行時の注意点!
上記で言いましたが私の場合、P-touch Editor 5.1で作成したテンプレート、ibx、のロケーションフォルダ。32bit版sdkなので¥Program Files (x86)¥、です。
ブラザーのサンプルは¥Program Files¥となっているので要注意。このまま実行すればまた別のエラーが発生して悩みます。
※くだらないエラーであればある程、原因特定するのに時間かかる事が多いのでご注意を。
以上で解決です。
ちなみに上記サンプルで普通に印刷出来ます。
< まとめ >
1.32bitか64bitか、SDKを間違えずにインストールする
※印刷したいラベルプリンターに対応しているSDKを間違えずにDLしインストールする
確認はこちら → こちら
2.SDK提供のコンポーネントをプロジェクトの参照に追加する
※SDKをインストールすると、参照の追加で勝手にCOMの一覧に出てくる
3.interop.bpac(COM)の相互運用型をfalseに
※参照設定下にあります(C#の場合)VBだとどこにあるのか知りません。
4.プロジェクトのターゲットプラットホームをx86にする
※PT-9700PC、PT-9800PCN等の場合、SDKが32bitだからx86にした。
確認はこちら → こちら
※64bitSDKならx64かAnyCPUでokでは?ご自身でテスト下さい。
5.ブラザー提供のサンプルプログラム
ラベルのテンプレートフォルダのフォルダ位置が正しいか確認
※Program Files (x86)かProgram Files 、どちらなのか、インストールしたSDK位置に合わせる
6.コンパイル → 実行
※上記はPT-9700PC(PT-9800PCN)が32bitSDKにしか対応していないから32bit版をDLしたり、ターゲットプラットホームをx86にしている
ブラザーのどのラベルプリンターでも同様!ではないので、先程紹介したリンクから確認する事
http://www.brother.co.jp/dev/bpac/env/index.htm ← ここ!
・エラーとは関係ないが、一応、どのフレームワークに対応しているのか試す
〇:.NET framework 2.0
〇:.NET framework 3.0
〇:.NET framework 3.5
〇:.NET framework 4
×:.NET framework 4.5
×:.NET framework 4.51
どうやら4.5以上はダメ、エラーが出る。だから素直に4を使いました。
よってVS2013でも開発出来る。
・それと使用フレームワークを.NET framework 2.0(や3.0?)に変更して遊んでいるとプロジェクトフォルダーにゴミがたんまり出来る(本当はゴミではないが・・)
system.なんちゃらとかMicrosoft.なんちゃらとか・・プロ内で使ってるからMSが親切にCOPYしてくれたのかな?
BrotherのSDKもサンプルも、元は古いので使用フレームワークが2.0や3.0になっている。
従って、遊んでるとゴミ?だらけになるので注意。
その場合は、フォルダ内の見た目が悪いので、プロジェクトを削除し、新しいモノに作り直しましょう
※ソースも消さないよう、どこかに保管しとかないと後で泣きますよ
そしてプロジェクトのプロパティーでフレームワークを4.0などになっているか、確認しましょう。

一応、プログラムからテンプレートのバーコードの数値をセットして印字するプログラムソース兼テストプログラム、載せときます。どうでも良い程度のコードですが、一応。C#。
ちゃんと環境が正しく、かつ、プリンターが正常に接続されていれば、
code39バーコードのコード:C987Z6001Q(末尾に自動でチェックデジットが追加されていた=助かった)が、印刷されます。テープ幅は12mmを使用。
const int TAPE_WIDTH = 12;
const string TEMPLATE_FOLDER = "C:\\Users\\xx\\xx管理システム\\";
const string TEMPLATE_FILE = "CODE39_1.lbx";
const string TEMPLATE_PRINTER = "";
public bool BarPrint()
{
string templatePath = TEMPLATE_FOLDER + TEMPLATE_FILE + TEMPLATE_PRINTER;
bool ret = false;
bpac.DocumentClass doc = new DocumentClass();
if (doc.Open(templatePath))
{
MessageBox.Show(doc.Width.ToString(), "tape幅");
MessageBox.Show(doc.Length.ToString(), "tape長DPI");
MessageBox.Show((doc.Length * 254 / 1440).ToString(), "tape長");
MessageBox.Show(doc.GetMediaId().ToString(), "メディアID");
MessageBox.Show(doc.GetMediaName(), "メディア名");
MessageBox.Show(doc.GetPrinterName(), "プリンター名");
MessageBox.Show(doc.GetBarcodeIndex("CODE39").ToString(), "バーコードインデックス");
MessageBox.Show(doc.CurrentSheet, "カレントシート");
MessageBox.Show(doc.CutLineCount.ToString(), "カットライン");
object[] sheetNames = doc.SheetNames as object[];
foreach (string sheetName in sheetNames)
{
MessageBox.Show(sheetName, "シート名");
}
// プリンターリストを取得
object[] printers = (object[])doc.Printer.GetInstalledPrinters();
foreach (string printerName in printers)
{
//オンラインかどうかをチェックする
if (doc.Printer.IsPrinterOnline(printerName))
{
MessageBox.Show(printerName, "Online");
}
else
{
MessageBox.Show(printerName, "Offline");
}
}
// バーコード生成&セット
doc.SetBarcodeData(doc.GetBarcodeIndex("CODE39"), "C987Z6001Q");
// 印刷
doc.StartPrint("", bpac.PrintOptionConstants.bpoDefault);
doc.PrintOut(1, bpac.PrintOptionConstants.bpoDefault);
doc.EndPrint(); // ここを通り過ぎると印刷される模様
doc.Close();
ret = true;
}
else
{
System.Windows.Forms.MessageBox.Show("プリンターがOPENできませんでした。", "エラー");
}
doc = null;
return ret;
}
}
<結果>
doc.Width 680 テープ幅
doc.Length 2556 テープ帳DPI
doc.Length * 254 / 1440 450 テープ長
doc.GetMediaId() 259 メディアID
doc.GetMediaName() 12mm メディア名
doc.GetPrinterName() Brother PT-9700PC プリンター名
doc.GetBarcodeIndex("CODE39") 0 バーコードインデックス
doc.CurrentSheet シート1 カレントシート
doc.CutLineCount 0 カットライン
doc.SheetNames as object[n] シート1 SheetNames
doc.Printer.IsPrinterOnline(printerName) Brother PT-9700PC オンライン
doc.SetBarcodeData(doc.GetBarcodeIndex("CODE39"), "C987Z6001Q");
印刷されたバーコード ⇒ C987Z6001QI
※印字してみたところ、自動でチェックデジットが追加されていた(上記の場合は I です)
それをバーコードリーダーで読込 ⇒ c987z6001qi
・元になったテンプレートと印刷結果を載せておきます
このテンプレートのバーコード、下のテープ部からはみ出てますが、はみ出た部分は無視され普通に印刷してくれます。
※ファイル名が違いますが・・でも同一テンプレートです
こんな小さな印刷物、テープ幅12mmにCODE39だから物凄く小さいです。
でも2千円のリーダーでもちゃんと読み取れます。
この写真はブラザーのテストプログラムから印字したものですが、上記プログラムからも印刷出来ますので。
という事で久々にプログラム組みましたが、やはり楽しいですね。
何時もDBしか相手にしていませんでしたが、こうやって目で見えるモノが出てくると、尚楽しいです。
おわり