I am struggling with the error subscript out of range at the code:
Set wsCondition = wbCondition.Worksheets(2)
This code is run very well on windows but when I try on MacOS the error occurs. I am a newbie to VBA and I completely do not understand why this error occurs.
Thanks in advance for your guys advice.
Option Explicit
Public Sub btn1_Click()
Dim i As Double
Dim N As Double
Dim strKeyWord As String
Dim myCount As Integer
Dim OrderCount As Integer
Dim SubTotal As Range, Country As Range, DisCount As Range, Quantity As Range, ItemName As Range, OrderName As Range, RequiredData As Range
Dim wsOrder As Worksheet
Dim wsResult As Worksheet
Dim wsCondition As Worksheet
Dim wbOrder As Workbook
Dim wbCondition As Workbook
Dim OrderFile As String
Dim ConditionFile As String
'Open Order wb
OrderFile = Application.GetOpenFilename()
Set wbOrder = Workbooks.Open(OrderFile)
Set wsOrder = wbOrder.Worksheets(1)
'Open Condition wb
ConditionFile = Application.GetOpenFilename()
Set wbCondition = Workbooks.Open(ConditionFile)
Set wsCondition = wbCondition.Worksheets(2)
Set wsResult = wbCondition.Worksheets(1)
With wsResult
.Range("A1").Value = "Product code"
.Range("B1").Value = "Order Condition"
.Range("C1").Value = "Order Name"
.Range("D1").Value = "Subtotal"
.Range("E1").Value = "Discount"
.Range("F1").Value = "Quantity"
.Range("G1").Value = "Item Name"
.Range("H1").Value = "Country"
.Range("A1").Characters(1, 12).Font.Bold = True
.Range("B1").Characters(1, 16).Font.Bold = True
.Range("C1").Characters(1, 16).Font.Bold = True
.Range("D1").Characters(1, 12).Font.Bold = True
.Range("E1").Characters(1, 12).Font.Bold = True
.Range("F1").Characters(1, 12).Font.Bold = True
.Range("G1").Characters(1, 12).Font.Bold = True
.Range("H1").Characters(1, 12).Font.Bold = True
.Range("A1").WrapText = True
.Range("B1").WrapText = True
.Range("C1").WrapText = True
.Range("D1").WrapText = True
.Range("E1").WrapText = True
.Range("F1").WrapText = True
.Range("G1").WrapText = True
.Range("H1").WrapText = True
.Range("A1").ColumnWidth = 13
.Range("A1").RowHeight = 17
.Range("B1").ColumnWidth = 12
.Range("B1").RowHeight = 17
.Range("C1").ColumnWidth = 14.5
.Range("C1").RowHeight = 17
.Range("G1").ColumnWidth = 99
.Range("G1").RowHeight = 17
End With
'using the CountA ws function (all non-blanks)
myCount = Application.CountA(wsCondition.Range("A:A"))
For i = 2 To myCount Step 1
strKeyWord = wsCondition.Range("A" & i)
wsOrder.Range("R:R").AutoFilter Field:=1, Criteria1:="=*" & strKeyWord & "*"
If wsOrder.Cells(Rows.Count, 1).End(xlUp).Row > 1 Then
Set SubTotal = wsOrder.Range("I2", wsOrder.Range("I" & Rows.Count).End(xlUp))
Set Country = wsOrder.Range("AG2", wsOrder.Range("AG" & Rows.Count).End(xlUp))
Set DisCount = wsOrder.Range("N2", wsOrder.Range("N" & Rows.Count).End(xlUp))
Set Quantity = wsOrder.Range("Q2", wsOrder.Range("Q" & Rows.Count).End(xlUp))
Set OrderName = wsOrder.Range("A2", wsOrder.Range("A" & Rows.Count).End(xlUp))
Set ItemName = wsOrder.Range("R2", wsOrder.Range("R" & Rows.Count).End(xlUp))
Set RequiredData = Union(SubTotal, Country, DisCount, Quantity, OrderName, ItemName)
RequiredData.SpecialCells(xlCellTypeVisible).Copy
OrderCount = wsOrder.Range("A2", wsOrder.Range("A" & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible).Cells.Count
With wsResult
If OrderCount >= 2 Then
For N = 1 To OrderCount Step 1
.Cells(.Rows.Count, "A").End(xlUp).Offset(1).Value = strKeyWord
.Cells(.Rows.Count, "B").End(xlUp).Offset(1).Value = "Available"
Next N
Else
.Cells(.Rows.Count, "A").End(xlUp).Offset(1).Value = strKeyWord
.Cells(.Rows.Count, "B").End(xlUp).Offset(1).Value = "Available"
End If
.Cells(.Rows.Count, "C").End(xlUp).Offset(1).PasteSpecial
End With
Else
With wsResult
.Cells(.Rows.Count, "A").End(xlUp).Offset(1).Value = strKeyWord
.Cells(.Rows.Count, "B").End(xlUp).Offset(1).Value = "No Order"
.Cells(.Rows.Count, "C").End(xlUp).Offset(1).Value = "N/A"
.Cells(.Rows.Count, "D").End(xlUp).Offset(1).Value = "N/A"
.Cells(.Rows.Count, "E").End(xlUp).Offset(1).Value = "N/A"
End With
End If
OrderCount = 0
Next i
wbCondition.Sheets("Result").Activate
wsOrder.AutoFilterMode = False
End Sub
This has nothing to do whether this code is running on a Mac or Win environment. You have to check if a second worksheet exists in the file you open. In your case you could add following code
If wbCondition.Worksheets.Count > 1 Then
Set wsCondition = wbCondition.Worksheets(2)
else
' Do sth in order to fix the error or end the sub
end if
If you get a subscript out of range it means you tried to access a worksheet that doesn’t exist. This may happen for the following reasons
The worksheet name given to Worksheets is spelled incorrectly.
The name of the worksheet has changed. The worksheet was deleted.
The index was to large e.g. You used Worksheets(5) but there are only four worksheets
The wrong workbook is being used e.g. Workbooks(“book1.xlsx”).Worksheets(“Sheet1”) instead of Workbooks(“book3.xlsx”).Worksheets(“Sheet1”)
You find this here
Related
I am generating a new workbook from a multiple workbooks, i can generate a summary of all the errors found, but when i try to copy the sheets with the error information i got the runtime error 9
These is the line failing
If exists = True Then
ActiveWorkbook.Sheets(sheetName).Copy After:=ThisWorkbook.Sheets(1)
End If
Other thing i havent add is that all the sheets on the multiple files have the same names, so i want to know if there is a way that the sheet when is copy i can add the file name and the sheet name
Sub getViolations()
Path = "C:\Users\omartinr\Desktop\New folder (4)\New folder\"
Filename = Dir(Path & "*.xls")
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Set TxtRng = ws.Range("A1:N1")
TxtRng.Font.ColorIndex = 2
TxtRng.Interior.ColorIndex = 5
TxtRng.Value = [{"Partition Name","Tag","EM Supply","SH Signal","PK","Sfactor","FiSH","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL"}]
TxtRng.HorizontalAlignment = xlCenter
Dim i As Integer
i = 2
Do While Filename <> ""
Workbooks.Open Filename:=Path & Filename, ReadOnly:=True
Dim wc As Worksheet
Set wc = ActiveWorkbook.Sheets("Violations Summary")
ws.Cells(i, 1).Value = ActiveWorkbook.Sheets("Violations Summary").Range("B1")
ws.Cells(i, 2).Value = ActiveWorkbook.Sheets("Violations Summary").Range("C1")
Dim count As Integer
count = 15
Dim sheetName As String, mySheetNameTest As String
Dim n As Integer
Dim exits As Boolean
For n = 3 To 14
If Not IsEmpty(wc.Cells(n, 2)) Then
If (wc.Cells(n, 2)) = 0 Then
ws.Cells(i, n).Font.ColorIndex = 4
ws.Cells(i, n).Value = wc.Cells(n, 2)
End If
If (wc.Cells(n, 2)) > 0 Then
Select Case wc.Cells(n, 1)
Case "PK"
sheetName = "Peak"
Case "Sfactor"
sheetName = "SF Supply"
Case Else
sheetName = wc.Cells(n, 1)
End Select
exists = sheetExists(sheetName)
If exists = True Then
ActiveWorkbook.Sheets(sheetName).Copy After:=ThisWorkbook.Sheets(1)
End If
ws.Cells(i, count) = wc.Cells(1, n).Value
ws.Cells(i, n).Font.ColorIndex = 3
ws.Cells(i, n).Value = wc.Cells(n, 2)
End If
If (ActiveWorkbook.Sheets("Violations Summary").Cells(n, 2)) < 0 Then
ws.Cells(i, n).Font.ColorIndex = 3
ws.Cells(i, n).Value = wc.Cells(n, 2)
End If
End If
If IsEmpty(wc.Cells(n, 2)) Then
ws.Cells(i, n).Value = ["NA"]
End If
count = count + 1
Next n
Workbooks(Filename).Close
Filename = Dir()
i = i + 1
Loop
End Sub
Function sheetExists(sheetToFind As String) As Boolean
sheetExists = False
For Each Sheet In Worksheets
If sheetToFind = Sheet.Name Then
sheetExists = True
Exit Function
End If
Next Sheet
End Function
Put option explicit at top so spelling of variables is checked and that they are declared. The variable exists was mispelt and there were a number of other variables not declared. I have put some other comments in with the code.
Some of the logic i think can be simplified and i have given some examples. Also, ensure consistent use of named variable wc. If nothing else it should be easier to debug now. Compiles on my machine so give it a try.
This all works on the assumption that each workbook you open has the "Violations Summary" sheet and it is spelt as shown.
You have the filename already stored in the variable Filename so you can use (concatenate?) that with the sheetname variable.
Option Explicit 'Set this to ensure all variable declared and consistent spelling
'Consider using WorkSheets collection rather than Sheets unless you have chart sheets as well?
Sub getViolations()
Dim Path As String 'Declare you other variables
Dim FileName As String
Path = "C:\Users\omartinr\Desktop\New folder (4)\New folder\"
FileName = Dir(Path & "*.xls")
Dim ws As Worksheet
Dim TxtRng As Range 'Declare this
Set ws = ThisWorkbook.Sheets("Sheet1")
Set TxtRng = ws.Range("A1:N1")
TxtRng.Font.ColorIndex = 2
TxtRng.Interior.ColorIndex = 5
TxtRng.Value = [{"Partition Name","Tag","EM Supply","SH Signal","PK","Sfactor","FiSH","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL"}]
TxtRng.HorizontalAlignment = xlCenter
Dim i As Integer
i = 2
Do While FileName <> ""
Workbooks.Open FileName:=Path & FileName, ReadOnly:=True
Dim wc As Worksheet 'Consider whether to place these declarations just before the loop, avoids risk others may think there will be reinitialization even though there isn't
Set wc = ActiveWorkbook.Sheets("Violations Summary")
ws.Cells(i, 1).Value = wc.Range("B1") 'Use the wc variable
ws.Cells(i, 2).Value = wc.Range("C1")
Dim count As Integer
Dim sheetName As String, mySheetNameTest As String
Dim n As Integer
Dim exists As Boolean 'Corrected spelling
count = 15
For n = 3 To 14
If Not IsEmpty(wc.Cells(n, 2)) Then
If (wc.Cells(n, 2)) = 0 Then
ws.Cells(i, n).Font.ColorIndex = 4
ws.Cells(i, n).Value = wc.Cells(n, 2)
End If
If (wc.Cells(n, 2)) > 0 Then
Select Case wc.Cells(n, 1)
Case "PK"
sheetName = "Peak"
Case "Sfactor"
sheetName = "SF Supply"
Case Else
sheetName = wc.Cells(n, 1)
End Select
exists = sheetExists(sheetName)
If exists Then 'Shortened by removing = True (evaluates in same way)
ActiveWorkbook.Sheets(sheetName).Copy After:=ThisWorkbook.Sheets(1)
End If
ws.Cells(i, count) = wc.Cells(1, n).Value
ws.Cells(i, n).Font.ColorIndex = 3
ws.Cells(i, n).Value = wc.Cells(n, 2)
End If
If (wc.Cells(n, 2)) < 0 Then 'used wc variable
ws.Cells(i, n).Font.ColorIndex = 3
ws.Cells(i, n).Value = wc.Cells(n, 2)
End If
Else 'Simplified this as if is not empty then is empty so can use else
ws.Cells(i, n).Value = ["NA"] 'what is pupose of square brackets? These can be removed i think
End If
count = count + 1
Next n
Workbooks(FileName).Close
FileName = Dir()
i = i + 1
Loop
End Sub
Function sheetExists(sheetToFind As String) As Boolean
Dim Sheet As Worksheet ' declare
sheetExists = False
For Each Sheet In Worksheets
If sheetToFind = Sheet.Name Then
sheetExists = True
Exit Function
End If
Next Sheet
End Function
After you copy the ActiveWorkbook.Sheets(sheetName) to ThisWorkbook, ThisWorkbook becomes the ActiveWorkbook. ActiveWorkbook.Sheets(sheetName).Copy After:=ThisWorkbook.Sheets(1) should not throw an error but will probably cause ActiveWorkbook.Sheets("Violations Summary") to fail. For this reason, you should always fully qualify your references.
Some idealist programmers say that a subroutine should perform 1 simply task. Personally, I believe that if you have to scroll up, down, left or right to see what your code is doing it is time to refactor it. When refactoring I try to extract logical groups of tasks in a separate subroutine. This makes debugging and modifying the code far easier.
Refactored Code
Option Explicit
Sub getViolations()
Const Path As String = "C:\Users\omartinr\Desktop\New folder (4)\New folder\"
Dim n As Long
Dim Filename As String
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Sheet1Setup ws
Filename = Dir(Path & "*.xls")
Do While Filename <> ""
ProcessWorkbook Filename, ws.Rows(n)
Filename = Dir()
Loop
End Sub
Sub ProcessWorkbook(WBName As String, row As Range)
Dim nOffset As Long, n As Long
Dim sheetName As String
Dim WB As Workbook
Set WB = Workbooks.Open(Filename:=Path & Filename, ReadOnly:=True)
With WB.Sheets("Violations Summary")
row.Columns(1).Value = .Range("B1")
row.Columns(2).Value = .Range("C1")
nOffset = 12
For n = 3 To 14
If .Cells(n, 2) = "" Then
row.Columns(n).Value = ["NA"]
ElseIf (.Cells(n, 2)) = 0 Then
row.Columns(n).Font.ColorIndex = 4
row.Columns(n).Font.ColorIndex = 0
ElseIf (.Cells(n, 2)) = 0 Then
Select Case wc.Cells(n, 1)
Case "PK"
sheetName = "Peak"
Case "Sfactor"
sheetName = "SF Supply"
Case Else
sheetName = wc.Cells(n, 1)
End Select
'Range.Parent refers to the ranges worksheet. row.Parent refers to ThisWorkbook.Sheets(1)
If SheetExists(WB, sheetName) Then .Copy After:=row.Parent.Sheets(1)
row.Columns(n + nOffset) = .Cells(1, n).Value
row.Columns(n).Font.ColorIndex = 3
row.Columns(n).Value = .Cells(n, 2)
End If
Next
End With
WB.Close SaveChanges:=False
End Sub
Function SheetExists(WB As Workbook, sheetToFind As String) As Boolean
Dim ws As Worksheet
For Each ws In WB.Worksheets
If sheetToFind = ws.Name Then
SheetExists = True
Exit Function
End If
Next
End Function
Sub Sheet1Setup(ws As Worksheet)
With ws.Range("A1:N1")
.Value = [{"Partition Name","Tag","EM Supply","SH Signal","PK","Sfactor","FiSH","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL"}]
.Font.ColorIndex = 2
.Interior.ColorIndex = 5
.HorizontalAlignment = xlCenter
End With
End Sub
Note: row is the target Row of ThisWorkbook.Sheets(1). row.Columns(3) is a fancy way to write row.Cells(1, 3) which refers to the 3rd cell in the target row. Also note that Cells, Columns, and Rows are all relative to the range they belong to. e.g. Range("C1").Columns(2) refers to D1, Range("C1").Rows(2).Columns(2) refers to D2, Range("C1").Cells(2,2) also refers to D2.
Basically, have this code which uses Vlookups and a match to find past order dates of a particular product. The sub fills text boxes in a userform with N/A if there are no past orders found in the sheet. Otherwise, finds the latest order and fills the information in the userform.
The program stops when this sub routine is called. Getting 'subscript out of range' (error 9), I run the debugger and go through the code and everything works the way it is supposed to. In both the N/A case and the case where there is past order info.
Sub PastOrderInfo()
Dim wks As Worksheet
Dim Date_Ordered As Variant
Dim PreviousDate As Variant
Dim Qty_Ordered As String
Dim Total_Cost As String
Dim Rng, RngCol As String
Dim Last_Row As Long
Dim i, NewRow As Integer
Set wks = Worksheets("Order Data")
With wks
Last_Row = .UsedRange.Rows(.UsedRange.Rows.count).Row
Rng = "A2:D" & Last_Row
RngCol = "A2:A" & Last_Row
For i = 2 To Last_Row
If i = 2 Then
On Error Resume Next
PreviousDate = Application.VLookup(CStr(ProdNum), .Range(Rng), 2, False)
On Error GoTo 0
If IsError(PreviousDate) Then
Me.TextBox4.Value = "N/A"
Me.TextBox5.Value = "N/A"
Me.TextBox6.Value = "N/A"
Exit Sub
End If
NewRow = Application.Match(CStr(ProdNum), .Range(RngCol), 0) + 2
Rng = "A" & NewRow & ":D" & Last_Row
RngCol = "A" & NewRow & ":A" & Last_Row
ElseIf i > 2 Then
On Error Resume Next
Date_Ordered = Application.VLookup(CStr(ProdNum), .Range(Rng), 2, False)
On Error GoTo 0
If IsError(Date_Ordered) Then
NewRow = NewRow - 1
Rng = "A" & NewRow & ":D" & Last_Row
Me.TextBox4.Value = CDate(PreviousDate)
Me.TextBox5.Value = Application.VLookup(CStr(ProdNum), .Range(Rng), 3, False)
Me.TextBox6.Value = Application.VLookup(CStr(ProdNum), .Range(Rng), 4, False)
Exit Sub
End If
NewRow = Application.Match(CStr(ProdNum), .Range(RngCol), 0) + NewRow
Rng = "A" & NewRow & ":D" & Last_Row
RngCol = "A" & NewRow & ":A" & Last_Row
If Date_Ordered > PreviousDate Then PreviousDate = Date_Ordered
End If
Next i
Me.TextBox4.Value = CDate(PreviousDate)
Me.TextBox5.Value = Application.VLookup(CStr(ProdNum), .Range(Rng), 3, False)
Me.TextBox6.Value = Application.VLookup(CStr(ProdNum), .Range(Rng), 4, False)
End With
End Sub
Here is the line which is the section of code which opens the userform, when I click to debug it highlights the ProDescription.Show line below the if .Range(cellselect)...:
Private Sub CommandButton1_Click()
Dim i, r, c As Integer
Dim wks As Worksheet
Dim cellselect As String
Set wks = Workbooks("Data Direct Orders2.xlsx").Worksheets("Direct Items")
With wks
If ProdNumberCmbBox.ListIndex = -1 Then
Unload Me
ErrorMsg.Show
End
Else
For r = 2 To 84
cellselect = "A" & r
If .Range(cellselect).Text = ProdNum Then
ProDescription.Show
Unload Me
End
End If
Next r
If c = 0 Then
Unload Me
ErrorMsg.Show
End
End If
End If
End With
End Sub
Here is the sub routine where the userform is initialized:
Private Sub UserForm_Initialize()
TextBox8.Value = ProdNum
Call PastOrderInfo
End Sub
Just figured it out.
The line:
Set wks = Worksheets("Order Data")
in
Sub PastOrderInfo()
Was the problem. Needed to specify the workbook, so after adding:
Set wks = Workbooks("VBA - Final Project.xlsm").Worksheets("Order Data")
It worked!
I'm trying to write an excel VBA to compare columns of a table with the current date and highlight if true.
Here is an example table:
The code that I'm working on is:
Private Sub Workbook_Open()
Dim tbl As Excel.ListObject 'Table name
Dim lr As Excel.ListRow 'Row index
Dim ws As Excel.Worksheet 'Work sheet
'column names
Dim keepInTouch As Range, invite As Range, present As Range, follow As Range
Set ws = ThisWorkbook.Worksheets(1) 'select work book index 1
Set tbl = ws.ListObjects("ContactList") 'set ContactList to tbl
Set keepInTouch = tbl.ListColumns("Keep in Touch").DataBodyRange 'Select the appropreate header
Set invite = tbl.ListColumns("Invite").DataBodyRange
Set present = tbl.ListColumns("Present").DataBodyRange
Set follow = tbl.ListColumns("Follow").DataBodyRange
'MsgBox tbl
For Each lr In tbl.ListRows
If lr.Range(1, tbl.ListColumns("Keep in Touch").Index).Value <> Date Then
keepInTouch.Interior.ColorIndex = xlNone
keepInTouch.Font.ColorIndex = 1
keepInTouch.Font.Bold = False
'If keepInTouch(1).Value = Date And keepInTouch(1).Value <> "" Then
ElseIf lr.Range(1, tbl.ListColumns("Keep in Touch").Index).Value = Date Then
keepInTouch.Interior.ColorIndex = 3
keepInTouch.Font.ColorIndex = 2
keepInTouch.Font.Bold = True
End If
Next lr
End Sub
Line 19: If keepInTouch.Index = Date And keepInTouch.Index <> "" Then causes
Run time error '438':
Object doesn't support this property or method.
What is the correct way of doing this?
If lr.Range(1, tbl.ListColumns("Keep in Touch").Index).Value = Date Then
For example lr.Range(1, 2) is the second column cell in the ListRow Range
keepInTouchIndex = tbl.ListColumns("Keep in Touch").Index
NameIndex = tbl.ListColumns("Name").Index
For Each lr In tbl.ListRows
With lr.Range.Cells(1, NameIndex)
If lr.Range.Cells(1, keepInTouchIndex).Value <> Date Then
.Interior.ColorIndex = 3
.Font.ColorIndex = 2
.Font.Bold = True
Else
.Interior.ColorIndex = xlNone
.Font.ColorIndex = 1
.Font.Bold = False
End If
End With
Next lr
I am stuck with a simple code error 1004, or Sub not defined depending on the code I use. I need help comparing numbers from two different sheets, and then replacing a value in one of the rowa.
(EX. sheet1 "A1" = 809565 matches Sheet2 "A28" = 809565, and then I must change the current string to "Above Ground(I)".)
Set dbsheet = ThisWorkbook.Sheets("Sheet1")
Set dbsheet_1 = ThisWorkbook.Sheets("Export_For_WMIS_Recon")
Col_Len = dbsheet.Cells(Rows.Count, 1).End(x1UP).Row
Col_Len_1 = dbsheet_1.Cells(Rows.Count, 1).End(x1UP).Row
For x = 1 To Col_Len
For i = 1 To Col_Len_1
Search_num = dbsheet.Cells(x, 1)
Comp_num = dbsheet_1.Cells(i, 1)
Comp_word = dbsheet_1.Cells(i, 3)
If Search_# = Comp_# And Comp_word = "Aboveground" Then
Comp_word = "ABOVE GROUND(I)"
End If
Next i
Next x
End Sub
Code 2:
row_number = 0
r_number_2 = 0
Do
DoEvent
r_number_2 = r_number_2 + 1
Search_# = ThisWorkbook.Sheets("Sheet1").Range("A" & row_number)
Comp_# = ThisWorkbook.Sheets("Export_For_WMIS_Recon").Range("A" & row_number)
If Search_# = Comp_# And ThisWorkbook.Sheets("Export_For_WMIS_Recon").Range("C" & row_number) = "Aboveground" Then
ThisWorkbook.Sheets("Export_For_WMIS_Recon").Range("C" & row_number) = "ABOVE GROUND(I)"
End If
Loop Until Comp_# = ""
Loop Until Search_# = ""
I think this is what you're looking for:
Sub tgr()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim rngFound As Range
Dim varFind As Variant
Dim strFirst As String
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Export_For_WMIS_Recon")
For Each varFind In ws1.Range("A1", ws1.Cells(Rows.Count, "A").End(xlUp)).Value
Set rngFound = ws2.Columns("A").Find(varFind, ws2.Cells(Rows.Count, "A"), xlValues, xlWhole)
If Not rngFound Is Nothing Then
strFirst = rngFound.Address
Do
If LCase(ws2.Cells(rngFound.Row, "C").Value) = "aboveground" Then
ws2.Cells(rngFound.Row, "C").Value = "ABOVE GROUND(I)"
End If
Set rngFound = ws2.Columns("A").Find(varFind, rngFound, xlValues, xlWhole)
Loop While rngFound.Address <> strFirst
End If
Next varFind
Set ws1 = Nothing
Set ws2 = Nothing
Set rngFound = Nothing
End Sub
I have some code here that would create a new template sheet for every unique cell in column A. It then distributes column E,F, L and O to its appropraite positions in the newly created template sheet.
However it puts the values from column E of the Data sheet in to the end of the created template sheet. How would I make it so it starts in row 4 which is the start of blank cells for the values.
Also if someone could help with a new command that will not put the same row in the template if it already has the column F value on the template sheet.
Sub Redemption()
Dim wsDatatable As Worksheet
Dim wsTempelate As Worksheet
Dim rangeFound As Range
Dim rangeNames As Range
Dim NameCells As Range
Dim stringFirst As String
Dim stringNames As String
Dim stringUniqueNames As String
Set wsDatatable = Sheets("DATA INPUT TABLE")
Set wsTempelate = Sheets("CLASS GROUPING ID")
Set rangeNames = wsDatatable.Range("A2", wsDatatable.Cells(Rows.Count, "A").End(xlUp))
For Each NameCells In rangeNames.Cells
If InStr(1, "|" & stringUniqueNames & "|", "|" & NameCells.Text & "|", vbTextCompare) = 0 Then
stringUniqueNames = stringUniqueNames & "|" & NameCells.Text
Set rangeFound = rangeNames.Find(NameCells.Text, rangeNames.Cells(rangeNames.Cells.Count), xlValues, xlWhole)
If Not rangeFound Is Nothing Then
stringFirst = rangeFound.Address
stringNames = NameCells.Text
stringNames = Trim(Left(WorksheetFunction.Trim(stringNames), 31))
If Evaluate("IsRef('" & stringNames & "'!A1)") = False Then
wsTempelate.Copy After:=Sheets(Sheets.Count)
ActiveSheet.Name = stringNames
End If
With Sheets(stringNames)
Do
If LCase(wsDatatable.Cells(rangeFound.Row, "I").Text) = "full liquidation" Or LCase(wsDatatable.Cells(rangeFound.Row, "I").Text) = "redemption" Then
.Cells(Rows.Count, "A").End(xlUp).Offset(1).Value = wsDatatable.Cells(rangeFound.Row, "E").Value
.Cells(Rows.Count, "B").End(xlUp).Offset(1).Value = wsDatatable.Cells(rangeFound.Row, "F").Value
.Cells(Rows.Count, "C").End(xlUp).Offset(1).Value = wsDatatable.Cells(rangeFound.Row, "B").Value
.Cells(Rows.Count, "D").End(xlUp).Offset(1).Value = wsDatatable.Cells(rangeFound.Row, "O").Value
.Cells(Rows.Count, "E").End(xlUp).Offset(1).Value = wsDatatable.Cells(rangeFound.Row, "L").Value
End If
Set rangeFound = rangeNames.Find(NameCells.Text, rangeFound, xlValues, xlWhole)
Loop While rangeFound.Address <> stringFirst
End With
End If
End If
Next NameCells
Set wsDatatable = Nothing
Set wsTempelate = Nothing
Set rangeFound = Nothing
Set rangeNames = Nothing
Set NameCells = Nothing
End Sub
With some changes, you can rewrite your code to make it start filling up values from row 4 and prevent duplicate insertions if it already has the column F value on the template sheet, this way:
Sub Redemption()
Dim wsDatatable As Worksheet
Dim wsTempelate As Worksheet
Dim rangeFound As Range
Dim rangeNames As Range
Dim NameCells As Range
Dim stringFirst As String
Dim stringNames As String
Dim stringUniqueNames As String
Set wsDatatable = Sheets("DATA INPUT TABLE")
Set wsTempelate = Sheets("CLASS GROUPING ID")
Set rangeNames = wsDatatable.Range("A2", wsDatatable.Cells(Rows.Count, "A").End(xlUp))
For Each NameCells In rangeNames.Cells
If InStr(1, "|" & stringUniqueNames & "|", "|" & NameCells.Text & "|", vbTextCompare) = 0 Then
stringUniqueNames = stringUniqueNames & "|" & NameCells.Text
Set rangeFound = rangeNames.Find(NameCells.Text, rangeNames.Cells(rangeNames.Cells.Count), xlValues, xlWhole)
If Not rangeFound Is Nothing Then
stringFirst = rangeFound.Address
stringNames = NameCells.Text
stringNames = Trim(Left(WorksheetFunction.Trim(stringNames), 31))
If Evaluate("IsRef('" & stringNames & "'!A1)") = False Then
wsTempelate.Copy After:=Sheets(Sheets.Count)
ActiveSheet.Name = stringNames
End If
Dim AR, BR, CR, DR, ER As Integer ' row pointers for columns A to E
Dim st As Boolean
With Sheets(stringNames)
Do
If LCase(wsDatatable.Cells(rangeFound.Row, "I").Text) = "full liquidation" Or LCase(wsDatatable.Cells(rangeFound.Row, "I").Text) = "redemption" Then
AR = .Cells(.Rows.Count, "A").End(xlUp).Row ' determines last not empty cell on column A
BR = .Cells(.Rows.Count, "B").End(xlUp).Row ' determines last " " cell on column B
CR = .Cells(.Rows.Count, "C").End(xlUp).Row ' determines last " " cell on column C
DR = .Cells(.Rows.Count, "D").End(xlUp).Row ' determines last " " cell on column D
ER = .Cells(.Rows.Count, "E").End(xlUp).Row ' determines last " " cell on column E
f_row = 3
If AR < f_row Then AR = f_row '
If BR < f_row Then BR = f_row '
If CR < f_row Then CR = f_row ' move pointers to row 3 on each column, when lower than that
If DR < f_row Then DR = f_row '
If ER < f_row Then ER = f_row ' notice it will start only after f_row since it's called afterwards with Offset(1)...
'
st = True ' this boolean variable will be turned to FALSE when a row is already present in template sheet, preventing it from filling up
Dim strA As String
Set fRange = Sheets(stringNames).Range("A1", "A" & CStr(AR + 1)) 'set range to start searching for duplicate identifiers
For Each nv In fRange
If wsDatatable.Cells(rangeFound.Row, "F").Value = nv Then st = False 'if there's a duplicate, turn st to FALSE
Next nv
If st = True Then
.Cells(AR, "A").Offset(1).Value = wsDatatable.Cells(rangeFound.Row, "F").Value
.Cells(BR, "B").Offset(1).Value = wsDatatable.Cells(rangeFound.Row, "B").Value
.Cells(CR, "C").Offset(1).Value = wsDatatable.Cells(rangeFound.Row, "O").Value
.Cells(DR, "D").Offset(1).Value = wsDatatable.Cells(rangeFound.Row, "L").Value
.Cells(ER, "E").Offset(1).Value = wsDatatable.Cells(rangeFound.Row, "E").Value
End If
End If
Set rangeFound = rangeNames.Find(NameCells.Text, rangeFound, xlValues, xlWhole)
Loop While rangeFound.Address <> stringFirst
End With
End If
End If
Next NameCells
Set wsDatatable = Nothing
Set wsTempelate = Nothing
Set rangeFound = Nothing
Set rangeNames = Nothing
Set NameCells = Nothing
End Sub