I have these two subs to import a text file into an excel workbook. However, the code I have will import all the files selected. How do I modify this code to limit the user to only select 50 or less files? Also, the program must notify the user the name of the last file imported.
Sub CopyData()
Application.ScreenUpdating = False
Dim fileDia As fileDialog
Dim I As Integer
Dim done As Boolean
Dim strpathfile As String, filename As String
I = 1
done = False
Set fileDia = Application.fileDialog(msoFileDialogFilePicker)
With fileDia
.InitialFileName = "C:\Users\5004239346\Desktop\Subhaac\PD_BACKUP"
.AllowMultiSelect = True
.Filters.Clear
.Title = "Navigate to and select required file."
If .Show = False Then
MsgBox "File not selected to import. Process Terminated"
Exit Sub
End If
Do While Not done
On Error Resume Next
strpathfile = .SelectedItems(I)
On Error GoTo 0
If strpathfile = "" Then
done = True
Else
filename = Mid(strpathfile, InStrRev(strpathfile, "\") + 1, Len(strpathfile) - (InStrRev(strpathfile, "\") + 4))
If Len(filename) > 31 Then filename = Left(filename, 26)
Transfer strpathfile, filename
strpathfile = ""
I = I + 1
End If
Loop
End With
Set fileDia = Nothing
Application.ScreenUpdating = True
WorksheetLoop
End Sub
Sub Transfer(mySource As String, wsName As String)
Dim wbSource As Workbook
Dim wsDestin As Worksheet
Dim lrow As Long
Set wsDestin = ActiveWorkbook.Sheets.Add(, ActiveWorkbook.Sheets(ActiveWorkbook.Sheets.Count)) 'Add the worksheet at the end
On Error Resume Next
wsDestin.Name = wsName 'set the name
On Error GoTo 0
Application.DisplayAlerts = False
If InStr(wsDestin.Name, "Sheet") <> 0 Then wsDestin.Delete: Exit Sub
Workbooks.OpenText filename:=mySource, _
Origin:=xlWindows, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _
xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _
Comma:=False, Space:=False, Other:=False, FieldInfo:=Array(1, 1), _
TrailingMinusNumbers:=True
Set wbSource = ActiveWorkbook
With wsDestin
lrow = .Range("A" & Rows.Count).End(xlUp).Row
wbSource.Sheets(1).UsedRange.Copy .Range("A" & lrow).Offset(1, 0)
wbSource.Close False
End With
Application.DisplayAlerts = True
End Sub
AFAIK you can't limit the number of files to select, but you can detect the number selected and act on that
If fileDia.SelectedItems.Count > 50 then
' User selected more than 50 files
For your second question, the name of the last selected file will be
fileDia.SelectedItems(fileDia.SelectedItems.Count)
Related
I have a macro which loops through excel files in a network drive path and performs few operations on the pivots and then tries to save the file in the same network path.
It works fine for the first 5 - 10 files and then it randomly stops saving the files.
The progress bar in the save box does not go any further.
Unable to save image
I have included the VBA code below
Sub CLEAR_ADI_PIVOT_DT_SRC()
Dim myPath As String
Dim myExtension As String
Dim myFile As String
Dim wb As Workbook
Dim ws As Worksheet
Dim FilePath As String
Dim PriorQuarter As String
Dim PrevQtrSheet As String
Dim filestr1 As String
Dim PrevQuarter As String
PrevQtrSheet = "Rebates Template " & Range("B2").Value
PrevQuarter = Range("B2").Value
PriorQuarter = Range("A2").Value
myPath = Range("I2").Value & "ADI\"
If Right(myPath, 1) <> "\" Then
myPath = myPath & "\"
End If
On Error GoTo ErrHandler
'Optimize Macro Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Target File Extension (must include wildcard "*")
myExtension = "*.xl*"
'Target Path with Ending Extension
myFile = Dir(myPath & myExtension)
'Loop through each Excel file in folder
Do While myFile <> ""
'Set variable equal to opened workbook
Application.DisplayAlerts = False
Debug.Print myPath & myFile
Set wb = Workbooks.Open(filename:=myPath & myFile, UpdateLinks:=False)
wb.Worksheets("ADI").Visible = True
wb.Worksheets("ADI").Activate
Cells.Find(What:="totals:", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Offset(-1, 0).Select
Dim AdiClearRange As Range
Set AdiClearRange = Range("AE" & ActiveCell.Row, "C14")
AdiClearRange.Select
Selection.ClearContents
Range("B15").Select
'Insert rows in ADI sheet
Dim x As Long
For x = 1 To 500
Range("B19:AE19").Select
Selection.Copy
Selection.Insert Shift:=xlDown
Range("B14").Select
Application.CutCopyMode = False
Next x
'Delete prior quarter template sheet
For Each Sheet In wb.Worksheets
If Sheet.Name = "Rebates Template " & PriorQuarter Then
Sheet.Delete
End If
Next Sheet
'change data source of previous quarter pivots
'Get range of the previous template
wb.Worksheets(PrevQtrSheet).Activate
Range("AH5").Select
If ActiveSheet.AutoFilterMode Then ActiveSheet.AutoFilter.ShowAllData
ActiveSheet.Range("$A$5:$KD$683").AutoFilter Field:=34, Criteria1:="<>"
'ActiveSheet.Range("$A$5:$KD$683").AutoFilter Field:=34, Criteria1:="<>0"
Range("AH5").Select
Selection.End(xlDown).Select
'Change range of pivot 1 and pivot 7 and apply previous quarter filter in pivots
Dim rng As Range
Dim SourceAddress As String
Set rng = Range("A5", "AH" & ActiveCell.Row)
SourceAddress = "'" & PrevQtrSheet & "'" & "!" & "$A$5:" & ActiveCell.Address(RowAbsolute:=True, ColumnAbsolute:=True)
Debug.Print SourceAddress
Sheets("Check").Select
Dim myPivotField As PivotField
Dim filterValue As String
ActiveSheet.PivotTables("PivotTable3").ChangePivotCache wb.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=SourceAddress)
ActiveSheet.PivotTables("PivotTable3").RefreshTable
ActiveSheet.Range("P1").Value = PrevQuarter
wb.Close SaveChanges:=True
'Get next file name
myFile = Dir
Loop
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
ResetSettings:
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
ErrHandler:
'MsgBox Err.Description, vbExclamation
'Resume ResetSettings
End Sub
Scenario: I have tons of Invoices received in my e-mail and saving them in a folder("C:\Users\Vbattul2\Desktop\Invoices\") and manually opening them one by one copying the needed data and pasting them to my excel tracker. Note that all the invoices have the same formats.
Opportunity to Automate: Automate the process of copy and paste of needed data from pdf and paste it to excel dummy worksheet(data delimited with colon & blank) and paste cell references in Excel invoice tracker.
Design: I will need to copy the pdf and paste it to a dummy worksheet then paste it to my excel invoice tracker.
I tried running this code from a thread posted 3 years ago:
VBA Copying data from pdf
I couldn't seem to understand this line, so it is returning me an
error: 1004 Method 'Range' of object'_Global failed
Line Error: For Each fName In Range("path")
I also tried replacing the ("path") to my folder path where I save all the invoices but it doesn't work.
Sub StartAdobe1()
Dim fName As Variant
Dim wbTransfer As Excel.Workbook
Dim wsNew As Excel.Worksheet
Dim dOpenCol As Double
Dim oPDFApp As AcroApp
Dim oAVDoc As AcroAVDoc
Dim oPDDoc As AcroPDDoc
'Define your spreadsheet
Set wbTransfer = Workbooks("transfer.xlsm")
Set wsNew = wbTransfer.Sheets("new")
'Find first open column
dOpenCol = wsNew.Cells(1, Columns.Count).End(xlToLeft).Column + 1
'Instantiate Acrobat Objects
Set oPDFApp = CreateObject("AcroExch.App")
Set oAVDoc = CreateObject("AcroExch.AVDoc")
Set oPDDoc = CreateObject("AcroExch.PDDoc")
For Each fName In Range("path")
'Open the PDF file. The AcroAVDoc.Open function returns a true/false
'to tell you if it worked
If oAVDoc.Open(fName.Text, "") = True Then
Set oPDDoc = oAVDoc.GetPDDoc
Else
Debug.Assert False
End If
'Copy all using Acrobat menu
oPDFApp.MenuItemExecute ("SelectAll")
oPDFApp.MenuItemExecute ("Copy")
'Paste into open column
wbTransfer.Activate
wsNew.Cells(1, dOpenCol).Select
ActiveSheet.Paste
'Select next open column
dOpenCol = dOpenCol + 1
oAVDoc.Close (1) '(1)=Do not save changes
oPDDoc.Close
Next
'Clean up
Set wbTransfer = Nothing
Set wsNew = Nothing
Set oPDFApp = Nothing
Set oAVDoc = Nothing
Set oPDDoc = Nothing
End Sub
i have uploaded an attachment where the actual result in dummy worksheet(paste as delimited values - colon & blank) should look like and the excel invoice tracker.
here are the links.
https://www.dropbox.com/preview/Marketing/desired%20output%20from%20pdf%20to%20excel.xlsm?role=work
https://www.dropbox.com/preview/Marketing/MRC%201380%20INVENTORY%202019.xlsb?role=work
So , what do you have now, all Excel files or all text files?
If all Excel files, try this.
Note: Copy all code below in a normal module of your workbook
#If VBA7 Then
Declare PtrSafe Function SetCurrentDirectoryA Lib _
"kernel32" (ByVal lpPathName As String) As Long
#Else
Declare Function SetCurrentDirectoryA Lib _
"kernel32" (ByVal lpPathName As String) As Long
#End If
Sub ChDirNet(szPath As String)
SetCurrentDirectoryA szPath
End Sub
Sub Basic_Example_2()
Dim MyPath 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
Dim SaveDriveDir As String
Dim FName As Variant
'Change ScreenUpdating, Calculation and EnableEvents
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
SaveDriveDir = CurDir
ChDirNet "C:\Users\Ron\test"
FName = Application.GetOpenFilename(filefilter:="Excel Files (*.xl*), *.xl*", _
MultiSelect:=True)
If IsArray(FName) Then
'Add a new workbook with one sheet
Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
rnum = 1
'Loop through all files in the array(myFiles)
For Fnum = LBound(FName) To UBound(FName)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(FName(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 = FName(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
ChDirNet SaveDriveDir
End Sub
If all text files, try this.
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, _
lpExitCode As Long) As Long
#Else
Private Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, _
lpExitCode As Long) As Long
#End If
Public Const PROCESS_QUERY_INFORMATION = &H400
Public Const STILL_ACTIVE = &H103
Public Sub ShellAndWait(ByVal PathName As String, Optional WindowState)
Dim hProg As Long
Dim hProcess As Long, ExitCode As Long
'fill in the missing parameter and execute the program
If IsMissing(WindowState) Then WindowState = 1
hProg = Shell(PathName, WindowState)
'hProg is a "process ID under Win32. To get the process handle:
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, hProg)
Do
'populate Exitcode variable
GetExitCodeProcess hProcess, ExitCode
DoEvents
Loop While ExitCode = STILL_ACTIVE
End Sub
Sub Merge_CSV_Files()
Dim BatFileName As String
Dim TXTFileName As String
Dim XLSFileName As String
Dim FileExtStr As String
Dim FileFormatNum As Long
Dim DefPath As String
Dim Wb As Workbook
Dim oApp As Object
Dim oFolder
Dim foldername
'Create two temporary file names
BatFileName = Environ("Temp") & _
"\CollectCSVData" & Format(Now, "dd-mm-yy-h-mm-ss") & ".bat"
TXTFileName = Environ("Temp") & _
"\AllCSV" & Format(Now, "dd-mm-yy-h-mm-ss") & ".txt"
'Folder where you want to save the Excel file
DefPath = Application.DefaultFilePath
If Right(DefPath, 1) <> "\" Then
DefPath = DefPath & "\"
End If
'Set the extension and file format
If Val(Application.Version) < 12 Then
'You use Excel 97-2003
FileExtStr = ".xls": FileFormatNum = -4143
Else
'You use Excel 2007 or higher
FileExtStr = ".xlsx": FileFormatNum = 51
'If you want to save as xls(97-2003 format) in 2007 use
'FileExtStr = ".xls": FileFormatNum = 56
End If
'Name of the Excel file with a date/time stamp
XLSFileName = DefPath & "MasterCSV " & _
Format(Now, "dd-mmm-yyyy h-mm-ss") & FileExtStr
'Browse to the folder with CSV files
Set oApp = CreateObject("Shell.Application")
Set oFolder = oApp.BrowseForFolder(0, "Select folder with CSV files", 512)
If Not oFolder Is Nothing Then
foldername = oFolder.Self.Path
If Right(foldername, 1) <> "\" Then
foldername = foldername & "\"
End If
'Create the bat file
Open BatFileName For Output As #1
Print #1, "Copy " & Chr(34) & foldername & "*.csv" _
& Chr(34) & " " & TXTFileName
Close #1
'Run the Bat file to collect all data from the CSV files into a TXT file
ShellAndWait BatFileName, 0
If Dir(TXTFileName) = "" Then
MsgBox "There are no csv files in this folder"
Kill BatFileName
Exit Sub
End If
'Open the TXT file in Excel
Application.ScreenUpdating = False
Workbooks.OpenText Filename:=TXTFileName, Origin:=xlWindows, StartRow _
:=1, DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, Tab:=False, Semicolon:=False, Comma:=True, _
Space:=False, Other:=False
'Save text file as a Excel file
Set Wb = ActiveWorkbook
Application.DisplayAlerts = False
Wb.SaveAs Filename:=XLSFileName, FileFormat:=FileFormatNum
Application.DisplayAlerts = True
Wb.Close savechanges:=False
MsgBox "You find the Excel file here: " & vbNewLine & XLSFileName
'Delete the bat and text file you temporary used
Kill BatFileName
Kill TXTFileName
Application.ScreenUpdating = True
End If
End Sub
See the link below for all details.
https://www.rondebruin.nl/win/section3.htm
Also, consider using this very useful Excel AddIn.
https://www.rondebruin.nl/win/addins/rdbmerge.htm
You would probably well served if you first convert all PDF files into text files, and import all data from all text files into Multiple sheets in Excel.
Sub convertpdf2()
Dim AcroXApp As Acrobat.AcroApp
Dim AcroXAVDoc As Acrobat.AcroAVDoc
Dim AcroXPDDoc As Acrobat.AcroPDDoc
Dim Filename As String
Dim jsObj As Object
Dim NewFileName As String
Filename = "C:\your_path_here\test.pdf"
NewFileName = "C:\your_path_here\Desktop\test.txt"
Set AcroXApp = CreateObject("AcroExch.App")
'AcroXApp.Show
Set AcroXAVDoc = CreateObject("AcroExch.AVDoc")
AcroXAVDoc.Open Filename, "Acrobat"
Set AcroXPDDoc = AcroXAVDoc.GetPDDoc
Set jsObj = AcroXPDDoc.GetJSObject
jsObj.SaveAs NewFileName, "com.adobe.acrobat.plain-text"
AcroXAVDoc.Close False
AcroXApp.Hide
AcroXApp.Exit
End Sub
Or, put everything in all the text files into one single sheet in Excel, assuming all files have the same schema, of course.
Import several test files into separate sheets in Excel.
Sub CombineTextFiles()
'updateby Extendoffice 20151015
Dim xFilesToOpen As Variant
Dim I As Integer
Dim xWb As Workbook
Dim xTempWb As Workbook
Dim xDelimiter As String
Dim xScreen As Boolean
On Error GoTo ErrHandler
xScreen = Application.ScreenUpdating
Application.ScreenUpdating = False
xDelimiter = "|"
xFilesToOpen = Application.GetOpenFilename("Text Files (*.txt), *.txt", , "Kutools for Excel", , True)
If TypeName(xFilesToOpen) = "Boolean" Then
MsgBox "No files were selected", , "Kutools for Excel"
GoTo ExitHandler
End If
I = 1
Set xTempWb = Workbooks.Open(xFilesToOpen(I))
xTempWb.Sheets(1).Copy
Set xWb = Application.ActiveWorkbook
xTempWb.Close False
xWb.Worksheets(I).Columns("A:A").TextToColumns _
Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, _
Tab:=False, Semicolon:=False, _
Comma:=False, Space:=False, _
Other:=True, OtherChar:="|"
Do While I < UBound(xFilesToOpen)
I = I + 1
Set xTempWb = Workbooks.Open(xFilesToOpen(I))
With xWb
xTempWb.Sheets(1).Move after:=.Sheets(.Sheets.Count)
.Worksheets(I).Columns("A:A").TextToColumns _
Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, _
Tab:=False, Semicolon:=False, _
Comma:=False, Space:=False, _
Other:=True, OtherChar:=xDelimiter
End With
Loop
ExitHandler:
Application.ScreenUpdating = xScreen
Set xWb = Nothing
Set xTempWb = Nothing
Exit Sub
ErrHandler:
MsgBox Err.Description, , "Kutools for Excel"
Resume ExitHandler
End Sub
If you have Acrobat installed, you can try the script below.
Sub Convert_to_TXT()
Dim AcroXApp As Acrobat.AcroApp
Dim AcroXAVDoc As Acrobat.AcroAVDoc
Dim AcroXPDDoc As Acrobat.AcroPDDoc
Dim Filename As String
Dim jsObj As Object
Dim NewFileName As String
Const sPath = "C:\Users\Excel\Desktop\test\"
Const sExt = ".pdf"
Const dPath = "C:\Users\Excel\Desktop\test\"
Const dExt = ".txt"
Dim sName As String, dName As String, fCount As Long
'loop through all files in source
sName = Dir(sPath & "*" & sExt)
Do While sName <> ""
fCount = fCount + 1
'we have sName. Now figure out dName
dName = Left(sName, InStrRev(sName, ".") - 1) & dExt
Set AcroXApp = CreateObject("AcroExch.App")
'AcroXApp.Show
Set AcroXAVDoc = CreateObject("AcroExch.AVDoc")
AcroXAVDoc.Open sName, "Acrobat"
Set AcroXPDDoc = AcroXAVDoc.GetPDDoc
Set jsObj = AcroXPDDoc.GetJSObject
jsObj.SaveAs dName, "com.adobe.acrobat.plain-text"
'find the next file
sName = Dir
Loop
AcroXAVDoc.Close False
AcroXApp.Hide
AcroXApp.Exit
MsgBox "Found " & fCount & " files."
End Sub
If you do NOT have Acrobat installed, you can try the script below
Sub ConvertToTXT()
Dim file As Variant, wdDoc As Document
file = Dir("C:\your_path\" & "*.pdf") 'txt path
Do While (file <> "")
Set wdDoc = Documents.Open(Filename:="C:\your_path\" & file, ReadOnly:=True, _
AddToRecentFiles:=False, Format:=wdOpenFormatAuto, Visible:=False)
wdDoc.SaveAs2 Filename:="C:\your_path\" & Replace(file, ".pdf", ".txt"), _
FileFormat:=wdFormatPDF, AddToRecentFiles:=False
wdDoc.Close False
file = Dir
Loop
End Sub
So the code is two parts.
Part A) Open a the folder directory and when you click OK. It Runs the Code of Part B. Then saves the file, and finally outputs a msg box.
Part B) It runs the code on the file.
Hypothesis: That 2 lines of code is the reason why it does not work. I believe the first is initiating the code to run and second is this Set ws = ThisWorkbook.Sheets("report123")
Here is the entire code
Public Sub CommandButton1_Click()
Dim wb As Workbook
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
'Optimize Macro Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Retrieve Target Folder Path From User
Set FldrPicker = Application.FileDialog(msoFileDialogFolderPicker)
With FldrPicker
.Title = "Select A Target Folder"
.AllowMultiSelect = False
If .Show <> -1 Then GoTo NextCode
myPath = .SelectedItems(1) & "\"
End With
'In Case of Cancel
NextCode:
myPath = myPath
If myPath = "" Then GoTo ResetSettings
'Target File Extension (must include wildcard "*")
myExtension = "*.xlsx"
'Target Path with Ending Extention
myFile = Dir(myPath & myExtension)
'Loop through each Excel file in folder
Do While myFile <> ""
'Set variable equal to opened workbook
Set wb = Workbooks.Open(Filename:=myPath & myFile)
'Ensure Workbook has opened before moving on to next line of code
DoEvents
My Code for the file starts here
ActiveSheet.Columns("A").Insert Shift:=xlToRight
ActiveSheet.Columns("A").Insert Shift:=xlToLeft
Range("A1").Value = "Source 2"
Range("B1").Value = "BU ID"
Columns("I").Replace What:="eas", _
Replacement:="reC", _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
MatchCase:=False, _
SearchFormat:=False, _
ReplaceFormat:=False
Dim arrData As Variant, LastRow As Long, i As Long, ws As Worksheet
Set ws = ThisWorkbook.Sheets("report123")
With ws
LastRow = .Cells(.Rows.Count, 3).End(xlUp).Row
arrData = .Range("A2", .Cells(LastRow, "C")).Value
For i = 1 To UBound(arrData)
If arrData(i, 3) Like "Bus*" Then
arrData(i, 1) = "BU CRM"
Else
arrData(i, 1) = "CSI ACE"
End If
If arrData(i, 3) Like "CSI*" Or arrData(i, 3) = vbNullString Then
arrData(i, 2) = vbNullString
Else
arrData(i, 2) = Right(arrData(i, 3), Len(arrData(i, 3)) - 12)
End If
Next i
.Range("A2", .Cells(LastRow, "C")).Value = arrData
End With
My Code for the file ends here
wb.Close SaveChanges:=True
DoEvents
myFile = Dir
Loop
MsgBox "Task Complete!"
ResetSettings:
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
I am still new to VBA, I am just curious if anyone has any recommendations for improving or simplifying this code. The program works fine the way it is, however it has to sort through anywhere from 10 to 30 files and marge them all. It can take a long time depending on the file size. The Excel files range from a few hundred lines to 800,000 each. Thanks for your help!
Option Compare Text
Sub MergeAllFiles()
Dim wb As Workbook
Dim myPath As String, MyFile As String, myExtension As String, Col1 As
String, MyFolder As String, Title As String
Dim i As Integer, j As Integer, WS_Count As Integer, k As Integer
Dim FldrPicker As FileDialog
Dim Mynote As String, Answer As String
Mynote = "Does each file have the same number of export fields?"
Answer = MsgBox(Mynote, vbQuestion + vbYesNo, "Confirmation Needed")
If Answer = vbNo Then
MsgBox "Cancelled"
GoTo ResetSettings
End If
j = 1
i = 1
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Retrieve Target Folder Path From User
Set FldrPicker = Application.FileDialog(msoFileDialogFolderPicker)
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Select A Target Folder"
.AllowMultiSelect = False
.Show
MyFolder = .SelectedItems(1)
Err.Clear
End With
Set NewBook = Workbooks.Add
With NewBook
.Title = "MasterList"
ActiveWorkbook.SaveAs Filename:="Mastersheet.xlsx"
End With
'Loop through each Excel file in folder
MyFile = Dir(MyFolder & "\", vbReadOnly)
If MyFile = "Batch.xlsx" Then GoTo NextLoop
Do While MyFile <> ""
DoEvents
Workbooks.Open Filename:=MyFolder & "\" & MyFile, UpdateLinks:=False
Title = ActiveWorkbook.Name
ActiveWorkbook.Sheets(i).Select
With ActiveWorkbook.Sheets(i)
If (ActiveSheet.AutoFilterMode And ActiveSheet.FilterMode)
Or ActiveSheet.FilterMode Then
ActiveSheet.ShowAllData
End If
End With
k = 1
l = 1
If j = 1 Then
k = 0
l = 0
End If
With Range("A1:AB1000000")
Set rFind = .Find(What:="Total Rate (Linehaul + Acc)",
LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
ActiveSheet.Range("A1:ABC1000000").AutoFilter
Field:=rFind.Column, Criteria1:="="
ActiveSheet.Range("A1:ABC1000000").Offset(1,
0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
ActiveSheet.AutoFilterMode = False
End With
ActiveSheet.UsedRange.Offset(l).Copy
Workbooks("Mastersheet.xlsx").Activate
Range("A" & Rows.Count).End(xlUp).Offset(k).Select
Selection.PasteSpecial Paste:=xlPasteAllExceptBorders,
Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Workbooks(Title).Activate
Application.CutCopyMode = False
Workbooks(MyFile).Close SaveChanges:=True
j = j + 1
If j = 50 Then Exit Do
NextLoop:
MyFile = Dir
Loop
ResetSettings:
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
Not sure if my code does exactly what yours does (had no sample data/input to check the output against), but maybe something like this:
Option Explicit
Private Sub MergeAllFiles()
If MsgBox("Does each file have the same number of export fields?", vbQuestion + vbYesNo, "Confirmation Needed") = vbNo Then
MsgBox "Files do not have same number of export fields. Code will stop running now."
Exit Sub
End If
'Retrieve Target Folder Path From User
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Select A Target Folder"
.AllowMultiSelect = False
.Show
If .SelectedItems.Count = 0 Then
MsgBox "Folder selection cancelled. Code will stop running now."
Exit Sub
End If
Dim folderPath As String
folderPath = .SelectedItems(1)
If VBA.Strings.StrComp(VBA.Strings.Right$(folderPath, 1), "\", vbBinaryCompare) <> 0 Then
folderPath = folderPath & "\"
End If
End With
Dim masterWorksheet As Worksheet
With Workbooks.Add
.SaveAs Filename:=ThisWorkbook.Path & "\Mastersheet.xlsx"
Set masterWorksheet = .Worksheets(1)
End With
' If you're only interested in .xlsx files, then maybe specify the file extension upfront
' when using dir(). This ensures you only loop through files with the given file extension.
' But if you do want multiple file extensions, you could remove extension from the dir()
' and just check file extension inside the loop.
Dim Filename As String
Filename = VBA.FileSystem.Dir$(folderPath & "*.xlsx", vbReadOnly)
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Dim workbookToCopyFrom As Workbook
Dim fileCount As Long
Dim cellFound As Range
Dim blankRowsToDelete As Range
Dim lastRow As Long
Do While Len(Filename) <> 0
If VBA.Strings.StrComp(Filename, "Batch.xlsx", vbBinaryCompare) <> 0 Then
fileCount = fileCount + 1
Set workbookToCopyFrom = Application.Workbooks.Open(Filename:=folderPath & Filename, UpdateLinks:=False)
' Did you want to copy-paste from all worksheets
' or just the worksheet at the first index?
With workbookToCopyFrom.Worksheets(1)
If .AutoFilterMode Then .AutoFilter.ShowAllData
With .Range("A1:AB1000000")
' Presume this check is done because you want to include headers the first time,
' but exclude headers for any subsequent files.
If fileCount = 1 Then
.Rows(1).Copy masterWorksheet.Rows(1)
End If
Set cellFound = .Find(What:="Total Rate (Linehaul + Acc)", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
' It's worth checking if the previous line found anything
' If it didn't, you will get an error below when accessing the 'column' property
.AutoFilter Field:=cellFound.Column, Criteria1:="="
Set blankRowsToDelete = Application.Intersect(.EntireRow, .Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow)
If Not (blankRowsToDelete Is Nothing) Then
blankRowsToDelete.Delete
End If
.Parent.AutoFilterMode = False
End With
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
If lastRow > 1 Then
.Range("A2:AB" & lastRow).Copy
masterWorksheet.Range("A" & .Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteAllExceptBorders, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Application.CutCopyMode = False
workbookToCopyFrom.Close SaveChanges:=False
End If
End With
If fileCount = 50 Then Exit Do
End If
DoEvents
Filename = Dir$()
Loop
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
The code I've tweaked from another similar post, copies Row 3 to the last row which contains data from 'Sheet1' from all the workbooks in a folder into the 'SH Dealing yyyy.xlsx' 'DealSlips' sheet (adding to the rows here as it sweeps down through the workbooks in the folder). However, it only copies the last row which has data in Column A. In the last row there may be data just in Column J or Column Z for example and it doesn't see these and they are not copied? I'm new to coding and have been pretty much guessing for a couple of hours what needs changing in the code!
Sub LoopAllExcelFilesInFolder()
'PURPOSE: To loop through all Excel files in a user specified folder and perform a set task on them
'SOURCE: www.TheSpreadsheetGuru.com
Dim wb As Workbook
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
Dim lRow As Long
Dim ws2 As Worksheet
Dim y As Workbook
'Optimize Macro Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Retrieve Target Folder Path From User
Set FldrPicker = Application.FileDialog(msoFileDialogFolderPicker)
With FldrPicker
.Title = "Z:\2016\Deal slips ordered mmddyy\"
.AllowMultiSelect = False
If .Show <> -1 Then GoTo NextCode
myPath = .SelectedItems(1) & "\"
End With
'In Case of Cancel
NextCode:
myPath = myPath
If myPath = "" Then GoTo ResetSettings
'Target File Extension (must include wildcard "*")
myExtension = "*.xls*"
'Target Path with Ending Extention
myFile = Dir(myPath & myExtension)
Set y = Workbooks.Open("Z:\2016\Report\SH Dealing yyyy.xlsx")
Set ws2 = y.Sheets("DealSlips")
'Loop through each Excel file in folder
Do While myFile <> ""
'Set variable equal to opened workbook
Set wb = Workbooks.Open(Filename:=myPath & myFile)
'Copy data on "Sheet1" sheet to "DealSlips" Sheet in other workbook
With wb.Sheets("Sheet1")
lRow = .Range("A" & Rows.Count).End(xlUp).Row
' lastRow = Sheets("Sheet1").Range("J" & Rows.Count).End(xlUp).Row
.Range("A3:Z" & lRow).Copy ws2.Range("A" & Rows.Count).End(xlUp)(2)
End With
wb.Close SaveChanges:=True
'Get next file name
myFile = Dir
Loop
'Message Box when tasks are completed
MsgBox "Task Complete!"
ResetSettings:
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
You can get your desired result by changing the following line:
lRow = .Range("A" & Rows.Count).End(xlUp).Row
With:
lRow = .UsedRange.Rows.Count
Your original code will count the number of rows on a specific column, in your case Column A, whereas the one using UsedRange will look at the last row on your Sheet including cells that contain formatting only.
UPDATE:
Another way to find the last row without counting the cells with formatting would be as below:
Dim lRow As Long, lRow2 As Long
lRow = wb.Sheets("Sheet1").Cells.Find(What:="*", _
After:=wb.Sheets("Sheet1").Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
wb.Sheets("Sheet1").Range("A3:Z" & lRow).Copy
lRow2 = ws2.Cells.Find(What:="*", _
After:=ws2.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
ws2.Range("A" & lRow2).PasteSpecial xlPasteAll
UPDATE 2:
After looking at your code a little close I realized that the lRow2 was throwing an error because the Sheet was actually blank, so I've added a line of code to add a "Header" to cell A1, so that it can calculate the last row appropriately, also I don't understand how you get the "Correct" result manually when I did it I got many more rows than you, but please check the code below, it worked for me (I think), I also moved the workbook with code (i.e. Book1.xlsm) outside the folder you are looping through and added an If statement to exclude the "SH Dealing yyyy.xlsx" workbook from the loop :
Sub LoopAllExcelFilesInFolder()
Dim wb As Workbook, y As Workbook
Dim myPath As String, myFile As String, myExtension As String
Dim FldrPicker As FileDialog
Dim lRow As Long, lRow2 As Long
Dim ws2 As Worksheet
'Optimize Macro Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Retrieve Target Folder Path From User
Set FldrPicker = Application.FileDialog(msoFileDialogFolderPicker)
With FldrPicker
.Title = "Z:\2016\Deal slips ordered mmddyy\"
.AllowMultiSelect = False
If .Show <> -1 Then GoTo NextCode
myPath = .SelectedItems(1) & "\"
End With
'In Case of Cancel
NextCode:
myPath = myPath
If myPath = "" Then GoTo ResetSettings
'Target File Extension (must include wildcard "*")
myExtension = "*.xls*"
'Target Path with Ending Extention
myFile = Dir(myPath & myExtension)
Set y = Workbooks.Open("Z:\2016\Report\SH Dealing yyyy.xlsx")
'amen
Set ws2 = y.Sheets("DealSlips")
'Loop through each Excel file in folder
Do While myFile <> ""
If Left(myFile, 2) <> "SH" Then
'Set variable equal to opened workbook
Set wb = Workbooks.Open(Filename:=myPath & myFile)
'Copy data on "Sheet1" sheet to "DealSlips" Sheet in other workbook
lRow = wb.Sheets("Sheet1").Cells.Find(What:="*", _
After:=wb.Sheets("Sheet1").Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row ' + 1
y.Sheets("DealSlips").Range("A1").Value = "Header"
lRow2 = y.Sheets("DealSlips").Cells.Find(What:="*", _
After:=y.Sheets("DealSlips").Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row + 1
wb.Sheets("Sheet1").Range("A3:Z" & lRow).Copy ws2.Range("A" & lRow2)
wb.Close SaveChanges:=True
'Get next file name
myFile = Dir
Else
myFile = ""
End If
Loop
'Message Box when tasks are completed
MsgBox "Task Complete!"
ResetSettings:
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub