Loop optimization/Customization - excel

The excel file I have is more than 1,000,000 rows and 26 columns.
Below is the code which is used to find a particular data and a new file is created on the basis of that data and currently it is taking around 15 mins to create a new file
Please if any expert can help me in processing the below macro faster.
Sub SplitSheetDataIntoMultipleWorkbooksBasedOnSpecificColumn()
Dim objWorksheet As Excel.Worksheet
Dim nLastRow, nRow, nNextRow As Integer
Dim strColumnValue As String
Dim objDictionary As Object
Dim varColumnValues As Variant
Dim varColumnValue As Variant
Dim objExcelWorkbook As Excel.Workbook
Dim objSheet As Excel.Worksheet
Set objWorksheet = ActiveSheet
nLastRow = objWorksheet.Range("A" & objWorksheet.Rows.Count).End(xlUp).Row
Set objDictionary = CreateObject("Scripting.Dictionary")
strColumnValue = "1021 VDDGC 104"
If objDictionary.Exists(strColumnValue) = False Then
objDictionary.Add strColumnValue, 1
End If
varColumnValues = objDictionary.Keys
For i = LBound(varColumnValues) To UBound(varColumnValues)
varColumnValue = varColumnValues(i)
'Create a new Excel workbook
Set objExcelWorkbook = Excel.Application.Workbooks.Add
Set objSheet = objExcelWorkbook.Sheets(1)
objSheet.Name = objWorksheet.Name
objWorksheet.Rows(1).EntireRow.Copy
objSheet.Activate
objSheet.Range("A1").Select
objSheet.Paste
For nRow = 2 To nLastRow
If CStr(objWorksheet.Range("K" & nRow).Value) = CStr(varColumnValue) Then
'Copy data with the same column "B" value to new workbook
objWorksheet.Rows(nRow).EntireRow.Copy
nNextRow = objSheet.Range("A" & objWorksheet.Rows.Count).End(xlUp).Row + 1
objSheet.Range("A" & nNextRow).Select
objSheet.Paste
objSheet.Columns("A:S").AutoFit
End If
Next
Next
End Sub

Copy Worksheet to a New Workbook
Copies (exports) the worksheet to a new workbook.
Sorts by and filters the criteria column.
Deletes the filtered rows.
Sub SplitWorksheetData()
Dim dt As Double: dt = Timer
Const Criteria As String = "1021 VDDGC 104"
Const CriteriaColumnIndex As Long = 2
Dim sws As Worksheet: Set sws = ActiveSheet ' improve!
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
If Not dict.Exists(Criteria) Then dict.Add Criteria, 1
Application.ScreenUpdating = False
Dim dwb As Workbook
Dim dws As Worksheet
Dim Key As Variant
For Each Key In dict.Keys
sws.Copy
Set dwb = Workbooks(Workbooks.Count)
Set dws = dwb.Worksheets(1)
If dws.FilterMode Then dws.ShowAllData
Dim drg As Range: Set drg = dws.Range("A1").CurrentRegion
Dim ddrg As Range: Set ddrg = drg.Resize(drg.Rows.Count - 1).Offset(1)
drg.Sort drg.Columns(CriteriaColumnIndex), xlAscending, , , , , , xlYes
drg.AutoFilter CriteriaColumnIndex, "<>" & Criteria
Dim vrg As Range
On Error Resume Next
Set vrg = ddrg.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
dws.AutoFilterMode = False
If Not vrg Is Nothing Then vrg.Delete
' Save code goes here...
'dwb.SaveAs...
Next Key
Application.ScreenUpdating = True
Debug.Print Timer - dt
MsgBox "Workbook created.", vbInformation
End Sub

Related

search header loop through in multiple files if matched then copy entire column and paste into single column

I have multiple workbooks in a Folder around 8 and there are Similar columns in some of these workbooks.
For Example:
There are 6 Workbooks out of 8 have similar column which Header name is "SouthRecord" i want to search that header in 1st row of each workbook if finds then copy that entire column from multiple workbooks availble in Folder and Paste appended result into an open workbook where from code is being run.
Code is copeing tha data but getting error on this line LastRow = sht.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row Object variable and with block variable not set.
If 4 workbooks has Same Header then these 4 column will be pasted into open workbook as single column.
I would appreciate your help.
Sub MultipleSimilarColinto_1()
Dim xFd As FileDialog
Dim xFdItem As String
Dim xFileName As String
Dim wbk As Workbook
Dim sht As Worksheet
Dim twb As Workbook
Dim LastRow As Long
Dim ws As Worksheet
Dim desWS As Worksheet
Dim colArr As Variant
Dim order As Long
Dim i As Long
Application.ScreenUpdating = False
Application.DisplayAlerts = False
ActiveWindow.View = xlNormalView
Set xFd = Application.FileDialog(msoFileDialogFolderPicker)
Set twb = ActiveWorkbook
Set desWS = twb.Sheets("Sheet1")
If xFd.Show Then
xFdItem = xFd.SelectedItems(1) & Application.PathSeparator
Else
Beep
Exit Sub
End If
xFileName = Dir(xFdItem & "*.xlsx")
Do While xFileName <> ""
Set wbk = Workbooks.Open(xFdItem & xFileName)
colArr = Array("MD")
For Each ws In wbk.Sheets
If ws.Name <> "Sheet1" Then
LastRow = ws.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
For i = LBound(colArr) To UBound(colArr)
order = ws.Rows(1).Find("MD", LookIn:=xlValues, lookat:=xlWhole).Column
ws.Range(ws.Cells(2, order), ws.Cells(LastRow, order)).Copy desWS.Cells(Rows.Count, "A").End(xlUp).Offset(1, 0)
Next i
End If
Next ws
wbk.Close SaveChanges:=True
xFileName = Dir
Loop
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
Import Columns From Workbooks
Option Explicit
Sub ImportColumns()
' Source
Const sFilePattern As String = "*.xlsx"
Const sExceptionsList As String = "Sheet1" ' comma-separated, no spaces
Const sHeader As String = "SouthRecord"
Const sHeaderRow As Long = 1
' Destination
Const dColumn As String = "A"
' Source
Dim sfd As FileDialog
Set sfd = Application.FileDialog(msoFileDialogFolderPicker)
'sfd.InitialFileName = "C:\Test\"
Dim sFolderPath As String
If sfd.Show Then
sFolderPath = sfd.SelectedItems(1) & Application.PathSeparator
Else
'MsgBox "You canceled.", vbExclamation
Beep
Exit Sub
End If
Dim sFileName As String: sFileName = Dir(sFolderPath & sFilePattern)
If Len(sFileName) = 0 Then
'MsgBox "No files found.", vbExclamation
Beep
Exit Sub
End If
Dim sExceptions() As String: sExceptions = Split(sExceptionsList, ",")
' Destination
Dim dwb As Workbook: Set dwb = ThisWorkbook ' workbook containing this code
Dim dws As Worksheet: Set dws = dwb.ActiveSheet ' improve!
Dim dfCell As Range
Set dfCell = dws.Cells(dws.Rows.Count, dColumn).End(xlUp).Offset(1)
' Loop.
Application.ScreenUpdating = False
Dim swb As Workbook
Dim sws As Worksheet
Dim srg As Range
Dim shrg As Range
Dim sData() As Variant
Dim sfCell As Range
Dim slCell As Range
Dim srCount As Long
Dim wsCount As Long
Do While Len(sFileName) > 0
Set swb = Workbooks.Open(sFolderPath & sFileName)
For Each sws In swb.Worksheets
If IsError(Application.Match(sws.Name, sExceptions, 0)) Then
Set shrg = sws.Rows(sHeaderRow)
Set sfCell = shrg.Find(sHeader, shrg.Cells(shrg.Cells.Count), _
xlFormulas, xlWhole)
If Not sfCell Is Nothing Then
Set sfCell = sfCell.Offset(1)
Set slCell = sfCell _
.Resize(sws.Rows.Count - sHeaderRow) _
.Find("*", , xlFormulas, , , xlPrevious)
If Not slCell Is Nothing Then
srCount = slCell.Row - sHeaderRow
Set srg = sfCell.Resize(srCount)
End If
End If
If srCount > 0 Then
If srCount = 1 Then
ReDim sData(1 To 1, 1 To 1): sData(1, 1) = srg.Value
Else
sData = srg.Value
End If
dfCell.Resize(srCount).Value = sData
Set dfCell = dfCell.Offset(srCount)
wsCount = wsCount + 1
srCount = 0
End If
End If
Next sws
swb.Close SaveChanges:=False
sFileName = Dir
Loop
' Save the destination workbook.
'dwb.Save
Application.ScreenUpdating = True
MsgBox wsCount & " '" & sHeader & "' columns copied.", vbInformation
End Sub

Error showing Run-time error '424' for index match vba

I would like to have a index match vba to be executed for one cell (C14) whereby the lookup cell would be C15. Please help advise where did the code went wrong?
Source data would be export workbook sheet1.
Sub Index_Match()
Dim custName As Range 'sourceRange
Dim BRN As Range 'lookupRange
Dim ws As Worksheet 'current sheet
Dim exportWb As Workbook
Dim exportWs As Worksheet
Set ws = Sheet1
Set exportWb = Workbooks.Open("C:\Users\hrhquek\desktop\export.xlsx")
Set exportWs = exportWb.Worksheets("Sheet1")
Set exportWb = ActiveWorkbook
ThisWorkbook.Activate
Set custName = exportWs.Cells(exportWs.Rows.Count, "B").End(xlUp).Row
Set BRN = exportWs.Cells(exportWs.Rows.Count, "E").End(xlUp).Row
ws.Cells(3, 14).Value = Application.WorksheetFunction.Index(custName,
Application.WorksheetFunction.Match(Cells(3, 15), BRN, 0))
End Sub
A VBA Lookup: INDEX/MATCH in VBA
Sub VBALookup()
' Source
Dim swb As Workbook
Set swb = Workbooks.Open("C:\Users\hrhquek\desktop\export.xlsx")
Dim sws As Worksheet: Set sws = swb.Worksheets("Sheet1")
Dim slRow As Long: sws.Cells(sws.Rows.Count, "E").End(xlUp).Row
Dim slrg As Range: Set slrg = sws.Range("E2:E" & slRow)
Dim svrg As Range: Set svrg = sws.Range("B2:B" & slRow)
' Destination
Dim dws As Worksheet: Set dws = Sheet1 ' code name in 'ThisWorkbook'
Dim dlCell As Range: Set dlCell = dws.Range("O3")
Dim dvCell As Range: Set dvCell = dws.Range("N3")
Dim dValue As Variant: dValue = dlCell.Value
' Attempt to find a match.
Dim MatchFound As Boolean
If Not IsError(dValue) Then
If Len(CStr(dValue)) > 0 Then
Dim sIndex As Variant: sIndex = Application.Match(dValue, slrg, 0)
If IsNumeric(sIndex) Then MatchFound = True
End If
End If
' Write result.
If MatchFound Then
dvCell.Value = svrg.Cells(sIndex).Value
MsgBox "Match found.", vbInformation
Else
dvCell.Value = Empty
MsgBox "No match found.", vbExclamation
End If
End Sub

How to Split a Workbook Based on a Column and Copy to the Workbook with the Same Column Value Using Excel VBA?

Here is the sub I am using that splits loops through each tab and split them into multiple workbooks based on the user-specified column, "Manufacturer Name".
Sub SplitSheetIntoMultWkbksBasedOnCol(Col As String)
Dim objWorksheet As Excel.Worksheet
Dim nLastRow, nRow, nNextRow As Integer
Dim strColumnValue As String
Dim objDictionary As Object
Dim varColumnValues As Variant
Dim varColumnValue As Variant
Dim objExcelWorkbook As Excel.Workbook
Dim objSheet As Excel.Worksheet
Dim wsSheet As Worksheet
For Each wsSheet In Worksheets
If wsSheet.Name <> "Open" Then
wsSheet.Activate
Set objWorksheet = ActiveSheet
nLastRow = objWorksheet.Range("A" & objWorksheet.Rows.Count).End(xlUp).Row
Set objDictionary = CreateObject("Scripting.Dictionary")
For nRow = 2 To nLastRow
'Get the specific Column
strColumnValue = objWorksheet.Range(Col & nRow).Value
If objDictionary.Exists(strColumnValue) = False Then
objDictionary.Add strColumnValue, 1
End If
Next
varColumnValues = objDictionary.Keys
For i = LBound(varColumnValues) To UBound(varColumnValues)
varColumnValue = varColumnValues(i)
'Create a new Excel workbook
Set objExcelWorkbook = Excel.Application.Workbooks.Add
Set objSheet = objExcelWorkbook.Sheets(1)
objSheet.Name = objWorksheet.Name
objWorksheet.Rows(1).EntireRow.Copy
objSheet.Activate
objSheet.Range("A1").Select
objSheet.Paste
For nRow = 2 To nLastRow
If CStr(objWorksheet.Range(Col & nRow).Value) = CStr(varColumnValue) Then
objWorksheet.Rows(nRow).EntireRow.Copy
nNextRow = objSheet.Range("A" & objWorksheet.Rows.Count).End(xlUp).Row + 1
objSheet.Range("A" & nNextRow).Select
objSheet.Paste
objSheet.Columns("A:B").AutoFit
End If
Next
Next
End If
Next wsSheet
Workbooks("Open_Spreadsheet_Split.xlsm").Activate
Sheets(1).Activate
End Sub
This is ending up making way too many workbooks. So instead, for each tab, I want to copy the rows with the same Manufacturer to the same workbook.
EDIT: make sure headers from each source sheet are included on each destination sheet.
Try this out:
Sub SplitSheetIntoMultWkbksBasedOnCol(Col As String)
Dim wbSrc As Workbook, ws As Worksheet, wsTmp As Worksheet
Dim dict As Object, lastRow As Long, nRow As Long, v
Dim dictHeader As Object 'for tracking whether headers have been copied
Set dict = CreateObject("Scripting.Dictionary")
Set wbSrc = ActiveWorkbook
Application.ScreenUpdating = False
For Each ws In wbSrc.Worksheets
If ws.Name <> "Open" Then
Set dictHeader = CreateObject("Scripting.Dictionary") 'reset header-tracking dictionary
For nRow = 2 To ws.Cells(Rows.Count, "A").End(xlUp).Row
v = ws.Cells(nRow, Col).Value 'get the specific Column
'need a new workbook?
If Not dict.exists(v) Then
Set wsTmp = Application.Workbooks.Add(xlWBATWorksheet).Worksheets(1) 'add new workbook with one sheet
dict.Add v, wsTmp.Range("A1") 'add key and the first paste destination
End If
'first row from this sheet for this value of `v`?
If Not dictHeader.exists(v) Then
ws.Rows(1).Copy dict(v) 'copy headers from this sheet
Set dict(v) = dict(v).Offset(1, 0) 'set next paste position
dictHeader.Add v, True 'flag header as copied
End If
ws.Rows(nRow).Copy dict(v) 'copy the current row
Set dict(v) = dict(v).Offset(1, 0) 'set next paste position
Next nRow
End If 'not "open" sheet
Next ws
Workbooks("Open_Spreadsheet_Split.xlsm").Activate 'ThisWorkbook?
Sheets(1).Activate
End Sub

How to apply vlookup only for empty cells using vba and another workbook

I want to apply vlookup only on the blank cells through VBA. I am using the below code, but it gives me a Run-time error 13 "Type mismatch".When I run the code step by step via F8, I also get an error 2042 at position If i = "" Then, which also indicates "#N/A".
Dim FileName3 As String
FileName3 = "C:xxxxxx.xlsx"
Dim wb As Workbook: Set wb = ThisWorkbook
Dim lastrow As Long
Dim ws As Worksheet: Set ws = wb.Sheets("Data")
lastrow = ws.cells(Rows.Count, 1).End(xlUp).Row
Dim wb2 As Workbook: Set wb2 = Workbooks.Open(Filename:=FileName3, ReadOnly:=True)
Dim rng As Range: Set rng = ThisWorkbook.Worksheets("Data").Range("S2" & lastrow)
Dim lookupRange As Range: Set lookupRange = wb2.Sheets("Page 1").Range("B2" & lastrow)
Dim i As Range
For Each i In rng
If i = "" Then
i = Application.VLookup(ThisWorkbook.Sheets("Data").Range("A" & i.Row), lookupRange, 2, False)
'MsgBox c.Row
End If
'
Next i
'/////// paste by value
Sheets("Data").Columns(52).Copy
Sheets("Data ").Columns(52).PasteSpecialxlPasteValues
wb2.Close False
ThisWorkbook.Save
I had tried it before with WorksheetFunction.VlookUp, but the same error comes up.
The VlookUp should be executed in the datasheet ("Data") in column "S" for all empty cells.
The LookUp Values are located in another workbook file. I would appreciate it very much if someone could help me.
VBA VLookup For Blank Cells
Option Explicit
Sub VLookupBlanks()
Const sFilePath As String = "C:\xxxxxx.xlsx"
Application.ScreenUpdating = False
Dim swb As Workbook
Set swb = Workbooks.Open(Filename:=sFilePath, ReadOnly:=True)
Dim sws As Worksheet: Set sws = swb.Worksheets("Page 1")
Dim slRow As Long: slRow = sws.Cells(sws.Rows.Count, "B").End(xlUp).Row
Dim srg As Range: Set srg = sws.Range("B2:C" & slRow)
Dim dwb As Workbook: Set dwb = ThisWorkbook
Dim dws As Worksheet: Set dws = dwb.Worksheets("Data")
Dim dlRow As Long: dlRow = dws.Cells(dws.Rows.Count, "A").End(xlUp).Row
Dim drg As Range: Set drg = dws.Range("S2:S" & dlRow)
Dim dCell As Range
Dim dValue As Variant
For Each dCell In drg.Cells
If Len(CStr(dCell.Value)) = 0 Then
dValue = Application.VLookup( _
dCell.EntireRow.Columns("A").Value, srg, 2, False)
If Not IsError(dValue) Then dCell.Value = dValue
End If
Next dCell
swb.Close SaveChanges:=False
With drg.EntireRow.Columns("AZ")
.Value = .Value
End With
dwb.Save
Application.ScreenUpdating = True
MsgBox "Columns updated.", vbInformation
End Sub
Please, try removing of:
Dim rng As Range: Set rng = ThisWorkbook.Worksheets("Data").Range("S2" & lastrow)
Dim lookupRange As Range: Set lookupRange = wb2.Sheets("Page 1").Range("B2" & lastrow)
Dim i As Range
For Each i In rng
If i = "" Then
i = Application.VLookup(ThisWorkbook.Sheets("Data").Range("A" & i.Row), lookupRange, 2, False)
'MsgBox c.Row
End If
'
Next i
with:
Dim rngV As Range
Dim rng As Range: Set rng = ws.Range("S2:S" & lastrow)
Dim lookupRange As Range: Set lookupRange = wb2.Sheets("Page 1").Range("B2:C" & lastrow)
On Error Resume Next 'only to avoid an error if no any empty cell exists in rng
Set rngV = rng.SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
If rngV Is Nothing Then Exit Sub 'no any empty cell...
rngV.Formula = "=Vlookup(A" & rngV.cells(1).row & ", " & lookupRange.Address(external:=True) & ", 2, False)"

Copy selected data to a specific sheet using VBA

I want to select particular columns and then paste this onto a particular sheet, if sheet exists then erase existing data and paste newly copied data. This should work in loop to be refreshed with new data entered in the main sheet.
My code creates the required sheet but pastes data into another new sheet.
Sub Datasort()
'The sheet with all the imported data columns must be active when this macro is run
Dim newSht As Worksheet, sSht As Worksheet, Hdrs As Variant, i As Long, Fnd As Range, Sheet_Name As String
Set sSht = Worksheets("all zip codes")
'Expand the array below to include all relevant column headers
Hdrs = Array("Country", "Zip codes", "GSS")
Application.ScreenUpdating = False
Sheet_Name = "Dataformatted"
Set newSht = Worksheets.Add(after:=sSht)
With sSht.UsedRange.Rows(1)
For i = LBound(Hdrs) To UBound(Hdrs)
Set Fnd = .Find(Hdrs(i), lookat:=xlWhole)
If Not Fnd Is Nothing Then
Intersect(Fnd.EntireColumn, sSht.UsedRange).Copy
newSht.Cells(1, i + 1).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
newSht.Cells(1, i + 1).PasteSpecial Paste:=xlPasteColumnWidths
End If
Next i
Application.CutCopyMode = False
End With
If (Sheet_Exists(Sheet_Name) = False) And (Sheet_Name <> "") Then
Worksheets.Add(after:=sSht).Name = Sheet_Name
End If
Application.ScreenUpdating = True
End Sub
Function Sheet_Exists(WorkSheet_Name As String) As Boolean
Dim newSht As Worksheet
Sheet_Exists = False
For Each newSht In ThisWorkbook.Worksheets
If newSht.Name = WorkSheet_Name Then
Sheet_Exists = True
End If
Next
End Function
(not tested), but you're adding sheet everytime it runs, so assuming everything else works fine, you should:
replace Set newSht = Worksheets.Add(after:=sSht) with below
if not Sheet_Exists(Sheet_Name) then Worksheets.Add(after:=sSht).Name = Sheet_Name
Set newSht = Worksheets(Sheet_Name)
and remove the following part
If (Sheet_Exists(Sheet_Name) = False) And (Sheet_Name <> "") Then
Worksheets.Add(after:=sSht).Name = Sheet_Name
End If
Copy Worksheet Columns
Option Explicit
Sub Datasort()
Const sName As String = "all zip codes"
Const dName As String = "Dataformatted"
Const dfcAddress As String = "A1"
Dim Headers As Variant: Headers = VBA.Array("Country", "Zip codes", "GSS")
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim srg As Range: Set srg = sws.UsedRange
Dim shrg As Range: Set shrg = srg.Rows(1)
Application.ScreenUpdating = False
Dim dws As Worksheet
On Error Resume Next
Set dws = wb.Worksheets(dName)
On Error GoTo 0
If dws Is Nothing Then
Set dws = wb.Worksheets.Add(After:=sws)
dws.Name = dName
Else
dws.UsedRange.Clear
End If
Dim dfCell As Range: Set dfCell = dws.Range(dfcAddress)
Dim scrg As Range
Dim hIndex As Variant
Dim c As Long
For c = 0 To UBound(Headers)
hIndex = Application.Match(Headers(c), shrg, 0)
If IsNumeric(hIndex) Then
Set scrg = srg.Columns(hIndex)
dfCell.Resize(scrg.Rows.Count).Value = scrg.Value
dfCell.EntireColumn.ColumnWidth = scrg.EntireColumn.ColumnWidth
Set dfCell = dfCell.Offset(, 1)
End If
Next c
Application.ScreenUpdating = True
MsgBox "Data formatted."
End Sub

Resources