Insert Multiple Bitmap Image into Multiple Worksheet - excel

In my folder, there is AA.bmp, AA.txt, BB.bmp and BB.txt
I am able to extract the data for AA.txt and BB.txt in a separate worksheet.
Am I also able to insert AA.bmp in the same sheet as AA.txt, and BB.bmp in the same sheet as BB.txt?
Sub ExtractData()
iPath = "C:\Users\NHWD78\Desktop\Report\Radiated Immunity\"
ifile = Dir(iPath & "*.txt")
Do While Len(ifile)
Sheets.Add , Sheets(Sheets.Count), , iPath & ifile
ifile = Dir
Range("A10:B10, A16:B19").Copy Destination:=Sheets(Sheets.Count).Range("A1")
Application.CutCopyMode = False
Range("A6:K600").Clear
Columns.AutoFit
Loop
End Sub
I have search throughout the website but only found a way to insert a fixed image with image name.

This will answer your query, its more of a solution than an answer which is not what this site is for, but take the time to read through it as it should be educationally useful too.
You are trying to parse a folder that has content similar to below:-
The result os for these to be in an Excel workbook, with a worksheet containing the text and image for each group (AA, BB, and CC)
First step I would take is to use Microsoft Scripting Runtime, this makes parsing the folder a lot easier. To enable this, within the VBA environment (known as the IDE), select 'Tools' > 'References...', scroll down to 'Microsoft Scripting Runtime' and tick it, then click 'OK' to close the dialog box.
That allows us to the File System Object, which is a very useful file and folder manipulation and interrogation feature set.
Firstly we care most about the *.txt files so lets begin by looping through them:-
Dim FSO As New FileSystemObject
Dim Fldr As Folder
Dim Fl As File
'First we set Fldr to be the folder we care about
Set Fldr = FSO.GetFolder("C:\Users\garye\Desktop\Work")
'Then start a loop to look through each file in the folder
For Each Fl In Fldr.Files
'If the files ends in .txt then we care about it (UCASE used to make it case insensitive)
If Right(UCase(Fl.Name), 4) = ".TXT" Then
'We have found a file
End If
'Do events returns the processor to the system for any other items to be process
'very useful in a loop on a Windows based machine to stop resource hogging and lock ups
DoEvents
Next
Set Fldr = Nothing
Next on the discovery of a text file we want to create a worksheet and import the text. For the sake of this example, it will all be done in a new workbook as well.
Dim WkBk As Workbook
Dim WkBk_Tmp As Workbook
Dim WkSht As Worksheet
Dim WkSht_Tmp As Worksheet
Dim StrName As String
'Create a new workbook
Set WkBk = Application.Workbooks.Add
'...
'Collect the name (i.e. AA from AA.txt)
StrName = Left(Fl.Name, Len(Fl.Name) - 4)
'Create a new worksheet in out new workbook
Set WkSht = WkBk.Worksheets.Add
'Change the worksheet name to the file name
WkSht.Name = StrName
'Open the file in Excel
Set WkBk_Tmp = Application.Workbooks.Open(Fl.Path)
Set WkSht_Tmp = WkBk_Tmp.Worksheets(1)
'Copy its contents into out worksheet
WkSht_Tmp.Cells.Copy WkSht.Cells
Set WkSht_Tmp = Nothing
'Close the file
WkBk_Tmp.Close 0
Set WkBk_Tmp = Nothing
Next we want to insert the image if it is there:-
Dim Rng As Range
'...
'See it a bmp file exists (i.e. AA.bmp)
If FSO.FileExists(Fldr.Path & "\" & StrName & ".bmp") Then
'This get the bottom row of data as a position to insert the image
Set Rng = WkSht.Range(WkSht.Range("A1").End(xlDown).Address).Next(2, 0)
'Add the picture
WkSht.Shapes.AddPicture Fldr.Path & "\" & StrName & ".bmp", msoFalse, msoCTrue, Rng.Left, Rng.Top, -1, -1
Set Rng = Nothing
End If
If we put all the above together it looks as below, hopefully this has been education in what is happening in the code, some good practices, how to approaching a task.
Option Explicit
Sub ExtractData()
Dim FSO As New FileSystemObject
Dim Fldr As Folder
Dim Fl As File
Dim WkBk As Workbook
Dim WkBk_Tmp As Workbook
Dim WkSht As Worksheet
Dim WkSht_Tmp As Worksheet
Dim StrName As String
Dim Rng As Range
'Create a new workbook
Set WkBk = Application.Workbooks.Add
'First we set Fldr to be the folder we care about
Set Fldr = FSO.GetFolder("C:\Users\garye\Desktop\Work")
'Then start a loop to look through each file in the folder
For Each Fl In Fldr.Files
'If the files ends in .txt then we care about it (UCASE used to make it case insensitive)
If Right(UCase(Fl.Name), 4) = ".TXT" Then
'Collect the name (i.e. AA from AA.txt)
StrName = Left(Fl.Name, Len(Fl.Name) - 4)
'Create a new worksheet in out new workbook
Set WkSht = WkBk.Worksheets.Add
'Change the worksheet name to the file name
WkSht.Name = StrName
'Open the file in Excel
Set WkBk_Tmp = Application.Workbooks.Open(Fl.Path)
Set WkSht_Tmp = WkBk_Tmp.Worksheets(1)
'Copy its contents into out worksheet
WkSht_Tmp.Cells.Copy WkSht.Cells
Set WkSht_Tmp = Nothing
'Close the file
WkBk_Tmp.Close 0
Set WkBk_Tmp = Nothing
'See it a bmp file exists (i.e. AA.bmp)
If FSO.FileExists(Fldr.Path & "\" & StrName & ".bmp") Then
'This get the bottom row of data as a position to insert the image
Set Rng = WkSht.Range(WkSht.Range("A1").End(xlDown).Address).Next(2, 0)
'Add the picture
WkSht.Shapes.AddPicture Fldr.Path & "\" & StrName & ".bmp", msoFalse, msoCTrue, Rng.Left, Rng.Top, -1, -1
Set Rng = Nothing
End If
Set WkSht = Nothing
End If
'Do events returns the processor to the system for any other items to be process
'very useful in a loop on a Windows based machine to stop resource hogging and lock ups
DoEvents
Next
Set Fldr = Nothing
Set WkBk = Nothing
MsgBox "Done!"
End Sub

Worksheet.Shapes.AddPicture will do it. Example below: -
Public Sub Sample()
Dim WkBk As Workbook
Dim WkSht As Worksheet
Dim Ole As Object
Set WkBk = ThisWorkbook
Set WkSht = WkBk.Worksheets(1)
WkSht.Shapes.AddPicture "C:\Users\garye\Desktop\AA.bmp", msoFalse, msoCTrue, 0, 0, -1, -1
Set WkSht = Nothing
Set WkBk = Nothing
End Sub

Related

How to find cell value in file names in a folder and open that file? File name contains more characters than cell value

This is the first week I learn vba so bear with me if I have a lot of questions;-)
So I have two folders, one folder contains the templates I need to update, the other contains the reports that the updates will be copied from. Cell A1 in each template contains the code that is specific to that BU. I need vba to find the code in the file names in the report folder and open that report. The problem is that the report names have different lengths, eg. it's named as XXX region_code_XXXXXXXXXXX, there can be any number of "X" before and after the code.
Sub Macro1()
Set fso = CreateObject("scripting.filesystemobject")
Set ff = fso.getfolder("C:\Users\35264\summary\test")
For Each file In ff.Files
Workbooks.Openfile
Set wbk2 = ActiveWorkbook
Sheets("Summary").Select
Range("A1").Select
rngX = Range("A1").Value
Now I need to find rngX in the file names in the report folder... I can't figure out how. Let me know if anyone can help! Thank you!
I am learning how to use dir function. I think it will be helpful to get the names of the reports first.
Combine the FileSystemObject Object With the Dir Function
Dir cannot be used in nested Do...Loops.
Using the FileSystemObject object, it opens files in one folder and uses the information in it to open specific files in another folder by using the Dir function. For each combination, it prints their names to the immediate window and closes each file without saving changes.
A better way to do this would be to write the file paths of the first folder to an array by using the Dir function and then loop through the elements of the array to open each file... etc.
Option Explicit
Sub PrintTemplatesAndReports()
' Templates
Const tFolderPath As String = "C:\Users\35264\summary\templates\"
Const tWorksheetName As String = "Summary"
Const rFilePatternAddress As String = "A1"
Const tFileExtensionLeft As String = "xls"
' Reports
Const rFolderPath As String = "C:\Users\35264\summary\reports\"
Const rFileExtensionPattern As String = ".xls*"
' 1st Worbook (ThisWorkbook)
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FolderExists(tFolderPath) Then Exit Sub
If Not fso.FolderExists(rFolderPath) Then Exit Sub
Dim fsoFolder As Object: Set fsoFolder = fso.Getfolder(tFolderPath)
' Templates (using the FileSystemObject object)
Dim fsoFile As Object
Dim twb As Workbook, tws As Worksheet
Dim tExtension As String, tFilePath As String
' Report (using Dir)
Dim rwb As Workbook
Dim rFilePattern As String, rFileName As String, rFilePath As String
' Counters
Dim ttCount As Long, tCount As Long, rCount As Long
For Each fsoFile In fsoFolder.Files
ttCount = ttCount + 1
tExtension = fso.GetExtensionName(fsoFile)
If InStr(1, tExtension, tFileExtensionLeft, vbTextCompare) = 1 Then
tCount = tCount + 1
tFilePath = tFolderPath & fsoFile.Name
' 2nd Workbook (Template)
Set twb = Workbooks.Open(tFilePath)
On Error Resume Next
Set tws = twb.Worksheets(tWorksheetName)
On Error GoTo 0
If Not tws Is Nothing Then
rFilePattern = CStr(tws.Range(rFilePatternAddress).Value)
rFileName = Dir(rFolderPath, "*" & rFilePattern _
& "*" & rFileExtensionPattern)
Do Until Len(rFileName) = 0
rCount = rCount + 1
rFilePath = rFolderPath & rFileName
' 3rd Workbook (Report)
Set rwb = Workbooks.Open(rFolderPath, rFileName)
' Do your thing, e.g.:
Debug.Print twb.Name, rwb.Name
rwb.Close SaveChanges:=False
rFileName = Dir ' next report
Loop
Set tws = Nothing
End If
twb.Close SaveChanges:=False
End If
Next fsoFile ' next template
MsgBox "Template files processed: " & tCount & "(" & ttCount & ")" _
& vbLf & "Report files processed: " & rCount & "(" & tCount & ")", _
vbInformation
End Sub

Get new worksheet from clicking a button

so currently i have this code that loops through a folder of mine specified by me and goes through every single file in the folder to extract Ranges "A18,A19,A14" and copy it to the current worksheet.
However now i need to change the way it works, now i would like to have a main sheet that contains the button to generate the coding that i have written as shown below but in a new sheet.
So basically what i need now is to have a main control sheet that only contains buttons , then do changes to the coding so that it creates a new sheet and generate the data there in the new sheet instead of the main control sheet.
Here is the image for the control sheet
Starting
And here is the end result i wish to get
What i need to see
Also, i have tried myself before asking this question on adding new sheets however it doesn't work
,here is the image of it
Not Working
Somehow it just extracts from one file when its supposed to extract 6 lines as shown in the "What i need to see" Picture.
I really appreciate any help, but if possible pls provide me the small part of the code needed to make this work!
Here is what i have currently
Sub ScanFiles()
Dim myFile As String, path As String
Dim erow As Long, col As Long
path = "c:\Users\Desktop\Tryout\"
myFile = Dir(path & "")
Application.ScreenUpdating = False
Range("A2:I20").ClearContents
Range("A1") = "Test"
Range("B1") = "Temp"
Range("C1") = "Start"
Range("D1") = "Type"
Do While myFile <> ""
Workbooks.Open (path & myFile)
Windows(myFile).Activate
ActiveSheet.Name = "Sheet1"
Set copyrange = Sheets("Sheet1").Range("A18,A19,A14,A19")
Windows("Reset.xlsm").Activate
erow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
col = 1
For Each cel In copyrange
cel.Copy
Cells(erow, col).PasteSpecial xlPasteValues
col = col + 1
Next
Windows(myFile).Close savechanges:=False
myFile = Dir()
Loop
Debug.Print myFile
Range("A:I").EntireColumn.AutoFit
Application.ScreenUpdating = True
End Sub
Ok, here try this.. Something I quickly wrote (busy at work). I have made a few assumptions being the Folder you loop thru has only the excel files you need to loop over. 2nd assumtion is each file only has 1 tab. These 2 assumptions are easily fixed if wrong.
I have made reference to Microsoft Scripting Runtime for FSO. DIR is a dead, I only ever use FSO as it much more useful and you can nest FSO loops (something you can't do with DIR)
Also included is an array to store your CopyRange to we can make you code nater and use a single For Loop.
Option Explicit
Sub ScanFiles()
Application.ScreenUpdating = False
Dim wkb As Workbook
Set wkb = ThisWorkbook
Dim wks As Worksheet
Set wks = Worksheets.Add
wks.Name = "NewWorksheet"
' Add Worksheet to accept data
With wks
'.Range("A2:I20").ClearContents -> No longer needed as you create a new sheet
.Range("A1:D1") = Array("Test", "Temp", "Start", "Type")
End With
' Set your copy ranges
Dim CopyRange(1 To 4) As String
CopyRange(1) = "A18"
CopyRange(2) = "A19"
CopyRange(3) = "A14"
CopyRange(4) = "A19"
' Early Binding - Add "Microsoft Scripting Runtime" Reference
Dim FSO As New Scripting.FileSystemObject
' Set FolderPath
Dim FolderPath As String
FolderPath = "c:\Users\Desktop\Tryout\"
' Set Folder FSO
Dim Folder As Scripting.Folder
Set Folder = FSO.GetFolder(FolderPath)
' Loop thru each file -> Assuming only 6 files as per you question
Dim File As Scripting.File
For Each File In Folder.Files
Dim wkbData As Workbook
Set wkbData = Workbooks.Open(File.path)
Dim wksData As Worksheet
Set wksData = wkbData.Worksheets("Sheet1") ' -> Assume this file has only 1 worksheet
Dim BlankRow As Long
BlankRow = wks.Range("A" & wks.Rows.Count).End(xlUp).Row + 1
Dim i As Long
For i = 1 To 4
wks.Cells(BlankRow, i).Value = wksData.Range(CopyRange(i)).Value
Next i
wkbData.Close False
Next File
Range("A:I").EntireColumn.AutoFit
Application.ScreenUpdating = True
End Sub

Excel Load list of files in a folder to worksheets with contents on click

Good day.
I am looking for a solution for a problem, where in i have hundreds of CSV files located in a folder/nested folders.
I am trying to write a VBA script, which loads the list of files in this directory to Excel's work sheet-1 as soft links to each files. when a link is clicked, i am expecting the file contents to be loaded to worksheet 2, which would be used for further reporting purposes.
I have tried writing a VB script to extract the list of folder contents, however, i couldn't get them converted to soft links and loading the file contents. Any suggestions on how (else) could this be achieved ?
Any help in this regard is highly appreciated. Thanks in advance.
There will be 2 parts of code. First code will go to a module to list names of the files in the folder and addresses. First column will be names, second column will be addresses
Sub ListFiles()
Dim wb As Workbook
Dim ws As Worksheet
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
Dim i As Long
Set wb = ActiveWorkbook '<-- Master workbook
Set ws = wb.Sheets("Sheet1") '<-- Sheet you store file names and addresses
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder("C:\youfolderaddress")
i = 1
For Each objFile In objFolder.Files
ws.Cells(i + 1, 1) = objFile.Name
ws.Cells(i + 1, 2) = objFile.Path
i = i + 1
Next objFile
End Sub
Second part will go to worksheet where you store the list of files and we are going to use workshet selection change:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim wb As Workbook
Dim ws1, ws2 As Worksheet
Dim newBook As Workbook
Dim newSheet As Worksheet
Set wb = ActiveWorkbook '<- Master workbook with all list etc.
Set ws1 = wb.Sheets("Sheet1") '<-- Sheet that contains the list
Set ws2 = wb.Sheets("Sheet2") '<-- Sheet that will display csv content
If Target.Column = 2 And Target.Value <> "" Then '2 is the number of the column that contains file addresses
ws2.Cells.ClearContents
Workbooks.Open Filename:=Target.Value
Set newBook = ActiveWorkbook
Set newSheet = newBook.ActiveSheet
newSheet.Cells.Copy
ws2.Activate
ActiveSheet.Cells(1, 1).Select
ActiveSheet.Paste
Application.DisplayAlerts = False
newBook.Close
Application.DisplayAlerts = True
End If
End Sub
You could use event handlers. I assume that you are able to load the names into sheet 1 and set a range variable equal to the resulting range of names. You can then use the selection change event to trigger your loading code using something like the following (in the sheet1 code module). Clicking on a cell containing a file name will cause that name to be displayed:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim fnames As Range
Set fnames = Range("fnames") 'adjust to match your code
If Union(Target, fnames).Address = fnames.Address And _
Target.Cells.Count = 1 Then
MsgBox Target.Value 'replace this by code to load csv in sheet 2
End If
End Sub
With this code you can, with a default directory, retreive the list of file and add on sheet with the list (linked) of this file.
You can change this code with your to select the different directory
Sub ListAllFile()
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
Dim ws As Worksheet
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set ws = Worksheets.Add
'Get the folder object associated with the directory
Set objFolder = objFSO.GetFolder("C:\Users\Desktop\Code\Excel")
ws.Cells(1, 1).Value = "The files found in " & objFolder.Name & "are:"
'Loop through the Files collection
For Each objFile In objFolder.Files
ws.Cells(ws.UsedRange.Rows.Count + 1, 1).Select
Selection.Hyperlinks.Add Anchor:=Selection, Address:=objFile.Name
Next
'Clean up!
Set objFolder = Nothing
Set objFile = Nothing
Set objFSO = Nothing
End Sub

Concatenate index name in the Workbooks Object

I am trying to create For Each loop for a several workbooks; however I am not able to set the workbook name in the array and thus resulted into this. I'm stuck in trying to concatenate the workbook name.
Here's my code:
'Open all .csv file in folder location
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(ThisWorkbook.Path)
For Each objFile In objFolder.Files
If InStr(objFile, ".csv") Then
Workbooks.Open (objFile)
End If
Next
' Declare variables
Dim WrkBkPrm As Workbook
Dim WrkBkSrc As Workbook
Dim WrkShtPrm As Worksheet
Dim WrkShtSrc As Worksheet
Dim TextSrc(4) As String
Dim SrcRng As Range
Dim DRng As Range
' Assign values to TextSrc() Array
TextSrc(0) = Cable
TextSrc(1) = Care
TextSrc(2) = MSD
TextSrc(3) = Business
'Set WrkBkPrm and WrkShtPrm values
Set WrkBkPrm = Workbooks("MasterFile" & ".xlsm")
Set WrkShtPrm = WrkBkPrm.Worksheets("Canvas")
'Activate Canvas Sheet
WrkBkPrm.Activate
WrkShtPrm.Select
Application.ScreenUpdating = False
'Start For Each Loop
For Each Src In TextSrc()
Set WrkBkSrc = Workbooks(Src & ".csv")
Set WrkShtSrc = WrkBkSrc.Worksheets(Src)
'Copy loop for 1st section
For i = 2 To 49
For j = 7 To 25
Set SrcRng = WrkShtSrc.Cells(i, j)
Set DRng = WrkShtPrm.Cells(i, j)
If SrcRng <> "" Then
DRng.Value = SrcRng.Value
End If
Next j
Next i
Next Src
Application.ScreenUpdating = True
I'd suggest you work on the file as soon as you get hold of the relevant info you need.
Something like:
Dim wb As Workbook
For Each objFile In objFolder.Files
If InStr(objFile.Name, ".csv") <> 0 Then
Set wb = Workbooks.Open(Thisworkbook.Path & "\" & objFile.Name)
'~~> Do your cool stuff with the opened CSV File
wb.Close False '~~> Close without saving
Set wb = Nothing '~~> Clean up although most of the time not necessary
End If
Next
As for the route you took, for you to use For Each Loop on TxtSrc, you need to declare it as variant.
Something like:
Dim TxtSrc As Variant, Src As Variant
TxtSrc = Array("Cable", "Care", "MSD", "Business")
For Each Src In TxtSrc
Set wb = Workbooks.Open(Thisworkbook.Path & "\" & Src & ".csv")
'~~> More cool stuff here
wb.Close False
Set wb = Nothing
Next
It is important that provide the correct argument for the Workbook Open Method.
You should always include the complete path in string format. HTH.

Looping through sub-folders in a parent directory - vba

I am looking to copy/paste data from workbooks within different sub-folders within a user selected directory.
To explain: Basically, I want to automate a process whereby I perform a copy/paste ritual from many workbooks into one Summary Workbook (from which the code is initiated).
I have allowed user input to select the parent directory in which the subfolders are contained.
I have reached the stage where the looping occurs, but the data is not being copied and pasted.
Can anyone see flaw in my code or why it is not working?
Your help will be greatly appreciated.
Sub AAA()
Dim FSO As Scripting.FileSystemObject
Dim FF As Scripting.Folder
Dim SubF As Scripting.Folder
Dim strFolderName As String
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
If .Show = -1 Then
strFolderName = .SelectedItems(1)
Else
MsgBox ("Selection Cancelled")
Exit Sub
End If
End With
Set FSO = New Scripting.FileSystemObject
Set FF = FSO.GetFolder(strFolderName)
For Each SubF In FF.SubFolders
DoOneFolder SubF
Next SubF
End Sub
Sub DoOneFolder(FF As Scripting.Folder)
Dim F As Scripting.File
Dim SubF As Scripting.Folder
Dim WBc As Workbook
Dim shtWBc As Object
Set shtWBc = Sheets("QC Results")
Dim shtBatchwbk As Object
Dim lastrow As Long
Set shtBatchwbk = ThisWorkbook.Sheets("QC Results")
lastrow = shtBatchwbk.Range("A65536").End(xlUp).Row
For Each F In FF.Files
If (F.Name) Like "QC_results*" & ".xlsm" Then
Set WBc = Workbooks.Open(F)
' Copy QC results range into batch summary workbook
shtWBc.Range("A4:SA11").Copy shtBatchwbk.Range("A" & lastrow)
WBc.Close SaveChanges:=False
Debug.Print F.Name
End If
Next F
For Each SubF In FF.SubFolders
DoOneFolder SubF
Next SubF
End Sub
I believe your problem is here:
Sub DoOneFolder(FF As Scripting.Folder)
Dim F As Scripting.File
Dim SubF As Scripting.Folder
Dim WBc As Workbook
Dim shtWBc As Object
Set shtWBc = Sheets("QC Results")
Dim shtBatchwbk As Object
Dim lastrow As Long
Set shtBatchwbk = ThisWorkbook.Sheets("QC Results")
lastrow = shtBatchwbk.Range("A65536").End(xlUp).Row
Notice that shtWBc and shtBatchwbk are most likely assigned to the exact same worksheet object.
shtBatchwbk is assigned from ThisWorkbook, and unless you have other workbooks open/active at the time, then shtWBc is assigned from the ActiveWorkbook, which would be the same workbook, thus the exact same worksheet.
The resolution would seem to be:
For Each F In FF.Files
If (F.Name) Like "QC_results*" & ".xlsm" Then
Set WBc = Workbooks.Open(F)
Set shtWBc = WBc.Sheets("QC Results") '##### ASSIGN THIS WORKSHEET FROM THE NEWLY OPNEED WORKBOOk
'Get the last row:
lastrow = shtBatchwbk.Range("A65536").End(xlUp).Row
' Copy QC results range into batch summary workbook
shtWBc.Range("A4:SA11").Copy shtBatchwbk.Range("A" & lastrow)
WBc.Close SaveChanges:=False
Debug.Print F.Name
End If
Next F
Otherwise, revise your Q to provide more detail per Alexandre's comment.
UPDATE FROM COMMENTS
If you only need values, then this should be more reliable and faster than copy/paste.
Instead of:
shtWBc.Range("A4:SA11").Copy shtBatchwbk.Range("A" & lastrow)
Do this:
shtBatchwbk.Range("A" & lastrow).Resize( _
shtWBc.Range("A4:SA11").Rows.Count, _
shtWBc.Range("A4:SA11").Columns.Count).Value = shtWBc.Range("A4:SA11").Value
And if you also want to copy formatting without doing the full "copy" because it sometimes changes/transposes numbers, etc., then you can add this as well:
shtWBc.Range("A4:SA11").Copy
shtBatchwbk.Range("A" & lastrow).PasteSpecial xlPasteFormats

Resources