I have many excel files, each with just one worksheet, in a folder that contain data from 5 sources. The source is located in Column L. I would like to read through each row of all files and create 5 master worksheets. I think the number of sources should not be limited to just 5 sources, the macro should just read all rows in all files and copy the row to a master worksheet based on the value located in cell L. The Start_Row is 3 for reading and writing. I think I have working code for reading through each file and each worksheet but having problem with reading and writing rows
Sub ParseByDevice()
Dim Path As String
Dim FileName As String
Dim Wkb As Workbook
Dim wbThis As Workbook
Dim ws As Worksheet
Dim Pws As Worksheet 'Parsed Worksheet based on Column L (i, 12)
Dim a As Range
Dim b As Range
Dim rw As Range
Dim cl As Range
Dim MyBook As Workbook
Dim newBook As Workbook
Dim FileNm As String
Application.EnableEvents = False
Application.ScreenUpdating = False
Path = "C:\xml\vac" 'Change as needed
FileName = Dir(Path & "\livevalues*.xls", vbNormal)
'
'ALL FILES IN FOLDER LOOP
'
Do Until FileName = ""
Set Wkb = Workbooks.Open(FileName:=Path & "\" & FileName)
'
'ALL EACH WORKSHEET IN WORKBOOK LOOP
'
'next worksheet in file;
'only expect one worksheet but maybe more in the future
'
For Each ws In Wkb.Worksheets
'
' FOR EACH ROW IN WORKSHEET LOOP
'
rw = 3 'first row after header
For Each rw In ws
MsgBox Wkb.Sheets(ws).row(rw, 12).Value 'this is temporary, just a visual check that things are going well
cl = Wkb.Sheets(ws).row(rw, 12).Value
Wkb.Sheets(ws).row(rw, 12).Copy Pws.Sheets(cl)
Next rw 'next row in worksheet
Next ws 'next worksheet in file;
Wkb.Close False
FileName = Dir()
Loop 'Do next file in folder
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
One approach:
Application.EnableEvents = False
Application.ScreenUpdating = False
Path = "C:\xml\vac" 'Change as needed
FileName = Dir(Path & "\livevalues*.xls", vbNormal)
Set MyBook = ThisWorkbook
Do Until FileName = ""
Set Wkb = Workbooks.Open(FileName:=Path & "\" & FileName)
For Each ws In Wkb.Worksheets
rw = 3 'first row after header
Do
tmp = ws.Cells(rw, 12).Value
If Len(tmp) = 0 Then Exit Do
Set Pws = Nothing
On Error Resume Next
Set Pws = ThisWorkbook.Sheets(tmp)
On Error GoTo 0
If Pws Is Nothing Then
Set Pws = MyBook.Worksheets.Add( _
after:=MyBook.Sheets(MyBook.Sheets.Count))
Pws.Name = tmp
End If
ws.Rows(rw).Copy Pws.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
rw = rw + 1
Loop
Next ws 'next worksheet in file;
Wkb.Close False
FileName = Dir()
Loop 'Do next file in folder
Application.EnableEvents = True
Application.ScreenUpdating = True
Related
I've frankensteined some code together which does the following:
Deletes first few rows in a worksheet if they're not the header names
Deletes columns with specific names
Does this for all worksheets in a specified folder
I need help updating the code to do the following:
If the first row already contains the headers, then it will just move to the next step
Keeps columns with specific names, delete the rest
Do this for all sheets within a worksheet, if there happen to be multiple ones
Thank you so much in advance for any help!
Option Explicit
Sub test()
Dim wkb As Workbook
Dim MyPath As String
Dim MyFile As String
Application.ScreenUpdating = False
Set wkb = ActiveWorkbook
MyPath = "C:\Users\Katerina Shapiro\Desktop\VBA" 'Change this based on your folder path'
If Right(MyPath, 1) <> "\" Then MyPath = MyPath & "\"
MyFile = Dir(MyPath & "*.xlsx")
Do While Len(MyFile) > 0
If MyFile <> wkb.Name Then
Workbooks.Open Filename:=MyPath & MyFile
Dim rng As Range
Set rng = Range("B1:B4") 'Change this if there are more rows to be deleted before the header'
rng.SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Dim xFNum, xFFNum, xCount As Integer
Dim xStr As String
Dim xArrName As Variant
Dim MR, xRg As Range
On Error Resume Next
Set MR = Range("A1:H1")
xArrName = Array("Placement (detail) url", "Placement (group)") 'enclose each column name with double quotes and separate them by comma
xCount = MR.Count
xStr = xArrName(xFNum)
For xFFNum = xCount To 1 Step -1
Set xRg = Cells(1, xFFNum)
For xFNum = 0 To UBound(xArrName)
xStr = xArrName(xFNum)
If xRg.Value = xStr Then xRg.EntireColumn.Delete
Next xFNum
Next
ActiveWorkbook.Close SaveChanges:=True
End If
MyFile = Dir
Loop
Application.ScreenUpdating = True
MsgBox "Completed...", vbInformation
End Sub
Should get you close:
Option Explicit
Sub test()
Dim wkb As Workbook, wbMod As Workbook, ws As Worksheet
Dim MyPath As String
Dim MyFile As String, h, keepCols, col As Long, i As Long
Application.ScreenUpdating = False
Set wkb = ActiveWorkbook 'ThisWorkbook ?
MyPath = "C:\Users\Katerina Shapiro\Desktop\VBA" 'Change this based on your folder path'
If Right(MyPath, 1) <> "\" Then MyPath = MyPath & "\"
keepCols = Array("Placement (detail) url", "Placement (group)") 'columns to keep
MyFile = Dir(MyPath & "*.xlsx")
Do While Len(MyFile) > 0
If MyFile <> wkb.Name Then
Set wbMod = Workbooks.Open(Filename:=MyPath & MyFile) 'get reference to opened file
For Each ws In wbMod.Worksheets 'loop over worksheets
'remove any empty rows at the top of the sheet
i = 0
Do While Application.CountA(ws.Rows(1)) = 0
ws.Rows(1).Delete
i = i + 1
If i >= 5 Then Exit Do 'don't keep deleting forever...
Loop
'loop column headers in Row 1 right to left: delete column if header not in "keep" array
For col = ws.Cells(1, Columns.Count).End(xlToRight).Column To 1 Step -1
If IsError(Application.Match(ws.Cells(1, col).Value, keepCols, 0)) Then
ws.Columns(col).Delete
End If
Next col
Next ws
wbMod.Close True 'save changes
End If
MyFile = Dir()
Loop
Application.ScreenUpdating = True
MsgBox "Completed...", vbInformation
End Sub
For i = 1 To 2 'This for loop deletes all rows on top of the workbook where the cell in column B is empty
If Cells(i, 2).Value = "" Then
Rows(i).Delete
i = i - 1
End If
Next
This one should solve your first problem.
WS_Count = ActiveWorkbook.Worksheets.Count
For i = 1 To WS_Count
...
Next i
If you implement this loop it looks how many sheets there are in the workbook and loop through it.
For i=1 to Cells(7, sht.Columns.Count).End(xlToLeft).Column
If Cells(1,i).Value="" Then 'You need to insertthe Names of the columns you want to keep here.
columns(i).delete
i=i-1
endif
Next
And this should solve the columns delete problem.
I am attempting to extra data from multiple .xlsm in a folder from a specific cell. The idea is to take a folder that has multiple .xlsm files and extract a specific cell into my current workbook.
See code.
Option Explicit
Const FOLDER_PATH = "C:\Users\maxd\OneDrive - Nortek, Inc\Coil Test Data\coils_35_and_36\36\WET\Testing\" '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
rowTarget = 7
'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 & "*.xlsm*")
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("Summary")
'import the data
With wsTarget
.Range("I" & rowTarget).Value = wsSource.Range("B25").Value
'optional source filename in the last column
.Range("N" & rowTarget).Value = sFile
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
Actual Results = it does nothing as if there is not a file in the folder.
Expected Results = It will pull the data from cell B25 and insert it to I7 of my current worksheet.
EDIT: When I F8 through the code, it gets to "Set wsSource = wbSource.Worksheets("Summary")" Then I get a runtime error 91
I want to open a workbook that contains only one sheet,
copy data up to column AC until last available row in column A,
paste the data into first empty row in column A in workbook "Mergedsheet.xlsx".
I want to loop over all workbooks present in a specific folder, but get lots of errors.
Sub MergeNew()
Dim WorkBk As Workbook
Dim MergedSheet As Worksheet
Dim SourceData As Range
Dim DestinationData As Range
Dim lastRow As Long
Dim NextRow As Range
Dim FolderPath As String
Dim FileNames As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False
FolderPath = "E:\Jan to March 2019\Bharuch 31\"
FileNames = Dir(FolderPath & "*.xls*")
Do While FileNames <> ""
Set WorkBk = Workbooks.Open(FolderPath & FileNames)
Range("A1:AC1").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Workbooks.Open Filename:="E:\Jan to March 2019\Bharuch 31\MergedSheet.xlsx"
lastRow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row + 1
Range("A" & lastRow).Select
ActiveSheet.Paste
'ActiveWindow.Close SaveChanges:=True
'ActiveWindow.Close SaveChanges:=False
Application.CutCopyMode = False
FileNames = Dir()
Loop
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
You are looping through a folder and copy-pasting each workbook's first sheet's data to workbook A. However, workbook A is also in that folder. So you should take care to skip it (when looping).
(Alternatively, you could provide a different argument to the DIR function (e.g. some wildcard criteria that excludes workbook A if possible), so that you don't have to constantly check inside the loop.)
Untested.
Option Explicit
Private Sub MergeNew()
'Application.ScreenUpdating = False 'Uncomment this when you know code is working.
'Application.DisplayAlerts = False 'Uncomment this when you know code is working.
Dim folderPath As String
folderPath = GetFolderPath(titleToShow:="Select the folder containing the files to loop through.")
Dim Filename As String
Filename = Dir$(folderPath & "*.xls*")
If Len(Filename) = 0 Then
MsgBox "Could not find a relevant file in '" & folderPath & "'. Code will stop running now."
Exit Sub ' No point in carrying on in such a case.
End If
Dim destinationFolderPath As String
destinationFolderPath = GetFolderPath(titleToShow:="Select the folder to save the 'MergedSheet.xlsx' file to.")
Dim destinationWorkbook As Workbook
Set destinationWorkbook = Application.Workbooks.Add
' This line may throw an error
destinationWorkbook.SaveAs Filename:=destinationFolderPath & "MergedSheet.xlsx", FileFormat:=xlOpenXMLWorkbook
Dim destinationSheet As Worksheet
Set destinationSheet = destinationWorkbook.Worksheets(1) ' I assume there's only 1 sheet in there, but change as necessary.
Do Until Len(Filename) = 0
Dim fullFilePathToOpen As String
fullFilePathToOpen = folderPath & Filename
If fullFilePathToOpen <> destinationWorkbook.FullName Then ' Probably could have just compared filename since directory is the same, but this is more explicit
Dim sourceWorkbook As Workbook
Set sourceWorkbook = Application.Workbooks.Open(Filename:=fullFilePathToOpen, ReadOnly:=True) ' If you don't make changes to the workbook you open, better to open as read-only
Dim sourceSheet As Worksheet
Set sourceSheet = sourceWorkbook.Worksheets(1) ' You say there's only one worksheet in there, so referring by index should be okay (for now)
Dim lastSourceRow As Long
lastSourceRow = sourceSheet.Cells(sourceSheet.Rows.Count, "A").End(xlUp).Row ' Assume last row can be determined from column A alone
Dim lastDestinationRow As Long
lastDestinationRow = destinationSheet.Cells(destinationSheet.Rows.Count, "A").End(xlUp).Row + 1
If destinationSheet.Rows.Count < (lastDestinationRow + lastSourceRow) Then
MsgBox "Ran out of rows (in sheet '" & sourceSheet.Name & "' of workbook '" & destinationWorkbook.Name & "')"
Exit Sub
End If
sourceSheet.Range("A1", sourceSheet.Cells(lastSourceRow, "AC")).Copy Destination:=destinationSheet.Cells(lastDestinationRow, "A")
sourceWorkbook.Close False
End If
Filename = Dir$()
Loop
'Application.ScreenUpdating = True 'Uncomment this when you know code is working.
'Application.DisplayAlerts = True 'Uncomment this when you know code is working.
End Sub
Private Function GetFolderPath(Optional ByVal titleToShow As String = vbNullString) As String
With Application.FileDialog(msoFileDialogFolderPicker)
If Len(titleToShow) > 0 Then .Title = titleToShow
.AllowMultiSelect = False ' Only one is allowed.
.Show
If .SelectedItems.Count = 0 Then
MsgBox "Folder selection appears to have cancelled. Code will stop running now"
End
End If
GetFolderPath = .SelectedItems(1) & "\"
End With
End Function
I keep getting an error on ActiveWorkbook.Sheets(1) = wsData. What happens is user will select a csv file, find matches then take csv file matches in column 4 & 6 and place cell value in ThisWorkbook column 11 & 12 (additional matches will be offset into next two columns).
How can I set the sheet name without knowing it? I thought this would work as it was mentioned in previous threads.
Dim wb As Workbook
Dim ws As Worksheet
Dim cel1 As Range, cel2 As Range
Dim mywb As String, wsData As String
thiswb = ActiveWorkbook.Name
NewFile = Application.GetOpenFilename("Excel CSV Files (*.csv*),*.csv*", , "Select Report")
'Check if file selected
If NewFile = "False" Then
MsgBox "No file was selected. Please try again.", vbExclamation
GoTo WalkOut
End If
'Open wb
Workbooks.Open Filename:=NewFile, ReadOnly:=True
Application.ScreenUpdating = False
'Check for matching part and paste data to col k
With NewFile
importwb = ActiveWorkbook.Name
Set wsData = ActiveWorkbook.Sheets(1)
'Set wsData = ActiveWorkbook.Sheets(1)
For Each cel1 In ThisWorkbook.Sheets("Limited Data").UsedRange.Columns("H").Cells
Dim offs As Long: offs = 3 ' <-- Initial offset, will increase by 2 after each match
For Each cel2 In Workbooks(importwb).Worksheets(wsData).UsedRange.Columns("Z").Cells
If cel1.Value = cel2.Value Then
cel1.Offset(, offs).Value = cel2.Offset(, -22).Value ' <- wb2(d) to wb1(K)
cel1.Offset(, offs + 1).Value = cel2.Offset(, -20).Value ' <- wb2(f) to wb1(L)
offs = offs + 2 ' <-- now shift the destination column by 2 for next match
End If
Next
Next
End With
Workbooks(importwb).Close savechanges:=False
WalkOut:
End Sub
Most of this is guesswork. Take a look at the changes and try to understand them. That way you can probably correct the code yourself to make it work:
Sub Something()
Dim wb As Workbook
Dim ws As Worksheet
Dim newFile As String
newFile = Application.GetOpenFilename("Excel CSV Files (*.csv*),*.csv*", , "Select Sequenced APT Parts and Tools Report")
'Check if file selected
If newFile = "False" Then
MsgBox "No file was selected. Please try again.", vbExclamation
Exit Sub
End If
'Open wb
Set wb = Workbooks.Open(Filename:=newFile, ReadOnly:=True)
'Check for matching part and paste data to col k
Set ws = wb.Sheets(1)
For Each cel1 In ThisWorkbook.Sheets("Limited Warranty Data").UsedRange.Columns("H").Cells
Dim offs As Long: offs = 3 ' <-- Initial offset, will increase by 2 after each match
For Each cel2 In ws.UsedRange.Columns("Z").Cells
If cel1.Value = cel2.Value Then
cel1.Offset(, offs).Value = cel2.Offset(, -22).Value ' <- wb2(d) to wb1(K)
cel1.Offset(, offs + 1).Value = cel2.Offset(, -20).Value ' <- wb2(f) to wb1(L)
offs = offs + 2 ' <-- now shift the destination column by 2 for next match
End If
Next
Next
wb.Close savechanges:=False
End Sub
Long time reader and admirer of StackOverflow.
Basically I am trying to to loop through a series of Excel files to copy a range of data and paste it on a single Excel workbook/sheet.
The cell range location (C3:D8, D3:E8) is not always consistent, but the table dimensions are: 29 R x 2 C. Also, the files only have 1 sheet, and aside from the table dimensions specified, no data values in other cells.
In its current form the code is executing, but not pasting anything to its destination Excel file.
I need it to
Find the data dimension in file (table)
Copy the table
Paste to destination (below previous table)
Loop through to next file
Repeat Step 1-4
The code is from:
Excel VBA: automating copying ranges from different workbooks into one final destination sheet?
Thanks a lot for any help, I really appreciate it and please feel tell me to specify anything if my question is vague.
Sub SourcetoDest()
Dim wbDest As Workbook
Dim wbSource As Workbook
Dim sDestPath As String
Dim sSourcePath As String
Dim shDest As Worksheet
Dim rDest As Range
Dim vaFiles As Variant
Dim i As Long
'array of folder names under sDestPath
'array of file names under vaFiles
vaFiles = Array("Book1.xls")
sDestPath = "C:\Users"
sSourcePath = "C:\Users"
Set wbDest = Workbooks.Open(sDestPath & "\" & "Book2.xlsm")
Set shDest = wbDest.Sheets(1)
'loop through the files
For i = LBound(vaFiles) To UBound(vaFiles)
'open the source
Set wbSource = Workbooks.Open(sSourcePath & "\" & vaFiles(i))
'find the next cell in col C
Set rDest = shDest.Cells(shDest.Rows.Count, 3).End(xlUp).Offset(1, 0)
'write the values from source into destination
rDest.Resize(5, 1).Value = wbSource.Sheets(1).Range("C7:D33").Value
wbSource.Close False
Next i
End Sub
The below should achieve what you're after.
Option Explicit
Sub copy_rng()
Dim wb As Workbook, wbDest As Workbook, ws As Worksheet, wsDest As Worksheet, wsSrc As Worksheet
Dim wbNames() As Variant
Dim destFirstCell As Range
Dim destColStart As Integer, destRowStart As Long, i As Byte
Dim destPath As String
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1") ' Amend to your sheet name
Set wsSrc = wb.Sheets("Sheet2") ' Amend to sheet name with table data
wbNames = ws.Range("A2:A" & lrow(1, ws)) ' Pass col number into lrow function
destPath = "C:\Users\"
Application.ScreenUpdating = False
For i = 1 To UBound(wbNames, 1)
Set wbDest = Workbooks.Open(destPath & wbNames(i, 1))
Set wsDest = wbDest.Worksheets(1)
With wsDest
Set destFirstCell = .Cells.Find(What:="*")
destColStart = destFirstCell.Column
destRowStart = destFirstCell.Row
.Range(Cells(destRowStart, destColStart), _
Cells(lrow(destColStart, wsDest), icol(destRowStart, wsDest))).Copy
End With
wsSrc.Cells(lrow(1, wsSrc) + 1, 1).PasteSpecial Paste:=xlPasteAll
wbDest.Close False
Next i
Application.ScreenUpdating = True
End Sub
Function lrow(ByVal col_num As Integer, sheet_name As Worksheet) As Long
lrow = sheet_name.Cells(Rows.Count, col_num).End(xlUp).Row
End Function
Function icol(ByVal row_num As Long, sheet_name As Worksheet) As Integer
icol = sheet_name.Cells(row_num, Columns.Count).End(xlToLeft).Column
End Function
Ensure you copy both of the functions across, they're used to create the dimensions of the table, and then copying the table.
You will need to amend the sheet name variables. Let me know if you have any questions.
You need to amend the range of where the workbook names are stored. You need to pass the column number in, so that the last row can be calculated. You can also amend the column in which data is pasted back into the workbook.
With the help of this code you can copy all workbooks and worksheets data
into one workbook
Sub copydata()
Dim fso As Scripting.FileSystemObject
Dim fill As Scripting.File
Dim oldfolder As String
Dim newfolder As String
Dim subfolder As Folder
Dim myfolder As Folder
Dim fd As FileDialog
Dim loopcount As Integer
Dim wb
Dim wb2 As Workbook
Dim rr As Range
Set fso = New Scripting.FileSystemObject
Set wb = ThisWorkbook
Set fd = Application.FileDialog(msoFileDialogFolderPicker)
fd.Title = "Please Select Folder to copy"
fd.ButtonName = "Go!"
fd.Show
oldfolder = fd.SelectedItems(1)
Set myfolder = fso.GetFolder(oldfolder)
'Application.ScreenUpdating = False
Application.EnableEvents = False
For Each subfolder In myfolder.SubFolders
For Each fill In subfolder.Files
If fill Like "*.xlsm" Or fill Like "*.xlsx" Or fill Like ".*xls" Then
'fill.Range("A1:Z100").Copy
Set wb2 = Application.Workbooks.Open(fill,0 , True)
wb2.Activate
For loopcount = 1 To wb2.Worksheets.Count
wb2.Activate
Worksheets(loopcount).Activate
Range("A1:Z300").Copy 'Replace your range
wb.Activate
Sheet1.Activate
Set rr = Range("A:A").Find("", Range("A1"))
rr.Select
ActiveSheet.Paste
ActiveCell.Offset(1, 0).Select
Next loopcount
wb2.Close False
End If
Application.CutCopyMode = False
Debug.Print fill.Name
Next fill
Next subfolder
MsgBox "Done"
For Each fill In myfolder.Files
Application.DisplayAlerts = False
If fill Like "*.xlsm" Or fill Like "*.xlsx" Or fill Like ".*xls" Or fill Like "*.xlsb" Then
'fill.Range("A1:Z100").Copy
Set wb2 = Application.Workbooks.Open(fill, 0, True)
wb2.Activate
For loopcount = 1 To wb2.Worksheets.Count
wb2.Activate
Worksheets(loopcount).Activate
Range("A:Z").EntireColumn.Hidden = False
Range("A1:Z1").AutoFilter
Range("A1:Z300").Copy
wb.Activate
Sheet1.Activate
Set rr = Range("A:A").Find("", Range("A1"))
rr.Select
ActiveSheet.Paste
ActiveCell.Offset(1, 0).Select
Next loopcount
wb2.Close False
End If
Application.CutCopyMode = False
Debug.Print fill.Name
Next fill
Application.EnableEvents = True
End Sub