【C#】CSharpWinForms開発Webカメラで二次元コード読取り&Excel出力

C#.NET

ad2

【C#】CSharpWinForms開発Webカメラで二次元コード読取り&Excel出力

ツール画面

二次元コードをWebカメラから読取り、リアルタイムにExcelに出力できるツールを作ってみた。

reader_excel_out_img1 reader_excel_out_img2

ソースコード

今回のアプリケーションの参照ライブラリは下記の画像の通りとなってます。各自Nugetからインストールして追加して下さい。

reader_excel_out_img3

それでは、ソースコードは下記の通りとなります。

using log4net;
using Microsoft.Office.Interop.Excel;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
using ZXing;
using Excel = Microsoft.Office.Interop.Excel;

namespace QR_reader_Excel_out_rev1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //ログ出力用
        public ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);    //ログ出力用

        private bool qrresult = true;
        public int camera_device_num = 0;

        public string result_str;
        public int sleep_time;

        //アプリケーションのオブジェクト
        public Excel.Application excel;
        //ブックのオブジェクト
        public Workbook workbook;
        //シートのオブジェクト
        public Worksheet Sheet;

        public Excel.Range rangefor_brank;
        public Excel.Range range_select;

        /// <summary>
        /// 画面起動
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            logger.Info("☆起動!");

            sleep_time_txt.Text = Properties.Settings.Default.Sleep_time_txt;

            sleep_time = int.Parse(sleep_time_txt.Text);

            //ボタン非表示
            restart_btn.Visible = false;

            //
            backgroundWorker1.RunWorkerAsync();

        }

        private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            using (VideoCapture capture = new VideoCapture(camera_device_num))
            {

                using (Mat normalframe = new Mat())

                    //無限ループ
                    while (qrresult == true)
                    {
                        //キャプチャ読込
                        capture.Read(normalframe);

                        if (!normalframe.Empty())
                        {

                            // 新しい画像を取得したので、
                            // ReportProgressメソッドを使って、ProgressChangedイベントを発生させる
                            //this.backgroundWorker1.ReportProgress(0, normalframe);

                            //画像表示
                            pictureBox.Image = normalframe.ToBitmap();


                            //画像処理QRコード
                            //コードの解析
                            BarcodeReader reader = new BarcodeReader();
                            reader.Options = new ZXing.Common.DecodingOptions { PossibleFormats = new[] { BarcodeFormat.All_1D, BarcodeFormat.QR_CODE, BarcodeFormat.DATA_MATRIX } };
                            reader.AutoRotate = true;                    //90度ずつ回転させて読取
                            reader.TryInverted = true;                   //読み取れなかったときに白黒反転。デコードが遅くなるので注意
                            reader.Options.TryHarder = true;             //ビットマップをよりDeepに解析

                            //QRコードのデコーダ処理
                            Result result = reader.Decode(normalframe.ToBitmap());

                            if (result != null)
                            {
                                //バックグラウンド処理1 プログレス更新時
                                this.backgroundWorker1.ReportProgress(0, result);


                            }
                        }
                    }
            }
        }

        private void BackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            qrresult = false;
            //QR読取結果の引数を取得
            ZXing.Result result = (ZXing.Result)e.UserState;
            result_str = result.Text;
            barcodeFormatBox.Text = result.BarcodeFormat.ToString();  //二次元コード種別表示
            readResultBox.Text = result_str;  //内容表示
            readResultBox.BackColor = Color.LightGreen;
        }

        private void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //履歴表示
            if (result_str != "")
            {
                logger.Info("読取内容履歴表示:" + result_str);
                out_report.Focus();
                out_report.AppendText(result_str + "\n");
            }

            //ボタン表示
            restart_btn.Visible = true;

            //背景色変更
            readResultBox.BackColor = Color.LemonChiffon;

            if (result_str != "")
            {
                //バックグラウンド処理2実行
                this.backgroundWorker2.RunWorkerAsync();
            }

            //テキストボックスの中身をクリア
            barcodeFormatBox.Text = string.Empty;
            readResultBox.Text = string.Empty;


            //*秒間待機させる
            System.Threading.Thread.Sleep(sleep_time);


            // BackgroundWorkerが処理中でなければ
            if (!backgroundWorker1.IsBusy)
            {
                qrresult = true;
                backgroundWorker1.RunWorkerAsync();
            }
        }

        /// <summary>
        /// Excel出力
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BackgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
        {
            Task.Run(() => Invoke(new System.Action(Write_excel)));
        }


        /// <summary>
        /// 読取再開ボタン押下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Restart_btn_Click(object sender, EventArgs e)
        {
            // BackgroundWorkerが処理中でなければ
            if (!backgroundWorker1.IsBusy)
            {
                qrresult = true;
                backgroundWorker1.RunWorkerAsync();
            }
        }

        /// <summary>
        /// 履歴クリアボタン押下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void History_clear_btn_Click(object sender, EventArgs e)
        {
            out_report.Clear();
        }

        /// <summary>
        /// カメラ切替ボタン押下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Camera_change_btn_Click(object sender, EventArgs e)
        {
            qrresult = false;
            backgroundWorker1.CancelAsync();

            if (camera_device_num == 0)
            {
                camera_device_num = 1;

            }
            else
            {
                camera_device_num = 0;
            }

            // BackgroundWorkerが処理中でなければ
            if (!backgroundWorker1.IsBusy)
            {
                qrresult = true;
                // バックグラウンド処理を開始
                backgroundWorker1.RunWorkerAsync();
            }
        }

        /// <summary>
        /// 書込み新規ファイル作成
        /// </summary>
        public void Write_excel()
        {
            if (checkBox1.Checked)
            {
                try
                {
                    rangefor_brank = Sheet.Range["A1"];      //セル選択

                    range_select = rangefor_brank.Offset[1, 0];            // 1行下のセルに書込み

                    //初回セルA2が空欄ならセルA2に代入
                    if (range_select.Value == "")
                    {
                        range_select.Value = result_str;               //二次元コード内容書込み

                    }
                    //セルA2が埋まっていれば、その1つ下の行に代入
                    else
                    {
                        Excel.Range end_rows = Sheet.Range["A1048576"];   //最終行
                        Excel.Range cell_select = end_rows.End[Excel.XlDirection.xlUp]; //上にいって使用最終行
                        Excel.Range cell_value_write = cell_select.Offset[1, 0]; //オフセットで1つ下の行
                        cell_value_write.Value = result_str;

                    }


                }
                catch (Exception e)
                {
                    logger.Error("Excel書込み:エラー:" + e.Message);
                    MessageBox.Show("Excel書込み:エラー:" + e.Message);
                }
                finally
                {
                    // アプリケーションのオブジェクトの解放
                    Marshal.ReleaseComObject(excel);
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    GC.Collect();
                }
            }


        }


        /// <summary>
        /// 画面閉じる時
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Properties.Settings.Default.Sleep_time_txt = sleep_time_txt.Text;
            Properties.Settings.Default.Save();

        }

        /// <summary>
        /// チェックボックスが押下したイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CheckBox1_CheckedChanged(object sender, EventArgs e)
        {
            //アプリケーションのインスタンス作成
            excel = new Excel.Application
            {
                //アプリケーションの表示
                Visible = true
            };

            // ファイル新規オープン
            workbook = excel.Workbooks.Add();
            Sheet = workbook.Sheets[1];      //シート[1]:左端のシート
        }

    }
}が

画面デザイン

画面設計は下記の通りです。

reader_excel_out_img4

出力機能

  • 1.履歴としてテキストボックスに出力し、残せる。
  • 2.Excelに出力できる。
  • 3.logファイルで残せる。

1.履歴欄に読み取った結果内容を出力していくので、Excel使用しなくてもすぐに読取結果を使用できる。

2.Excelに出力もできるので、読み取ったら、Excel上ですぐに結果を編集できる。

3.log4netの設定をしておけば、気にせず、logファイルを残せるので、過去の読取結果も見れる。

サンプル

QRコード5個用意して連続で読み取った結果、Excelにも連続で出力されている。

reader_excel_out_img5