A friend in our Product Support team in Neuchâtel asked me to help develop a little application to sort drawing files on disk. He has some old Clipper scripts that he used during a previous life as a CAD Manager to sort drawing files into different folders based on their version (held in the first six bytes of the DWG file, as mentioned in this previous post and this post of Shaan’s). We decided I’d implement it in VB.NET, to make it easier for him to understand and extend.
The application is simple enough, but could make a mess of your file system: we started with just a “Copy" function but decided to extend it to cover “Move”. These functions place files in sub-folders of the selected root folder named after the version numbers of the drawings encountered:
DWGs folder
|_ R11
|_ R14
|_ 2000
|_ 2004
|_ 2007
|_ 2010
The “List” process parses sub-folders until it encounters an exception, at which point it defaults to listing only the drawings in the root folder. The DWGs from the various folders all then get either copied or moved into one of the version folders under the root.
Because of the potential for harm to folder hierarchies brought by introducing “Move”, I’ve decided to leave the code in source form only (and here it is). Which means someone needs to build it to make use of it, and assuming they can do that then they can presumably take responsibility for whatever the code does to their (or their users’) file system(s). ;-)
Here’s the main VB.NET file:
Imports System.Windows.Forms
Imports System.IO
Imports System.Text
Class SortOnVersionWindow
Private Sub BrowseButton_Click( _
ByVal sender As System.Object, _
ByVal e As System.Windows.RoutedEventArgs) _
Handles BrowseButton.Click
Dim fbd As FolderBrowserDialog = New FolderBrowserDialog()
fbd.Description = _
"Select the root folder for the DWG version sort:"
If Directory.Exists(FolderBox.Text) Then
fbd.SelectedPath = FolderBox.Text
End If
Dim dr As DialogResult = fbd.ShowDialog()
If dr = Forms.DialogResult.OK Then
FolderBox.Text = fbd.SelectedPath
End If
End Sub
Private Sub FolderBox_TextChanged( _
ByVal sender As System.Object, _
ByVal e As System.Windows.Controls.TextChangedEventArgs) _
Handles FolderBox.TextChanged
Dim tb As System.Windows.Controls.TextBox = _
DirectCast(sender, System.Windows.Controls.TextBox)
ListButton.IsEnabled = Directory.Exists(tb.Text)
End Sub
Private Sub ListButton_Click( _
ByVal sender As System.Object, _
ByVal e As System.Windows.RoutedEventArgs) _
Handles ListButton.Click
Try
FileList.ItemsSource = _
Directory.GetFiles( _
FolderBox.Text, "*.dwg", SearchOption.AllDirectories)
Catch ex As Exception
MessageBox.Show( _
"A problem was found accessing sub-folders in this " + _
"location: will simply get the drawings in the root " + _
"folder.", _
"Sort On Drawing Version")
FileList.ItemsSource = _
Directory.GetFiles(FolderBox.Text, "*.dwg")
End Try
CopyButton.IsEnabled = True
MoveButton.IsEnabled = True
End Sub
Private Sub MoveButton_Click( _
ByVal sender As System.Object, _
ByVal e As System.Windows.RoutedEventArgs) _
Handles MoveButton.Click
SortFiles(True)
End Sub
Private Sub CopyButton_Click( _
ByVal sender As System.Object, _
ByVal e As System.Windows.RoutedEventArgs) _
Handles CopyButton.Click
SortFiles(False)
End Sub
Private Sub SortFiles(ByVal move As Boolean)
Dim numSorted As Integer = 0
Dim numSkipped As Integer = 0
Try
If FileList.Items.Count = 0 Then
MessageBox.Show( _
"Nothing to sort!", _
"Sort On Drawing Version")
Return
End If
SortProgress.Minimum = 0
SortProgress.Maximum = FileList.Items.Count - 1
SortProgress.Value = 0
For Each fn In FileList.Items
Dim ver As String = GetVersion(fn)
If Not String.IsNullOrEmpty(ver) Then
Dim loc As String = FolderBox.Text + "\" + ver
If Not Directory.Exists(loc) Then
Directory.CreateDirectory(loc)
End If
Dim dest As String = loc + "\" + Path.GetFileName(fn)
If Not File.Exists(dest) Then
If move Then
File.Move(fn, dest)
Else
File.Copy(fn, dest)
End If
numSorted += 1
Else
numSkipped += 1
End If
SortProgress.Value += 1
End If
Next
MessageBox.Show( _
String.Format( _
"{0} file{1} {2}, {3} (already existing) file{4} skipped.", _
numSorted, IIf(numSorted = 1, "", "s"), _
IIf(move, "moved", "copied"), numSkipped, _
IIf(numSkipped = 1, "", "s")), _
"Sort On Drawing Version")
SortProgress.Value = 0
FileList.ItemsSource = Nothing
Catch ex As Exception
MessageBox.Show( _
"A problem was found while sorting files: " + _
ex.Message, _
"Sort On Drawing Version")
End Try
End Sub
Private Function GetVersion(ByVal fn As String) As String
Dim data(5) As Byte
Dim res As Integer
Dim s As String = String.Empty
Dim fs As FileStream = File.OpenRead(fn)
Using (fs)
res = fs.Read(data, 0, 6)
If res = 6 Then
Dim enc As ASCIIEncoding = New ASCIIEncoding()
s = enc.GetString(data)
Dim sh As String = s.Substring(0, 5)
If sh = "MC0.0" Then
Return "R1.0"
ElseIf sh = "AC1.2" Then
Return "R1.2"
ElseIf s = "AC1.40" Then
Return "R1.4"
ElseIf s = "AC1.50" Then
Return "R2.05"
ElseIf s = "AC2.10" Then
Return "R2.10"
ElseIf s = "AC2.21" Then
Return "R2.21"
ElseIf s = "AC2.22" Then
Return "R2.22"
ElseIf s = "AC1001" Then
Return "R2.22"
ElseIf s = "AC1002" Then
Return "R2.5"
ElseIf s = "AC1003" Then
Return "R2.6"
ElseIf s = "AC1004" Then
Return "R9"
ElseIf s = "AC1006" Then
Return "R10"
ElseIf s = "AC1009" Then
Return "R11"
ElseIf s = "AC1012" Then
Return "R13"
ElseIf s = "AC1014" Then
Return "R14"
ElseIf s = "AC1015" Then
Return "2000"
ElseIf s = "AC1018" Then
Return "2004"
ElseIf s = "AC1021" Then
Return "2007"
ElseIf s = "AC1024" Then
Return "2010"
Else
Return "Unknown"
End If
End If
fs.Close()
End Using
Return s
End Function
End Class
Here’s the main dialog, implemented using WPF, to give you an idea of how it works:
This tool may end up being a Plugin of the Month, at some point, but we’ll see. I worry about the damage that can be done by “Move” (unless we maintain some kind of undo stack or display prominent health warnings).
On the subject of our Plugins of the Month… Viru Aithal, who manages our DevTech team in India, is beavering away on a replacement for ScriptPro (whether we use the ScriptPro name or simply call it “Batch Processor” remains to be seen). He’s reimplemented – and in many ways extended – the popular ScriptPro tool using .NET, which also means it will work well on 64-bit systems (a limitation of the current VB6-implemented ScriptPro). If anyone is interested in Beta-testing this tool prior to its release, please drop me an email.