I'm trying to open an Excel file from Access and do some stuff with It, but code is not stable. Sometimes It works, other times not. Here's how I do this:
Dim FilePath As String
Dim ExcelApp As Excel.Application
FilePath = "C:\Users\Lucky\Desktop\Test.xls"
Set ExcelApp = CreateObject("Excel.Application")
ExcelApp.Workbooks.Open (FilePath)
With ExcelApp
'do some stuff here
End With
ExcelApp.Workbooks.Close
Set ExcelApp = Nothing
I've also noticed that once I run code, Excel starts proccess under Task Manager, that has to be killed manually in order to get code working again. Otherwise I get two types of error with Excel file:
one is that If I click Excel file, It doesn't open, It just flashes for a second and dissapears
and other is that Excel file opens in "read-only" mode...
So I reckon there is some flaw when file is closed in my code. How can I fix this ?
I can't see what's wrong with your code - maybe the path to the desktop?
This is the code I usually use - I've added another function to help choose the file. It uses late binding, so no need to set a reference to Excel - you don't get the IntelliSense and can't use Excel constants such as xlUp - you have to use the numerical equivalent.
Public Sub Test()
Dim oXLApp As Object
Dim oXLWrkBk As Object
Dim oXLWrkSht As Object
Dim vFile As Variant
Dim lLastRow As Long
vFile = GetFile()
Set oXLApp = CreateXL
Set oXLWrkBk = oXLApp.WorkBooks.Open(vFile, False)
Set oXLWrkSht = oXLWrkBk.WorkSheets(1) 'First sheet. Can also use "Sheet1", etc...
lLastRow = oXLWrkSht.Cells(oXLWrkSht.Rows.Count, "A").End(-4162).Row '-4162 = xlUp
MsgBox "Last row in column A is " & lLastRow
oXLWrkBk.Close False
oXLApp.Quit
Set oXLWrkBk = Nothing
Set oXLApp = Nothing
End Sub
Public Function CreateXL(Optional bVisible As Boolean = True) As Object
Dim oTmpXL As Object
'''''''''''''''''''''''''''''''''''''''''''''''''''''
'Defer error trapping in case Excel is not running. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''
On Error Resume Next
Set oTmpXL = GetObject(, "Excel.Application")
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
'If an error occurs then create an instance of Excel. '
'Reinstate error handling. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
If Err.Number <> 0 Then
Err.Clear
On Error GoTo ERROR_HANDLER
Set oTmpXL = CreateObject("Excel.Application")
End If
oTmpXL.Visible = bVisible
Set CreateXL = oTmpXL
On Error GoTo 0
Exit Function
ERROR_HANDLER:
Select Case Err.Number
Case Else
MsgBox "Error " & Err.Number & vbCr & _
" (" & Err.Description & ") in procedure CreateXL."
Err.Clear
End Select
End Function
Function GetFile(Optional startFolder As Variant = -1, Optional sFilterName As String = "") As Variant
Dim fle As Object
Dim vItem As Variant
'''''''''''''''''''''''''''''''''''''''''''
'Clear the file filter and add a new one. '
'''''''''''''''''''''''''''''''''''''''''''
Application.FileDialog(3).Filters.Clear
Application.FileDialog(3).Filters.Add "'Some File Description' Excel Files", "*.xls, *.xlsx, *.xlsm"
Set fle = Application.FileDialog(3)
With fle
.Title = "Select a file"
.AllowMultiSelect = False
If startFolder = -1 Then
.InitialFileName = CurrentProject.Path
Else
If Right(startFolder, 1) <> "\" Then
.InitialFileName = startFolder & "\"
Else
.InitialFileName = startFolder
End If
End If
If .Show <> -1 Then GoTo NextCode
vItem = .SelectedItems(1)
End With
NextCode:
GetFile = vItem
Set fle = Nothing
End Function
I have managed to solve my problem. There is nothing wrong with code in my question, except that instead of declaring
Dim ExcelApp As Excel.Application
It's better to use
Dim ExcelApp As Object
But much bigger problem is with code that does changes in Excel, such as this line:
x = Range(Cells(1, i), Cells(Rows.Count, i).End(xlUp)).Value
And correct synthax is:
x = ExcelApp.Range(ExcelApp.Cells(1, i), ExcelApp.Cells(ExcelApp.Rows.Count, i).End(xlUp)).Value 'maybe also better to replace xlUp with -4162
So, whenever you use some code for Excel file from Access, DON'T FORGET to reference everything to Excel object. And ofcourse, before everything, a proper reference must be set in VBA console, in my case Microsoft Office 15.0 library.
Related
From MS Access, I am attempting to open every XLSX file within a folder and edit a specific cell within the excel document. However some of these files are protected and some are not. Therefore I am trying to add an IF statement to check for this potential roadblock (I know the password for the protected workbooks and it is consistent across all of them).
I have tried the below code but it keeps returning various errors after every time I alter some of it to work (current error is "Wrong Number of arguments or invalid property):
Private Sub Command0_Click()
Dim xl As Excel.Application
Dim wb As Excel.Workbook
Dim ws As Excel.Worksheet
Dim fso As FileSystemObject
Dim objFolder As Folder
Dim objFile As File
Dim strPath As String
Dim strFile As String
Dim errnum As Long
Dim errtxt As String
'Specify the path to the folder.
strPath = CurrentProject.Path & "\originals"
'***** Set a reference to "Microsoft Scripting Runtime" by using
'***** Tools > References in the Visual Basic Editor (Alt+F11)
'Create an instance of the FileSystemObject.
Set fso = New Scripting.FileSystemObject
'Alternatively, without the reference mentioned above:
'Set fso = CreateObject("Scripting.FileSystemObject")
'Get the folder.
Set objFolder = fso.GetFolder(strPath)
'If the folder does not contain files, exit the sub.
If objFolder.Files.Count = 0 Then
MsgBox "No files found in the specified folder.", vbApplicationModal + _
vbExclamation + vbOKOnly, "Runtime Error"
Exit Sub
End If
'Turn off screen updating. It may run quicker if updating is disabled, but
'if the work to be done is minimal, it may not be necessary.
Set xl = Excel.Application
xl.ScreenUpdating = False
DoCmd.SetWarnings False
'Loop through each file in the folder
For Each objFile In objFolder.Files
strFile = objFile.Path
'Open each file and perform actions on it.
Set wb = xl.Workbooks.Open(objFile.Path)
'Set inline error trap in case PLOG tab does not exist.
On Error Resume Next
Set ws = wb.Worksheets("Whole Foods Market PLOG")
wb.Application.DisplayAlerts = False
errnum = Err.Number
errtxt = Err.Description
On Error GoTo -1
Select Case errnum
Case 0 'Zero = no error.
If ws.ProtectContents = True Then
ws.Unprotect "550" 'enter password
End If
ws.Cells(11, 20).Value = Date
ws.Protect "550", True, True
wb.Save
Case 9 'Subscript out of range; most likely the tab does not exist.
MsgBox "The workbook '" & objFile.Name & "' does not have a 'PLOG' tab."
Case 58
MsgBox "Fix This"
Case 91
Resume Next
Case Else 'All other errors.
MsgBox "Runtime error #" & CStr(errnum) & ": " & IIf(Right(errtxt, 1) = ".", errtxt, errtxt & ".")
End Select
wb.Application.DisplayAlerts = True
wb.Close False
Set wb = Nothing
Next objFile
'Turn screen updating back on
xl.ScreenUpdating = True
'IMPORTANT: Clean up & quit Excel. If this is not done, Excel will stay in memory
'after the macro ends. If this is done repeatedly, many individual instances of Excel
'will build up in memory, and will stay there until killed with an task app such as
'Windows Task Manager or SysInternals ProcessExplorer, or until the system is rebooted,
'and it may even prevent Windows from shutting down properly because all those instances
'of Excel are waiting for user input at the "Save workbook? Yes/No/Cancel" dialog.
xl.Quit
Set xl = Nothing
End Sub
I simply want the code to go through each excel file within the folder and do this:
if the workbook is protected then
unprotect it,
edit cell,
reprotect it,
save/close
if the workbook is not protected then
edit cell,
reprotect it,
save/close
Edit1: fixed a typo I saw in the original code
ws.Unprotect "550", True, True
This would be the "wrong number of arguments". Worksheet.Unprotect takes a single, optional, Password parameter - VBA doesn't know what to do with these two True arguments.
Option Compare Database
Option Explicit
Public Sub SO56995486()
'Declare the variables
Dim xl As Excel.Application
Dim wb As Excel.Workbook
Dim ws As Excel.Worksheet
Dim fso As Scripting.FileSystemObject
Dim objFolder As Scripting.Folder
Dim objFile As Scripting.file
Dim fileList As VBA.Collection
Dim fldrPath As String
Dim fullpath As String
Dim filename As String
Dim errnum As Long
Dim c As Long
Dim i As Long
'Specify the path to the folder.
fldrPath = "C:\Temp\"
'Set up a log file.
Open fldrPath & "_logfile.txt" For Output As #1
'***** Set a reference to "Microsoft Scripting Runtime" by using
'***** Tools > References in the Visual Basic Editor (Alt+F11)
'Set up the major object variables.
Set xl = Excel.Application
Set fso = New Scripting.FileSystemObject
Set fileList = New VBA.Collection
'Get the folder.
Set objFolder = fso.GetFolder(fldrPath)
'If the folder does not contain files, exit the sub.
If objFolder.Files.Count = 0 Then
MsgBox "No files found in the specified folder.", vbApplicationModal + _
vbExclamation + vbOKOnly, "Runtime Error"
Exit Sub
End If
'Create a list of all XLSX files in the folder.
For Each objFile In objFolder.Files
filename = objFile.Name
If UCase(fso.GetExtensionName(filename)) = "XLSX" Then
fileList.Add objFile
End If
Next
'Remove any Excel temp files. Tricky loop since items may be deleted.
i = 1
Do
Set objFile = fileList.ITEM(i)
filename = Left(objFile.Name, 2)
If filename = "~$" Then
fileList.Remove (i)
Else
i = i + 1
End If
Loop Until i >= fileList.Count
'Remove any open files. Tricky loop again.
i = 1
Do
Set objFile = fileList.ITEM(i)
fullpath = objFile.Path
If IsFileOpen(fullpath) Then
fileList.Remove (i)
Else
i = i + 1
End If
Loop Until i >= fileList.Count
'Turn off screen updating. It may run quicker if updating is disabled, but
'if the work to be done is minimal, it may not be necessary.
xl.ScreenUpdating = False
DoCmd.SetWarnings False
'Loop through each file in the folder
For Each objFile In fileList
fullpath = objFile.Path
'Open the file. Use inline error trap in case it can't be opened.
On Error Resume Next
Set wb = xl.Workbooks.Open(fullpath)
errnum = Err.Number
On Error GoTo 0
Select Case errnum
Case 0 'File opened ok.
'Use inline error trap in case PLOG tab does not exist.
On Error Resume Next
Set ws = wb.Worksheets("PLOG")
errnum = Err.Number
On Error GoTo 0
Select Case errnum
Case 0 'Tab reference grabbed ok.
If ws.ProtectContents = True Then
ws.Unprotect "550" 'enter password
End If
ws.Cells(11, 20).value = Date
ws.Protect "550", True, True
On Error Resume Next
wb.Save
errnum = Err.Number
On Error GoTo 0
Select Case errnum
Case 0 'Saved ok.
Print #1, "OK: " & objFile.Name
Case Else
Print #1, "Couldn't save: " & objFile.Name
End Select
Case 9 'Subscript out of range; probably tab does not exist.
Print #1, "Tab does not exist: " & objFile.Name
Case Else 'Other errors.
Print #1, "Other error (" & CStr(errnum) & "): " & objFile.Name
End Select
Case Else
Print #1, "Can't open file: "; Tab(20); objFile.Name
End Select
wb.Close True
Set wb = Nothing
Next
'Turn screen updating back on
xl.ScreenUpdating = True
DoCmd.SetWarnings True
'IMPORTANT: Clean up & quit Excel. If this is not done, Excel will stay in memory
'after the macro ends. If this is done repeatedly, many individual instances of Excel
'will build up in memory, and will stay there until killed with an task app such as
'Windows Task Manager or SysInternals ProcessExplorer, or until the system is rebooted,
'and it may even prevent Windows from shutting down properly because all those instances
'of Excel are waiting for user input at the "Save workbook? Yes/No/Cancel" dialog.
xl.Quit
Set xl = Nothing
Close #1
End Sub
Public Function IsFileOpen(filename As String) As Boolean
Dim filenum As Integer
Dim errnum As Integer
On Error Resume Next
filenum = FreeFile()
' Attempt to open the file and lock it.
Open filename For Input Lock Read As #filenum
Close filenum
errnum = Err
On Error GoTo 0
Select Case errnum
Case 0
'No error.
IsFileOpen = False
Case 55, 70
'File already open.
IsFileOpen = True
Case Else
'Other error.
'IsFileOpen = ?
End Select
End Function
I'm running code which opens a user provided spreadsheet. It just brings in the first column excluding the header. running the code once works as expected except it leaves the EXCEL.EXE instance open at the end. I've read several questions having this similar problem, all the answers surround finding any object which was not quit/closed and then set to nothing. I do this for every object in my code and even have error checking which catches if it doesn't complete and to quit and clear the objects. On the second run of the code after the EXCEL.EXE doesn't close it throws a "(1004) Application-defined or Object Defined error" on .Cells(Rows.Count, 1).End(xlUp).Row anyone know why that is?
any help would be appreciated
Private Sub SplitImports()
Dim StringVar As Variant
Dim strLn As String
'Asks user for Filepath
StringVar = InputBox("Please enter the file path for your list", "Import", "H:\FNMA_WFDC")
'Ends Function if no input or cancel is detected
MsgBox (StringVar)
If (StringVar = vbNullString) Then
MsgBox ("No input, Please try again")
Quittracker = True
Exit Sub
End If
'Scrubs outer quotes if present
StringVar = Replace(StringVar, Chr(34), "", 1, 2)
'Creates the object to check the file
Dim FSO As Object
Set FSO = CreateObject("Scripting.Filesystemobject")
MsgBox ("Got Passed the FSO Object")
'Checks that our file exists, exits if not
If (Not FSO.FileExists(StringVar)) Then
MsgBox ("File does not exist, try again")
Quittracker = True
Exit Sub
End If
Set FSO = Nothing
Dim xlApp As Object 'Excel.Application
Dim xlWrk As Workbook 'Excel.Workbook
Dim i As Long
Set xlApp = New Excel.Application
MsgBox ("Dimmed the excel objects")
xlApp.Visible = False
On Error GoTo ErrorTrap
Set xlWrk = xlApp.Workbooks.Open(StringVar) 'opens the excel file for processing
MsgBox ("objects are set")
With xlWrk.Worksheets("Sheet1")
.Columns("A").NumberFormat = "#"
MsgBox (.Cells(Rows.Count, 1).End(xlUp).Row)
'walks through the excel sheet to the end and inserts the lines below the headerline into the database
For i = 2 To .Cells(Rows.Count, 1).End(xlUp).Row
DoCmd.RunSQL "Insert Into Split_List(Criteria) values('" & .Cells(i, 1).Text & "')"
Next i
End With
MsgBox ("About to Clear and close the objects")
'closes the workbook and quits the application
xlWrk.Saved = True
xlWrk.Close
Set xlWrk = Nothing
xlApp.Quit
Set xlApp = Nothing
MsgBox ("End of the import sub")
Exit Sub
ErrorTrap:
xlWrk.Saved = True
xlWrk.Close
Set xlWrk = Nothing
xlApp.Quit
Set xlApp = Nothing
MsgBox ("(" & Err.Number & ") " & Err.Description
Quittracker = True
Exit Sub
I have already spent too many hours looking for the right answer and every which way I try it doesn't work the way I want it to.
I receive the "Application or Object defined error" referencing the Excel file when I run the following. It compiles just fine, so I am not sure where I went wrong. I need it to pull data from two different places on an Excel sheet, place them in specific defined labels in a Word doc, save it with custom name and continue to do so until the end of the list in Excel. Data begins in A1 and B1 respectively.
Dim oXL As Object
Dim oWB As Object
Dim exWb As String
Dim oSheet As Object
Dim bStartExcel As Boolean
Dim objDoc As Object
Dim fcount As Long
Dim iRow As Integer
exWb = "C:\Documents\Waivers_needed_0926_Take2.xlsx"
On Error Resume Next
'If Excel running use it
Set oXL = GetObject(, "Excel.application")
If Err.Number <> 0 Then 'If Excel isn't running then start it
bStartExcel = True
Set oXL = CreateObject("Excel.Application")
End If
On Error GoTo Err_Handler
'Open the workbook
Set oWB = oXL.Workbooks.Open(FileName:=exWb)
'Process the worksheet
Set oSheet = oXL.ActiveWorkbook.Worksheets(4)
For iRow = 1 to 100
With oSheet.Cells(iRow, 0)
ActiveDocument.Amt_Paid.Caption = .Value
End With
With oSheet.Cells(iRow, 1)
ActiveDocument.Payee.Caption = .Value
End With
'Save Word Document with new name
fcount = fcount + 1
With ActiveDocument
.SaveAs FileName:="C:\Documents\Waivers\" & Split(ActiveDocument.Name, ".")(0) & "_" & Format(Now(), "YYYYMMDD") & "_" & fcount & ".doc"
End With
Next iRow
Exit Sub
I am trying to update the source to all the links in a word report by using a macro in word VBA. I want to be able to offer a dialog box to user then they select file and it replaces current source in all links in the word doc. The code i have below works but really slowly. I also seem to have to open excel in the background or the links wont work? not sure why this is??
It seems to go through eack link in tuen. Is there a way to globally change all the links at the same time possibly using find and repalce? please any help is greatly appreciated! I need this for a reprot in work and so i need to find a solution as soon as possible.
Private Sub CommandButton1_Click()
Dim OldFile As String
Dim xlsobj As Object
Dim xlsfile_chart As Object
Dim dlgSelectFile As FileDialog 'FileDialog object '
Dim thisField As Field
Dim selectedFile As Variant
'must be Variant to contain filepath of selected item
Dim newFile As Variant
Dim fieldCount As Integer '
Dim x As Long
On Error GoTo LinkError
'create FileDialog object as File Picker dialog box
Set dlgSelectFile = Application.FileDialog
(FileDialogType:=msoFileDialogFilePicker)
With dlgSelectFile
.Filters.Clear 'clear filters
.Filters.Add "Microsoft Excel Files", "*.xls, *.xlsb, *.xlsm,
*.xlsx" 'filter for only Excel files
'use Show method to display File Picker dialog box and return user's
action
If .Show = -1 Then
'step through each string in the FileDialogSelectedItems collection
For Each selectedFile In .SelectedItems
newFile = selectedFile 'gets new filepath
Next selectedFile
Else 'user clicked cancel
Exit Sub
End If
End With
Set dlgSelectFile = Nothing
' update fields
Set xlsobj = CreateObject("Excel.Application")
xlsobj.Application.Visible = False
Set xlsfile_chart = xlsobj.Application.Workbooks.Open(newFile,
ReadOnly = True)
Application.ScreenUpdating = False
With xlsobj.Application
.calculation = xlcalculationmanual
.enableevents = False
End With
fieldCount = ActiveDocument.Fields.Count
For x = 1 To fieldCount
With ActiveDocument.Fields(x)
If .Type = 56 Then
.LinkFormat.SourceFullName = newFile
End If
End With
Next x
With xlsobj.Application
.calculation = xlcalculationmanual
.enableevents = True
End With
Application.ScreenUpdating = True
MsgBox "Data has been sucessfully linked to report"
'clean up
xlsfile_chart.Close SaveChanges:=False
Set xlsfile_chart = Nothing
xlsobj.Quit
Set xlsobj = Nothing
Exit Sub
LinkError:
Select Case Err.Number
Case 5391 'could not find associated Range Name
MsgBox "Could not find the associated Excel Range Name " & _
"for one or more links in this document. " & _
"Please be sure that you have selected a valid " & _
"Quote Submission input file.", vbCritical
Case Else
MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical
End Select
' clean up
Set xlsfile_chart = Nothing
xlsobj.Quit
Set xlsobj = Nothing
End Sub
Dim FolderName As String
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
.Show
On Error Resume Next
FolderName = .SelectedItems(1)
On error go to 0
End With
If FolderName = "" Then
Exit Sub
End If
'Continue with code using FolderName as your source path
Hopefully this will serve as a good starting point for you. This will get you the path of the source folder and store it in FolderName. You can then build your link using:
CompletePath = FolderName + [FileNameGoesHere]
(Don't forget to make sure your FolderName has a "\" on the end, else the path will be incorrectly formatted, if it doesn't you can add it in or perform a check to ensure it is present on the end of the FolderName string
I have +500 Excel files (*.xls) having macros, all located in same folder.
I want to remove all macros from these files. Removing macros manually one by one from all files will take too much time.
Is it possible to create a new macro in a separate excel file which will remove all macros from these closed files?
Thanks for your guidance in advance.
I have coded routines around macro ListComponentsSingleWbk to meet your requirement. I have tested then with a variety of workbooks and I believe they provide the functionality you seek.
Both ListComponentsCtrl and DeleteLinesCtrl contain the statement Path = .... You will need to amend these statements to match the path of your folder.
I use macro ListComponentsSingleWbk to provide daily backups of the macros I am developing. I have coded ListComponentsCtrl to call ListComponentsSingleWbk for every XLS files in a folder.
I suggest you run ListComponentsCtrl before you do anything else. It will create a file with the name “BkUp yymmdd hhmm.txt” where “yymmdd hhmm” represent the current date and time. Following the run, “BkUp yymmdd hhmm.txt” will contain:
The name of every workbook it has found.
The name of every component within a workbook that might contain code.
If there is code within a component, a list of that code.
Running ListComponentsCtrl will ensure you have a complete backup if you discover in a month’s time that you have deleted macros from the wrong workbooks.
DeleteCodeCtrl calls DeleteCodeSingleWbk for every XLS files in a folder.
DeleteCodeSingleWbk:
Removes all standard and class modules from a workbook.
Clears any code from the code modules of the worksheets.
Clears any code from the code module of ThisWorkbook.
Option Explicit
' This module was built from information scattered across many sites. The
' most useful were:
' http://vbadud.blogspot.co.uk/2007/05/insert-procedure-to-module-using.html
' http://support.microsoft.com/kb/282830
' http://msdn.microsoft.com/en-us/library/aa443716(v=vs.60).aspx
' http://www.ozgrid.com/forum/showthread.php?t=32709
' This module needs a reference to:
' "Microsoft Visual Basic for Applications Extensibility n.n"
' The security system will probably prevent access to VBComponents unless you:
' For Excel 2003, from Excel (not VB Editor)
' Click Tools
' Click Macro
' Click Security
' Click Trusted Publishers
' Tick Trust access to Visual Basic Project
' For other versions of Excel search for "programmatic access to Visual Basic project not trusted"
Sub DeleteCodeCtrl()
Dim FileObj As Object
Dim FileSysObj As Object
Dim FolderObj As Object
Dim Path As String
Application.ScreenUpdating = False
Application.EnableEvents = False
' ### Change to directory containing your Excel workbooks
' Note: trailing "\" is assumed by later code
Path = ThisWorkbook.Path & "\TestFiles\"
Set FileSysObj = CreateObject("Scripting.FileSystemObject")
Set FolderObj = FileSysObj.GetFolder(Path)
For Each FileObj In FolderObj.Files
If LCase(Right(FileObj.Name, 4)) = ".xls" Then
Call DeleteCodeSingleWbk(Path & FileObj.Name)
End If
Next
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Sub DeleteCodeSingleWbk(ByVal WbkName As String)
Dim CodeLineCrnt As Long
Dim InxC As Long
Dim NumCodeLines As Long
Dim VBC As VBComponent
Dim VBCType As Long
Dim VBP As VBProject
Dim VBMod As CodeModule
Dim Wbk As Workbook
Err.Clear
' Switch off normal error handling in case attempt to open workbook fails
On Error Resume Next
' Second parameter = False means links will not be updated since not interested in data
' Third parameter = False mean open for updating
Set Wbk = Workbooks.Open(WbkName, False, False)
' Restore normal error handling.
On Error GoTo 0
If Err.Number <> 0 Then
On Error Resume Next
' In case partially open
Wbk.Close SaveChanges:=False
On Error GoTo 0
Else
Set VBP = Wbk.VBProject
' Process components in reverse sequence because deleting a component
' will change the index numbers of components below it.
For Each VBC In VBP.VBComponents
VBCType = VBC.Type
If VBCType = vbext_ct_StdModule Or VBCType = vbext_ct_ClassModule Then
' Component is a module and can be removed
VBP.VBComponents.Remove VBC
ElseIf VBCType = vbext_ct_Document Then
' Component can have a code module which can be cleared
Set VBMod = VBC.CodeModule
NumCodeLines = VBMod.CountOfLines
If NumCodeLines > 0 Then
Call VBMod.DeleteLines(1, NumCodeLines)
End If
End If
Next
Wbk.Close SaveChanges:=True
End If
End Sub
Sub ListComponentsCtrl()
Dim BkUpFileObj As Object
Dim FileObj As Object
Dim FileSysObj As Object
Dim FolderObj As Object
Dim Path As String
Application.ScreenUpdating = False
Application.EnableEvents = False
' ### Change to directory containing your Excel workbooks
' Note: trailing "\" is assumed by later code
Path = ThisWorkbook.Path & "\TestFiles\"
Set FileSysObj = CreateObject("Scripting.FileSystemObject")
Set FolderObj = FileSysObj.GetFolder(Path)
' Second parameter = False means existing file will not be overwritten
' Third parameter = False means ASCII file will be created.
Set BkUpFileObj = FileSysObj.CreateTextFile(Path & "BkUp " & Format(Now(), "yymmyy hhmm") & ".txt", _
False, False)
For Each FileObj In FolderObj.Files
If LCase(Right(FileObj.Name, 4)) = ".xls" Then
Call ListComponentsSingleWbk(Path & FileObj.Name, BkUpFileObj)
End If
Next
BkUpFileObj.Close
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Sub ListComponentsSingleWbk(ByVal WbkName As String, ByRef BkUpFileObj As Object)
Dim CodeLineCrnt As Long
Dim InxC As Long
Dim NumCodeLines As Long
Dim VBC As VBComponent
Dim VBCType As Long
Dim VBP As VBProject
Dim VBMod As CodeModule
Dim Wbk As Workbook
Call BkUpFileObj.WriteLine("Workbook " & WbkName)
Err.Clear
' Switch off normal error handling in case attempt to open workbook fails
On Error Resume Next
' Second parameter = False means links will not be updated since not interested in data
' Third parameter = True mean open read only
Set Wbk = Workbooks.Open(WbkName, False, True)
' Restore normal error handling.
On Error GoTo 0
If Err.Number <> 0 Then
Call BkUpFileObj.WriteLine(" Unable to open workbook: " & Err.desc)
Else
Set VBP = Wbk.VBProject
For InxC = 1 To VBP.VBComponents.Count
Set VBC = VBP.VBComponents(InxC)
VBCType = VBC.Type
If VBCType = vbext_ct_StdModule Or VBCType = vbext_ct_ClassModule Or _
VBCType = vbext_ct_Document Then
' Component can have a code module
Set VBMod = VBC.CodeModule
NumCodeLines = VBMod.CountOfLines
If NumCodeLines = 0 Then
Call BkUpFileObj.WriteLine(" No code associated with " & _
VBCTypeNumToName(VBCType) & " " & VBC.Name)
Else
Call BkUpFileObj.WriteLine(" Code within " & _
VBCTypeNumToName(VBCType) & " " & VBC.Name)
For CodeLineCrnt = 1 To NumCodeLines
Call BkUpFileObj.WriteLine(" " & VBMod.Lines(CodeLineCrnt, 1))
Next
End If
End If
Next
End If
Wbk.Close SaveChanges:=False
End Sub
Function VBCTypeNumToName(ByVal VBCType As Long) As String
Select Case VBCType
Case vbext_ct_StdModule ' 1
VBCTypeNumToName = "Module"
Case vbext_ct_ClassModule ' 2
VBCTypeNumToName = "Class Module"
Case vbext_ct_MSForm ' 3
VBCTypeNumToName = "Form"
Case vbext_ct_ActiveXDesigner ' 11
VBCTypeNumToName = "ActiveX Designer"
Case vbext_ct_Document ' 100
VBCTypeNumToName = "Document Module"
End Select
End Function
Given you couldnt get Tony's code to work try this version:
Change "C:\temp" to the path of your choice
All xls files will be opened, saved as "orginalfilename_no_code.xlsx" and the prior version will be removed
Sub CullCode()
Dim StrFile As String
Dim strPath As String
Dim WB As Workbook
strPath = "c:\temp\"
StrFile = Dir(strPath & "*.xls*")
With Application
.DisplayAlerts = False
.ScreenUpdating = False
.EnableEvents = False
End With
Do While Len(StrFile) > 0
Set WB = Workbooks.Open(strPath & StrFile)
WB.SaveAs strPath & StrFile & "_no_code.xlsx", 51
WB.Close False
Kill strPath & StrFile
StrFile = Dir
Loop
With Application
.DisplayAlerts = True
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub