Comparing files in two different folders with string variable names - vbscript

Due to automatic naming conventions I'm stuck with, files are saved in a particular archive one of two ways. Either they have a 13-digit match to the record in the database, or they have a 10 digit match. The ones which have the 13 digit also have the ten digit match, and should be treated preferentially. I have two scripts right now that work: one just looks for 13-digit matches and moves them to another folder. The other moves by datemodified, which is not a very stable variable.
My attempts at combining look something like this:
'dimming of obj, folder paths, sql db info and connection open above
SQL = "SELECT ticket FROM orders WHERE dateinvoice>'6/1/16"
Recordset.Open SQL, Connection
Do While Not Recordset.EOF
ticket = Recordset("ticket")
id = Right(ticket, 2)
suffix = CInt(id)
compare = Left(ticket, Len(ticket) - 3)
search = compare & "-0" & suffix
For Each objFile In colFiles.Files
If Left(objFile.Name, 13) = search Then
Set objNewestFile = objFile
skip = 1
Else
skip = 0
End If
If Left(objFile.Name, 10) = search And skip = 0 Then
Set objNewestFile = objFile
End If
Next
Recordset.MoveNext
On Error Resume Next
objFSO.CopyFile objNewestFile.Path, strDestFolder
Set objFile = Nothing
Loop
This is the scaled-down version I went back to, having attempted various convoluted solutions like:
storing the skipped records in an array,
having a second loop through comparing files in folder1 to folder2 (every time I use FileExists it doesn't seem to recognize the destination),
creating a temporary SQL table to store the skipped records in.
The following have been very useful:
Compare two files in two different folders and replace it by the newer
https://blogs.technet.microsoft.com/heyscriptingguy/2005/06/20/how-can-i-determine-if-a-file-exists-and-if-it-does-exit-the-script/
Classic ASP 3.0 Create Array from a Recordset
ETA: There can be many duplicate files that share the 10 digit identifier. The only good rule is: if it has the 13 identifier version, that's the one to move. Part of my issue lies in setting paths if I use FileExists-- when I try wildcards, it doesn't recognize the path. If I don't use them, it doesn't compensate for all the variables.

Related

VB6 listbox sorting differently in different operating systems

I am working on an VB6 application where some of my customers use the old version and some of my customers use the new version.
In the new version, there is a listbox populated with subfolders of a directory using the FileSystemObject and a For Each loop:
Dim objFileSys As New FileSystemObject
Dim myFolder as Folder
Set myFolder = objFileSys.GetFolder(Path)
For Each mysubfolder In myFolder.SubFolders
listbox1.AddItem mysubfolder.Name
Next
In the old version, the Dir$ function is used:
Dim DirName As String
DirName = Dir$(Path, ATTR_DIRECTORY)
Do While DirName <> ""
If DirName <> "." And DirName <> ".." Then
If (GetAttr(Path & DirName) And ATTR_DIRECTORY) = ATTR_DIRECTORY Then
listbox1.AddItem DirName
End If
End If
DirName = Dir$
Loop
In the old version, the listbox1.sort property is true, and in the new version, the listbox1.sort property is false. There is no code that performs any sorting whatsoever.
Here is where it gets weird. When I run the applications in Windows 10, the list box is sorted correctly in both versions. When I run the application in Windows 7, the old version (the one with listbox.sort=true) is not sorting correctly, but the new version (the one with the listbox.sort=false) is sorting correctly.
What could be causing this to happen?
This is likely down to the order the files are being returned by the file system API call in the operating system. It may also be down to the filesystem being used.
Many filesystems are not inherently sorted structures, but client software used to represent them obscures this fact by sorting e.g. file and folder lists.
e.g. a common problem with flash MP3 players was people copying music files to them and them playing out of order, because the firmware was just reading the files in the order they occurred in the file allocation table, and ignoring the filenames (even if they had 01 - track name kind of names).
It sounds like one of the following is true
The Windows 10 API sorts file names when it returns lists of them
Given the fervour that MS puts into backward compatibility, I'm not sure this is true, especially since all the user software has long since got used to unsorted lists
Your Windows 10 system is newer, and the files were copied onto it fresh
This means the files are on the disk in the actual order they were copied, which is probably the sorted order
The Windows 7 box likely has had the files for some time and they're written on the disk in a non-sorted order
Therefore it's just good fortune that the "old" code works on Windows 10
So that may explain the "random" sort order.
Back to VB6 : the Sorted property of the VB6 ListBox control is what's called an "Action" property - setting it does something. The control doesn't sort lists while you are populating them. Populate the list THEN set the .Sorted property.
The new code is likely producing a sorted list because FileSystemObject behaves differently to Dir$() (ie, it probably sorts the files because this was a common frustration)
Dim DirName As String
DirName = Dir$(Path, ATTR_DIRECTORY)
Do While DirName ""
If DirName "." And DirName ".." Then
If (GetAttr(Path & DirName) And ATTR_DIRECTORY) = ATTR_DIRECTORY Then
listbox1.AddItem DirName
End If
End If
DirName = Dir$
Loop
listbox1.Sorted = True ' After the loop

Looping over all databases in a directory

I need to loop over all databases in a certain directory, where the database name is ACPwxyz.mdb, where wxyz is the equivalent to an MMYY value for the period that database was used for.
E.g., the database for July 2017 would be ACP0717.mdb.
I've never written in VB6 before and I totally hate it, but it's an extension to an existing project so I'm stuck with it!
Is there a way of looping over all files in a directory, checking if the file name follows the format of ACPwxyz.mdb or not, and if it does, then opening a connection to it?
I've looked around a bit and see Dir(x, y), but I'm not sure if I can use this in this situation?
Any tips would be appreciated.
You can use Dir, yes.
If you use something like this:
Dim strFile As String
strFile = Dir(yourDBPath, "ACP????.mdb") ' mdb for MS-Access files
Do Until strFile = ""
If Len(strFile) = 11 Then ' Ensure the DB file name is 11 characters, which yours are
'Do something // You can also check the file name doesn't = a certain name if needed
End If
strFile = Dir
Loop
Dir accepts either an asterisk (*), or a question mark (?) as wildcards in file names, so this will look for any database in the set path that is called ACP followed by 4 characters.

Iterate over pre-filtered list of folders

I'm working with a client's flat folder structure that has a single folder containing 45k subfolders with 8-digit folder names, e.g. 51023231. I have a small script that ripples through them and copies them into a bin-sorted set of subfolders elsewhere on the network (for use with SharePoint), such that the first 5 digits are used as a parent folder, i.e. the contents of 51023231 are copied into 51023\51023231. It works perfectly well, and I've managed to some modest optimisation when dealing with folders new to the destination.
However, it can take an hour or so to run over the entire 45k set of folders doing folder by folder comparisons, I was wondering if it was possible to run a system-level query to return only an initial list of folders whose modification dates were after a given point, and then run the existing script over that. I've done the usual Google-is-your-friend type trawl, and keep hitting the idea of using WMI to do this, but I don't get much further. Is this because it simply isn't possible with VBScript?
Any pointers gratefully received.
It's possible with VBScript using WMI. It's not something you'd be able to do using the FileSystemObject, if that's what you're implying.
You can query WMI's Win32_Directory class to filter folders by modified date. The only tricky part is the datetime format used by WMI. But the SWbemDateTime class can convert a VBScript date to a datetime value.
Here's an example:
' Create a datetime value for use in our WMI query...
Dim dt
Set dt = CreateObject("WbemScripting.SWbemDateTime")
dt.SetVarDate DateSerial(2015, 8, 31)
Dim objWMI
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
' Find all subfolders of 'c:\some\path' that were modified > 2015/08/31
Dim objFolders
Set objFolders = objWMI.ExecQuery("select * from Win32_Directory" _
& " where Drive='C:' and Path='\\some\\path\\' and LastModified>'" & dt & "'")
Dim objFolder
For Each objFolder in objFolders
WScript.Echo objFolder.Name
Next

needing help creating a script to find if a folder has been modified in the last day and if not create a txt file in a location

I'm trying to create a script that finds if a folder hasn't been modified in the last day and create a text file in a location. However if it has been modified in the last day I want it to quit the script.
At the moment, I have only been able to create one (due to my basic knowledge of VBscripting) that finds if a folder exists and if so creates a script.
This however, doesn't work as the subfolder is created daily with a new name and obviously this means my script would have to be changed daily which is pointless.
I need to have the parent folder read and a text file created in another locationif the last modified date isn't < 1 day.
This is the script so far:
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FolderExists("c:\test") Then
wsscript.quit
Else
dim filesys, filetxt, getname, path
Set filesys = CreateObject("Scripting.FileSystemObject")
Set filetxt = filesys.CreateTextFile("c:\test\test.txt", True)
path = filesys.GetAbsolutePathName("c:\test\test.txt")
getname = filesys.GetFileName(path)
filetxt.WriteLine("file doesnt exist.")
filetxt.Close
End If
I know I need to change the .folderExists line to something like
if file.DateLastModified > dateadd("h", -24, Now) then
I would like a day parameter rather than an hour; I know this means turning the h into a d but I am unsure past that.
it has been solved by Mr Bond! the wonderful man he is. however i now have another question, any idea how to add a command to send an outlook email into this? as the else option.
Use the DateLastModified property of the Folder object.
If objFSO.GetFolder("c:\test").DateLastModified >= Date - 1 Then
' Folder modified within last day
Else
' Folder modified more than a day ago
End
There's no need to use DateAdd() to add/subtract days. You can just use integer arithmetic.
Note that this will yield a time of zero/midnight. So it's really checking to see if the folder was modified since the start of the day yesterday, not in the last 24 hours. That may or may not be what you want.

Windows / NTFS: Number of files in a directory, without enumerating them

Is there a way in Windows to get the number of files in a directory (non-recursively is good enough) without the potentially significant overhead of enumerating them all through FindFirst/NextFile?
The purpose is for an estimate how many files need to be processed.
The directory structure is known and not deep, and folders usually don't contain unknown files.
Since the data is not essential to continue and the folder is virtually always on a local drive, an NTFS-specific command would be acceptable (provided that does not require elevation).
Any ideas?
Keeping track of the number of files in a directory is an overhead that doesn't provide any benefit for a file system, so none of them do it.
Counting files on a local drive should be fast enough for most purposes. It will certainly take a small fraction of the time needed to process the files.
Assuming that Indexing service is running and the directory is indexed, we can query the catalog and count the files on a given directory.
I dont know if querying the catalog is faster, its the only idea came on my mind.
Regards.
Sample code in VB.NET
Sub Main()
Try
' Catalog Name
Dim strCatalog As String = "System"
Dim strQuery As String
strQuery = "Select DocPageCount,DocTitle,Filename,Size,PATH,URL from SCOPE('shallow traversal of ""C:\Windows""')"
Dim connString As String = "Provider=MSIDXS.1;Integrated Security .='';Data Source='" & strCatalog & "'"
Dim cn As New System.Data.OleDb.OleDbConnection(connString)
cn.Open()
Dim cmd As New System.Data.OleDb.OleDbCommand(strQuery, cn)
Dim rdr As System.Data.OleDb.OleDbDataReader = cmd.ExecuteReader()
Dim files As Integer = 0
While rdr.Read()
files += 1
Console.WriteLine("Path: {0} Filename: {1} Size : {2}", rdr("PATH"), rdr("Filename"), rdr("Size"))
End While
rdr.Close()
rdr = Nothing
cmd.Dispose()
cmd = Nothing
cn.Close()
Console.WriteLine("Total Files: {0}", files)
Catch ex As Exception
Console.WriteLine(ex)
End Try
End Sub
More info: Searching your web site with the Microsoft Indexing Service and ASP.NET

Resources