Copy Cells from 2 or more workbooks to a new workbook - vba

I am trying to write some code which copies cells C24, C25 and D24, D25 from all the .xls files from location "C:\MyPath\" and I'm new to using VBA but I was looking for some solution online and was able to make up some code which combines all excel files in a folder and copies it to single workbook with each workbook going into each sheet.
Th code I worked on is
Option Explicit
Sub CopyWorksheets()
Const sPath = "C:\MyPath\"
Dim sFile As String
Dim wbkSource As Workbook
Dim wSource As Worksheet
Dim wbkTarget As Workbook
On Error GoTo ErrHandler
Application.ScreenUpdating = False
Set wbkTarget = ActiveWorkbook
sFile = Dir(sPath & "*.xls*")
Do While Not sFile = ""
Set wbkSource = Workbooks.Open(Filename:=sPath & sFile, AddToMRU:=False)
For Each wSource In wbkSource.Worksheets
With wbkTarget
wSource.Copy After:=.Sheets(.Sheets.Count)
End With
Next
wbkSource.Close SaveChanges:=False
sFile = Dir
Loop
ExitHandler:
Application.ScreenUpdating = True
Exit Sub
ErrHandler:
MsgBox Err.Description, vbExclamation
Resume ExitHandler
End Sub
May I know the changes or additions to the above code to get my solution?

I copied your code to a new workbook. I renamed worksheet Sheet1 as C24D25 and created a header row:
A B C D E F
1 Workbook Worksheet C24 D24 C25 D25
At the top of your routine I added the extra variables and constants I required:
Const colTgtWbk As Long = 1
Const colTgtWsht As Long = 2
Const colTgtC24 As Long = 3
Const colTgtC25 As Long = 5
Dim wshtTarget As Worksheet
Dim rowTgtCrnt As Long
Set wshtTarget = ActiveWorkbook.Worksheets("C24D25")
rowTgtCrnt = 2
Replace “C24D25” with your name for the worksheet into which values are collected.
I amended the definition of sPath to a folder on my laptop containing several workbooks.
Near the top of your code I commented out:
'On Error GoTo ErrHandler
and near the end I commented out:
'ExitHandler:
'Exit Sub
'ErrHandler:
'MsgBox Err.Description, vbExclamation
'Resume ExitHandler
I never include my own error handler during development and I never include one in a production macro unless I have discovered a need during development. An error handler routine is not the best method for handling errors you expect and can test for. They should be reserved for errors you cannot test for such as attempting to open a file for which you may not have read permission.
Around your main block:
Set wbkSource = Workbooks.Open(Filename:=sPath & sFile, AddToMRU:=False)
to
wbkSource.Close SaveChanges:=False
I added an If:
If sFile <> wbkTarget.Name Then
End If
This avoids attempting to reopen the workbook in which you are collecting data.
I deleted:
With wbkTarget
wSource.Copy After:=.Sheets(.Sheets.Count)
End With
and replaced this code with:
With wshtTarget
.Cells(rowTgtCrnt, colTgtWbk).Value = wbkSource.Name
.Cells(rowTgtCrnt, colTgtWsht).Value = wSource.Name
wSource.Range("C24:D24").Copy Destination:=.Cells(rowTgtCrnt, colTgtC24)
wSource.Range("C25:D25").Copy Destination:=.Cells(rowTgtCrnt, colTgtC25)
rowTgtCrnt = rowTgtCrnt + 1
End With
This is the code that builds the rows in worksheet C24D25.
At the bottom I added:
wshtTarget.Columns.AutoFit
This expands the columns to the width of the data found.
The result of the changes above is:
Option Explicit
Sub CopyWorksheets()
Const colTgtWbk As Long = 1
Const colTgtWsht As Long = 2
Const colTgtC24 As Long = 3
Const colTgtC25 As Long = 5
Dim wshtTarget As Worksheet
Dim rowTgtCrnt As Long
Set wshtTarget = ActiveWorkbook.Worksheets("C24D25")
rowTgtCrnt = 2
Const sPath = "C:\DataArea\SOTest\Excel\"
Dim sFile As String
Dim wbkSource As Workbook
Dim wSource As Worksheet
Dim wbkTarget As Workbook
Application.ScreenUpdating = False
Set wbkTarget = ActiveWorkbook
sFile = Dir(sPath & "*.xls*")
Do While sFile <> ""
If sFile <> wbkTarget.Name Then
Set wbkSource = Workbooks.Open(Filename:=sPath & sFile, AddToMRU:=False)
For Each wSource In wbkSource.Worksheets
With wshtTarget
.Cells(rowTgtCrnt, colTgtWbk).Value = wbkSource.Name
.Cells(rowTgtCrnt, colTgtWsht).Value = wSource.Name
wSource.Range("C24:D24").Copy Destination:=.Cells(rowTgtCrnt, colTgtC24)
wSource.Range("C25:D25").Copy Destination:=.Cells(rowTgtCrnt, colTgtC25)
rowTgtCrnt = rowTgtCrnt + 1
End With
Next
wbkSource.Close SaveChanges:=False
End If
sFile = Dir
Loop
wshtTarget.Columns.AutoFit
Application.ScreenUpdating = True
End Sub
I hope the purposes of the changes I have made are obvious, Ask questions if necessary.

Related

Trying to copy static cell value from workbook A and paste into dynamic location in workbook B

I'm trying to:
Copy cell "B2:C2" from every workbook in a folder from the "Results" worksheet.
Paste the value into Cell A1:A2 Sheet1 in workbook "x"in the same folder.
I think I know how to open and do something to every workbook within a folder.
Option Explicit
Sub LoopThroughDirectory()
Dim MyFile As String
Dim WorkbookCounter As Long
WorkbookCounter = 1
Dim Filepath As String
Dim wb As Workbook
Dim RowCounter As Long
RowCounter = 1
Filepath = "C:\Test\"
Application.ScreenUpdating = False
MyFile = Dir(Filepath)
'Opens workbooks located C:\Test\ in order
Do While Len(MyFile) > 0
Set wb = Workbooks.Open(Filepath & MyFile)
Application.DisplayAlerts = False
'Copy cells B2 & C2 from the results worksheet
ThisWorkbook.Worksheets("x").Range(Cells(RowCounter, 1), Cells(RowCounter, 2)).Value = _
wb.Worksheets("Results").Range("B2:C2").Value
'Close wb most recently opened
wb.Close SaveChanges:=False
Application.CutCopyMode = False
WorkbookCounter = WorkbookCounter + 1
If WorkbookCounter > 1000 Then
Exit Sub
End If
MyFile = Dir
RowCounter = RowCounter + 1
Loop
ActiveWorkbook.Save
Application.ScreenUpdating = True
End Sub
Update: With help in the comments below the above code now correctly loops through the correct folder and updates cell A1:A2.
Instead of overwriting cell A1:A2 I'd like to paste the copied text one line down.
i.e. Workbook 1 = A1:A2, Workbook 2 = B1:B2, etc
I don't see any check to make sure you are not trying to open ThisWorkbook and there is no check to see if there is a Results worksheet in the source workbook; in fact there is no check to ensure that you are trying to open a workbook at all, you could be trying to open a JPG.
Further error control could be added to ensure that you are not trying to open another workbook that is already open. I suspect that after all the testing, you might have a few.
Option Explicit
Sub LoopThroughDirectory()
Dim myFile As String, filepath As String
Dim wbc As Long, ws As Worksheet, wb As Workbook
wbc = 0
filepath = "C:\Test\"
'Application.ScreenUpdating = False
'only try to open workbooks
myFile = Dir(filepath & "*.xls*")
'Opens workbooks located C:\Test\ in order
Do While Len(myFile) > 0
'make sure myFile isn't ThisWorkbook
If Split(myFile & ".", ".")(0) <> Split(ThisWorkbook.Name & ".", ".")(0) Then
Set wb = Workbooks.Open(Filename:=filepath & myFile, ReadOnly:=True)
'Application.DisplayAlerts = False
'check if there is a Results worksheet
On Error Resume Next
Set ws = wb.Worksheets("Results")
On Error GoTo 0
If Not ws Is Nothing Then
'transfer cells B2 & C2 from the results worksheet
With ws.Range("B2:C2")
ThisWorkbook.Worksheets("x").Range("A1").Offset(wbc, 0).Resize(.Rows.Count, .Columns.Count) = .Value
End With
End If
'Close wb most recently opened
wb.Close SaveChanges:=False
wbc = wbc + 1
If wbc > 1000 Then Exit Do
End If
Set ws = Nothing
myFile = Dir
Loop
ActiveWorkbook.Save
'Application.ScreenUpdating = True
End Sub

Copy data from multiple workbook to one workbook after using Autofilter

I am trying to copy data from multiple WB to one WB after using filter. I am able to select the copy range but I don't know how to paste them to the destination WB without making the data overwritten.
I am sorry for the format of my code. I do not know how to fix it when I post it here.
Here is my code:
Option Explicit
Const FOLDER_PATH = "D:\Programming\VBA\Linh\CARD DELIVERY\New folder\" 'REMEMBER END BACKSLASH
Sub ImportWorksheets()
'=============================================
'Process all Excel files in specified folder
'=============================================
Dim sFile As String 'file to process
Dim wsTarget As Worksheet
Dim wbSource As Workbook
Dim wsSource As Worksheet
Dim rowTarget As Long 'output row
Dim rowCount As Long
rowTarget = 2
'check the folder exists
If Not FileFolderExists(FOLDER_PATH) Then
MsgBox "Specified folder does not exist, exiting!"
Exit Sub
End If
'reset application settings in event of error
On Error GoTo errHandler
Application.ScreenUpdating = False
'set up the target worksheet
Set wsTarget = Sheets("Sheet1")
'loop through the Excel files in the folder
sFile = Dir(FOLDER_PATH & "*.xls*")
Do Until sFile = ""
'open the source file and set the source worksheet - ASSUMED WORKSHEET(1)
Set wbSource = Workbooks.Open(FOLDER_PATH & sFile)
Set wsSource = wbSource.Worksheets(1) 'EDIT IF NECESSARY
wsSource.Range("A2", Range("P" & Rows.Count).End(xlUp)).AutoFilter Field:=12, Criteria1:="Phát thành công"
wsSource.Range("I2", Range("I" & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible).Copy
rowCount = wsSource.Range("I2", Range("I" & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible).Cells.Count
'import the data
With wsTarget
End With
'close the source workbook, increment the output row and get the next file
wbSource.Close SaveChanges:=False
rowTarget = rowTarget + 1
sFile = Dir()
Loop
errHandler:
On Error Resume Next
Application.ScreenUpdating = True
'tidy up
Set wsSource = Nothing
Set wbSource = Nothing
Set wsTarget = Nothing
End Sub
Private Function FileFolderExists(strPath As String) As Boolean
If Not Dir(strPath, vbDirectory) = vbNullString Then FileFolderExists = True
End Function
just add:
'import the data
wsTarget
.cells(.Rows.Count, "A").End(xlUp).Offset(1).PasteSpecial
End With
to keep pasting filtered data in wsTarget column A from row 2 downwards

combine multiple text files in a single excel sheet

I have 27 txt files with the same format and columns, and I want to append all of these in a single excel sheet. I have checked some previous threads here, but I could only find the code below which helped me to import txt fiels into separate sheets. However, I also want to append these separate sheets into a sheet that I want to append all my data.
Sub Test()
'UpdatebyExtendoffice6/7/2016
Dim xWb As Workbook
Dim xToBook As Workbook
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
Dim xFiles As New Collection
Dim I As Long
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a folder [Vendor_data_25DEC]"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
If Right(xStrPath, 1) <> "\" Then xStrPath = xStrPath & "\"
xFile = Dir(xStrPath)
'xFile = Dir(xStrPath & "*.txt") 'this is the original version that you can amend according to file extension
If xFile = "" Then
MsgBox "No files found", vbInformation, "Vendor_data_25DEC"
Exit Sub
End If
Do While xFile <> ""
xFiles.Add xFile, xFile
xFile = Dir()
Loop
Set xToBook = ThisWorkbook
If xFiles.Count > 0 Then
For I = 1 To xFiles.Count
Set xWb = Workbooks.Open(xStrPath & xFiles.Item(I))
xWb.Worksheets(1).Copy after:=xToBook.Sheets(xToBook.Sheets.Count)
On Error Resume Next
ActiveSheet.Name = xWb.Name
On Error GoTo 0
xWb.Close False
Next
End If
End Sub
I am not sure how to do this with VBA in order to combine the data in separate sheets into a single sheet quickly. I know the consolidate feature of excel but it also includes lots of manual steps, so I seek for a faster and automated solution. Any help is much appreciated.
Thanks a lot in advance.
Sub Combiner()
Dim strTextFilePath$, strFolder$
Dim wksTarget As Worksheet
Dim wksSource As Worksheet
Dim x As Long
Set wksTarget = Sheets.Add()
strFolder = "c:\Temp\test\"
strTextFilePath = Dir(strFolder)
While Len(strTextFilePath) > 0
'// "x" variable is just a counter.
'// It's purpose is to track whether the iteration is first or not.
'// If iteration is first (x=1), then we include header (zero offset down),
'// otherwise - we make an offset (1 row offset down).
x = x + 1
Set wksSource = Workbooks.Open(strFolder & strTextFilePath).Sheets(1)
With wksTarget
wksSource.Range("A1").CurrentRegion.Offset(IIf(x = 1, 0, 1)).Copy _
.Cells(.Rows.Count, 1).End(xlUp).Offset(1)
End With
wksSource.Parent.Close False
strTextFilePath = Dir()
Wend
MsgBox "Well done!", vbInformation
End Sub

Name Already exist error for newly created tab using VBA

I tried to create VBA macro in excel where one excel sheet tracks a path and creates a new tab in another sheet. It works well but when I create another tab "accidentally" with same name it gives me error as "Name already taken try another one". I don't want to create one more tab with same name. Instead it should stop me from creating tabs with same name
Is there anyway if there that name already exist it gives me a pop up saying name already exist I get only one option as ok to click. I click Ok and the additional sheet that is created doesn't get saved (or if already created deletes itself or save as same name with (2) next to it as excel usually do for repeated sheets). I am trying something like this
If wb.ActiveSheet.Name = sName Then wb.ActiveSheet.Delete
Here is my code
Private Sub Filling_List()
Dim sPath As String
Dim sFile As String
Dim wb As Workbook
Dim sName As String 'add sName declaration
Dim wb1 As Workbook
Dim ws1 As Worksheet
Set wb1 = ThisWorkbook
Set ws1 = ThisWorkbook.Worksheets("S0")
Application.ScreenUpdating = False
sPath = "C:\Users\arp\Desktop\Filling list macro\"
sFile = sPath & "ArF Filling List.xlsm"
Set wb = Workbooks.Open(sFile)
wb.Worksheets("ArF Templete").Copy After:=Worksheets(Worksheets.Count)
sName = ws1.Range("A1") & " " & ws1.Range("T2")
wb.ActiveSheet.Name = sName
'If wb.ActiveSheet.Name = sName Then wb.ActiveSheet.Delete "I am trying this but it doesn't work"
If sName = vbNullString Then Exit Sub 'compare against vbNullstring not empty string literal
With wb.Worksheets(sName)
.Cells(3, "E") = InputBox("Your Initials:")
'.Cells(5, "E") = InputBox("Col?:")
.Cells(6, "E") = InputBox("I:")
.Cells(7, "E") = InputBox("ET1 B:")
.Range("B03") = wb1.Worksheets("Que").Range("B02").Value2
.Range("B04") = wb1.Worksheets("Que").Range("E01").Value2
.Range("B05") = wb1.Worksheets("Que").Range("B01").Value2
.Cells(3, "E") = wb1.Worksheets("Que").Range("E02").Value2
.Cells(5, "E") = "Yes"
'Filling order
.Range("B38:B43") = wb1.Worksheets("Que & Tsc Cal").Range("B04:B09").Value2
.Range("C38:C43") = wb1.Worksheets("Que & Tsc Cal").Range("C04:C09").Value2
.Range("D38:D43") = wb1.Worksheets("Que & Tsc Cal").Range("A04:A09").Value2
'Retains
End With
Application.ScreenUpdating = True
End Sub
I developed above version with the help of you guys here and joining bits and pieces from other threads.Any suggestions to make it better are very welcome.
I use a check if the named tab/sheet is available:
If IsError(Evaluate("SHEETNAME!A1")) Then
'Nothing
Else
Sheets("SHEETNAME").Delete
End If
Sheets.Add(After:=Sheets(Sheets.Count)).Name = "SHEETNAME"
Or as suggested by Scott to have it be simpler and cleaner:
If Not IsError(Evaluate("SHEETNAME!A1")) Then Sheets("SHEETNAME").Delete
Sheets.Add(After:=Sheets(Sheets.Count)).Name = "SHEETNAME"
Edit 1:
Application.DisplayAlerts = False
If IsError(Evaluate("SHEETNAME!A1")) Then Sheets.Add(After:=Sheets(Sheets.Count)).Name = "SHEETNAME"
Application.DisplayAlerts = True
[W]hen I create another tab "accidentally" with same name it gives me error . . . I don't want to create one more tab with same name. Instead it should stop me from creating tabs with same name
This is not an uncommon problem with macros that create tabs--it is easy to accidentally run them twice. To prevent this, first check to see if the tab already exists and only after verifying that it doesn't exist, call the Worksheets.Copy method.
Private Sub Filling_List()
Dim sPath As String
Dim sFile As String
Dim wb As Workbook
Dim sName As String 'add sName declaration
Dim wb1 As Workbook
Dim ws1 As Worksheet
Set wb1 = ThisWorkbook
Set ws1 = ThisWorkbook.Worksheets("S0")
Application.ScreenUpdating = False
sPath = "C:\Users\arp\Desktop\Filling list macro\"
sFile = sPath & "ArF Filling List.xlsm"
Set wb = Workbooks.Open(sFile)
sName = ws1.Range("A1") & " " & ws1.Range("T2")
On Error Resume Next
Dim wslTest As Worksheet
Set wslTest = wb.Worksheets(sName)
If Err.Number = 0 Then
MsgBox "Tab: " & sName & " already exists.", vbInformation
wslTest.Activate
Exit Sub
End If
On Error GoTo 0
wb.Worksheets("ArF Templete").Copy After:=wb.Worksheets(wb.Worksheets.Count)
wb.ActiveSheet.Name = sName
' rest of code
End Sub
The code below should do what you want, you may need to adapt it for your project.
Option Explicit
Sub addsheet()
Dim sht As Worksheet
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets.add
On Error Resume Next 'Prevent Excel from stopping on an error but just goes to next line
ws.Name = "Sheet1"
If Err.Number = 1004 Then
MsgBox "Worksheet with this name already exists"
Application.DisplayAlerts = False 'Prevent confirmation popup on sheet deletion
ws.Delete
Application.DisplayAlerts = True 'Turn alerts back on
On Error GoTo 0 'Stop excel from skipping errors
Exit Sub 'Terminate sub after a failed attempt to add sheet
End If
On Error GoTo 0 'Stop Excel from skipping errors.
End Sub

VBA code not stable

It started on Monday this week, when I finished with my code,the codes purpose was to pull data from a specific sheet in a specific folder from all spreadsheets in that folder.
But just last night he started crashing excel spreadsheet every time i pushed the run button.
Any idea why?
Option Explicit
Sub ImportSheet()
Dim i As Integer
Dim SourceFolder As String
Dim FileList As Variant
Dim GrabSheet As String
Dim FileType As String
Dim ActWorkBk As String
Dim ImpWorkBk As String
Dim NoImport As Boolean
Application.EnableEvents = False
SourceFolder = "C:\Users\Jarryd.Ward\Desktop\Test\"
FileType = "*.xlsx"
GrabSheet = "Summary"
FileList = ListFiles(SourceFolder & "/" & FileType)
Application.ScreenUpdating = False
ActWorkBk = ActiveWorkbook.Name
NoImport = False
For i = 1 To UBound(FileList)
Workbooks.Open (SourceFolder & "\" & FileList(i))
ImpWorkBk = ActiveWorkbook.Name
On Error Resume Next
ActiveWorkbook.Sheets(GrabSheet).Select
If Err > 0 Then
NoImport = True
GoTo nxt
End If
Err.Clear
On Error GoTo 0
ActiveWorkbook.Sheets(GrabSheet).Copy After:=Workbooks(ActWorkBk).Sheets(Workbooks(ActWorkBk).Sheets.Count)
ActiveSheet.Name = ImpWorkBk
On Error Resume Next
ActiveSheet.Name = FileList(i) & " - " & GrabSheet
Err.Clear
On Error GoTo 0
nxt:
Workbooks(ImpWorkBk).Activate
Application.DisplayAlerts = False
ActiveWorkbook.Saved = True
ActiveWorkbook.Close SaveChanges:=False
Application.DisplayAlerts = True
Workbooks(ActWorkBk).Activate
Next i
Application.ScreenUpdating = True
End Sub
Try opening and closing your files this way to see if it helps. It should minimize the calls to activate this or that. And closing out by variable instead of activesheet will insure that your code isn't trying to close the main workbook by accident.
Sub testOpen()
Dim manyWBs As Workbook
Dim myWB As Workbook
Set myWB = ThisWorkbook
For Each file In folder
Set manyWBs = Workbooks.Open("C:\temp\filename")
' do events.......
manyWBs.Worksheets("Sheet1").Range("A1:B13").Copy _
Destination:=myWB.Worksheets("Sheet1").Range("A1:b13")
manyWBs.Close
Set manyWBs = Nothing
Next file
Set myWB = Nothing
End Sub