Change checkbox result value - vba

Everything is working fine in this code like adding the checkboxes etc.. except for 2 things;
the main one is: the condition to change the value (at the very bottom of the code) is not working
and the other one is: the delete checkboxes (at the very first of the code) doesn't seem to work properly because sometimes i find more than 1 checkbox have been created in 1 cell
how do i upload the file here to clear things up ?
Sub AddCheckBoxes()
Dim i, LRow As Single
Dim MyLeft, MyTop, MyHeight, MyWidth As Double
Application.ScreenUpdating = False
LRow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To LRow
If Cells(i, "A").Value <> "" Then
If Cells(i, "C").Value <> "" Then
Cells(i, "C").ClearContents
ActiveSheet.Shapes.Cells(i, "C").Select
Selection.delete
ElseIf IsEmpty(Cells(i, "C")) Then
MyLeft = Cells(i, "C").Left
MyTop = Cells(i, "C").Top
MyHeight = Cells(i, "C").Height
MyWidth = Cells(i, "C").Width
Set cbx = ActiveSheet.CheckBoxes.Add(MyLeft, MyTop, MyWidth, MyHeight)
With cbx
.Name = "CheckBox" & i
.Caption = ""
.Display3DShading = False
End With
End If
If cbx.Value = xlOff Then
Range("B" & i).Value = 1
ElseIf cbx.Value = xlOn Then
Range("B" & i).Value = 2
End If
End If
Next i
Application.ScreenUpdating = True
End Sub

Related

VBA code executes in break mode but skips to the end during normal run

This code works perfectly if I run it in break mode by stepping through each line. However, if I run it normally, it seems like it just skips to the end. It gives me a message box of a one second run time and none of the lines of code have been executed. Any help would be greatly appreciated!
Sub addVals()
Dim i As Integer, j As Integer, sheetName As String, timer As Double
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
timer = Now()
For i = 1 To 7
sheetName = Range("sheetnames2").Offset(i, 0).Value
For j = 1 To 3000
If Sheets(sheetName).Range("P" & j).Value <> 0 Then
For Each Cell In Range("R" & j, "R" & j + 30)
If Cell = 1 Then Range("S" & j).Value = Cell.Offset(0, -17).Value: Exit For
Next Cell
Else
End If
Next j
Next i
Application.Calculation = xlCalculationAutomatic
MsgBox (Format(Now() - timer, "HH:MM:SS"))
End Sub
Couple of corrections:
Sub addVals()
Dim i As Integer, j As Integer, sheetName As String, timer As Double
Dim sht As Worksheet, Cell As Range
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
timer = Now()
For i = 1 To 7
sheetName = Range("sheetnames2").Offset(i, 0).Value
With Sheets(sheetName) '<< scope the loop to the correct sheet
For j = 1 To 3000
If .Range("P" & j).Value <> 0 Then
For Each Cell In .Range("R" & j).Resize(30, 1).Cells
If Cell.Value = 1 Then
.Range("S" & j).Value = Cell.Offset(0, -17).Value
Exit For '<< unless you really meant what you wrote?
End If
Next Cell
End If
Next j
End With
Next i
Application.Calculation = xlCalculationAutomatic
MsgBox (Format(Now() - timer, "HH:MM:SS"))
End Sub
Note this one-liner:
If Cell = 1 Then Range("S" & j).Value = Cell.Offset(0, -17).Value: Exit For
is functionally the same as:
If Cell = 1 Then
Range("S" & j).Value = Cell.Offset(0, -17).Value
End If
Exit For
and is not the same as:
If Cell = 1 Then
Range("S" & j).Value = Cell.Offset(0, -17).Value
Exit For
End If
...so it might not be behaving as you expect

excel vba code corrupting my file consistently after a few runs

I have a relatively long set of subs that get run on a list of my excel files a few times a day. after a few runs, the file then becomes corrupted which normally would not be an issue b/c it doesn't really effect any of the data. however, I have another program that opens up each of the excel and pulls some key data from each one to make a summary sheet. because the corrupted file gives a message that says something along the lines of "there is a problem with some of your content" the summary program stops with a
run-time error '1004': Method of object 'Workbooks' Failed
I can not for the life of me figure out what in my code is causing the corruption. Is there a way I can have the summary code ignore the corruption notification? Ive tried a handful of different things including turning the application notifications off in my code to no avail.
Any help is greatly appreciated! ill post my all my code with a brief description below:
Here is the code from the summary file that opens each of the
individual files and pulls data:
Sub OEEsummmary()
Dim ActCycCell, ExpCycCell, ExpCurCycCell, ShiftCell, DifCell, DownCell, DTResACell, DTResBCell, PartCell, OpNamCell, OprCell, RejCell, RejResCell As Range
Dim MySheet As Worksheet
Dim Txt$, MyPath$, MyWB$
Dim myValue As Integer
Dim x As Long
Dim v As Variant, r As Range, rWhere As Range
MyPath = "L:\Manufacturing Engineering\Samuel Hatcher\"
x = 2
Set MySheet = ActiveSheet
'Application.ScreenUpdating = False
Application.EnableEvents = False
MySheet.Range("B2:G18").ClearContents
MySheet.Range("J2:O18").ClearContents
Do While MySheet.Range("A" & x).Value <> ""
MyWB = MySheet.Range("A" & x).Text
Workbooks.Open Filename:=MyPath & MyWB, ReadOnly:=True, IgnoreReadOnlyRecommended:=True
Set ActCycCell = ActiveSheet.Range("E21")
Set ExpCycCell = ActiveSheet.Range("D21")
Set ShiftCell = ActiveSheet.Range("E2")
Set DownCell = ActiveSheet.Range("K28")
Set DTResACell = ActiveWorkbook.Worksheets("Downtime").Range("O9")
Set DTResBCell = ActiveWorkbook.Worksheets("Downtime").Range("O10")
Set PartCell = ActiveSheet.Range("E4")
Set ExpCurCycCell = ActiveSheet.Range("D22")
If ActiveSheet.Range("I3") = "" Then
Set OpNamCell = ActiveSheet.Range("I2")
Else
Set OpNamCell = ActiveSheet.Range("I3")
End If
Set OprCell = ActiveSheet.Range("C4")
Set RejCell = ActiveSheet.Range("H21")
Set RejResCell = ActiveWorkbook.Worksheets("Rejected Parts").Range("H5")
With MySheet.Range("A" & x)
.Offset(0, 14).Value = OprCell.Value
.Offset(0, 13).Value = OpNamCell.Value
.Offset(0, 12).Value = PartCell.Value
.Offset(0, 11).Value = ShiftCell.Value
.Offset(0, 10).Value = RejResCell.Value
.Offset(0, 9).Value = RejCell.Value
.Offset(0, 6).Value = ActCycCell.Value
.Offset(0, 5).Value = ExpCycCell.Value
.Offset(0, 4).Value = ExpCurCycCell.Value
.Offset(0, 3).Value = DTResBCell.Value
.Offset(0, 2).Value = DTResACell.Value
.Offset(0, 1).Value = DownCell.Value
End With
ActiveWorkbook.Close savechanges:=False
x = x + 1
Loop
Call sort
'Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Clears the page of data to prepare it for a new shift of entering
data:
Sub ClearFrontEnd()
Sheets("Front End").Unprotect ("29745")
'prompts user to confirm if they realy want to clear entry
response = MsgBox("Are You Sure?", vbYesNo)
If response = vbNo Then
Exit Sub
End If
'checks to see if operator number is there
If range("I3").Value = "" Then
MsgBox "ENTER OPORATOR # AND CLICK NEW SHIFT AGAIN"
Else
Call StopTimer
Call prodChoose
Call transfer
Application.ScreenUpdating = False
ActiveWorkbook.Save
Sheets("Front End").Unprotect ("29745")
Sheets("Front End").Select
'Deletes the data from the entry and unique key fields
range("E8:E20").ClearContents
range("I8:I27").ClearContents
range("J8:J27").ClearContents
range("K8:K27").ClearContents
range("I3").ClearContents
range("H8").Value = ""
range("H9").Value = ""
range("H10").Value = ""
range("H11").Value = ""
range("H12").Value = ""
range("H13").Value = ""
range("H14").Value = ""
range("H15").Value = ""
range("H16").Value = ""
range("H17").Value = ""
range("H18").Value = ""
range("H19").Value = ""
range("H20").Value = ""
range("A1").Select
MsgBox "Please enter the correct values for SHIFT #, SHIFT LENGTH, PART #, AND OPORATOR #, Thanks! Have a great day!!"
End If
Sheets("Front End").Protect ("29745")
Call timerchoose
Application.ScreenUpdating = True
End Sub
This copies the data from the front page to a raw data sheet every
hour:
Sub transfer()
Sheets("Front End").Unprotect ("29745")
Application.ScreenUpdating = False
Dim x As Long
Dim v As Variant, r As range, rWhere As range
'set starting point at row 8
x = 8
'defines the sheet the data is being coppied from and pasted to
Dim sourceSheet As Worksheet: Set sourceSheet = ThisWorkbook.Worksheets("Front End")
Dim destSheet As Worksheet: Set destSheet = ThisWorkbook.Worksheets("Raw Data")
If sourceSheet.range("I3").Value = "" Then
Call StartTimer
Exit Sub
Else
Do While range("L" & x).Value <> ""
'Checks if the unique code is in the raw data sheet or not
v = sourceSheet.range("M" & x).Value
Set rWhere = destSheet.range("S:S")
Set r = rWhere.Find(what:=v, After:=rWhere(1))
If r Is Nothing Then
'selects the next row where the 1st column is empty
lMaxRows = destSheet.Cells(destSheet.Rows.Count, "A").End(xlUp).Row
'pastes the data from the specified cells into the next empty row
destSheet.range("A" & lMaxRows + 1).Value = sourceSheet.range("C2").Value
destSheet.range("M" & lMaxRows + 1).Value = sourceSheet.range("E2").Value
destSheet.range("N" & lMaxRows + 1).Value = sourceSheet.range("E4").Value
destSheet.range("P" & lMaxRows + 1).Value = sourceSheet.range("G4").Value
destSheet.range("Q" & lMaxRows + 1).Value = sourceSheet.range("C4").Value
destSheet.range("O" & lMaxRows + 1).Value = sourceSheet.range("I3").Value
destSheet.range("B" & lMaxRows + 1).Value = sourceSheet.range("J" & x).Value
destSheet.range("C" & lMaxRows + 1).Value = sourceSheet.range("K" & x).Value
destSheet.range("D" & lMaxRows + 1).Value = sourceSheet.range("L" & x).Value
destSheet.range("E" & lMaxRows + 1).Value = sourceSheet.range("I" & x).Value
destSheet.range("S" & lMaxRows + 1).Value = sourceSheet.range("M" & x).Value
x = x + 1
Else
x = x + 1
End If
Loop
x = 8
Do While range("D" & x).Value <> 0
If range("E" & x).Value <> "" Then
'Checks if the unique code is in the raw data sheet or not
v = sourceSheet.range("A" & x).Value
Set rWhere = destSheet.range("S:S")
Set r = rWhere.Find(what:=v, After:=rWhere(1))
If r Is Nothing Then
'selects the next row where the 1st column is empty
lMaxRows = destSheet.Cells(destSheet.Rows.Count, "A").End(xlUp).Row
'pastes the data from the specified cells into the next empty row
destSheet.range("A" & lMaxRows + 1).Value = sourceSheet.range("C2").Value
destSheet.range("M" & lMaxRows + 1).Value = sourceSheet.range("E2").Value
destSheet.range("N" & lMaxRows + 1).Value = sourceSheet.range("E4").Value
destSheet.range("P" & lMaxRows + 1).Value = sourceSheet.range("G4").Value
destSheet.range("Q" & lMaxRows + 1).Value = sourceSheet.range("C4").Value
destSheet.range("O" & lMaxRows + 1).Value = sourceSheet.range("I3").Value
destSheet.range("B" & lMaxRows + 1).Value = sourceSheet.range("B" & x).Value
destSheet.range("L" & lMaxRows + 1).Value = sourceSheet.range("C" & x).Value
destSheet.range("F" & lMaxRows + 1).Value = sourceSheet.range("D" & x).Value
destSheet.range("G" & lMaxRows + 1).Value = sourceSheet.range("E" & x).Value
destSheet.range("I" & lMaxRows + 1).Value = sourceSheet.range("G" & x).Value
destSheet.range("K" & lMaxRows + 1).Value = sourceSheet.range("H" & x).Value
destSheet.range("H" & lMaxRows + 1).Value = sourceSheet.range("N" & x).Value
destSheet.range("J" & lMaxRows + 1).Value = sourceSheet.range("O" & x).Value
destSheet.range("S" & lMaxRows + 1).Value = sourceSheet.range("A" & x).Value
x = x + 1
Else
x = x + 1
End If
Else
x = x + 1
End If
Loop
'sorts Raw Data table after new data is added
Dim ws As Worksheet
Set ws = ActiveWorkbook.Worksheets("Raw Data")
'specifies how to sort the data
With ws.Sort.SortFields
.Clear
.add Key:=ws.range("A2:A" & lMaxRows + 1), SortOn:=xlSortOnValues, _
Order:=xlAscending, DataOption:=xlSortNormal
.add Key:=ws.range("B2:B" & lMaxRows + 1), SortOn:=xlSortOnValues, _
Order:=xlAscending, DataOption:=xlSortNormal
'specifies range over which to sort
End With
With ws.Sort
.SetRange ws.range("A1:S" & lMaxRows + 1)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End If
Sheets("Front End").Protect ("29745")
Call SortDTWeek
Call SortDTMonth
Call StartTimer
Application.ScreenUpdating = True
End Sub
This checks a few cells constantly to see if they have been double
clicked, if so it puts the current time in that cell
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As range, cancel As Boolean)
'Adds downtime start and finish values
'Check to see if the click/selected cell is in columns I or J
If Not Intersect(Target, range("J:K")) Is Nothing Then
'Make sure cell is in range
If Target.Row > 7 And Target.Row <= 27 Then
'Update the value
Target.Value = Time()
End If
End If
End Sub
Checks to see if a set of cells has been changed, if so it puts the
now() value in a corresponding "key" column
Private Sub Worksheet_Change(ByVal Target As range)
Sheets("Front End").Unprotect ("29745")
Dim cell As range
'Adds unique keyA values
'Check to see if the changed cell is in column E
If Not Intersect(Target, range("E:E")) Is Nothing Then
For Each cell In Target.Cells
If cell.Value <> vbNullString And Target.Row > 7 And Target.Row <= 20 Then
'Update the "KeyA" value
Sheets("Front End").range("A" & Target.Row).Value = Now()
End If
Next cell
Else
'Adds unique keyB values
'Check to see if the changed cell is in column K
If Not Intersect(Target, range("K:K")) Is Nothing Then
For Each cell In Target.Cells
If cell.Value <> vbNullString And (Target.Row > "6" And Target.Row <= "27") Then
'Update the "KeyM" value
range("M" & Target.Row).Value = Now()
End If
Next cell
End If
End If
Sheets("Front End").Unprotect ("29745")
End Sub
thanks for any input this issue has been driving me crazy
as #MLind suggested in the comments, to bypass the corrupted file error and pull some data out i added this to my code:
Workbooks.Open Filename:=MyPath & MyWB, ReadOnly:=True, IgnoreReadOnlyRecommended:=True,
CorruptLoad:=xlExtractData
and used
Application.DisplayAlerts = False
within the loop to prevent any pop up boxes from stopping the sub

Merging over 2000 Cells using VBA?

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.

Copy range to another sheet and insert name from Input Box with this copy

I have User form where I have command button and input text box.
I want to copy specified range from one worksheet, then name and paste in another sheet.
My code looks like this, but it is not working.
Private Sub CommandButton1_Click()
Dim i, LastRow
Dim ws As Worksheet
Dim k As Integer
Set ws = Worksheets("Vali")
LastRow = Sheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
For i = 4 To LastRow 'find fulfiled rows
If Sheets("Sheet1").Cells(i, "D").Value = 1 Then
Sheets("Sheet1").Range(Cells(i, "B"), Cells(i, "D")).Copy Destination:=Sheets("Vali").Range("A" & Rows.Count).End(xlUp).Offset(1)
End If
Next i
Dim i As Integer
'Next we use a looping process 'We start the loop from row 2 because our worksheet has headers in row 1
For k = 2 To 100
'Now we define a condition that only if there is data under the headers ItemID, Description,
If Cells(k, "A").Value <> "" And Cells(k, "B").Value <> "" And Cells(k, "C").Value <> "" And Cells(k, "D").Value <> "" And Cells(k, "E").Value = "" Then
Cells(k, "D").Value = Me.txtname.Value
End If
Next
Range("E:E").EntireColumn.AutoFit
Range("B4:D21").ClearContents 'clear content on previos sheet, from where we made copy
ActiveWorkbook.Save
ValiFinish.Hide
End Sub
Not sure what you were trying to do with your test on you second loop, because there was no sheet reference, so I choose, let me know if it wasn't that
Private Sub CommandButton1_Click()
Application.ScreenUpdating = False
Dim LastRow As Double
Dim ws As Worksheet
Dim Wv As Worksheet
Dim k As Integer
Dim i As Integer
Dim Ti()
ReDim Ti(0)
Dim StartPaste As Double
Dim EndPaste As Double
Dim PastedRange As String
Set ws = Worksheets("Sheet1")
Set Wv = Worksheets("Vali")
LastRow = ws.Range("A" & Rows.Count).End(xlUp).Row
StartPaste = Wv.Range("A" & Rows.Count).End(xlUp).Offset(1).Row
For i = 2 To LastRow
If ws.Cells(i, "D").Value = 1 Then
ws.Range(ws.Cells(i, "A"), ws.Cells(i, "D")).Copy _
Destination:=Wv.Range("A" & Rows.Count).End(xlUp).Offset(1)
Ti(UBound(Ti)) = i
ReDim Preserve Ti(UBound(Ti) + i)
EndPaste = Wv.Range("A" & Rows.Count).End(xlUp).Offset(1).Row - 1
'2 options because i'm not sur where you want to add the text :
'First one (write on Vali, I think that's what you are looking to do) :
If Wv.Cells(EndPaste, "A").Value <> "" And Wv.Cells(EndPaste, "B").Value <> "" And Wv.Cells(EndPaste, "C").Value <> "" _
And Wv.Cells(EndPaste, "D").Value <> "" And Wv.Cells(EndPaste, "E").Value = "" Then
Wv.Cells(Wv.Range("A" & Rows.Count).End(xlUp).Row, "E").Value = ValiFinish.TxTNaMe.Value
End If
'Second one (write on Sheet1) :
If ws.Cells(i, "A").Value <> "" And ws.Cells(i, "B").Value <> "" And ws.Cells(i, "C").Value <> "" _
And ws.Cells(i, "D").Value <> "" And ws.Cells(i, "E").Value = "" Then
ws.Cells(ws.Range("A" & Rows.Count).End(xlUp).Row, "E").Value = ValiFinish.TxTNaMe.Value
End If
'end of options
End If
Next i
PastedRange = "" & Wv.Name & "!R" & StartPaste & "C1:R" & EndPaste & "C3"
ActiveWorkbook.Names.Add Name:=ValiFinish.TxTNaMe.Value, RefersToR1C1:=PastedRange
'clear content on previous sheet, from where we made copy
For i = LBound(Ti) To UBound(Ti) - 1
ws.Range("$B$" & Ti(i) & ":$D$" & Ti(i)).ClearContents
Next i
Wv.Range("E:E").EntireColumn.AutoFit
Set ws = Nothing
Set Wv = Nothing
ActiveWorkbook.Save
ValiFinish.Hide
Application.ScreenUpdating = True
End Sub

How do you speed up VBA code with a named range?

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 ;-)