VBA - Skip corrupted files - excel

I copied code from another site that opens every Excel file on a path and sets the password to "".
I have 480 Excel files on that path, and the code stops whenever it encounters a corrupted file.
Is there a way to identify every file that is corrupted?
Is there a way to avoid corrupted files?
Sub RemovePasswords()
Dim xlBook As Workbook
Dim strFilename As String
Const fPath As String = "C:\Path\" 'The folder to process, must end with "\"
Const strPassword As String = "openpassword" 'case sensitive
Const strEditPassword As String = "editpassword" 'If no password use ""
strFilename = Dir$(fPath & "*.xls") 'will open xls & xlsx etc
While Len(strFilename) <> 0
Application.DisplayAlerts = False
Set xlBook = Workbooks.Open(FileName:=fPath & strFilename, _
Password:=strPassword, _
WriteResPassword:=strEditPassword)
xlBook.SaveAs FileName:=fPath & strFilename, _
Password:="", _
WriteResPassword:="", _
CreateBackup:=True
xlBook.Close 0
Application.DisplayAlerts = True
strFilename = Dir$()
Wend
End Sub
On the other hand, whenever the code encounters a corrupted file it just stops and doesn't let me know which file is corrupted.
I know that there is a way to put a "if" to skip this errors, but I don't know how to do it.

Please, try the next adapted code:
Sub RemovePasswords()
Dim xlBook As Workbook, strFilename As String
Const fPath As String = "C:\Path\" 'The folder to process, must end with "\"
Const strPassword As String = "openpassword" 'case sensitive
Const strEditPassword As String = "editpassword" 'If no password use ""
strFilename = dir$(fPath & "*.xls") 'will open xls & xlsx etc
While Len(strFilename) <> 0
On Error Resume Next 'skip the error, if the case
Set xlBook = Workbooks.Open(fileName:=fPath & strFilename, _
password:=strPassword, _
WriteResPassword:=strEditPassword)
If err.Number = 0 Then 'if no error:
Application.DisplayAlerts = False
xlBook.saveas fileName:=fPath & strFilename, _
password:="", _
WriteResPassword:="", _
CreateBackup:=True
xlBook.Close 0
Application.DisplayAlerts = True
End If
On Error GoTo 0 'restart raising errors when the case
strFilename = dir$()
Wend
End Sub

I would change the code suggested by FaneDuru a little, in order to comply to your first demand. This code will output corrupt filenames in the debug panel.
Sub RemovePasswords()
Dim xlBook As Workbook
Dim strFilename As String
Const fPath As String = "C:\Path\" 'The folder to process, must end with "\"
Const strPassword As String = "openpassword" 'case sensitive
Const strEditPassword As String = "editpassword" 'If no password use ""
strFilename = Dir$(fPath & "*.xls") 'will open xls & xlsx etc
Application.DisplayAlerts = False
On Error Resume Next
While Len(strFilename) <> 0
Set xlBook = Workbooks.Open(FileName:=fPath & strFilename, _
Password:=strPassword, WriteResPassword:=strEditPassword)
If err.Number = 0 Then
xlBook.SaveAs FileName:=fPath & strFilename, _
Password:="", WriteResPassword:="", CreateBackup:=True
xlBook.Close 0
Else
Debug.Print strFilename 'This will output corrupt filenames in the debug pane
err.Clear
End If
strFilename = Dir$()
Wend
On Error GoTo 0
Application.DisplayAlerts = True
End Sub

Related

Excel VBA - Opened workbook with wildcard or partial match cannot save as copy

I would like to open a workbook using a wildcard or partial name match and save a copy with another name.
However, there is an error -
Always at the " Workbooks(myFolderPath & "" & MyFileName).SaveCopyAs Filename:="NEW NAME.xlsx" " line
Here is my code:
Sub GENERATE()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'If workbook name like "Report Due" then open, if not already opened
Dim MyFileName As Variant
Dim myFolderPath As String
myFolderPath = Application.DefaultFilePath
MyFileName = Dir(myFolderPath & "\" & "Report Due*.xlsx")
If MyFileName <> "" Then
Workbooks.Open (myFolderPath & "\" & MyFileName)
End If
Workbooks(myFolderPath & "\" & MyFileName).SaveCopyAs Filename:="NEW NAME.xlsx"
Workbooks(myFolderPath & "\" & MyFileName).Close SaveChanges:=False
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
I'd be happy to see what's wrong! Many thanks!
Set a reference to the workbook when you open it, then you shouldn't need to use it's name to reference when saving the copy.
Option Explicit
Sub GENERATE()
Dim wb As Workbook
Dim MyFileName As Variant
Dim myFolderPath As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'If workbook name like "Report Due" then open, if not already opened
myFolderPath = Application.DefaultFilePath
MyFileName = Dir(myFolderPath & "\" & "Report Due*.xlsx")
If MyFileName <> "" Then
Set wb = Workbooks.Open(myFolderPath & "\" & MyFileName)
wb.SaveCopyAs Filename:="NEW NAME.xlsx"
wb.Close SaveChanges:=False
End If
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

I have 100's of password protected excel workbooks (2016) in a specific file location, there are 2 passwords I have to unlock them

The below code works for removing 1 known password from multiple excel documents, however if a file in the folder hasn't got the correct password the code will not continue looping through the files left. There are 2 known passwords '191034' and '211034', which cover all the password protected documents in the folder. Is it possible to have 1 piece of code that can loop through the files testing both passwords or will I need to edit the below code so that it will continue looping if password is incorrect and then run a separate code with the other password?
The code:
Sub RemovePasswords()
Dim xlBook As Workbook
Dim strFilename As String
Const fPath As String = "C:\Users\ha.smith\Documents\Excel Test\Test Files\CRU\" 'The folder to process, must end with "\"
Const strPassword As String = 211034 'case sensitive
Const strEditPassword As String = "" 'If no password use ""
strFilename = Dir$(fPath & "*.xls") 'will open xls & xlsx etc
While Len(strFilename) <> 0
Application.DisplayAlerts = False
Set xlBook = Workbooks.Open(FileName:=fPath & strFilename, _
Password:=strPassword, _
WriteResPassword:=strEditPassword)
xlBook.SaveAs FileName:=fPath & strFilename, _
Password:="", _
WriteResPassword:="", _
CreateBackup:=False
xlBook.Close 0
Application.DisplayAlerts = True
strFilename = Dir$()
Wend
End Sub
You just need to give it a list of passwords and try them all. If one fails try another.
Option Explicit
Public Sub RemovePasswords()
Dim PasswordList() As Variant
PasswordList = Array("191034", "211034") ' list your passwords
Const strEditPassword As String = "" 'If no password use ""
Const fPath As String = "C:\Temp\" 'The folder to process, must end with "\"
Dim strFilename As String
strFilename = Dir$(fPath & "*.xls") 'will open xls & xlsx etc
Do While Len(strFilename) <> 0
Application.DisplayAlerts = False
Dim strPassword As Variant
For Each strPassword In PasswordList ' loop through password list and try them all
On Error Resume Next ' prevent error if wrong password is used
Dim xlBook As Workbook
Set xlBook = Workbooks.Open(Filename:=fPath & strFilename, _
Password:=strPassword, _
WriteResPassword:=strEditPassword)
If Err.Number = 0 Then ' if password was correct save the file
On Error GoTo 0
xlBook.SaveAs Filename:=fPath & strFilename, _
Password:="", _
WriteResPassword:="", _
CreateBackup:=False
xlBook.Close 0
Exit For ' stop trying other passwords if the correct password was found.
End If
On Error GoTo 0
Next strPassword
Application.DisplayAlerts = True
strFilename = Dir$()
Loop
End Sub

excel vba code to check for a folder if it exists, if not create a folder

I am a newbie in excel vba coding and trying to create pdf of a excel sheet range. My code works well in windows OS but somehow it doesn't work in Mac OS. The Code is as below:
`
Sub GeneratePDF()
Dim wsA As Worksheet
Dim wbA As Workbook
Dim strTime As String
Dim strName As String
Dim strPath As String
Dim strFile As String
Dim strPathFile As String
Dim myFile As Variant
Dim VelleName As String
Dim SelectedRange As Range
With ThisWorkbook.Worksheets("modulo")
.Activate
.Range(.Cells(1, 1), .Cells(33, 10)).Select
Selection.Name = "SelectedRange"
End With
On Error GoTo errHandler
Set wbA = ActiveWorkbook
Set wsA = ActiveWorkbook.Worksheets("modulo")
strTime = Format(Now(), "ddmmyyyy\_hhmm")
'get active workbook folder, if saved
strPath = wbA.Path
If strPath = "" Then
strPath = Application.DefaultFilePath
End If
strPath = strPath & "\"
VelleName = ThisWorkbook.Worksheets("database").Range("B" & Desiredrow) & "_" & ThisWorkbook.Worksheets("database").Range("C" & Desiredrow)
'replace spaces and periods in sheet name
strName = Replace(VelleName, " ", "_")
strName = Replace(strName, ".", "_")
strName = Replace(strName, "-", "_")
strName = Replace(strName, "/", "_")
'create default name for savng file
strFile = strName & "_" & strTime & ".pdf"
strPathFile = strName & "_" & strTime
' select folder for file
If Dir(strPath & Application.PathSeparator & "forme", vbDirectory) = "" Then '<== check if folder exists but its not detecting even though i had created a folder there.
MkDir (ThisWorkbook.Path & Application.PathSeparator & "forme") '<== Create Folder and its not working for Mac OS.
End If
myFile = ThisWorkbook.Path & Application.PathSeparator & "forme" & Application.PathSeparator & strPathFile
'export to PDF if a folder was selected
If myFile <> "False" Then
With wsA.PageSetup
.Orientation = xlPortrait
.PrintArea = "SelectedRange"
.Zoom = False
.FitToPagesTall = 1
.FitToPagesWide = 1
End With
wsA.ExportAsFixedFormat _
Type:=xlTypePDF, _
Filename:=myFile, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=False
MsgBox "Il file pdf รจ stato creato: " _
& vbCrLf _
& myFile
End If
exitHandler:
Exit Sub
errHandler:
MsgBox "Impossibile creare il file pdf"
Resume exitHandler
End Sub
`
I have tried searching a lot on internet but havent found any source which specifically teaches vba coding in Mac OS. Moreover, i got only one link https://macexcel.com/examples/filesandfolders/makefolder/ but i dont think it would work as it should be only one line of command and the biggest issue i dont have Mac OS available now. So can somebody test my code change my command to make it compatible it with Mac OS
I used to use this code and also add to check file exist
'Only Change code Here
Sub Verify()
Dim myPath As String
myPath = "C:\abc" '<--------This line
If Not PathExist(myPath) Then MkDir (myPath)
End Sub
Private Function PathExist(path_ As String) As Boolean
On Error GoTo ErrNotExist
Call ChDir(path_)
PathExist = True
Exit Function
ErrNotExist:
PathExist = False
End Function
Private Function FileExist(filePath_ As String) As Boolean
FileExist = Len(Dir(filePath_)) <> 0
End Function

Saving specific named worksheets in workbook based on criteria using VBA

I am writing a function to take all the worksheets labeled "STORE #01" and create separate files for reach store that contain two tabs:
1 - The same "Compare Depts" sheet which all files will have
2 - The unique sheet associated with that store
Files must be stored as Store_01_City.xls.
When I run the macro, I do not see any files created. Also, the workbook I am running the macro in is password protected but I have entered the password obviously.
Sub SplitBook()
Dim xPath As String
Dim FilePath As String
xPath = Application.ThisWorkbook.Path
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each xWs In ThisWorkbook.Worksheets
If InStr(xWs.Name, "Store") <> 0 Then
Dim WB As Workbook
Set WB = xWs.Application.Workbooks.Add
ThisWorkbook.Sheets("Compare Depts").Copy Before:=WB.Sheets(1)
Sheets(xWs.Name).Copy Before:=WB.Sheets(2)
FilePath = "\" & Left(xWs.Name, 5) & "_" & Right(xWs.Name, 2)
& "_" & Application.ThisWorkbook.VLookup(Right(xWs.Name, 2),
ThisWorkbook.Sheets("Table").Range(H3, K100), 4)
WB.SaveAs Filename:=xPath & FilePath & ".xls"
WB.Close SaveChanges:=False
Set WB = Nothing
End If
Next xWs
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
I found a way to by-pass the password for the old Macro and modified it. This also works, but is much slower than your function #Thomas Inzina
Sub ProcessStoreDistribution()
Application.DisplayAlerts = False
For Each c In ThisWorkbook.Sheets("Table").Range("StoreList")
Process c
Next c
Application.DisplayAlerts = True
MsgBox prompt:="Process Completed"
End Sub
Sub Process(ByVal c As Integer)
Dim wb As Workbook
ThisWorkbook.Activate
StoreNum = WorksheetFunction.VLookup(c, Sheets("Table").Range("StoreTable"), 2)
StoreName = WorksheetFunction.Proper(WorksheetFunction.VLookup(c, Sheets("Table").Range("StoreTable"), 5))
myST = "STORE #" & Right(StoreNum, 2)
mySTN = WorksheetFunction.Substitute(WorksheetFunction.Substitute(ActiveWorkbook.FullName, "PPE", "(PPE"), ".xlsm", ") Store Distribution Files")
Application.DisplayAlerts = False
Sheets(Array("COMPARE DEPTS", myST)).Select
Sheets(Array("COMPARE DEPTS", myST)).Copy
Set wb = ActiveWorkbook
Sheets(Array("COMPARE DEPTS", myST)).Select
Cells.Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Sheets("COMPARE DEPTS").Activate
Application.CutCopyMode = False
If Len(Dir(mySTN, vbDirectory)) = 0 Then
MkDir mySTN
End If
mySTN = mySTN & "\STORE_" & StoreNum & "_" & StoreName & ".xls"
wb.SaveAs Filename:=mySTN _
, FileFormat:=xlExcel8, Password:="", WriteResPassword:="", _
ReadOnlyRecommended:=False, CreateBackup:=False
ActiveWindow.Close
ThisWorkbook.Activate
Application.DisplayAlerts = True
End Sub
Updated
File picker added to get the external workbook.
I had to add a parameter to the VLookup and cast Right(.Name, 2) to an int. Hopefully it's smooth sailing from here.
Option Explicit
Sub ProcessExternalWorkBook()
Dim ExternalFilePath As String, password As String
ExternalFilePath = GetExcelWorkBookPath
If Len(ExternalFilePath) Then
password = Application.InputBox(Prompt:="Enter Password applicable", Type:=2)
SplitBook ExternalFilePath, password
End If
End Sub
Function GetExcelWorkBookPath() As String
With Application.FileDialog(msoFileDialogFilePicker)
.Title = "Select a Excel WorkBook"
.AllowMultiSelect = False
.InitialFileName = "Path"
.Filters.Clear
.Filters.Add "Excel WorkBooks", "*.xls, *.xlsx, *.xlsm, *.xlsb"
If .Show = -1 Then
GetExcelWorkBookPath = .SelectedItems(1)
End If
End With
End Function
Sub SplitBook(ExternalFilePath As String, Optional sPassword As String)
Dim FilePath As String
Dim wb As Workbook, wbSource As Workbook
Dim xWs As Worksheet
Dim Secured
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set wbSource = Application.Workbooks.Open(Filename:=ExternalFilePath, ReadOnly:=True, password:=sPassword)
For Each xWs In wbSource.Worksheets
If InStr(xWs.Name, "Store") <> 0 Then
Debug.Print xWs.Name & ": was processed"
FilePath = getNewFilePath(xWs)
If Len(FilePath) Then
Sheets(Array("Compare Depts", xWs.Name)).Copy
Set wb = ActiveWorkbook
wb.SaveAs Filename:=FilePath, _
FileFormat:=xlExcel8, password:="", WriteResPassword:="", _
ReadOnlyRecommended:=False, CreateBackup:=False
wb.Close SaveChanges:=False
Else
MsgBox xWs.Name & " was not found by VLookup", vbInformation
End If
Else
Debug.Print xWs.Name & ": was skipped"
End If
Next xWs
Set wb = Nothing
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Function getNewFilePath(xWs As Worksheet) As String
Dim s As String, sLookup As String
On Error Resume Next
With xWs
sLookup = WorksheetFunction.VLookup(CInt(Right(.Name, 2)), .Parent.Sheets("Table").Range("H3", "K100"), 4, False)
s = ThisWorkbook.Path & "\"
s = s & Left(.Name, 5) & "_" & Right(.Name, 2) & "_" & sLookup
If Err.Number = 0 Then getNewFilePath = s & ".xls"
End With
On Error GoTo 0
End Function
Function getCellValue(cell)
Dim s
s = cell.innerHTML
s = Replace(s, "<br>", "")
s = Replace(s, "<br />", "")
getCellValue = s
End Function

How to browse for save directory?

By clicking a button in Excel, the user exports a specific sheet to a csv with a dynamic filename and the csv is saved in a pre-determined directory.
Instead of saving to a predetermined directory, can users have the browse window to choose a directory to save to?
Sub Export()
Dim MyPath As String
Dim MyFileName As String
MyPath = "C:\importtest"
MyFileName = "MR_Update_" & Sheets("Monthly Review").Range("D3").Value & "_" & Format(Date, "ddmmyyyy")
If Not Right(MyPath, 1) = "\" Then MyPath = MyPath & "\"
If Not Right(MyFileName, 4) = ".csv" Then MyFileName = MyFileName & ".csv"
Sheets("Export Data").Copy
With ActiveWorkbook
.SaveAs Filename:= _
MyPath & MyFileName, _
FileFormat:=xlCSV, _
CreateBackup:=False
.Close False
End With
End Sub
Excel has an inbuilt FileSave Dialog. It is called .GetSaveAsFilename. Use that.
Syntax
expression.GetSaveAsFilename(InitialFilename, FileFilter, FilterIndex, Title, ButtonText)
Usage
Dim fileSaveName As Variant
fileSaveName = Application.GetSaveAsFilename( _
fileFilter:="Excel Files (*.csv), *.csv")
If fileSaveName <> False Then
'
'~~> Your code to save the file here
'
End If
As Patrick suggested, you're looking for the .FileDialog property.
To implement it, try this:
Sub Export()
Dim MyPath As String
Dim MyFileName As String
MyFileName = "MR_Update_" & Sheets("Monthly Review").Range("D3").Value & "_" & Format(Date, "ddmmyyyy")
If Not Right(MyFileName, 4) = ".csv" Then MyFileName = MyFileName & ".csv"
Sheets("Export Data").Copy
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Select a Folder"
.AllowMultiSelect = False
.InitialFileName = "" '<~~ The start folder path for the file picker.
If .Show <> -1 Then GoTo NextCode
MyPath = .SelectedItems(1) & "\"
End With
NextCode:
With ActiveWorkbook
.SaveAs Filename:=MyPath & MyFileName, FileFormat:=xlCSV,CreateBackup:=False
.Close False
End With
End Sub
Try This......
Sub Export()
Dim MyPath As String
Dim MyFileName As String
MyPath = "C:\importtest"
MyFileName = "MR_Update_" & Sheets("Monthly Review").Range("D3").Value & "_" & Format(Date, "ddmmyyyy")
If Not Right(MyFileName, 4) = ".csv" Then MyFileName = MyFileName & ".csv"
Sheets("Export Data").Copy
With ActiveWorkbook
.SaveAs Filename:= _
MyFileName, _
FileFormat:=xlCSV, _
CreateBackup:=False
.Close False
End With
End Sub
Here's a script I've been using lately that I like a lot. Thought I would leave this here:
Sub ExportCSV()
Dim FlSv As Variant
Dim MyFile As String
Dim sh As Worksheet
Dim MyFileName As String
Dim DateString As String
DateString = Format(Now(), "yyyy-mm-dd_hh_mm_ss_AM/PM") '<~~ uses current time from computer clock down to the second
MyFileName = DateString & "_" & "Whatever you like"
Set sh = Sheets("Sheet you'd like to export")
sh.Copy
FlSv = Application.GetSaveAsFilename(MyFileName, fileFilter:="CSV (Comma delimited) (*.csv), *.csv", Title:="Where should we save this?")
If FlSv = False Then GoTo UserCancel Else GoTo UserOK
UserCancel: '<~~ this code is run if the user cancels out the file save dialog
ActiveWorkbook.Close (False)
MsgBox "Export canceled"
Exit Sub
UserOK: '<~~ this code is run if user proceeds with saving the file (clicks the OK button)
MyFile = FlSv
With ActiveWorkbook
.SaveAs (MyFile), FileFormat:=xlCSV, CreateBackup:=False
.Close False
End With
End Sub

Resources