I have written a program that analyzes a worksheet (with 8000 rows and 40 columns) and returns all of the relevant product ID's but my program is unbearably slow, it takes about 5 minutes to run, so In looking for a way to speed it up I came across some code to disable screenupdating, display status bar, calculation, and events. which doubled the programs run time (from 5 to 10 minutes) But i need the program to be able to run faster still. I kept searching and came across This This seems like it's exactly what i need but i don't exactly understand how to implement it.
Let me explain what my code needs to do and maybe you can help me find a better way. It might be helpful to tell you what the information is about. I work for a company that sells holsters, and we are trying to find a way to gather all of the product ID's for different types of holsters for 1 gun together. So in the first column we have the Gun names, in the 4th column we have the Holster Type and in the 12th column we have the Product ID #.
What I'm trying to do is to for any given line, make the program look throught the rest of the file and return the product ID's for the matching products (products with the exact same name) in lines 33-39 i.e column 33 will have the related concealment holster, 34 will have the related ankle holster etc.
I have already written a code to do this but how can i do it with this named DataRange Method?
Do
ActiveCell.Offset(1, 0).Activate
Location = ActiveCell.Address
GunName = ActiveCell.Value
X = 0
Range("A1").Activate
Do
If ActiveCell.Offset(X, 0).Value = GunName Then
PlaceHolder = ActiveCell.Address
If ActiveCell.Offset(X, 3).Value = "CA" Then
Range(Location).Offset(0, 34).Value = ActiveCell.Offset(X, 12).Value
ElseIf ActiveCell.Offset(X, 3).Value = "AA" Or ActiveCell.Offset(X, 3).Value = "AR" Then
If ActiveCell.Offset(X, 4).Value = "NA-LH" Or ActiveCell.Offset(X, 4).Value = "NA" Or ActiveCell.Offset(X, 4).Value = "11-LH" Or ActiveCell.Offset(X, 4).Value = "13-LH" Or ActiveCell.Offset(X, 4).Value = "12-A-LH" Or ActiveCell.Offset(X, 4).Value = "12-B-LH" Or ActiveCell.Offset(X, 4).Value = "12-C-LH" Or ActiveCell.Offset(X, 4).Value = "12-JB-LH" Or ActiveCell.Offset(X, 4).Value = "12-LS-LH" Or ActiveCell.Offset(X, 4).Value = "12-LS-b-LH" Or ActiveCell.Offset(X, 4).Value = "11-LS-LH" Or ActiveCell.Offset(X, 4).Value = "21L" Then
Else
Range(Location).Offset(0, 35).Value = ActiveCell.Offset(X, 12)
End If
ElseIf ActiveCell.Offset(X, 3).Value = "BA" Or ActiveCell.Offset(X, 3).Value = "BR" Then
Range(Location).Offset(0, 36).Value = ActiveCell.Offset(X, 12)
ElseIf ActiveCell.Offset(X, 3).Value = "HA" Or ActiveCell.Offset(X, 3).Value = "HR" Then
Range(Location).Offset(0, 37).Value = ActiveCell.Offset(X, 12)
ElseIf ActiveCell.Offset(X, 3).Value = "VA" Or ActiveCell.Offset(X, 3).Value = "VR" Then
Range(Location).Offset(0, 38).Value = ActiveCell.Offset(X, 12)
ElseIf ActiveCell.Offset(X, 3).Value = "TA" Or ActiveCell.Offset(X, 3).Value = "TR" Then
Range(Location).Offset(0, 39).Value = ActiveCell.Offset(X, 12)
End If
End If
X = X + 1
Loop Until IsEmpty(ActiveCell.Offset(X, 0).Value)
ActiveCell.Range(Location).Activate
Loop Until IsEmpty(ActiveCell.Value)
AA, BA CA etc are the holster types.
EDIT
After viewing the sample file and clarifying through the below comments, here is the updated code. I believe this should work for you:
Sub tgr()
Dim rngData As Range
Dim GunCell As Range
Dim rngFound As Range
Dim arrResults() As Variant
Dim ResultIndex As Long
Dim cIndex As Long
Dim strFirst As String
Dim strTemp As String
On Error Resume Next
With Range("DataRange")
.Sort .Resize(, 1), xlAscending, Header:=xlYes
Set rngData = .Resize(, 1)
End With
On Error GoTo 0
If rngData Is Nothing Then Exit Sub 'No data or no named range "DataRange"
With rngData
ReDim arrResults(1 To .Rows.Count, 1 To 6)
For Each GunCell In .Cells
If GunCell.Row > 1 Then
ResultIndex = ResultIndex + 1
If LCase(GunCell.Text) <> strTemp Then
strTemp = LCase(GunCell.Text)
Set rngFound = .Find(strTemp, .Cells(.Cells.Count), xlValues, xlWhole)
If Not rngFound Is Nothing Then
strFirst = rngFound.Address
Do
If InStr(1, " CA BA HA VA TA ", " " & .Parent.Cells(rngFound.Row, "D").Text & " ", vbTextCompare) > 0 Then
Select Case UCase(.Parent.Cells(rngFound.Row, "D").Text)
Case "CA": cIndex = 1
Case "BA": cIndex = 3
Case "HA": cIndex = 4
Case "VA": cIndex = 5
Case "TA": cIndex = 6
End Select
arrResults(ResultIndex, cIndex) = .Parent.Cells(rngFound.Row, "M").Text
ElseIf InStr(1, " AA AR ", " " & .Parent.Cells(rngFound.Row, "D").Text & " ", vbTextCompare) > 0 _
And InStr(1, " NA-LH NA 11-LH 13-LH 12-A-LH 12-B-LH 12-C-LH 12-JB-LH 12-LS-LH 12-LS-b-LH 11-LS-LH 21L ", " " & .Parent.Cells(rngFound.Row, "E").Text & " ", vbTextCompare) = 0 Then
cIndex = 2
arrResults(ResultIndex, cIndex) = .Parent.Cells(rngFound.Row, "M").Text
End If
Set rngFound = .Find(strTemp, rngFound, xlValues, xlWhole)
Loop While rngFound.Address <> strFirst
End If
Else
For cIndex = 1 To UBound(arrResults, 2)
arrResults(ResultIndex, cIndex) = arrResults(ResultIndex - 1, cIndex)
Next cIndex
End If
End If
Next GunCell
End With
Range("AI2:AI" & Rows.Count).Resize(, UBound(arrResults, 2)).ClearContents
If ResultIndex > 0 Then Range("AI2").Resize(ResultIndex, UBound(arrResults, 2)).Value = arrResults
End Sub
Avoid .Activate, which is VERY slow and generally useless. Instead try something in this style:
Option Explicit
Sub sample()
Dim c As Range
For Each c In Range("a:a").SpecialCells(xlCellTypeConstants)
If c.Offset(x, 0).Value = GunName Then
'etc etc
End If
Next c
End Sub
Oh ! and make sure you use Option Explicit and you Dim your variables. It's not for speed, it is to avoid errors. And use comments ;-)
Related
I use following code to transfer my userform data (from textboxes to respective cell values in row A2) which works fine for me as i want the data to be pushed down when added:
Private Sub CommandButton1_Click()
Dim emptyRow As Long
'Validation
If WorksheetFunction.CountIf(Sheets("RawData").Range("A:A"),
Me.TextBox1.Value) = False Then
MsgBox "Ticket Does Not Exist", vbCritical
End If
'Determine emptyRow
emptyRow = WorksheetFunction.CountA(Range("A:A")) + 1
'Transfer information
With ThisWorkbook.Sheets("WOTracker")
.Cells(2, 1).EntireRow.Insert
.Cells(2, 1).Value = TextBox1.Value
.Cells(2, 5).Value = TextBox2.Value
.Cells(2, 2).Value = TextBox3.Value
.Cells(2, 3).Value = TextBox4.Value
.Cells(2, 6).Value = TextBox5.Value
.Cells(2, 7).Value = ComboBox1.Value
.Cells(2, 8).Value = ComboBox2.Value
.Cells(2, 9).Value = TextBox8.Value
.Cells(2, 4).Value = TextBox9.Value
End With
'Formatting
Dim dDate As Date
dDate = DateSerial(Month(Date), Day(Date), Year(Date))
TextBox2.Value = Format(TextBox2.Value, "mm/dd/yy")
dDate = TextBox2.Value
With ThisWorkbook.Sheets("WOTracker")
Sheets("WOTracker").Range("A2:Z2").Font.Bold = False
Sheets("WOTracker").Range("A2:Z2").Font.Underline = xlUnderlineStyleNone
End With
End Sub
In the same sheet, there is column L where i would like to calculate the difference between current date and the date mentioned in column E2 (in # of days) and i would like this to be dynamic so when a new line of data is added to row A2, this formula is applied in L2 while maintaining the formula in the rest of the column L for the data that will be pushed down.
I have tried copy/pastespecial and it doesnt work....
I hope this makes sense.
Would really appreciate assistance!
I would make some organizational changes to your code first
Private Sub CommandButton1_Click()
Dim emptyRow As Long
'Validation
If WorksheetFunction.CountIf(Sheets("RawData").Range("A:A"),
Me.TextBox1.Value) = False Then
MsgBox "Ticket Does Not Exist", vbCritical
End If
'Transfer information
With ThisWorkbook.Sheets("WOTracker")
.Cells(2, 1).EntireRow.Insert
'Determine emptyRow
emptyRow = .Range("L" & Rows.Count).End(xlUp).Row
'changed from WorksheetFunction.CountA(Range("A:A")) + 1 so we can retrieve last
'row in column L
.Cells(2, 1).Value = TextBox1.Value
.Cells(2, 5).Value = TextBox2.Value
.Cells(2, 2).Value = TextBox3.Value
.Cells(2, 3).Value = TextBox4.Value
.Cells(2, 6).Value = TextBox5.Value
.Cells(2, 7).Value = ComboBox1.Value
.Cells(2, 8).Value = ComboBox2.Value
.Cells(2, 9).Value = TextBox8.Value
.Cells(2, 4).Value = TextBox9.Value
.Range("L2:L" & emptyRow) = "=DAYS(TODAY(),$E$2)"
End With
'Formatting <- Might consider deleting the lines containing dDate since it's never
'used
Dim dDate As Date
dDate = DateSerial(Month(Date), Day(Date), Year(Date))
TextBox2.Value = Format(TextBox2.Value, "mm/dd/yy")
dDate = TextBox2.Value
With ThisWorkbook.Sheets("WOTracker")
Sheets("WOTracker").Range("A2:Z2").Font.Bold = False
Sheets("WOTracker").Range("A2:Z2").Font.Underline = xlUnderlineStyleNone
End With
End Sub
The line .Range("L2:L" & emptyRow) = "=DAYS(TODAY(),$E$2)" will calculate the difference in days between the current date and the date in cell E2 for every cell in column L.
If, instead, what you wanted is for each line to subtract from today with respect to it's row number, just change
.Range("L2:L" & emptyRow) = "=DAYS(TODAY(),$E$2)"
To
.Range("L2") = "=DAYS(TODAY(),$E$2)"
And the insert operation will update the formula automatically.
So I currently have this code;
Function ISMERGED(CellAddress As Range) As Boolean
ISMERGED = CellAddress.MergeCells
End Function
Sub Demerge()
Dim CurrentCell As Range
For Each CurrentCell In ActiveSheet.UsedRange
If ISMERGED(CurrentCell) Then CurrentCell.UnMerge
Next
End Sub
Sub Txfer()
Dim x As Long
Dim TestRow As Range
Call Demerge
With Worksheets("Sheet2")
.UsedRange.Delete
.Cells(1, 1).Formula = "Test Name"
.Cells(1, 2).Formula = "Test Description"
.Cells(1, 3).Formula = "Step Name"
.Cells(1, 4).Formula = "Test Step"
.Cells(1, 5).Formula = "Expected Result"
End With
With Worksheets("Sheet2")
For x = 2 To Worksheets("Sheet1").UsedRange.Rows.Count
If Worksheets("Sheet1").Cells(x, 2).Value <> "" Then
.Cells(x, 2).Formula = Worksheets("Sheet1").Cells(x, 4).Value
.Cells(x, 3).Formula = Worksheets("Sheet1").Cells(x, 2).Value
.Cells(x, 4).Formula = Worksheets("Sheet1").Cells(x, 3).Value
.Cells(x, 5).Formula = Worksheets("Sheet1").Cells(x, 5).Value
'add in further columns
Else
.Cells(.UsedRange.Rows.Count, 4).Formula = .Cells(.UsedRange.Rows.Count, 4).Value & Chr(10) & Worksheets("Sheet1").Cells(x, 3).Value
.Cells(.UsedRange.Rows.Count, 5).Formula = .Cells(.UsedRange.Rows.Count, 5).Value & Chr(10) & Worksheets("Sheet1").Cells(x, 5).Value
'concatenate existing content of target cell with data from current source row
End If
Next x
End With
'now to tidy up the blanks...
Worksheets("Sheet2").Activate
Worksheets("Sheet2").Cells(Worksheets("Sheet2").UsedRange.Rows.Count, 2).Activate
Do
If Application.CountA(ActiveCell.EntireRow) = 0 Then ActiveCell.EntireRow.Delete
ActiveCell.Offset(-1, 0).Activate
Loop Until ActiveCell.Row < 2
Range("A1:E1").Font.Bold = True
End Sub
I want to add an "if" statement that if there is anything in the Test Data (This is the data in "Cells(x, 2).Formula = Worksheets("Sheet1").Cells(x, 4).Value") field of the source sheet, I would like to have the test description field contain: “Test Data: “ followed by the text from the source. If the source cell is empty, I would like the Description field to also be empty.
Basically I just want to add the words "Test Data" before the text that is being moved if their is text present in the original cell
When I run my code, I keep getting a type mismatch error even though all the variables are defined as variants. I'm not sure what the issue is. I'm kind of new to VBA so I would appreciate any help! Thanks!
Sub drink_2()
Columns("E:H").Insert shift:=xlToRight, copyorigin:=xlFormatFromLeftOrAbove
Range("F6").value = "Drink Price"
Range("G6").value = "Drink Revenue"
Range("H6").value = "Gross Sales less Drink Revenue"
Dim i As Variant
Dim item As Variant
Dim drink_price As Variant
Dim wbk As Workbook
Set wbk = Workbooks.Open("C:\Users\username\Documents\vlookup table drink prices.xlsx")
Dim lookup_range As Variant
lookup_range = wbk.Worksheets("Sheet1").Range("A:B").value
i = 7
Do While Cells(i, 1).value <> ""
item = Cells(i, 1).value
Cells(11, 1).value = item
drink_price = Application.WorksheetFunction.VLookup(item, lookup_range, 2, False)
zero_check = Application.WorksheetFunction.IfError(drink_price, 0)
If IsError(Application.WorksheetFunction.VLookup(item, lookup_range, 2, False)) Then
Cells(i, 6).value = ""
Else
Cells(i, 6).value = Application.WorksheetFunction.VLookup(item, lookup_range, 2, False)
End If
Cells(i, 7).Formula = Cells(i, 6).value * Cells(i, 5).value
Cells(i, 8).Formula = Cells(i, 4).value - Cells(i, 7).value
Range("F:G").NumberFormat = "#,##0.00"
i = i + 1
Loop
Cells.EntireColumn.AutoFit
End Sub
This is probably the problem line:
lookup_range = wbk.Worksheets("Sheet1").Range("A:B").value
You should be getting a range, not a value, so you need to use the set keyword and drop the value property.
set lookup_range = wbk.Worksheets("Sheet1").Range("A:B")
I have wrote the following code to merge cells in excel, the data is around 26000 rows, the code is running on core I7 CPU with 8 GB RAM, the problem that it still working since 4 days, the average rows per day is 3000 row!, any one know how to get the result, because its a report that should be delivered since three days!
Sub MergeCellss()
lastRow = Worksheets("A").Range("A65536").End(xlUp).Row
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayAlerts = False
For i = 2 To lastRow
If Cells(i, 2).Value <> Cells(i - 1, 2).Value And Cells(i, 2).Value <> Cells(i + 1, 2).Value Then
intUpper = i
Debug.Print ("<> -1 and <> +1 " & intUpper)
End If
If Cells(i, 2).Value <> Cells(i - 1, 2).Value And Cells(i, 2).Value = Cells(i + 1, 2).Value Then
intUpper = i
Debug.Print ("<> -1 and = +1 " & intUpper & " UPPPER LIMIT")
End If
If Cells(i, 2).Value <> Cells(i + 1, 2).Value And Cells(i, 2).Value = Cells(i - 1, 2).Value Then
Application.DisplayAlerts = False
Debug.Print ("<> +1 and = -1:" & i & "LOWER LIMIT")
DoEvents
For x = 1 To 8
Range(Cells(intUpper, x), Cells(i, x)).Merge
Next x
For j = 18 To 26
Range(Cells(intUpper, j), Cells(i, j)).Merge
Next j
Cells(intUpper, 14).Value = "=sumif(M" & CStr(intUpper) & ":M" & CStr(i) & ","">0"")"
Range(Cells(intUpper, 14), Cells(i, 14)).Merge
Range(Cells(i, 1), Cells(i, 26)).Borders(xlEdgeBottom).LineStyle = xlDouble
End If
If Cells(i, 2).Value <> Cells(i + 1, 2).Value And Cells(i, 2).Value <> Cells(i - 1, 2).Value Then
Debug.Print ("One Cells: " & i)
Range(Cells(i, 1), Cells(i, 26)).Borders(xlEdgeBottom).LineStyle = xlDouble
Cells(intUpper, 14).Value = Cells(intUpper, 13).Value
DoEvents
End If
Next i
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.DisplayAlerts = True
End Sub
the code above will merge the all cells containing repeated data like User Name, Date of Birth, .... into one cell, and leave the training courses and experiences as it is.
I wonder how can I run this code in less than 1 hour.
Here is some rewrite on your code. The two primary differences are the use of If ... ElseIf ... End If and the grouping of the first and fourth conditional operations (the conditions were the same).
Sub Merge_Cells()
Dim lastRow As Long, rw As Long
Dim intUpper As Long, x As Long
Dim vVALs As Variant
appTGGL bTGGL:=False
Debug.Print Timer
With Worksheets("A")
.Cells(1, 1) = Timer
lastRow = .Cells(Rows.Count, 1).End(xlUp).Row
For rw = 2 To lastRow
vVALs = Array(.Cells(rw - 1, 2).Value, .Cells(rw, 2).Value, .Cells(rw + 1, 2).Value)
If vVALs(1) <> vVALs(0) And vVALs(1) <> vVALs(2) Then
'the first and fourth conditions were the same so they are both here
'original first If condition
intUpper = rw
'Debug.Print ("<> -1 and <> +1 " & intUpper)
'original fourth If condition
'Debug.Print ("One Cells: " & rw)
.Range(.Cells(rw, 1), .Cells(rw, 26)).Borders(xlEdgeBottom).LineStyle = xlDouble
.Cells(intUpper, 14).Value = .Cells(intUpper, 13).Value
ElseIf vVALs(1) <> vVALs(0) And vVALs(1) = vVALs(2) Then
intUpper = rw
'Debug.Print ("<> -1 and = +1 " & intUpper & " UPPPER LIMIT")
ElseIf vVALs(1) = vVALs(0) And vVALs(1) <> vVALs(2) Then
'Debug.Print ("<> +1 and = -1:" & rw & "LOWER LIMIT")
For x = 1 To 26
If x < 9 Or x > 17 Then _
.Range(.Cells(intUpper, x), .Cells(rw, x)).Merge
Next x
.Cells(intUpper, 14).Value = "=sumif(M" & CStr(intUpper) & ":M" & CStr(rw) & ","">0"")"
.Range(.Cells(intUpper, 14), .Cells(rw, 14)).Merge
.Cells(rw, 1).Resize(1, 26).Borders(xlEdgeBottom).LineStyle = xlDouble
End If
Next rw
.Cells(1, 2) = Timer
End With
Debug.Print Timer
appTGGL
End Sub
Sub appTGGL(Optional bTGGL As Boolean = True)
Application.Calculation = IIf(bTGGL, xlCalculationAutomatic, xlCalculationManual)
Application.ScreenUpdating = bTGGL
Application.EnableEvents = bTGGL
Application.DisplayAlerts = bTGGL
End Sub
I've also read the three primary conditional values into a variant array to reduce repeated worksheet value reads.
So I have a code I have written the first part of the code is to create a new worksheet with the headings specified. The second part of the code is meant to populate that table with certain information. The problem I am having is getting the correct bits of information to go into the correct columns.
I need the code to search for the value 9.1 in column G in all worksheets within a workbook
if that value is found I need it to copy this to column b in the new sheet along with the following information :
Engine Effect from Column F Same row must be pasted to Column C in the worksheet entitled FHA
Part number is always located in Cell J3 this must be pasted into column D and is always the same
Part Name Is Always located in C2 this must be pasted into column E and is always the same
FM ID from Column B same row must be pasted to Column F in the worksheet entitled FHA
Failure Mode & Cause from Column C Same row must be pasted to column G in FHA
FMCN Value From Column N pasted to Column H In FHA
As It stands the code I have is
Sub createWSheetFHA()
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = "FHA"
Cells(1, 2) = "FHA TABLE"
Cells(2, 2) = "FHA Ref"
Cells(2, 3) = "Engine Effect"
Cells(2, 4) = "Part No"
Cells(2, 5) = "Part Name"
Cells(2, 6) = "FM I.D"
Cells(2, 7) = "Failure Mode & Cause"
Cells(2, 8) = "FMCM"
Cells(2, 9) = "PTR"
Cells(2, 10) = "ETR"
Range(Cells(2, 2), Cells(2, 10)).Font.Bold = True
Range(Cells(1, 2), Cells(1, 10)).MergeCells = True
Range(Cells(1, 2), Cells(1, 10)).Font.Bold = True
End Sub
Sub Populate_FHA_Table_2()
Dim wks As Excel.Worksheet, i As Integer, n As Integer
Application.ScreenUpdating = False
Sheets("FHA").Range("A2:" & Columns.Count & ":" & Rows.Count).Delete
i = 1
For Each wks In ActiveWorkbook.Worksheets
If wks.Name <> "FHA" Then
wks.UsedRange.AutoFilter Field:=7, Criteria1:="9.1"
Sheets(i).Range(Sheets(i).Range("G1").Offset(1), Sheets(i).Range("B1").End(xlDown)).Copy _
Sheets("FHA").Range("C" & Rows.Count).End(xlUp)
Sheets(i).Range(Sheets(i).Range("F1").Offset(1), Sheets(i).Range("D1").End(xlDown)).Copy _
Sheets("FHA").Range("d" & Rows.Count).End(xlUp)
Sheets(i).Range(Sheets(i).Range("J1").Offset(1), Sheets(i).Range("E1").End(xlDown)).Copy _
Sheets("FHA").Range("e" & Rows.Count).End(xlUp)
Sheets(i).Range(Sheets(i).Range("C1").Offset(1), Sheets(i).Range("H1").End(xlDown)).Copy _
Sheets("FHA").Range("E" & Rows.Count).End(xlUp)
Sheets(i).Range(Sheets(i).Range("B1").Offset(1), Sheets(i).Range("H1").End(xlDown)).Copy _
Sheets("FHA").Range("F" & Rows.Count).End(xlUp)
Sheets(i).Range(Sheets(i).Range("C1").Offset(1), Sheets(i).Range("H1").End(xlDown)).Copy _
Sheets("FHA").Range("G" & Rows.Count).End(xlUp)
Sheets(i).Range(Sheets(i).Range("N1").Offset(1), Sheets(i).Range("H1").End(xlDown)).Copy _
Sheets("FHA").Range("H" & Rows.Count).End(xlUp)
wks.UsedRange.AutoFilter
End If
i = i + 1
Next
Application.ScreenUpdating = True
End Sub
You have some mismatches in your code (Example using 'for each wk' then accessing via an index 'i'; where they may not necessarily match)
Try something like this...
I have added in some dynamic flow control which isn't strictly needed but if and when your headers change in the future, it may be easier to have it in this form.
Likewise I have tried to add in some error handling as well
Sub Create_FHA_Sheet()
Dim Headers() As String: Headers = _
Split("FHA Ref,Engine Effect,Part No,Part Name,FM I.D,Failure Mode & Cause,FMCM,PTR,ETR", ",")
If Not WorksheetExists("FHA") Then Worksheets.Add().Name = "FHA"
Dim wsFHA As Worksheet: Set wsFHA = Sheets("FHA")
wsFHA.Move after:=Worksheets(Worksheets.Count)
wsFHA.Cells.Clear
Application.ScreenUpdating = False
With wsFHA
For i = 0 To UBound(Headers)
.Cells(2, i + 2) = Headers(i)
.Columns(i + 2).EntireColumn.AutoFit
Next i
.Cells(1, 2) = "FHA TABLE"
.Range(.Cells(1, 2), .Cells(1, UBound(Headers) + 2)).MergeCells = True
.Range(.Cells(1, 2), .Cells(1, UBound(Headers) + 2)).HorizontalAlignment = xlCenter
.Range(.Cells(1, 2), .Cells(2, UBound(Headers) + 2)).Font.Bold = True
End With
Dim RowCounter As Long: RowCounter = 3
Dim SearchTarget As String: SearchTarget = "9.1"
Dim SourceCell As Range, FirstAdr As String
If Worksheets.Count > 1 Then
For i = 1 To Worksheets.Count - 1
With Sheets(i)
Set SourceCell = .Columns(7).Find(SearchTarget, LookAt:=xlWhole)
If Not SourceCell Is Nothing Then
FirstAdr = SourceCell.Address
Do
wsFHA.Cells(RowCounter, 3).Value = .Cells(SourceCell.Row, 6).Value
wsFHA.Cells(RowCounter, 4).Value = .Cells(3, 10).Value
wsFHA.Cells(RowCounter, 5).Value = .Cells(2, 3).Value
wsFHA.Cells(RowCounter, 6).Value = .Cells(SourceCell.Row, 2).Value
wsFHA.Cells(RowCounter, 7).Value = .Cells(SourceCell.Row, 3).Value
wsFHA.Cells(RowCounter, 8).Value = .Cells(SourceCell.Row, 14).Value
Set SourceCell = .Columns(7).FindNext(SourceCell)
RowCounter = RowCounter + 1
Loop While Not SourceCell Is Nothing And SourceCell.Address <> FirstAdr
End If
End With
Next i
End If
Application.ScreenUpdating = True
End Sub
Public Function WorksheetExists(ByVal WorksheetName As String) As Boolean
On Error Resume Next
WorksheetExists = (ThisWorkbook.Sheets(WorksheetName).Name <> "")
On Error GoTo 0
End Function