Excel VBA Password Protection check [duplicate] - excel

This question already has an answer here:
Ignore Excel Files That Are Password Protected [duplicate]
(1 answer)
Closed 8 years ago.
I have a project in which I have to go over 1,000+ excel files in a folder, and see which ones are password protected and which ones aren't. In order to save time, I wrote a macro to do this, which is as follows:
Sub CheckWbook()
Dim Value As String, a As Single, myfolder as string
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
myfolder = .SelectedItems(1) & "\"
End With
Range("C4") = myfolder
Range("B7:C" & Rows.Count) = ""
a = 0
Value = Dir(myfolder)
Do Until Value = ""
If Value = "." Or Value = ".." Then
Else
If Right(Value, 3) = "xls" Or Right(Value, 4) = "xlsx" Or Right(Value, 4) = "xlsm" Then
On Error Resume Next
Workbooks.Open Filename:=myfolder & Value, Password:="zzzzzzzzzzzz"
If Err.Number > 0 Then
Range("C7").Offset(a, 0).Value = "Yes"
End If
Workbooks(Value).Close False
On Error GoTo 0
Range("B7").Offset(a, 0).Value = Value
a = a + 1
End If
End If
Value = Dir
Loop
End Sub
The problem I'm having is that the popup for the password is still present: it does not fill in the password. Any help would be highly appreciated. -A
Edit
Changed the code a bit, and got past the error message, but now I'm getting stuck at the password popup, that stops the macro from completely working, despite the On Error Resume Next feature.
Then, I came across this code that I thought could help:
Option Explicit
Public Sub ProcessBatch()
Dim strFileName As String
Dim strFilePath As String
Dim oDoc As Document
' Set Directory for Batch Process
strFilePath = "C:\Test\"
' Get Name of First .doc File from Directory
strFileName = Dir$(strFilePath & "*.doc")
While Len(strFileName) <> 0
' Set Error Handler
On Error Resume Next
' Attempt to Open the Document
Set oDoc = Documents.Open( _
FileName:=strFilePath & strFileName, _
PasswordDocument:="?#nonsense#$")
Select Case Err.Number
Case 0
' Document was Successfully Opened
Debug.Print strFileName & " was processed."
Case 5408
' Document is Password-protected and was NOT Opened
Debug.Print strFileName & " is password-protected " & _
"and was NOT processed."
' Clear Error Object and Disable Error Handler
Err.Clear
On Error GoTo 0
' Get Next Document
GoTo GetNextDoc
Case Else
' Another Error Occurred
MsgBox Err.Number & ":" & Err.Description
End Select
' Disable Error Handler
On Error GoTo 0
'-------------------------------------
'-------------------------------------
'---Perform Action on Document Here---
'-------------------------------------
'-------------------------------------
' Close Document
oDoc.Close
' Clear Object Variable
Set oDoc = Nothing
GetNextDoc:
' Get Next Document from Specified Directory
strFileName = Dir$()
Wend
End Sub
but this fails to recognize the oDoc as a Document. Any ideas on how to get it working?

to open the excel file? or sheet
if it is a sheet should be
ActiveSheet.Unprotect Password: = "yourpassword"
if it is an excel
ActiveWorkbook.Unprotect("youtpassword")
I hope it serves you a hug I learned a lot here I hope you will also hopefully serve my help

Related

Excel to Word Macro resulting in Run-time error 462

I've written a VBA macro which resides in an Excel workbook. When run, it will open an existing Word document (which is stored in the same directory as the Excel workbook), copy some content from cells in the Excel workbook into the Word document, save the Word doc under a new name (in the same directory) and kill the original Word doc. This process works as expected on first run. But on a second run, I get a Run-time error 462. I'm sure it's due to my ignorance around creating and using application instances within VBA code (I've just begun learning). I'm using Microsoft 365 Apps for Enterprise.
Sub ExcelToWord()
Dim wordApp As Word.Application
Dim wDoc As Word.Document
Dim strFile As String
'Open Word file
strFile = ("G:\HOME\Word File.docx")
Set wordApp = CreateObject("word.Application")
Set wDoc = wordApp.Documents.Open("G:\HOME\Word File.docx")
wordApp.Visible = True
'Copy data from Excel to Word
wDoc.ContentControls(1).Range.Text = Sheets("Model").Cells(4, 2)
wDoc.ContentControls(2).Range.Text = Format(Date, "mm/dd/yyyy")
wDoc.ContentControls(3).Range.Text = Sheets("Model").Range("X4")
Word.Application.Activate
'Save Word Document with new name
ActiveDocument.SaveAs Filename:=ActiveDocument.Path & "\" & Format(Sheets("Model").Range("B14"), "YYYY") & " " & ThisWorkbook.Sheets("Model").Range("B4") & " " & Format(Date, "YYYY-mm-dd") & ".docx"
'Delete original Word document
Kill strFile
End Sub
I've researched this for hours and tried multiple solutions, including commenting out all of the Copy Data block to try and zero in on the error. But no luck. I hope I've posted this request properly. Thank you in advance for any help.
Is this what you are trying? I have commented the code but if you face any issues, simply ask. What you have is Early Binding. I have used Late Binding so that you do not need to add any references to the MS Word application.
Option Explicit
Private Const wdFormatXMLDocument As Integer = 12
Sub ExcelToWord()
Dim oWordApp As Object, oWordDoc As Object
Dim FlName As String
Dim FilePath As String
Dim NewFileName As String
'~~> This is the original word file. Change as applicable
FlName = "G:\HOME\Word File.docx"
'~~> Check if word file exists
If Dir(FlName) = "" Then
MsgBox "Word File Not Found"
Exit Sub
End If
'~~> Establish an Word application object if open
On Error Resume Next
Set oWordApp = GetObject(, "Word.Application")
'~~> If not open then create a new word application instance
If Err.Number <> 0 Then
Set oWordApp = CreateObject("Word.Application")
End If
Err.Clear
On Error GoTo 0
oWordApp.Visible = True
Set oWordDoc = oWordApp.Documents.Open(FlName)
With oWordDoc
'~~> File path
FilePath = .Path & "\"
'~~> New File name
NewFileName = FilePath & _
Format(ThisWorkbook.Sheets("Model").Range("B14").Value, "YYYY") & _
" " & _
ThisWorkbook.Sheets("Model").Range("B4").Value & _
" " & _
Format(Date, "YYYY-mm-dd") & ".docx"
'~~> Copy data from Excel to Word
.ContentControls(1).Range.Text = Sheets("Model").Cells(4, 2).Value2
.ContentControls(2).Range.Text = Format(Date, "mm/dd/yyyy")
.ContentControls(3).Range.Text = Sheets("Model").Range("X4").Value2
'~~> Save the word document
.SaveAs Filename:=NewFileName, FileFormat:=wdFormatXMLDocument
DoEvents
End With
'~~> Delete original Word document
Kill FlName
End Sub

how to copy and past content Word document from Excel, VBA

I have a Word document containing a few lines of text and a table with many place holders I will fill in from Excel later in the same document but saving it as PDF.
My final goal is to duplicate the whole text in the word file as it is before any modification and paste it every time I have to complete it with the values in the Excel file.
Inside word VBA, this works perfectly. Copy the whole document and past it at the end, duplicating the table and the lines of text.
Selection.WholeStory
Selection.Copy
Selection.MoveDown Unit:=wdParagraph, Count:=2
Selection.PasteAndFormat (wdFormatOriginalFormatting)
And in Excel VBA, I have this working just fine. Except the * Asterics part, I don't know how to execute the code that works in Word VBA from Excel VBA.
Sub GenerateDoc()
DocLoc = Application.ActiveWorkbook.Path & "\CategoryTable2.docx"
'Open Word Template
With Sheet2
On Error Resume Next 'If Word is already running
Set WordApp = GetObject("Word.Application")
If Err.Number <> 0 Then
'Launch a new instance of Word
Err.Clear
'On Error GoTo Error_Handler
Set WordApp = CreateObject("Word.Application")
End If ' Work Running Check
WordApp.Visible = True 'Make the application visible to the user
Set WordDoc = WordApp.Documents.Open(Filename:=DocLoc, ReadOnly:=False) 'Open Template
'This is not workin, no error throw however
'*****************************************
WordDoc.Content.WholeStory
WordDoc.Content.Copy
'***************************************
For component = 15 To 150
iRow = component
If .Cells(iRow, 1).Value = 0 And .Cells(iRow, 2).Text <> "" Then
For CustCol = 3 To 85 'Move Through Columns
If Left(.Cells(13, CustCol).Text, 1) = "[" And Right(.Cells(13, CustCol).Text, 1) = "]" Then
varName = .Cells(13, CustCol).Value 'Determine Variable Name
'varName = "[" & varName & "]"
VarValue = Trim(.Cells(iRow, CustCol).Text) 'Determine Variable Value
With WordDoc.Content.Find
.Text = varName
.Replacement.Text = Application.WorksheetFunction.Text(VarValue, "General")
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll 'Find & Replace all instances
End With
End If
Next CustCol
End If
Next component
'This is not working, no error throw however
'**************************************************************************
WordDoc.Content.MoveDown Unit:=wdParagraph, Count:=2
WordDoc.Content.PasteAndFormat (wdFormatOriginalFormatting)
'**************************************************************************
Filename = Application.ActiveWorkbook.Path & "\ComponentsTable.pdf" 'Create full filename & Path with current workbook location, Last Name & First Name
On Error Resume Next
Kill (Filename) 'Delete filename with the same name if it exists
On Error GoTo 0
On Error Resume Next
WordDoc.ExportAsFixedFormat OutputFileName:=Filename, ExportFormat:=wdExportFormatPDF
WordDoc.Close False
WordApp.Quit
Set WordDoc = Nothing
Set WordApp = Nothing
End With
End Sub
You need to change the logic of your approach.
'WordDoc.Content.WholeStory' specifies an object. Your code does nothing with it. WordDoc.Content.Copy copies an unrelated, other object. Perhaps you mean 'WordDoc.Content.WholeStory.Copy' but this argument is moot. Imagine the entire Word document as one string containing text as well as formatting characters. Therefore you can't copy the WholeStory which is a range. You can only copy its Text.
Once you assign the Text to a string you can paste it to a single cell in Excel. In other words, the String created in Word is understood by Excel and handled within Excel the way Excel handles its own strings. However, that string will definitely contain many characters Excel can't interpret and may contain some that Excel interprets differently. They may even cause Excel to split the original string into more than one cell.
Therefore you need to parse the string lifted from Word and manipulate it into the format you want it to have in Excel. The transition you are asking about takes place at the point where a Word-string becomes an Excel-string. Bear in mind that a Word-range can't become an Excel-range because the two are entirely different animals.
Ok, I found something interesting.
I was not getting any error message because of the
ON ERROR RESUME NEXT
I found that to avoid this, ON ERROR GOTO 0 worked. After that, it was easy to google for errors and find what was wrong. Also, my logic was flawed, I fix it like this. The *Asterix is the interesting part.
Reference https://learn.microsoft.com/en-us/office/vba/api/word.range.copy
Sub GenerateDoc()
Dim WordApp As New Word.Application
Dim WordDoc As Word.Document
DocLoc = Application.ActiveWorkbook.Path & "\CategoryTable2.docx"
'Open Word Template
With Sheet2
On Error Resume Next 'If Word is already running
Set WordApp = GetObject("Word.Application")
If Err.Number <> 0 Then
'Launch a new instance of Word
Err.Clear
'On Error GoTo Error_Handler
Set WordApp = CreateObject("Word.Application")
End If ' Work Running Check
WordApp.Visible = True 'Make the application visible to the user
Set WordDoc = WordApp.Documents.Open(Filename:=DocLoc, ReadOnly:=False) 'Open Template
On Error GoTo 0
'**********************************************************
WordDoc.Range(WordDoc.Content.Start, WordDoc.Content.End).Cut
'
' WordDoc.Content.Selection.WholeStory
' WordDoc.Content.Selection.Copy
For component = 15 To 150
iRow = component
If .Cells(iRow, 1).Value = 0 And .Cells(iRow, 2).Text <> "" Then
'Now past a template copy
'*****************************************************************************************
Set myRange = WordDoc.Range(Start:=WordDoc.Content.End - 1, End:=WordDoc.Content.End - 1)
myRange.Paste
For CustCol = 3 To 85 'Move Through Columns
If Left(.Cells(13, CustCol).Text, 1) = "[" And Right(.Cells(13, CustCol).Text, 1) = "]" Then
varName = .Cells(13, CustCol).Value 'Determine Variable Name
'varName = "[" & varName & "]"
VarValue = Trim(.Cells(iRow, CustCol).Text) 'Determine Variable Value
With WordDoc.Content.Find
.Text = varName
.Replacement.Text = Application.WorksheetFunction.Text(VarValue, "General")
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll 'Find & Replace all instances
End With
End If
Next CustCol
End If
Next component
' WordDoc.MoveDown Unit:=wdParagraph, Count:=2
' WordDoc.PasteAndFormat (wdFormatOriginalFormatting)
Filename = Application.ActiveWorkbook.Path & "\ComponentsTable.pdf" 'Create full filename & Path with current workbook location, Last Name & First Name
On Error Resume Next
Kill (Filename) 'Delete filename with the same name if it exists
On Error GoTo 0
On Error Resume Next
WordDoc.ExportAsFixedFormat OutputFileName:=Filename, ExportFormat:=wdExportFormatPDF
WordDoc.Close False
WordApp.Quit
Set WordDoc = Nothing
Set WordApp = Nothing
End With
End Sub

Search for a string and move files containing string from source folder to destination folder

I have large number of .csv files in a folder and each file has few separation codes in them. Separation code usually will be 5 digit code eg: B82A6.
I have to copy files with a certain separation code and move them to a destination folder.
I am new to VBA. I've been searching for code to modify it to my use.
Sub Test()
Dim R As Range, r1 As Range
Dim SourcePath As String, DestPath As String, SeperationCode As String
SourcePath = "C:\Users\hr315e\Downloads\Nov_03_2019\"
DestPath = "C:\Users\hr315e\Downloads\Target\"
Set r1 = Range("A1", Range("A" & Rows.Count).End(xlUp))
For Each R In r1
SeperationCode = Dir(SourcePath & R)
Do While SeperationCode <> ""
If Application.CountIf(r1, SeperationCode) Then
FileCopy SourcePath & SeperationCode, DestPath & SeperationCode
R.Offset(0, 1).Value = SeperationCode
Else
MsgBox "Bad file: " & SeperationCode & " ==>" & SeperationCode & "<== "
End If
SeperationCode = Dir(SourcePath & "B82A6" & R.Value & "B82A6")
Loop
Next
End Sub
So, here's the code that should work for you.
As you can see, this is a version of code which I linked to you with small updates:
Sub GoThroughFilesAndCopy()
Dim BrowseFolder As String, DestinationFolder As String
Dim FileItem As Object
Dim oFolder As Object
Dim FSO As Object
Dim TempFileName As String
Dim CheckCode As String
Application.ScreenUpdating = False
' selecting the folder with files
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Select the folder with files"
.Show
On Error Resume Next
Err.Clear
BrowseFolder = .SelectedItems(1)
If Err.Number <> 0 Then
MsgBox "You didn't select anything!"
Application.ScreenUpdating = True
Exit Sub
End If
On Error GoTo 0
End With
' or you may hardcode it (data from your post):
'BrowseFolder = "C:\Users\hr315e\Downloads\Nov_03_2019\"
' selecting the destination folder
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Select the the destination folder"
.Show
On Error Resume Next
Err.Clear
DestinationFolder = .SelectedItems(1)
If Err.Number <> 0 Then
MsgBox "You didn't select anything!"
Application.ScreenUpdating = True
Exit Sub
End If
On Error GoTo 0
End With
' or you may hardcode it (data from your post):
'DestinationFolder = "C:\Users\hr315e\Downloads\Target\"
CheckCode = "Some string" ' this is you check code
Set FSO = CreateObject("Scripting.FileSystemObject") ' creating filesystem object
Set oFolder = FSO.getfolder(BrowseFolder) ' creating folder object
For Each FileItem In oFolder.Files 'looking through each file in selected forlder
TempFileName = ""
If UCase(FileItem.Name) Like "*.CSV*" Then 'try opening only .csv files
TempFileName = BrowseFolder & Application.PathSeparator & FileItem.Name ' getting the full name of the file (with full path)
If CheckTheFile(TempFileName, CheckCode) Then ' if the file passes the checking function
If Dir(DestinationFolder & Application.PathSeparator & FileItem.Name) = "" Then 'if the file doesn't exist in destination folder
FileCopy Source:=TempFileName, Destination:=DestinationFolder & Application.PathSeparator & FileItem.Name ' it is copied to destination
Else ' otherwise, there are to options how to deal with it further
'uncomment the part you need below:
' this will Overwrite existing file
'FSO.CopyFile Source:=TempFileName, Destination:=DestinationFolder & Application.PathSeparator & FileItem.Name
' this will get new name for file and save it as copy
'FileCopy Source:=TempFileName, Destination:=GetNewDestinationName(FileItem.Name, DestinationFolder)
End If
End If
End If
Next
Application.ScreenUpdating = True
End Sub
'////////////////////////////////////////////////////////////////////////
Function CheckTheFile(File As String, Check As String) As Boolean
Dim TestLine As String
Dim TestCondition As String
TestCondition = "*" & Check & "*" ' this is needed to look for specific text in the file, refer to Like operator fro details
CheckTheFile = False
Open File For Input As #1 ' open file to read it line by line
Do While Not EOF(1)
Line Input #1, TestLine ' put each line of the text to variable to be able to check it
If TestLine Like TestCondition Then ' if the line meets the condition
CheckTheFile = True ' then function gets True value, no need to check other lines as main condition is met
Close #1 ' don't forget to close the file, beacuse it will be still opened in background
Exit Function ' exit the loop and function
End If
Loop
Close #1 ' if condiotion is not found in file just close the file, beacuse it will be still opened in background
End Function
'////////////////////////////////////////////////////////////////////////
Function GetNewDestinationName(File As String, Destination As String) As String
Dim i As Integer: i = 1
Do Until Dir(Destination & Application.PathSeparator & "Copy (" & i & ") " & File) = "" ' if Dir(FilePath) returns "" (empty string) it means that the file does not exists, so can save new file with this name
i = i + 1 ' incrementing counter untill get a unique name
Loop
GetNewDestinationName = Destination & Application.PathSeparator & "Copy (" & i & ") " & File ' return new file name
End Function
Basically, there is one sub, which is mostly copy-paste from linked topic, and two simple functions.

Excel VBA continues to 'Open File' even after Cancel

Okay here it is. I've done a bunch of coding in the last 3 or 4 months, learned a lot, BUT, I can't figure out why this code STILL opens a file when I hit cancel at the end once the popup window comes up showing my filtered filenames. Any advice would be highly appreciated.
Sub OpenByPartialName()
' Returns popup window with only filtered filenames matching
' Partial Filename input
Dim WB As Workbook
Dim Ans As String
Dim MyFile As String
Dim path As String
' Folder Path Name for Forms
path = ("S:\Forms Folder\")
Ans = InputBox("Enter Partial filename Filter", "Open File With Partial Name Filter")
MyFile = Dir("S:\Forms Folder\" & "*" & Ans & "*.xls")
MyFilter = path & "*" & Ans & "*.xls"
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = False
.InitialFileName = MyFilter
If .Show = 1 Then
MyFile = .SelectedItems(1)
End If
End With
On Error Resume Next
Set WB = Workbooks.Open(MyFile)
End Sub
That would be a dirty hack, but if you had an Else branch here:
If .Show = 1 Then
MyFile = .SelectedItems(1)
Else
MyFile = vbNullString
End If
...the code that actually opens the file could verify whether MyFile is empty or not before trying:
On Error Resume Next
If MyFile <> vbNullString Then Set WB = Workbooks.Open(MyFile)
That said I think you should be handling at least error 53 ("file not found") here, instead of just shoving all errors under the carpet.
Also the WB reference isn't used. Perhaps the Sub should be a Function that returns the opened workbook, or Nothing if opening fails?
This is what I use to select a directory. If the function returns an empty string, I don't try to open the file.
Private Function FolderPicker() As String
'*******************************************
' returns directory path to be printed to
' does not allow multiple selections,
' so returning the first item in selected
' items is sufficient.
'
' returns empty string On Error or if the
' user cancels
'********************************************
On Error GoTo ErrHandler
Const DefaultDirectory As String = "C:Path\to\default\directory\"
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
.Title = "Choose Directory to Print to"
.InitialFileName = DefaultDirectory
.InitialView = msoFileDialogViewSmallIcons
If .Show <> -1 Then
FolderPicker = vbNullString
Else
FolderPicker = .SelectedItems(1)
End If
End With
Exit Function
ErrExit:
FolderPicker = vbNullString
Exit Function
ErrHandler:
MsgBox "Unexpected Error: " & Err.number & vbCrLf & "Source: " & Err.Source & _
"Description: " & Err.Description, vbCritical, "ERROR!"
Resume ErrExit
End Function
So, you would call it like this.
MyFile = FolderPicker
If MyFile <> vbNullString Then
Set WB = Workbooks.Open(MyFile)
End If
Much blood, sweat and tears later (Serious web surfing, cobbling code together and retesting) I have found an answer that works without any problems for pressing 'Cancel' at any point.
Sub OpenAuditPartialName()
' Returns popup window with only filtered
' filenames matching input criteria.
' Filenames are saved from another code that uses 3 variables to generate a _
' filename 'Filename part1_Filename part2_Filename part3 Forms.xls'
Dim WB As Workbook
Dim Ans As String
Dim MyFile As String
Dim path As String
' Folder path for Forms
path = ("S:\Forms Folder\")
Ans = InputBox("Enter any part of the filename to search by." & vbCrLf & vbCrLf & _
"Full or Partial information is OK." & vbCrLf & vbCrLf & "Filename part1" _
& vbCrLf & "Filename part2" & vbCrLf & "Filename part3", "Enter Partial Filename Filter")
' Exits on 'Cancel' as it should
If Ans = "" Then
Exit Sub
End If
MyFile = Dir(path & "*" & Ans & "*.xls")
MyFilter = path & "*" & Ans & "*.xls"
'*******************************************
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = False
.InitialFileName = MyFilter
' Now accepts the 'Cancel' instead of continuing to open the first file
' in the filtered list when pressed
If .Show = 0 Then
ElseIf Len(Ans) Then
MyFile = .SelectedItems(1)
On Error Resume Next
Set WB = Workbooks.Open(MyFile)
Else
Exit Sub
End If
'*******************************************
End With
End Sub

Running macro (to assign linked cells to all checkboxes on given sheets) on all files in a folder

I am trying to reassign all the linked cells for checkboxes on three given worksheets in a large collection of workbooks.
The macro I have works successfully on any book I have open:
Sub CheckBoxesControl()
On Error Resume Next
Dim i As Long
For i = 1 To 400
Sheet4.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AA" & i
Sheet21.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AB" & i
Sheet22.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AC" & i
Next i
End Sub
However I want to run this across a large number of sheets, so I tried the following:
Sub CheckBoxesControl()
On Error Resume Next
Dim path As String
Dim file As String
Dim wkbk As Workbook
Dim i As Long
Application.ScreenUpdating = False
Application.DisplayAlerts = False
path = "C:\file\path\"
file = Dir(path)
Do While Not file = ""
Workbooks.Open (path & file)
Set wkbk = ActiveWorkbook
For i = 1 To 400
Sheet4.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AA" & i
Sheet21.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AB" & i
Sheet22.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AC" & i
Next i
wkbk.Save
wkbk.Close
file = Dir
Loop
End Sub
The macro certainly opens and closes each file, and runs without error, but it is not having the desired affect.
It only changes the check boxes for the sheet I run the macro from still (despite apparently opening saving and closing all the others).
Am I failing to correctly set the active workbook?
EDIT 1: Suggested fix (failed)
Method suggested in comments (proved unsuccessful):
Sub CheckBoxesControl()
On Error Resume Next
Dim path As String
Dim file As String
Dim wkbk As Workbook
Dim i As Long
Application.ScreenUpdating = False
Application.DisplayAlerts = False
path = "C:\file\path\"
file = Dir(path)
Do While Not file = ""
Set wkbk = Workbooks.Open(path & file)
For i = 1 To 400
wkbk.Sheet4.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AA" & i
wkbk.Sheet21.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AB" & i
wkbk.Sheet22.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AC" & i
If Err.Number <> 0 Then
End If
Next i
wkbk.Save
wkbk.Close
file = Dir
Loop
End Sub
EDIT 2: REMOVING ON ERROR RESUME NEXT
Suggestedion to remove the error ignoring has illustrated the following: when the macro runs an error:
Run-time error 1004
The item with the specific name wasn't found.
Debugging this error highlights:
Sheet4.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AA" & i
I believe I realise what this issue is: I'm using a "go between 1 and 400" loop to ensure I catch all the checkboxes on each page, but there isn't a checkbox for each one of those instances, (checkbox1 doesn't exist for example, on all pages - notably not on sheet 4)
I remember now this is why I had On error resume next there in the first place... but I need "next" to be the next "i" in the loop, not the next expression completely.
Update 4
For those keeping score at home, the problem is that OP was using the sheets CodeName, which cannot be used when referring to it from a macro in another spreadsheet.
Modify to accept the worksheet Name, and either of the subs can be called like:
Dim ws As Worksheet
Set ws = wkbk.Sheets("10. Prevention Finance")
UpdateChkBoxes3 ws, "ChkBoxOutput!AA"
Set ws = wkbk.Sheets("...") '#Modify the sheet name
UpdateChkBoxes3 ws, "ChkBoxOutput!AB"
Set ws = wkbk.Sheets("...") '#Modify the sheet name
UpdateChkBoxes3 ws, "ChkBoxOutput!AC"
Update 3 (non-ActiveX Checkboxes)
Sub UpdateChkBoxes3(sht as Worksheet, lnkdCell as String)
Dim cb as CheckBox
Dim cbNum As Integer
With sht
For Each cb In sht.CheckBoxes
cbNum = Replace(cb.Name, "Check Box ", vbNullString)
cb.LinkedCell = lnkdCell & cbNum
Next
End With
I also revised the sub in Update 2, previously had pasted in my testing code, instead of the proper sub that requires sht/lnkdCell as arguments.
Update 2
To account for non-indexed checkbox names, but still looping over all checkboxes in each worksheet, call this subroutine. I attempt to get the numeric value from the checkbox's .Name property, this should relate it to the cell location just like your i indexing did before, only you will avoid errors where checkboxes don't exist, because we're not looping over an Index, we're looping over the shapes themselves. This should work with ActiveX checkboxes:
Sub UpdateChkBoxes2(sht As Worksheet, lnkdCell As String)
'To address non-sequential/missing check box names not aligned with index
Dim cb As OLEObject
Dim cbNum As Integer
With sht
For Each cb In sht.OLEObjects
If cb.progID Like "Forms.CheckBox*" Then
cbNum = Replace(cb.Name, "Check Box ", vbNullString)
cb.LinkedCell = lnkdCell & cbNum
End If
Next
End With
End Sub
Update
Try something like this, which assumes CheckBoxes are named sequentially according to their index, and that there are no missing indices.
UpdateChkBoxes Sheet4, "ChkBoxOutput!AA"
UpdateChkBoxes Sheet21, "ChkBoxOutput!AB"
UpdateChkBoxes Sheet22, "ChkBoxOutput!AC"
'## Replaced the following error-prone code:
'For i = 1 To .CheckBoxes.Count
' wkbk.Sheet4.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AA" & i
' wkbk.Sheet21.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AB" & i
' wkbk.Sheet22.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AC" & i
' If Err.Number <> 0 Then
'
' End If
'Next i
Then, include this subroutine:
Sub UpdateChkBoxes(sht as Worksheet, lnkdCell as String)
With sht
For i = 1 to .CheckBoxes.Count
.CheckBoxes("Check Box " & i).LinkedCell = lnkdCell & i
Next
End With
End Sub
Original Response
OK, I think the problem is that nothing in your code is actually iterating over the files within a folder. You will need to use a FileSystemObject to do this. You can enable reference to the Microsoft Scripting Runtime dictionary, or, simply declare these variables as generic Object instead of Scripting....
Create an FSO, then assign a folder, and loop over the File objects within this folder. Open the file, and then pass it to a subroutine to perform your checkbox operations.
Something like this:
Option Explicit
Sub LoopFiles()
'## Requires reference to Microsoft Scripting Runtime Library
Dim path As String
Dim fso As New Scripting.FileSystemObject
Dim folder As Scripting.folder
Dim file As Scripting.file
Dim wkbk As Workbook
path = ThisWorkbook.path
Set folder = fso.GetFolder(path)
For Each file In folder.Files
Select Case UCase(Right(file.Name, 4)) '## Make sure you're only working on XLS file types
Case "XLSX", "XLSM", ".XLS" 'etc.
'
Set wkbk = Workbooks.Open(file.Name)
'Now, send this WOrkbook Object to a subroutine
CheckBoxesControl wkbk
wkbk.Save
wkbk.Close
Case Else
'Do nothing
End Select
Next
Set folder = Nothing
Set fso = Nothing
End Sub
Sub CheckBoxesControl(wkbk As Workbook)
Dim i As Long
On Error Resume Next
With wkbk
For i = 1 To 400
.Sheet4.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AA" & i
.Sheet21.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AB" & i
.Sheet22.CheckBoxes("Check Box " & i).LinkedCell = "ChkBoxOutput!AC" & i
Next i
End With
On Error GoTo 0
End Sub

Resources