I've created this macro in excel that enables a user to copy multiple files from one folder to another. The macros works, it does what it's supposed to do. I just want to add some additional functions to it and I'm not able to make it work. These are the few things that I want to add:
1-check if a file already exists in the destination folder and ask if the user wants to overwrite yes/no. If yes overwrite, If no skip to the next file to be copied.
2-If a file(s) is missing in the source folder the ErrHandler copies the name(s) of the missing file(s) from column A to the M column. The way I did this it works, but it's not how I want it to work. What I want is, if the file name in cell A3, A7, A10 are missing. Those names should be copied to M1, M2, M3 and so on. Instead of copying them to M3, M7, M10
I'm also having 2 other problems:
1-The ErrHandler messagebox it appears more than it should. Once the copy is completed it still shows it 2 more times.
2-The macro it rewrites how the file name is written. For example if the original file name is written in lower case and in a cell I write it in upper case. Once the file is copied it will be written in upper case. I want to keep the original name.
Dim r As Long
Dim SourcePath As String
Dim dstPath As String
Dim myFile As String
SourcePath = Range("F1")
dstPath = Range("F3")
On Error GoTo ErrHandler
For r = 1 To 3000
myFile = Range("A" & r)
FileCopy SourcePath & "\" & myFile, dstPath & "\" & myFile
If Range("A" & r) = "" Then
Exit For
End If
Next r
MsgBox "The file(s) can found in: " & vbNewLine & dstPath, , "COPY COMPLETED"
ErrHandler:
MsgBox "Copy error: " & SourcePath & "\" & myFile & vbNewLine & vbNewLine & _
"File could not be found in the source folder", , "MISSING FILE(S)"
Range("A" & r).Copy Range("M" & r)
Resume Next
End Sub
For the 1st issue, you just need to add an Exit Sub before the ErrHandler: label.
For the second issue, you could try something like:
myFile = dir(SourcePath & "\" & Range("A" & r))
FileCopy SourcePath & "\" & myFile, dstPath & "\" & myFile
This way myFile will contain the original source case.
Related
I am trying to figure out how to check that the layout (not the full content) of a CSV file is the same of that in the preceding month (or, if that file doesn't exist, the last available CSV file).
Often companies change the format/layout of their CSV extracts, so I want my code to automatically detect any changes (new columns added, changing order of columns, etc).
Please let me know if you have an idea of how this could be achieved!
Thanks in advance!
Please, try the next code. It assumes that the csv to be compared is comma separated and ending lines are vbCrLf:
Private Sub CheckCSVfile()
Dim ws As Worksheet, strFile As String, ans As VbMsgBoxResult, sep As String
Dim arrRef, arrCSV, cols, i As Long, strProbl As String
ans = MsgBox("Is the active sheet the one you wan to use as reference to compare the CSV file structure?" & vbCrLf & _
"If this is the situation, please press ""Yes""!", vbYesNo, "Confirm the active sheet as reference")
If ans <> vbYes Then Exit Sub
Set ws = ActiveSheet
'Put the first sheet row values in an array (2D array):
arrRef = ws.Range(ws.cells(1, 1), ws.cells(1, ws.cells(1, ws.Columns.count).End(xlToLeft).Column)).value
''Browse for the .csv file to be checked:
strFile = Application.GetOpenFilename("Text Files (*.csv),*.csv", , "Please select the csv file to be checked.")
If strFile = "False" Then Exit Sub
'Put the content of the csv file in an array (split by the line ending separator). If not vbCrLf, use the appropriate one:
arrCSV = Split(CreateObject("Scripting.FileSystemObject").OpenTextFile(strFile, 1).ReadAll, vbCrLf)
sep = "," 'the csv file separator. Use here the correct one if not comma
cols = Split(arrCSV(0), sep) 'number of columns of the first csv file row (zero based array)
If UBound(cols) + 1 <> UBound(arrRef, 2) Then '+ 1 for the first array because it is of 0 based type
strProbl = strProbl & "The number of columns in the new csv file is different (" & UBound(cols) & " against " & UBound(arrRef) & ")." & vbCrLf
End If
'Comparing each header:
For i = 0 To UBound(arrRef, 2) - 1
If UCase(arrRef(1, i + 1)) <> UCase(cols(i)) Then
strProbl = strProbl & "The value in the column " & i + 1 & " is different (" & cols(i) & " against " & arrRef(1, i + 1) & ")" & vbCrLf
End If
Next i
Stop
If strProbl <> "" Then
MsgBox "The new csv file has a different structure: " & vbCrLf & vbCrLf & strProbl, vbCritical, "Structure problems..."
Else
MsgBox "The both files structure is the same!", vbInformation, "No any structure problem"
End If
End Sub
You must firstly open and activate the sheet of the previous csv file (to be used as reference) and then run the above code.
Please, send some feedback after testing it...
I have a macro that created a folder by data within a pathway, and I want a cut of a manager roster to be saved in that folder. Since the folder name varies, this needs to be dynamic.
I want it to go something like this:
Dim sPath As String
sPath = "M:\mgr1_TCR_Reports\"
If Len(Dir(sPath & "_" & Format(Date, "mm_dd_yyyy"), vbDirectory)) = 0 Then
MkDir (sPath & "_" & Format(Date, "mm_dd_yyyy"))
End If
End Sub
and saving this like:
.SaveAs Filename:="M:\mgr1_TCR_Reports\" & "_" & Format(Date, "mm_dd_yyyy_") & "\" & Manager, FileFormat:=xlOpenXMLWorkbook, Password:=""
.Close
But I keep getting a runtime 1004: document not saved on ^^^ the second line of code I provided.
Any idea what's going on?
I am trying to rename a file using based on a list in excel such that column A has old file name and Column B has new file name. It worked for some files but its not renaming some files.
THis is the macro that I used:
Sub RenameFiles()
Dim xDir As String
Dim xFile As String
Dim xRow As Long
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
If .Show = -1 Then
xDir = .SelectedItems(1)
xFile = Dir(xDir & Application.PathSeparator & "*")
Do Until xFile = ""
xRow = 0
On Error Resume Next
xRow = Application.Match(xFile, Range("A:A"), 0)
If xRow > 0 Then
Name xDir & Application.PathSeparator & xFile As _
xDir & Application.PathSeparator & Cells(xRow, "B").Value
End If
xFile = Dir
Loop
End If
End With
End Sub
Here is a screenshot of my excel file names:
Can anyone tell me whats the issue here ?
Any help would be appreciated. Thanks in advance
I have undergone with similar requirement. I solved it using bit different approach.
Here's is exactly what I did:
1) I create Excel similar to yours.
2) Column A will have Old Filename
3) Column B will have New Filename
4) I will write DOS Command in Column C, using Excel Formula.
Once done, I will copy the data from Column C and create a BATCH File out of it. Once I run the BATCH File, it gets my work done. This formula assumes that you don't have any special characters.
Sharing the formula that I wrote in Column C:
="REN " & CHAR("34") & A2 & CHAR(34) & " " & CHAR(34) & B2 & "" & CHAR(34)
And also adding screenshot of my Excel as reference.
I am using this code down below to use a VLOOKUP in another file that you select using the GetOpenFilename. I want shtName to be the name of the sheet in the file that you select, but whenever I step through it, it is always the name of the sheet that I am working in and putting the VLOOKUP in.
I have shtName in my VLOOKUP and it doesn't show anything when I step through it. X shows the filename and path, but shtName right after shows nothing. But my VLOOKUP ends up working anyway and it puts the sheet in the formula.
Why is that? I want to be able to do it myself and so I know I get the sheet name from the file you are selecting.
Dim iRet As Integer
Dim strPrompt As String
Dim strTitle As String
' Promt
strPrompt = "Please select the last Kronos Full File before the dates of this HCM Report." & vbCrLf & _
"This will be used to find the Old Position, Org Unit, and Old Cost Center." & vbCrLf & _
"For example, if the date of this report is 7-28-17 thru 8-25-17, the closest Kronos Full File you would want to use is 7-27-17."
' Dialog's Title
strTitle = "Last Kronos Full File for Old Positions"
'Display MessageBox
iRet = MsgBox(strPrompt, vbOK, strTitle)
Dim LR As Long
Dim X As String
Dim lNewBracketLocation As Long
X = Application.GetOpenFilename( _
FileFilter:="Excel Files (*.xls*),*.xls*", _
Title:="Choose the Kronos Full File.", MultiSelect:=False)
MsgBox "You selected " & X
'Find the last instance in the string of the path separator "\"
lNewBracketLocation = InStrRev(X, Application.PathSeparator)
'Edit the string to suit the VLOOKUP formula - insert "["
X = Left$(X, lNewBracketLocation) & "[" & Right$(X, Len(X) - lNewBracketLocation)
shtName = ActiveWorkbook.Worksheets(1).name
LR = Range("E" & Rows.Count).End(xlUp).Row
Range("T2").Formula = "=VLOOKUP($E2,'" & X & "]shtName'!$B$1:$AP$99999,15,0)"
Stop
Range("T2").AutoFill Destination:=Range("T2:T" & Range("E" & Rows.Count).End(xlUp).Row)
Stop
Range("T2:T" & Range("E" & Rows.Count).End(xlUp).Row).Select
Stop
Range("U2").Formula = "=VLOOKUP($E2,'" & X & "]shtName'!$B$1:$AP$99999,41,0)"
Range("U2").AutoFill Destination:=Range("U2:U" & Range("E" & Rows.Count).End(xlUp).Row)
Range("U2:U" & Range("E" & Rows.Count).End(xlUp).Row).Select
Range("V2").Formula = "=VLOOKUP($E2,'" & X & "]shtName'!$B$1:$AP$99999,18,0)"
Range("V2").AutoFill Destination:=Range("V2:V" & Range("E" & Rows.Count).End(xlUp).Row)
Range("V2:V" & Range("E" & Rows.Count).End(xlUp).Row).Select
Cells.Select
Cells.EntireColumn.AutoFit
Something like the following should give you the worksheets name out of a file
Dim wbk As Workbook
Set wbk = Workbooks.Open(Filename:="YOUR_FILE_PATH", ReadOnly:=True)
Dim shtName As String
shtName = wbk.Worksheets(1).Name
wbk.Close
Note: We can open the workbook in read only mode if we don't plan to change anything.
Additionally I recommend (for a good code following good practices):
Always specify a worksheet.
Eg for every Range("") like Worksheets("YourSheetName").Range("")
Or use With statements:
With Worksheets("YourSheetName")
.Range("A1").Value = 5 'recognize the starting full stop referring to the with statement
End With
Same for every Rows, Columns, Cells, etc.
Avoid using .Select, .Activate and Selection. at all.
(there are many tutorials out there in the Internet how to avoid them).
Use Option Explicit and declare all your variables before use.
(avoids many issues, especially typos).
I am currently having an error with a vba script, tried to fix it but still gives an error as listed in the title.
The aim of the script is to copy file names based on an input form a worksheet and then copy them to a destination saving them with the current date in the name.
Set FSO = CreateObject("scripting.filesystemobject")
FILE = Sheet1.Range("G3").Value
FILE2 = Sheet1.Range("G4").Value
SourceFile = Source & "\" & FILE & ".xls"
DestFile = DestPath & "\" & FILE & " " & ShortDate & ".csv"
SourceFile2 = Source & "\" & FILE2 & ".xls"
DestFile2 = DestPath & "\" & FILE2 & " " & ShortDate & ".csv"
'Setsup Flag File
Dim oFile As Object
Set oFile = FSO.CreateTextFile(DestPath & "\OIS.FLAG")
oFile.WriteLine Format(Sheets("Sheet1").Range("C7").Value, "yyyy/mm/dd")
oFile.Close
FSO.CopyFile SourceFile, DestFile
FSO.CopyFile SourceFile2, DestFile2
Source is just set to "C:\Users\Data"
DestPath is just "C:\Users\updates"
When I run the script the first copy works, so SourceFile is copied, but then the runtime error occurs for the second one SourceFile2, but I've checked multiple times and the SourceFile2 Exists...
Any Tips, or something I'm missing? Also Checked other similar threads, and it's not because the string is too long?
If I input the whole name for SourceFile2 i.e "C:\Users\Data\file2.xls" then it works but I've checked the syntax a million times and seems to be fine, maybe a fresh pair of eyes will help, any suggestions would be massively appreciated :)