Introduction
This Windows application lets you scan image in a given folder (and subfolders) and generate CSV file based on the output. This article uses the BarcodeImaging.dll library developed by Berend Engelbrecht to scan barcodes: Reading Barcodes from an Image - III.
Background
I found that BarcodeImaging.dll library does a pretty decent job, but for some cases I needed to use Byte Scout (Bytescout.BarCodeReader.dll) library (which costs $20 and is slow). I tried Byte Scout library for comparison but left it unchecked in the application, in case someone will still want to try it.
Using the Code
To use this program, simply select a folder and click Process. The program will create a CSV file within target folder.
Here is the code:
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
Here is the code for AppSetting.vb to persist user settings:
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
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()
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
History
- 16th January, 2019: Initial version