Check file in destination folder if exist - vb6

I am trying to determine the number of files that would be copied from the source folder to the destination and then assign this value to the progressbar.max.But using the code below I get Runtime error 5, Invalid procedure call or argument at the marked position.Please Guide
Private Sub cmdCopy_Click()
Dim sFileName As String 'Source File
Dim sDirName As String 'Source Directory
Dim dDirName As String 'Destination Directory
Dim fiFileCount As Integer 'Number of Files to be copied
Dim fbFileMatch As Boolean
If prgFCount.Visible = True Then prgFCount.Visible = False
dDirName = "D:\Destination\"
sDirName = "C:\Source\"
sFileName = Dir(sDirName)
' Disable this button so the user cannot
' start another copy.
cmdCopy.Enabled = False
cmdCancel.Enabled = True
fiFileCount = 0
Do While Len(sFileName) > 0
fbFileMatch = False
If Len(Dir$(dDirName & sFileName)) > 0 Then
fbFileMatch = True
End If
If fbFileMatch = False Then
fiFileCount = fiFileCount + 1
End If
sFileName = Dir '## Error at this Point ##
Loop
If fiFileCount = 0 Then
cmdCopy.Enabled = True
cmdCancel.Enabled = False
Exit Sub
End If
prgFCount.Min = 0
prgFCount.Max = fiFileCount
prgFCount.Visible = True
End Sub

If Len(Dir$(dDirName & sFileName)) > 0 Then
You set up your directory iteration with the line:
sFileName = Dir(sDirName)
Calling the Dir function without parameters will get the next item meeting the file name pattern and attributes is retrieved. The Len(Dir$ call is screwing it up.
I would suggest rewriting your code to loop through all the files in your source folder and build a list, then loop through the list and look for matches in your destination folder.
Something like this:
...
sFileName = Dir$(sDirName)
Do While Len(sFileName) > 0
i = i + 1
ReDim Preserve strSourceFileList(i)
strSourceFileList(i) = sFileName
sFileName = Dir()
Loop
If i > 0 Then
For i = LBound(strSourceFileList) To UBound(strSourceFileList)
sFileName = Dir$(dDirName & strSourceFileList(i))
If Len(sFileName) = 0 Then
fiFileCount = fiFileCount + 1
End If
Next i
End If
...

Dir returns the name of a matching file, directory, or folder.
Calling Dir should be fine but in your case it generates the error.
You also have no loop implemented to iterrate through all the available source files.
Using the FileSystemObject is one of the options.
To use the FileSystemObject, click the Project menu option, followed by the References... menu option.
This will open the References Dialog.
Tick the box beside the reference named "Microsoft Scripting Runtime" and click OK.
Now you can declare a variable as a FileSystemObject. In addition you get access to more objects such as File, Folder, Files and more.
Using the FileSystemObject gives you access to a wide range of features.
The code below demonstrates how to get the count of files which do not exist in the destination and will be copied, using the FileSystemObject.
Private Sub cmdCopy_Click()
Dim fso As New FileSystemObject
Dim sourceFolder As Folder
Dim sourceFile As File
Dim destinationFolder As Folder
Dim filesToBeCopied As Integer
Set sourceFolder = fso.GetFolder("C:\-- Temp --\Source")
Set destinationFolder = fso.GetFolder("C:\-- Temp --\Destination")
filesToBeCopied = 0
' Iterrate through each file in the source folder.
For Each sourceFile In sourceFolder.Files
' Check if the source file exists in the destination folder
If Not (fso.FileExists(destinationFolder + "\" + sourceFile.Name)) Then
filesToBeCopied = filesToBeCopied + 1
End If
Next
End Sub
I have tested the above code and it correctly increments the count of filesToBeCopied to the expected number.

Related

Zip all files in folder except the zip archive itself

I am using this code to zip all files in a folder into a newly created .zip file:
Dim FileNameZip, FolderName
Dim filename As String, DefPath As String
Dim oApp As Object
(defining all paths needed)
'Create empty Zip File
NewZip (FileNameZip)
Set oApp = CreateObject("Shell.Application")
'Copy the files to the compressed folder
oApp.Namespace(FileNameZip).CopyHere oApp.Namespace(FolderName).items
'Keep script waiting until Compressing is done
On Error Resume Next
Do Until oApp.Namespace(FileNameZip).items.Count = oApp.Namespace(FolderName).items.Count
Application.Wait (Now + TimeValue("0:00:01"))
Loop
This works without problems as long as my target folder is different from the folder where my files are.
But I have a problem when I try to take all files from a folder, put them into .zip and have the archive generated in the same folder - it creates the archive and then tries to put it into itself, which of course fails.
I am looking for a way to zip all files from a folder except this one newly created.
I looked here: https://msdn.microsoft.com/en-us/library/office/ff869597.aspx but this looks very Outlook-specific and I have no idea how to apply this to a Windows folder.
Rather than add all files at once, which will include the zip file you create, loop through the files with the FileSystemObject and compare their names against the zip file name before adding to the zip:
Sub AddFilesToZip()
Dim fso As Object, zipFile As Object, objShell As Object
Dim fsoFolder As Object, fsoFile As Object
Dim timerStart As Single
Dim folderPath As String, zipName As String
folderPath = "C:\Users\darre\Desktop\New folder\" ' folder to zip
zipName = "myzipfile.zip" ' name of the zip file
Set fso = CreateObject("Scripting.FileSystemObject") ' create an fso to loop through the files
Set zipFile = fso.CreateTextFile(folderPath & zipName) ' create the zip file
zipFile.WriteLine Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0)
zipFile.Close
Set objShell = CreateObject("Shell.Application")
Set fsoFolder = fso.GetFolder(folderPath)
For Each fsoFile In fsoFolder.Files ' loop through the files...
Debug.Print fsoFile.name
If fsoFile.name <> zipName Then ' and check it's not the zip file before adding them
objShell.Namespace("" & folderPath & zipName).CopyHere fsoFile.Path
timerStart = Timer
Do While Timer < timerStart + 2
Application.StatusBar = "Zipping, please wait..."
DoEvents
Loop
End If
Next
' clean up
Application.StatusBar = ""
Set fsoFile = Nothing
Set fsoFolder = Nothing
Set objShell = Nothing
Set zipFile = Nothing
Set fso = Nothing
MsgBox "Zipped", vbInformation
End Sub
I would create the zip file in the temporary folder and finally move it to the destination folder. Two notes worth mentioning:
1- The approach of looping until the Item counts are the same in the folder and the zip file is risky, because if the zipping fails for an individual item, it results in an infinite loop. For this reason it's preferable to loop as long as the zip file is locked by the shell.
2- I will use early binding with the Shell because late-binding the Shell32.Application seems to have issues on some installations. Add a reference to Microsoft Shell Controls and Automation
Sub compressFolder(folderToCompress As String, targetZip As String)
If Len(Dir(targetZip)) > 0 Then Kill targetZip
' Create a temporary zip file in the temp folder
Dim tempZip As String: tempZip = Environ$("temp") & "\" & "tempzip1234.zip"
CreateObject("Scripting.FileSystemObject").CreateTextFile(tempZip, True).Write _
Chr$(80) & Chr$(75) & Chr$(5) & Chr$(6) & String(18, 0)
' compress the folder into the temporary zip file
With New Shell ' For late binding: With CreateObject("Shell32.Application")
.Namespace(tempZip).CopyHere .Namespace(folderToCompress).Items
End With
' Move the temp zip to target. Loop until the move succeeds. It won't
' succeed until the zip completes because zip file is locked by the shell
On Error Resume Next
Do Until Len(Dir(targetZip)) > 0
Application.Wait Now + TimeSerial(0, 0, 1)
Name tempZip As targetZip
Loop
End Sub
Sub someTest()
compressFolder "C:\SO\SOZip", "C:\SO\SOZip\Test.zip"
End Sub
I found zipping via VBA to be hard to control without third party tools, the below may not be a direct answer but may aid as a solution. The below is an excerpt of the code I used to generate epubs which are not much more than zip files with a different extension. This zipping section never failed in hundreds of runs.
Public Function Zip_Create(ByVal StrFilePath As String) As Boolean
Dim FSO As New FileSystemObject
Dim LngCounter As Long
If Not FSO.FileExists(StrFilePath) Then
'This makes the zip file, note the FilePath also caused issues
'it should be a local file, suggest root of a drive and then use FSO
'to open it
LngCounter = FreeFile
Open StrFilePath For Output As #LngCounter
Print #LngCounter, "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Close #LngCounter
End If
Zip_Create = True
End Function
Public Function Zip_Insert(ByVal StrZipFilePath As String, ByVal StrObject As String) As Boolean
Dim BlnYesNo As Boolean
Dim LngCounter As Long
Dim LngCounter2 As Long
Dim ObjApp As Object
Dim ObjFldrItm As Object
Dim ObjFldrItms As Object
Dim StrContainer As String
Dim StrContainer2 As String
If Procs.Global_IsAPC Then
'Create the zip if needed
If Not FSA.File_Exists(StrZipFilePath) Then
If Not Zip_Create(StrZipFilePath) Then
Exit Function
End If
End If
'Connect to the OS Shell
Set ObjApp = CreateObject("Shell.Application")
'Pause, if it has just been created the next piece of
'code may not see it yet
LngCounter2 = Round(Timer) + 1
Do Until CLng(Timer) > LngCounter2
DoEvents
Loop
'Divide the path and file
StrContainer = Right(StrObject, Len(StrObject) - InStrRev(StrObject, "\"))
StrObject = Left(StrObject, Len(StrObject) - Len(StrContainer))
'Connect to the file (via the path)
Set ObjFldrItm = ObjApp.NameSpace(CVar(StrObject)).Items.Item(CVar(StrContainer))
'Pauses needed to avoid all crashes
LngCounter2 = CLng(Timer) + 1
Do Until CLng(Timer) > LngCounter2
DoEvents
Loop
'If it is a folder then check there are items to copy (so as to not cause and error message
BlnYesNo = True
If ObjFldrItm.IsFolder Then
If ObjFldrItm.GetFolder.Items.Count = 0 Then BlnYesNo = False
End If
If BlnYesNo Then
'Take note of how many items are in the Zip file
'Place item into the Zip file
ObjApp.NameSpace(CVar(StrZipFilePath)).CopyHere ObjFldrItm
'Pause to stop crashes
LngCounter2 = CLng(Timer) + 1
Do Until CLng(Timer) > LngCounter2
DoEvents
Loop
'Be Happy
Zip_Insert = True
End If
Set ObjFldrItm = Nothing
Set ObjApp = Nothing
End If
End Function

VBS to Search for Multiple Files Recursively in C:\Users

I need to recursively search for multiple files through the C:\Users directory tree recursively.
If I find any of the specified files in any of the sub-directories, I want to echo out the full path.
Here is what I have:
Dim fso,folder,files,sFolder,newFolder
Dim arr1
arr1 = Array("myFile1.pdf","myFile2.pdf","myFile3.pdf","nutbag.rtf","whoa.txt")
Set fso = CreateObject("Scripting.FileSystemObject")
sFolder = "C:\Users"
Set folder = fso.GetFolder(sFolder)
Set files = folder.SubFolders
For each folderIdx In files
IF (Instr(folderIdx.Name,"Default") <> 1) Then
If (Instr(folderIdx.Name,"All Users") <> 1) Then
newFolder = sfolder & "\" & folderIdx.Name
CopyUpdater fso.GetFolder(newFolder)
End If
End If
Next
Sub CopyUpdater(fldr)
For Each f In fldr.Files
For Each i in arr1
If LCase(f.Name) = i Then
WScript.echo(f.name)
End If
Next
Next
For Each sf In fldr.SubFolders
CopyUpdater sf
Next
End Sub
If I run it as 'Administrator', I get:
VBScript runtime error: Permission Denied
If I run it as 'Local System' user, I get:
VBScript runtime error: Path not found
If I add, 'On Error Resume Next' to the beginning to suppress the errors, I get nothing back.
I have placed a text file called 'whoa.txt' in numerous locations around the C:\Users sub-dirs.
My suspicion is that it is a Windows permissions thing, but I am unsure.
Thanks much.
First I didn't use your code, it confuses me what you are trying to accomplish.
Next you should run the script in Administrator mode command prompt. This should allow you to check if the file is there.
Then paste code below to a vbs file and cscript it. This code displays all the matched filenames.My idea is that instead of going through all files in any folder for a matching filename, check if those wanted files exists in that folder - this is generally faster as some folders contains hundreds of files if not thousands (check your Temp folder!).
Option Explicit
Const sRootFolder = "C:\Users"
Dim fso
Dim arr1
Dim oDict ' Key: Full filename, Item: Filename
Main
Sub Main
arr1 = Array("myFile1.pdf", "myFile2.pdf", "myFile3.pdf", "nutbag.rtf", "whoa.txt")
Set fso = CreateObject("Scripting.FileSystemObject")
Set oDict = CreateObject("Scripting.Dictionary")
' Call Recursive Sub
FindWantedFiles(sRootFolder)
' Display All Findings from Dictionary object
DisplayFindings
Set fso = Nothing
Set oDict = Nothing
End Sub
Sub FindWantedFiles(sFolder)
On Error Resume Next
Dim oFDR, oItem
' Check if wanted files are in this folder
For Each oItem In arr1
If fso.FileExists(sFolder & "\" & oItem) Then
oDict.Add sFolder & "\" & oItem, oItem
End If
Next
' Recurse into it's sub folders
For Each oFDR In fso.GetFolder(sFolder).SubFolders
FindWantedFiles oFDR.Path
Next
End Sub
Sub DisplayFindings()
Dim oKeys, oKey
oKeys = oDict.Keys
For Each oKey In oKeys
wscript.echo oKey
Next
End Sub

Error on merging ppt files using visual basic scripting

I am a newbie to visual basic scripting..
I was trying to combine multiple ppt files into a single ppt using the following .vbs code.
it was supposed to create a new ppt called merged.ppt from all the ppts stored in a subfolder called PPTmerge.
But on executing I get error on line:
Set out = Application.Presentations.Open(f)
Can someone help me please...!
Const PPTMERGE_FILE = "Merged.ppt"
Const PPTMERGE_FOLDER = ".\PPTmerge"
Dim Application
Set Application=CreateObject("PowerPoint.Application")
Application.Visible = True 'must do this for merge to work
Dim first 'to open power point only once
first = True
Dim fs
Set fs=CreateObject("Scripting.FileSystemObject")
Dim folder
Set folder = fs.GetFolder(PPTMERGE_FOLDER)
Dim out
Dim f
Dim ff
For Each ff in folder.Files
f = PPTMERGE_FOLDER + "\" + ff.Name
If first Then
Dim p
Set out = Application.Presentations.Open(f)
out.SaveAs PPTMERGE_FOLDER + "\..\" + PPTMERGE_FILE
first = False
Else
out.Slides.InsertFromFile f, out.Slides.Count
End If
Next
If Not first Then
out.Save
out.SlideShowSettings.Run
'out.Close
End If
Set folder = Nothing
Set out = Nothing
Set folder = Nothing
'Application.Quit
Set Application = Nothing
You haven't specified the full path name.
Try const pptmerge_folder = "full path name here"
The code on line 2.

VB Script to replace text by using folder structure

I am very new to VB Script. I am in need of VB Script to replace the specific text
Below is my file directory
E:\TEST\98\6549871\1959893\HTML
E:\TEST\98\6549871\1959793\HTML
E:\TEST\98\6549876\1959863\HTML
E:\TEST\96\6749473\6959895\HTML
E:\TEST\99\2548878\5959893\HTML
etc.,
Where in each HTML sub-folder, test.html and img.html page will contain. In that html pages I want to find the text ="img/ and needs to replace with ="/image/98/6549871/1959893/HTML/img/ where in ="/image/ is common for all files and remaining values are as per folder structure (i.e. 1st level folder name, 2nd level folder name, 3rd level folder name and 4th level folder name)
For every individual file I need to do like above, and taking too much time to do this activity.
Can any body help me on this to replace all ="img/ in a single shot base on the folder directory.
Thanks in advance
Something like this..not tested, but shoudl point you in the right direction
Option Explicit
Dim fileCount
Sub ProcessSubDirectory( ByVal directory)
On Error Resume Next
Dim fso
Dim dir
Dim folder
Dim file
Set fso = CreateObject("Scripting.FileSystemObject")
Set dir = fso.GetFolder(directory)
If Err.Number <> 0 THen
MsgBox "Failed to open dir ( " & directory & " )"
Exit Sub
End If
On Error Goto 0
For Each file in dir.Files
Call HandleFileFix( file.Path )
Next
For Each folder in dir.SubFolders
Call ProcessSubDirectory( folder.Path )
Next
Set fso = Nothing
End Sub
Sub HandleFileFix( ByVal file)
Dim fso
Dim f
Dim fo
Dim contents
DIm path
Set fso = CreateObject("Scripting.FileSystemObject")
Set fo = fso.GetFile( file )
Set f = fso.OpenTextFile( file, 1 )
path = fo.Path
path = Replace( path, fo.Drive, "")
path = Replace( path, fo.Name, "")
path = Replace( path, "\", "/")
If f.AtEndOfStream = false then
contents = f.ReadAll
End If
f.Close
Set f = Nothing
contents = Replace( contents, "='img/", "='" & path & "/img/")
' write file back to disk
Set f = fso.OpenTextFile( file, 2 )
f.Write contents
f.Close
fileCount = fileCount + 1
Set f = Nothing
End Sub
fileCount = 0
Call ProcessSubDirectory( "D:\TEST\" )
MsgBox "done (" & CStr(fileCount) & ")"

How do I save an entire VB6 project to a new folder? Modules and all

How do I save an entire VB6 project to a new folder? Modules and all. I'm in a position where I need to work with some old VB6 projects. I'd like to save them to a new folder but when I save the project, all that is saved is the vbp file. No modules, no frm files. I want to be able to save all the info to a single folder without moving each BAS file one at a time. Is this even possible?
Addition: The first 2 replies make good sense. But my problem is that the BAS modules seem to be scattered all over the place. Making Windows Explorer do the work a bit tricky. If I have to I will but was looking for an easier way.
Thanks
Given the new "addition" to the question:
Move the VBP and the files in Windows Explorer to a completely new directory.
Open the VBP in a text editor and change any absolute paths to relative paths. VBP files are simple text files, and the format is even documented in the VB6 manual.
Here's an example. This evil VBP below has many absolute paths
Type=Exe
Form=c:\who\knows\where\B_Form.frm
Module=CModule; z:\magic\mapped\network\drive\heehee\C_Module.bas
Class=DClass; x:\personal\usb\stick\D_Class.cls
It would be changed to this benign VBP, which references local copies of the files. You can use relative paths for subdirectories.
Type=Exe
Form=B_Form.frm
Module=CModule; C_Module.bas
Class=DClass; subdirectory\D_Class.cls
If you mean from within Visual Studio, I don't think you can except by doing Save As for each file...
But the simpler approach is to just use Windows Explorer and copy the whole folder structure for the solution into another folder, (or do a recursive "Get" from your source code repository to a different local destination), and then open the solution or project file in the new location... The pointers in the project file that tell Visual Studio where 5all the individual source code and other files are located are generally all stored as relative paths, relative to the folder that the project file is in...
It's been a while since I used VB6, but I'd be tempted to move them using Windows Explorer, then manually edit the VBP file to point to the new locations afterwards. If I remember right, relative paths are fine in the VBP, so you may not even need to manke any changes.
Unbind from source control, if capable/appropriate.
Check into source control as a brand new solution/project
Recursive 'get' from your SCM into a new directory.
There's your new copy.
Create a VB6 Add-in. You can download it from: http://pan.baidu.com/s/1CXO3k
Or you can use below code to create your own.
Option Explicit
Public VBInstance As VBIDE.VBE
Public Connect As Connect
Private Sub CancelButton_Click()
Connect.Hide
End Sub
Private Sub OKButton_Click()
On Error Resume Next
Dim strProject As String
Dim strPath As String
Dim strPath2 As String
Dim strFile As String
Dim strPrjFile As String
Dim rst As VbMsgBoxResult
Dim m, n As Long
Dim col2 As Collection, col As Collection
Dim vbCom As VBComponent
Dim fso As FileSystemObject
Dim ts As TextStream
Dim f1 As String, f2 As String
strProject = Me.VBInstance.ActiveVBProject.FileName
strPath = ParseFileName(strProject, strPrjFile)
strPath2 = setFolder
If strPath = "" Or strPath = strPath2 Then
MsgBox "target folder is invalid or same as the project folder. Can't copy."
Exit Sub
End If
Set col2 = New Collection
Set col = New Collection
Set fso = New FileSystemObject
Set ts = fso.CreateTextFile(strPath2 & "\wemeet.log", False)
For m = Me.VBInstance.ActiveVBProject.VBComponents.Count To 1 Step -1
Set vbCom = Me.VBInstance.ActiveVBProject.VBComponents(m)
For n = 1 To vbCom.FileCount
f1 = vbCom.FileNames(n)
ParseFileName f1, strFile
f2 = strPath2 & "\" & strFile
fso.CopyFile f1, f2
col.Add f1
col2.Add f2
ts.WriteLine "" & Now() & " [Move]: " & f1
ts.WriteLine "" & Now() & " [To ]: " & f2
ts.WriteBlankLines 1
Next
Me.VBInstance.ActiveVBProject.VBComponents.Remove vbCom
Next
For m = 1 To col2.Count
Me.VBInstance.ActiveVBProject.VBComponents.AddFile col2.Item(m)
ts.WriteLine "" & Now() & " [Add]: " & col2.Item(m)
ts.WriteBlankLines 1
Next
Me.VBInstance.ActiveVBProject.SaveAs strPath2 & "\" & strPrjFile
ts.WriteLine "" & Now() & " [SaveAs]: " & strPath2 & "\" & strPrjFile
ts.WriteBlankLines 1
ts.Close
fso.OpenTextFile strPath2 & "\wemeet.log"
Set fso = Nothing
Set col = Nothing
Set col2 = Nothing
Set vbCom = Nothing
Connect.Hide
End Sub
Private Function ParseFileName(ByVal sPath As String, ByRef sFile As String) As String
Dim fso As New FileSystemObject
If fso.FileExists(sPath) Then
ParseFileName = fso.GetParentFolderName(sPath)
sFile = fso.GetFileName(sPath)
Else
ParseFileName = ""
sFile = ""
End If
Set fso = Nothing
End Function
Private Function setFolder() As String
Dim objDlg As Object
Dim objStartFolder As Object
Set objDlg = CreateObject("Shell.Application")
Set objStartFolder = objDlg.BrowseForFolder(&H0, "Select a folder", &H10 + &H1)
If InStr(1, TypeName(objStartFolder), "Folder") > 0 Then
setFolder = objStartFolder.ParentFolder.ParseName(objStartFolder.Title).Path
End If
Set objDlg = Nothing
End Function

Resources