I have requirements as below :
There is a folder named BATCH inside D:// drive of my PC.
Now this D://BATCH contains excel files with any random names. Every excel file has only one record.
I have to create .exe file or any Desktop Application which lets the user to browse the BATCH folder and then can upload the content or data from the excel files to our Server. We have to put the excel data into JSON and then have to upload it to the server.
One more thing is that If I have uploaded data from 3 files and then again user tries to upload by selecting the folder, data which are new or not uploaded only those data should be upload. The data in BATCH folder is generating daily with connected machine.
My background is for Web and Mobile development. So, little bit confused of achieving this thing as explained above.
So, How can I achieve this? Which technology I have to use or which are the tools that can be useful?
Thanks for the support.
There are probably a bunch of ways to skin this cat. Maybe import everything from all Excel files in the folder into one single Excel file, and export this to SQL Server. Just a thought.
Sub InsertInto()
'Declare some variables
Dim cnn As adodb.Connection
Dim cmd As adodb.Command
Dim strSQL As String
'Create a new Connection object
Set cnn = New adodb.Connection
'Set the connection string
cnn.ConnectionString = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=Northwind;Data Source=Server_Name"
'Create a new Command object
Set cmd = New adodb.Command
'Open the Connection to the database
cnn.Open
'Associate the command with the connection
cmd.ActiveConnection = cnn
'Tell the Command we are giving it a bit of SQL to run, not a stored procedure
cmd.CommandType = adCmdText
'Create the SQL
strSQL = "UPDATE TBL SET JOIN_DT = '2019-12-10' WHERE EMPID = 2"
'Pass the SQL to the Command object
cmd.CommandText = strSQL
'Execute the bit of SQL to update the database
cmd.Execute
'Close the connection again
cnn.Close
'Remove the objects
Set cmd = Nothing
Set cnn = Nothing
End Sub
Just to embellish my original answer a bit...you can easily import data from multiple excel files in a folder, into one single Excel file, using a concept like the one below.
Sub Basic_Example_1()
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String
Dim SourceRcount As Long, Fnum As Long
Dim mybook As Workbook, BaseWks As Worksheet
Dim sourceRange As Range, destrange As Range
Dim rnum As Long, CalcMode As Long
'Fill in the path\folder where the files are
MyPath = "C:\Users\Ron\test"
'Add a slash at the end if the user forget it
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
'If there are no Excel files in the folder exit the sub
FilesInPath = Dir(MyPath & "*.xl*")
If FilesInPath = "" Then
MsgBox "No files found"
Exit Sub
End If
'Fill the array(myFiles)with the list of Excel files in the folder
Fnum = 0
Do While FilesInPath <> ""
Fnum = Fnum + 1
ReDim Preserve MyFiles(1 To Fnum)
MyFiles(Fnum) = FilesInPath
FilesInPath = Dir()
Loop
'Change ScreenUpdating, Calculation and EnableEvents
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
'Add a new workbook with one sheet
Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
rnum = 1
'Loop through all files in the array(myFiles)
If Fnum > 0 Then
For Fnum = LBound(MyFiles) To UBound(MyFiles)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(MyPath & MyFiles(Fnum))
On Error GoTo 0
If Not mybook Is Nothing Then
On Error Resume Next
With mybook.Worksheets(1)
Set sourceRange = .Range("A1:C1")
End With
If Err.Number > 0 Then
Err.Clear
Set sourceRange = Nothing
Else
'if SourceRange use all columns then skip this file
If sourceRange.Columns.Count >= BaseWks.Columns.Count Then
Set sourceRange = Nothing
End If
End If
On Error GoTo 0
If Not sourceRange Is Nothing Then
SourceRcount = sourceRange.Rows.Count
If rnum + SourceRcount >= BaseWks.Rows.Count Then
MsgBox "Sorry there are not enough rows in the sheet"
BaseWks.Columns.AutoFit
mybook.Close savechanges:=False
GoTo ExitTheSub
Else
'Copy the file name in column A
With sourceRange
BaseWks.cells(rnum, "A"). _
Resize(.Rows.Count).Value = MyFiles(Fnum)
End With
'Set the destrange
Set destrange = BaseWks.Range("B" & rnum)
'we copy the values from the sourceRange to the destrange
With sourceRange
Set destrange = destrange. _
Resize(.Rows.Count, .Columns.Count)
End With
destrange.Value = sourceRange.Value
rnum = rnum + SourceRcount
End If
End If
mybook.Close savechanges:=False
End If
Next Fnum
BaseWks.Columns.AutoFit
End If
ExitTheSub:
'Restore ScreenUpdating, Calculation and EnableEvents
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
End Sub
See the link below for some ideas of how to get data from several Excel files/sources, consolidate into one single file/source.
http://www.rondebruin.nl/win/s3/win008.htm
Keep an open mind about this kind of stuff. There are several other ways to do essentially the same kind of thing.
The question is too broad and you can achieve your requirement in many ways.
If you consider using c# you can develop a WPF or Winforms Project.
You will need to follow these basic steps
A function to browse and pick your file like FolderBrowserDialog available in System.Windows.Forms. In case you are using WPF you have to add reference to the library
Read the excel contents. In this case you may need references to any library/nuget package like Epplus, Microsoft.Office.Interop.Excel, LinqToExcel or ExcelLibrary
Convert data to json format using Newtonsoft.Json nuget package
Upload or save data to SQL Server - Here you would need a connection string to the database and save the same in your .config file. you can use ADO, linq to sql etc for that.
Sample Code
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Excel files (*.xls)|*.csv|All files (*.*)|*.*";
if (openFileDialog.ShowDialog()== DialogResult.OK)
{
//Open file and read contents
var excelFile = new LinqToExcel.ExcelQueryFactory(path);
var query =
from row in excelFile.Worksheet("Sheet1")
let item = new
{
Column1 = row["Column1"].Cast<string>(),
Column2 = row["Column2"].Cast<int>(),
}
select item;
foreach (var item in query)
{
MyCustomClass myClass = new MyCustomClass();
myClass.Column1 = item.Column1;
myClass.Column2 = item.Column2;
//Do something
}
//convert to json
// Save to database
}
Related
I’m trying to make VBA script for Access 2013 which will help to process Word 2013 forms from folder, attach these files of Word 2013 form to relevant record entry and attach pdf file from same folder with the same name.
Since I’m not a programmer each try leads me to next error.
Can anyone help to make it work.
Thanks.
This code does task of collecting data from files .docx in folder.
Then not to keep files in folder I would like to save them in DB by the proper record.
How to add code that will attach pdf and docx file to the relevant record, assuming that filename of docx and pdf is the same?
I need a clue how to incert it to relevant record or start new part of script. what commands can be used and in what place to start new part of script?
Private Sub ImportFormdata_Click()
Dim appWord As Word.Application
Dim doc As Word.Document
Dim SourceFolderPath As String
Dim FormFile As String
Dim strName As String
Dim rst As DAO.Recordset
SourceFolderPath = CurrentProject.Path & "\"
FormFile = Dir(SourceFolderPath & "*.docx", vbNormal)
Do While FormFile <> ""
Set appWord = CreateObject("Word.Application")
strName = SourceFolderPath & FormFile
Set doc = appWord.Documents.Open(strName)
appWord.Visible = False
Set rst = CurrentDb.OpenRecordset("FormData")
With rst
.AddNew
![Question1] = doc.FormFields("Q1").result
![Question2] = doc.FormFields("Q2").result
![Question3] = doc.FormFields("Q3").result
![File name] = FormFile
.Update
.Close
End With
doc.Close
appWord.Quit
FormFile = Dir
Loop
MsgBox "Forms imported!"
End Sub
I have a Access DB containing several different tables, each with a different structure (number & names of fields, number of rows, title).
What I would like to do is to export all these tables into txt files, with a given separator ("|"), point as decimal separator, quotes for strings.
I have browsed the internet and what I got was:
use DoCmd.TransferText acExportDelim command
save a customized export specification and apply it
I get an error messagge ("object does not exist") and I think it is related to the fact that the export specification is "sheet-specific", i.e. does not apply to tables with different fields and fieldnames.
Can you help me?
thanks!!
EDIT.
I post also the original code I run. As I said before, I am new to VBA, so I just looked for a code on the web, adapted it to my needs, and run.
Public Sub ExportDatabaseObjects()
On Error GoTo Err_ExportDatabaseObjects
Dim db As Database
Dim db As DAO.Database
Dim td As TableDef
Dim sExportLocation As String
Dim a As Long
Set db = CurrentDb()
sExportLocation = "C:\" 'Do not forget the closing back slash! ie: C:\Temp\
For a = 0 To db.TableDefs.Count - 1
If Not (db.TableDefs(a).Name Like "MSys*") Then
DoCmd.TransferText acExportDelim, "Export_specs", db.TableDefs(a).Name, sExportLocation & db.TableDefs(a).Name & ".txt", True
End If
Next a
Set db = Nothing
MsgBox "All database objects have been exported as a text file to " & sExportLocation, vbInformation
Exit_ExportDatabaseObjects:
Exit Sub
Err_ExportDatabaseObjects:
MsgBox Err.Number & " - " & Err.Description
Resume Exit_ExportDatabaseObjects
End Sub
Before running the code, I manually exported the first table saving the Export_specs to a file.
Consider a db with two tables, A and B.
When I run the code A is properly exported, then I get the following errore message "3011 - The Microsoft Access database engine could not find the object 'B#txt'. Make sure the object exists and that you spell its name and the path name correctly. If 'B#txt' is not a local object, check your network connection or contact the server administration".
So, it's kind of complex. I've created a routine that imports files using ImportExport Specs, you should be able to easily adapt to your purpose. The basic operation is to create a spec that does exactly what you want to one file. Then, export this spec using this code:
Public Function SaveSpecAsXMltoTempDirectory(sSpecName As String)
Dim oFSO As FileSystemObject
Dim oTS As TextStream
Set oFSO = New FileSystemObject
Set oTS = oFSO.CreateTextFile("C:\Temp\" & sSpecName & ".xml", True)
oTS.Write CurrentProject.ImportExportSpecifications(sSpecName).XML
oTS.Close
Set oTS = Nothing
Set oFSO = Nothing
End Function
Then open this file in Notepad and replace the file name with some placeholder (I used "FILE_PATH_AND_NAME" in this sample). Then, import back into database using this code:
Public Function SaveSpecFromXMLinTempDirectory(sSpecName As String)
Dim oFSO As FileSystemObject
Dim oTS As TextStream
Dim sSpecXML As String
Dim oSpec As ImportExportSpecification
Set oFSO = New FileSystemObject
Set oTS = oFSO.OpenTextFile("C:\Temp\" & sSpecName & ".xml", ForReading)
sSpecXML = oTS.ReadAll
For Each oSpec In CurrentProject.ImportExportSpecifications
If oSpec.Name = sSpecName Then oSpec.Delete
Next oSpec
Set oSpec = CurrentProject.ImportExportSpecifications.Add(sSpecName, sSpecXML)
Set oSpec = Nothing
oTS.Close
Set oTS = Nothing
Set oFSO = Nothing
End Function
Now you can cycle thru the files and replace the placeholder in the spec with the filename then execute it using this code:
Public Function ImportFileUsingSpecification(sSpecName As String, sFile As String) As Boolean
Dim oSpec As ImportExportSpecification
Dim sSpecXML As String
Dim bReturn As Boolean
'initialize return variable as bad until function completes
bReturn = False
'export data using saved Spec
' first make sure no temp spec left by accident
For Each oSpec In CurrentProject.ImportExportSpecifications
If oSpec.Name = "Temp" Then oSpec.Delete
Next oSpec
sSpecXML = CurrentProject.ImportExportSpecifications(sSpecName).XML
If Not Len(sSpecXML) = 0 Then
sSpecXML = Replace(sSpecXML, "FILE_PATH_AND_NAME", sFile)
'now create temp spec to use, get template text and replace file path and name
Set oSpec = CurrentProject.ImportExportSpecifications.Add("Temp", sSpecXML)
oSpec.Execute
bReturn = True
Else
MsgBox "Could not locate correct specification to import that file!", vbCritical, "NOTIFY ADMIN"
GoTo ExitImport
End If
ExitImport:
On Error Resume Next
ImportFileUsingSpecification = bReturn
Set oSpec = Nothing
Exit Function
End Function
Obviously you'll need to find the table name in the spec XML and use a placeholder on it as well. Let me know if you can't get it to work and i'll update for export.
I have a query "myQuery" that returns more than 65,000 records, and as such, cannot be exported to one .xlsx file.
I'm attempting to break up this output to multiple files.
I'm still very much a beginner with VBA, but I've put the following together as best I can from research. This code is intended to iterate through the queried data, then output a new file for each 65,000 records.
Private Sub btnfrm1export_Click()
Dim outputFileName As String
Dim dlgOpen As FileDialog
Dim numFiles As Integer
Dim rs As String
Dim numr As Integer
Dim sql As String
Dim rec As Recordset
'Allows user to pick destination for files and gives value to sItem.
Set dlgOpen = Application.FileDialog(msoFileDialogFolderPicker)
With dlgOpen
.Title = "Select a Folder"
.AllowMultiSelect = False
If .Show <> -1 Then
sItem = .SelectedItems(1)
End If
End With
'Counts the records in myQuery to give the number of files needed to numFiles, assuming 60,000 records per file.
Set rec = CurrentDb.OpenRecordset("myQuery")
numFiles = Round(rec.RecordCount / 60000, 0)
numr = 1
' Changes the SQL of the query _vba in the current Database to select 60000 records from myQuery
rs = "SELECT TOP 60000 myQuery.* FROM myQuery"
CurrentDb.QueryDefs("_vba").sql = rs
'Defines SQL for clearing top 60000 (used in the following loop).
sql = "DELETE TOP 60000 myQuery.* FROM myQuery"
'Loops once to create each file needed
Do While numFiles > 0
'Sets a file name based on the destination folder, the file number numr, and information from a combobutton cbo1 on Form frm1.
outputFileName = sItem & "\" & Forms!frm1!cbo1 & "_Report_Pt" & numr & "_" & Format(Date, "yyyyMMdd") & ".xlsx"
'Outputs top 60000 of myQuery records to an excel file.
DoCmd.OutputTo acOutputQuery, "_vba", acFormatXLSX, outputFileName
numFiles = numFiles - 1
numr = numr + 1
'Deletes top 60000 from myQuery.
CurrentDb.Execute sql
Loop
End Sub
However, I'm getting:
Run-time error '2302': Microsoft Access can't save the output data to the file you've selected.
at DoCmd.OutputTo acOutputQuery, "_vba", acFormatXLSX, outputFileName
I do need this to be automated in vba and without pop-ups, etc. Any suggestions to make my code more efficient and proper is appreciated, but the REAL question is how to eliminate the error with DoCmd.OutputTo or make this work.
Thanks for any and all help!
Although the subject line concerns trying to output multiple Excel files, the real issue is trying to create an Excel file from an Access table or query which contains more than 65,000 rows - by using VBA. If VBA is NOT a requirement, then you can export a query or table by right-clicking on the object name, selecting export, then Excel. DO NOT check the box for 'Export data with formatting...' and it will work.
The code shown below was found at: http://www.myengineeringworld.net/2013/01/export-large-access-tablequery-to-excel.html (Created By Christos Samaras) and will properly export a large table/query to Excel
Option Compare Database
Option Explicit
Sub Test()
'Change the names according to your own needs.
DataToExcel "Sample_Table", "Optional Workbook Path", "Optional Target Sheet Name"
'Just showing that the operation finished.
MsgBox "Data export finished successfully!", vbInformation, "Done"
End Sub
Function DataToExcel(strSourceName As String, Optional strWorkbookPath As String, Optional strTargetSheetName As String)
'Use this function to export a large table/query from your database to a new Excel workbook.
'You can also specify the name of the worksheet target.
'strSourceName is the name of the table/query you want to export to Excel.
'strWorkbookPath is the path of the workbook you want to export the data.
'strTargetSheetName is the desired name of the target sheet.
'By Christos Samaras
'http://www.myengineeringworld.net
Dim rst As DAO.Recordset
Dim excelApp As Object
Dim Wbk As Object
Dim sht As Object
Dim fldHeadings As DAO.Field
'Set the desired recordset (table/query).
Set rst = CurrentDb.OpenRecordset(strSourceName)
'Create a new Excel instance.
Set excelApp = CreateObject("Excel.Application")
On Error Resume Next
'Try to open the specified workbook. If there is no workbook specified
'(or if it cannot be opened) create a new one and rename the target sheet.
Set Wbk = excelApp.Workbooks.Open(strWorkbookPath)
If Err.Number <> 0 Or Len(strWorkbookPath) = 0 Then
Set Wbk = excelApp.Workbooks.Add
Set sht = Wbk.Worksheets("Sheet1")
If Len(strTargetSheetName) > 0 Then
sht.Name = Left(strTargetSheetName, 34)
End If
End If
'If the specified workbook has been opened correctly, then in order to avoid
'problems with other sheets that might contain, a new sheet is added and is
'being renamed according to the strTargetSheetName.
Set sht = Wbk.Worksheets.Add
If Len(strTargetSheetName) > 0 Then
sht.Name = Left(strTargetSheetName, 34)
End If
On Error GoTo 0
excelApp.Visible = True
On Error GoTo Errorhandler
'Write the headings in the target sheet.
For Each fldHeadings In rst.Fields
excelApp.ActiveCell = fldHeadings.Name
excelApp.ActiveCell.Offset(0, 1).Select
Next
'Copy the data in the target sheet.
rst.MoveFirst
sht.Range("A2").CopyFromRecordset rst
sht.Range("1:1").Select
'Format the headings of the target sheet.
excelApp.Selection.Font.Bold = True
With excelApp.Selection
.HorizontalAlignment = -4108 '= xlCenter in Excel.
.VerticalAlignment = -4108 '= xlCenter in Excel.
.WrapText = False
With .Font
.Name = "Arial"
.Size = 11
End With
End With
'Adjusting the columns width.
excelApp.ActiveSheet.Cells.EntireColumn.AutoFit
'Freeze the first row - headings.
With excelApp.ActiveWindow
.FreezePanes = False
.ScrollRow = 1
.ScrollColumn = 1
End With
sht.Rows("2:2").Select
excelApp.ActiveWindow.FreezePanes = True
'Change the tab color of the target sheet.
With sht
.Tab.Color = RGB(255, 0, 0)
.Range("A1").Select
End With
'Close the recordset.
rst.Close
Set rst = Nothing
Exit Function
Errorhandler:
DoCmd.SetWarnings True
MsgBox Err.Description, vbExclamation, Err.Number
Exit Function
End Function
I am creating an MS Access 2010 database. I am using the API to do what the common dialog control did in previous versions of MS Access to open a directory and select a file. My client would like me to be able to open all of the files in the directory when a user clicks on a folder (so the user does not click on a file, just a folder). I cannot find an even triggering when the folder is clicked on within the common dialog control that comes up using the API.
Can anyone tell me how to open all the files in a directory (they will be .pdf files) when using the API for the common dialog control in MS ACCESS 2010?
The API calls I am using are here: http://access.mvps.org/access/api/api0001.htm
Use a FileSystemObject from Microsoft.Scripting.Runtime (must add reference to the project).
The following sub adds to a collection the string names of all pdf files in a given folder.
Get the folder path from the dialog (with folder picking option, not file picking)
Sub GetFolderPDFFiles(FolderPath As String, Col As Collection)
Dim FS As New FileSystemObject
Dim Dir As Folder
Dim Arq As File
Set Dir = FS.GetFolder(FolderPath)
For Each Arq In Dir.Files
If UCase(Right(Arq.Name, 4)) = ".PDF" Then
Call Col.Add(Arq.Path)
End If
Next
End Sub
This worked great for me... it will promt the dialog box to select the folder and open the .pdf files. it will also list all the files in Table1.
Option Compare Database
'function to select the folder where the files are:
Function ChooseFolder() As String
Dim fldr As FileDialog
Dim sItem As String
Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
With fldr
.Title = "Select a Folder"
.AllowMultiSelect = False
.InitialFileName = strPath
If .Show <> -1 Then GoTo NextCode
sItem = .SelectedItems(1)
End With
NextCode:
ChooseFolder = sItem
Set fldr = Nothing
End Function
Enter the routines to open and list the pdf files in the folder (it also look for files in subfolders):
Sub Open_List_Files()
'Declare the variables
Dim objFSO As Scripting.FileSystemObject
Dim objFolder, objTopFolder As Scripting.Folder
Dim strTopFolderName As String, ProjectF As String
Dim i As Long
' call the function to select the folder
Call Módulo1.ChooseFolder
'Create an instance of the FileSystemObject
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Get the top folder
Set objTopFolder = objFSO.GetFolder(ChooseFolder)
'Call the RecursiveFolder routine
Call RecursiveFolder(objTopFolder, True)
End Sub
Sub RecursiveFolder(objFolder As Scripting.Folder, IncludeSubFolders As Boolean)
'Declare the variables
Dim objFile As Object
Dim objSubFolder As Scripting.Folder
Dim DBStr, filepath As String
'Loop through each file in the folder
For Each objFile In objFolder.Files
On Error Resume Next
If InStr(objFile.Name, ".pdf") Then
DBStr = "INSERT INTO Table1 ([File Name]) " & _
" VALUES (" & _
"'" & objFile.Name & "', " & "');"
CurrentDb.Execute DBStr
'open the file
Application.FollowHyperlink objFile
End If
Next objFile
'Loop through files in the subfolders
If IncludeSubFolders Then
For Each objSubFolder In objFolder.SubFolders
Call RecursiveFolder(objSubFolder, True)
Next objSubFolder
End If
End Sub
Run the Open_List_Files() Macro and there you go! :)
I am trying to write a VBA script which imports all of the Excel files in a folder into a table in Access 2003, first checking if they have been imported or not. That part is fine. The issue I run into is clearing out some of the formulas that don't get used on the spreadsheet which causes difficulty when Access tries to import the range. when running the code as-is, I get an error "User-defined type not defined".
I am using late binding since I am developing for a site that uses multiple versions of Office and therfore can't reference the same library using early binding. The problem code is below:
Private Sub Command2_Click()
'Declare Variables
Dim xlApp As Object
Dim xlBook As Object
Dim LSQL As String
Dim SkippedCounter As Integer
Dim ImportedCounter As Integer
Dim BUN As Long
Dim SubmitDate As Date
Dim LSQL2 As String
Dim LSQL3 As String
'Start counters for final notice
SkippedCounter = 0
ImportedCounter = 0
Dim myDir As String, fn As String
'Set directory for importing files
myDir = "U:\Five Star\Operations\restore\Surveys\My InnerView - 2010\Action plans\Action plans - input for DB\"
'Function for selecting files in folder
fn = Dir(myDir & "*.xls")
'Determine if there are files in side the folder
If fn = "" Then
MsgBox "Folder is Empty!"
Else
'Begin cycling through files in the folder
Do While fn <> ""
'Create new Excel Object
Set xlApp = CreateObject("Excel.Application")
'Make it appear on the screen while importing
xlApp.Visible = True
'Open the workbook at hand
Set xlBook = xlApp.Workbooks.Open(myDir & fn)
'Check to see if it has been imported already
If xlBook.Sheets("Action plan form").Range("A1").Value = "Imported" Then
'If it has been imported, add 1 to the counter, close the file and close the instance of Excel
SkippedCounter = SkippedCounter + 1
xlBook.Close
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
Else
'Otherwise, unprotect the worksheet
xlBook.UnProtect Password:="2010"
Dim c As Range
'Unhide worksheet needed and clean it up
xlBook.Sheets("Action plan DB data").Visible = True
xlBook.Sheets("Action plan DB data").Range("B10:O10").ClearFormats
xlBook.Sheets("Action plan DB data").Range("N11:N84").ClearFormats
For Each c In xlBook.Sheets("Action plan DB data").Range("DB_import")
If c.Value = "" Or c.Value = 0 Then c.Clear
Next c
...
The rest of the code should run fine, it jsut has an issue with the declaration of "range" and looping through it. Thanks for your help!
Remove As Range from Dim c As Range and that will make c into an object. That way when it gets late-bound to a range you won't have any issues.