65.9K
CodeProject 正在变化。 阅读更多。
Home

条形码扫描器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (9投票s)

2019年1月16日

CPOL
viewsIcon

15214

downloadIcon

1285

这个Windows应用程序可以扫描指定文件夹中的图像,并生成CSV文件以显示每个图像文件的条码。

引言

这个Windows应用程序可以扫描给定文件夹(及其子文件夹)中的图像,并基于输出生成CSV文件。本文使用了Berend Engelbrecht开发的BarcodeImaging.dll库来扫描条码:从图像中读取条码 - III

背景

我发现BarcodeImaging.dll库做得相当不错,但在某些情况下我需要使用Byte Scout(Bytescout.BarCodeReader.dll)库(需要付费20美元且速度较慢)。我尝试了Byte Scout库进行比较,但将其在应用程序中未选中,以防有人仍然想尝试它。

Using the Code

要使用此程序,只需选择一个文件夹并单击处理。程序将在目标文件夹中创建一个CSV文件。

这是代码

	Dim oAppSetting As New AppSetting()
	Dim oLogFile As System.IO.StreamWriter
	Dim bStartFile As Boolean = True

	Private Sub Form1_FormClosing(sender As Object, _
            e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
		oAppSetting.SetValue("FromPath", txtFrom.Text)
		oAppSetting.SetValue("RegName", txtRegName.Text)
		oAppSetting.SetValue("RegKey", txtRegKey.Text)
		oAppSetting.SetValue("StartFile", txtStartFile.Text)

		oAppSetting.SetValue("BarcodeType", cbBarcodeType.SelectedIndex)
		oAppSetting.SetValue("Direction", cbDirection.SelectedIndex)

		oAppSetting.SetValue("UseBarcodeZones", IIf(chkUseBarcodeZones.Checked, "1", "0"))
		oAppSetting.SetValue("Log", IIf(chkLog.Checked, "1", "0"))
		oAppSetting.SetValue("ShowTime", IIf(chkShowTime.Checked, "1", "0"))
		oAppSetting.SetValue("CSV", IIf(chkCSV.Checked, "1", "0"))

		oAppSetting.SetValue("Bytescout", IIf(chkBytescout.Checked, "1", "0"))
		oAppSetting.SetValue("Fast", IIf(chkFast.Checked, "1", "0"))

		oAppSetting.SaveData()
	End Sub

	Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

		oAppSetting.LoadData()

		txtFrom.Text = oAppSetting.GetValue("FromPath")
		txtRegName.Text = oAppSetting.GetValueDef("RegName", txtRegName.Text)
		txtRegKey.Text = oAppSetting.GetValueDef("RegKey", txtRegKey.Text)
		txtStartFile.Text = oAppSetting.GetValue("StartFile")

		Dim sBarcodeType As String = oAppSetting.GetValue("BarcodeType")
		If sBarcodeType <> "" Then
			cbBarcodeType.SelectedIndex = CInt(sBarcodeType)
		Else
			cbBarcodeType.SelectedIndex = 0
		End If

		Dim sDirection As String = oAppSetting.GetValue("Direction")
		If sDirection <> "" Then
			cbDirection.SelectedIndex = CInt(sDirection)
		Else
			cbDirection.SelectedIndex = 0
		End If

		chkUseBarcodeZones.Checked = oAppSetting.GetValue("UseBarcodeZones") = "1"
		chkLog.Checked = oAppSetting.GetValue("Log") <> "0"
		chkShowTime.Checked = oAppSetting.GetValue("ShowTime") <> "0"
		chkCSV.Checked = oAppSetting.GetValue("CSV") <> "0"

		chkBytescout.Checked = oAppSetting.GetValue("Bytescout") = "1"
		chkFast.Checked = oAppSetting.GetValue("Fast") = "1"

		BytescoutChecked()
	End Sub

	Public Shared Function GetShortName(ByVal sLongFileName As String) As String

		If sLongFileName.Length < 250 Then
			Return sLongFileName
		End If

		Dim lRetVal As Long
		Dim iLen As Integer = 1024
		Dim sShortPathName As System.Text.StringBuilder = New System.Text.StringBuilder(iLen)
		lRetVal = GetShortPathName(sLongFileName, sShortPathName, iLen)
		Dim sRet As String = sShortPathName.ToString()

		If sRet <> "" Then
			Return sRet
		Else
			Return sLongFileName
		End If

	End Function

	Private Sub btnFrom_Click(sender As System.Object, e As System.EventArgs) Handles btnFrom.Click
		fldFrom.SelectedPath = txtFrom.Text
		fldFrom.ShowDialog()
		txtFrom.Text = fldFrom.SelectedPath
	End Sub

	Private Sub btnProcess_Click(sender As System.Object, e As System.EventArgs) _
               Handles btnProcess.Click
		btnProcess.Enabled = False

		Dim sFromPath As String = txtFrom.Text
		If Not Directory.Exists(sFromPath) Then
			btnProcess.Enabled = True
			MsgBox("Folder does not exist")
			Exit Sub
		End If

		If chkCSV.Checked Then
			Dim sLogFileName As String = Now.Month.ToString() & "-" & _
			 Now.Day.ToString() & "-" & _
			 Now.Year.ToString() & "_" & _
			 Now.Hour.ToString() & "-" & _
			 Now.Minute.ToString() & "-" & _
			 Now.Second.ToString() & ".csv"
			Dim sLogFilePath As String = IO.Path.Combine(sFromPath, sLogFileName)
			oLogFile = New System.IO.StreamWriter(sLogFilePath)
		End If

		If txtStartFile.Text <> "" Then
			bStartFile = False
		End If

		txtOutput.Text = ""
		txtOutput.AppendText("Starting..." & vbCrLf)
		ProccessFolder(sFromPath)
		txtOutput.AppendText("Done!")

		btnProcess.Enabled = True

		If chkCSV.Checked Then
			oLogFile.Close()
		End If

	End Sub

	Sub ProccessFolder(ByVal sFolderPath As String)
		Dim sFromPath As String = txtFrom.Text
		Dim oFiles As String() = Directory.GetFiles(sFolderPath)
		ProgressBar1.Maximum = oFiles.Length
		For i As Integer = 0 To oFiles.Length - 1
			Dim sFromFilePath As String = oFiles(i)

			If txtStartFile.Text <> "" Then
				If Trim(LCase(txtStartFile.Text)) = LCase(sFromFilePath) Then
					bStartFile = True
				End If
			End If

			If bStartFile Then
				Dim oFileInfo As New FileInfo(GetShortName(sFromFilePath))
				Dim sExt As String = PadExt(oFileInfo.Extension)

				If sExt = "JPG" Or sExt = "GIF" Or sExt = "PNG" Or sExt = "BMP" Or sExt = "TIF" Then

					If chkBytescout.Checked Then
						Bytescout_ReadBarcode(sFromFilePath)
					Else
						ReadBarcode(sFromFilePath)
					End If

				End If
			End If

			ProgressBar1.Value = i
			Application.DoEvents()
		Next

		ProgressBar1.Value = 0

		Dim oFolders As String() = Directory.GetDirectories(sFolderPath)
		For i As Integer = 0 To oFolders.Length - 1
			Dim sChildFolder As String = oFolders(i)
			Dim iPos As Integer = sChildFolder.LastIndexOf("\")
			Dim sFolderName As String = sChildFolder.Substring(iPos + 1)
			ProccessFolder(sChildFolder)
		Next

	End Sub

	Private Sub ReadBarcode(sFromFilePath As String)

		Dim sFromPath As String = txtFrom.Text
		Dim sFileName As String = sFromFilePath.Replace(sFromPath & "\", "")

		Dim oImage As System.Drawing.Image = Nothing

		Try
			oImage = System.Drawing.Image.FromFile(sFromFilePath)
		Catch ex As Exception
			If chkLog.Checked Then
				txtOutput.AppendText(sFileName & vbTab & "Could not open" & vbCrLf)
			End If

			WriteLog(sFileName & "," & "Could not open")
			Exit Sub
		End Try

		Dim barcodes As New System.Collections.ArrayList
		Dim iScans As Integer = 100
		Dim dtStart As DateTime = DateTime.Now

		BarcodeImaging.UseBarcodeZones = chkUseBarcodeZones.Checked

		Dim oBarcodeType As BarcodeImaging.BarcodeType = BarcodeImaging.BarcodeType.All
		Select Case cbBarcodeType.Text
			Case "Code39"
				oBarcodeType = BarcodeImaging.BarcodeType.Code39
			Case "Code128"
				oBarcodeType = BarcodeImaging.BarcodeType.Code128
			Case "EAN"
				oBarcodeType = BarcodeImaging.BarcodeType.EAN
		End Select

		Select Case cbDirection.Text
			Case "All"
				BarcodeImaging.FullScanBarcodeTypes = oBarcodeType
				BarcodeImaging.FullScanPage(barcodes, oImage, iScans)
			Case "Vertical"
				BarcodeImaging.ScanPage(barcodes, oImage, iScans, _
                                        BarcodeImaging.ScanDirection.Horizontal, oBarcodeType)
			Case "Horizontal"
				BarcodeImaging.ScanPage(barcodes, oImage, iScans, _
                                        BarcodeImaging.ScanDirection.Vertical, oBarcodeType)
		End Select

		Dim sSec As String = ""
		If chkShowTime.Checked Then
			sSec = vbTab & DateTime.Now.Subtract(dtStart).TotalSeconds.ToString("#0.00")
		End If

		If barcodes.Count = 0 Then

			If chkLog.Checked Then
				txtOutput.AppendText(sFileName & vbTab & "Failed" & sSec & vbCrLf)
			End If

			WriteLog(sFileName & "," & "Failed")
		Else
			For Each bc As Object In barcodes

				If chkLog.Checked Then
					txtOutput.AppendText(sFileName & vbTab & bc & sSec & vbCrLf)
				End If

				WriteLog(sFileName & "," & bc)
			Next
		End If

		oImage.Dispose()
	End Sub

以下是AppSetting.vb的代码,用于持久化用户设置

Public Class AppSetting

	Private oDS As New Data.DataSet
	Private oTable As New Data.DataTable
	Private sFilePath As String = ""

	Public Sub New()
		Dim sAssPath As String = System.Reflection.Assembly.GetExecutingAssembly().Location
		Dim sPath As String = System.IO.Path.GetDirectoryName(sAssPath)
		sFilePath = System.IO.Path.Combine(sPath, "Settings.xml")
	End Sub

	Public Sub LoadData()
		oDS = New Data.DataSet()

		If System.IO.File.Exists(sFilePath) Then
			oDS.ReadXml(sFilePath)
			If oDS.Tables.Count > 0 Then
				oTable = oDS.Tables(0)
				Exit Sub
			End If
		End If

		'setup New
		oTable = New Data.DataTable()
		oTable.Columns.Add(New Data.DataColumn("key"))
		oTable.Columns.Add(New Data.DataColumn("value"))
		oDS.Tables.Add(oTable)
	End Sub

	Public Sub SaveData()
		'If System.IO.File.Exists(sFilePath) Then
		'	System.IO.File.Delete(sFilePath)
		'End If

		oTable.DataSet.WriteXml(sFilePath, XmlWriteMode.WriteSchema)
	End Sub

	Public Sub SetValue(ByVal sKey As String, ByVal sValue As String)

		Dim oDataRow As DataRow
		Dim oDataRows As DataRow() = oTable.Select("key = '" & Replace(sKey, "'", "''") & "'")
		If oDataRows.Length > 0 Then
			oDataRows(0)("value") = sValue
		Else
			oDataRow = oTable.NewRow()
			oDataRow("key") = sKey
			oDataRow("value") = sValue
			oTable.Rows.Add(oDataRow)
		End If

	End Sub

	Public Function GetValue(ByVal sKey As String) As String
		Dim oDataRows As DataRow() = oTable.Select("key = '" & Replace(sKey, "'", "''") & "'")
		If oDataRows.Length > 0 Then
			Return oDataRows(0)("value") & ""
		End If
		Return ""
	End Function

	Public Function GetValueDef(ByVal sKey As String, ByVal sDefVal As String) As String
		Dim sValue As String = GetValue(sKey)
		If sValue <> "" Then
			Return sValue
		End If

		Return sDefVal
	End Function
End Class

历史

  • 2019年1月16日:初始版本
© . All rights reserved.