Updating For Each loop variable - excel

The aim is to find the circularity between value in column c and all values obtained from updated "firstvalue" variable which are comma separated and stored in column "M".
Sub circular()
Dim rng As Range, rng2 As Range, firstvalue As String, secondvalue As String
Set sh = ThisWorkbook.Worksheets("Sheet1")
lr = sh.Range("C" & Rows.Count).End(xlUp).Row
For Each rng In sh.Range("C5:C" & lr) 'iterating over each cell in column "c" from C5 till lastrow "lr".
firstvalue = rng.Offset(0, 10).value 'Corresponding cell value which is comma seperated in column
"M" i:e after 10 columns from "C".
Dim n As Variant
For Each n In Split(firstvalue, ",") 'Looping through each value obtained from split function.
Set rng2 = sh.Range("C5:C" & lr).Find(Trim(n), LookIn:=xlValues) 'Finding that split value again
in column "C".
If Not rng2 Is Nothing Then 'if exists in column c then get.
secondvalue = rng2.Offset(0, 10).value 'corresponding cell values.
firstvalue = firstvalue & "," & secondvalue 'now first value is concatnated
with initial firstvalue
End If
Next n
MsgBox firstvalue
'Now i want to itterate over updated "firstvalue" in split function and this goes on in circular
fashion until rng value exists in firstvalue.
Next rng 'then change next rng and continue the above whole process for this value and so on.
End Sub
This code is working for initial firstvalue, can any one suggest any method to iterate over updated first value.

I'm not sure if I understand your goal exactly, but this code should find all predecessors for each task:
Sub circular()
Dim sh As Worksheet
Dim rTask As Range
Dim oCell As Range
Dim oFound As Range
Dim lr As Long, j As Long
Dim aPredecessors As Variant
Dim sCurTask As String
Dim secondValue As String
Set sh = ThisWorkbook.Worksheets("Sheet1")
lr = sh.Range("C" & Rows.Count).End(xlUp).Row
Set rTask = sh.Range("C5:C" & lr)
For Each oCell In rTask
sCurTask = Trim(oCell.Text)
aPredecessors = getPredecessors(Trim(oCell.Offset(0, 10).Text))
j = LBound(aPredecessors)
Do Until j > UBound(aPredecessors)
secondValue = aPredecessors(j)
If sCurTask = secondValue Then
ReDim Preserve aPredecessors(j)
Debug.Print "Task '" & sCurTask & "': Cyclic link '" & secondValue & "' for '" & Join(aPredecessors, ",") & "'!"
aPredecessors(j) = aPredecessors(j) & " !!!"
Else
If secondValue <> vbNullString Then
Set oFound = rTask.Find(secondValue, LookIn:=xlValues)
If oFound Is Nothing Then
ReDim Preserve aPredecessors(j)
Debug.Print "Task '" & sCurTask & "': Task '" & secondValue & "' for '" & Join(aPredecessors, ",") & "' not found!"
aPredecessors(j) = aPredecessors(j) & " ???"
Else
Call addNewTasks(aPredecessors, Trim(oFound.Offset(0, 10).Text))
End If
End If
End If
j = j + 1
Loop
oCell.Offset(0, 11).Value = Join(aPredecessors, ",")
Next oCell
End Sub
Function getPredecessors(sPredecessors As String)
Dim i As Long
Dim aTemp As Variant, sRes As String
Dim sTest As String
sRes = vbNullString
aTemp = Split(sPredecessors, ",")
For i = LBound(aTemp) To UBound(aTemp)
sTest = Trim(aTemp(i))
If InStr("," & sRes & ",", "," & sTest & ",") = 0 Then sRes = sRes & sTest & ","
Next i
If Len(sRes) > 1 Then sRes = Left(sRes, Len(sRes) - 1)
getPredecessors = Split(sRes, ",")
End Function
Sub addNewTasks(aData As Variant, sPredecessors As String)
Dim i As Long, uB As Long
Dim aTemp As Variant
Dim sTest As String, sValid As String
aTemp = Split(sPredecessors, ",")
If UBound(aTemp) >= 0 Then ' Not empty
sValid = "," & Join(aData, ",") & ","
For i = LBound(aTemp) To UBound(aTemp)
sTest = Trim(aTemp(i))
If sTest <> vbNullString Then
If InStr(sValid, "," & sTest & ",") = 0 Then
uB = UBound(aData) + 1
ReDim Preserve aData(uB)
aData(uB) = sTest
sValid = "," & Join(aData, ",") & ","
End If
End If
Next i
End If
End Sub

Related

How to select the cells in a column that have a specific text in their value

I'm trying to get the cells that contain match the certain text criteria I search for.
I keep getting the error
Run-Time error 424 Object required
on line 12
cell = Sheets("Sheet1").Range("A" & row_num)
and I'm not sure why?
Any and all help with this would be greatly appreciated!
Option Compare Text
Sub FindingColumn()
Dim Col1Rng As Range, Col3Rng As Range
Dim Column1Search As String, Column2Search As String, Column3Search As
String
row_num = 0
Column1Search = InputBox("Col 1 Criteria: ")
Do
DoEvents
row_num = row_num + 1
cell = Sheets("Sheet1").Range("A" & row_num)
If Col2Rng = Empty And InStr(cell, Column1Search) Then
Col2Rng = cell.Address(0, 0)
ElseIf InStr(cell, Column1Search) Then
Col2Rng = Col2Rng & "," & cell.Address(0, 0)
End If
Loop Until cell = ""
Range(Col2Rng).Select
End Sub
This should serve as the basis for what you're trying to do
Sub FindingColumn()
Dim Col1Rng As Range, Column1Search As String, foundCellCol1 As Range
Set Col1Rng = ActiveSheet.Range("A:A")
Column1Search = InputBox("Col 1 Criteria: ")
Set foundCellCol1 = Col1Rng.Find(What:=Column1Search)
If Not foundCellCol1 Is Nothing Then foundCellCol1.Select Else: MsgBox "Search term not found!"
End Sub
Can you generate a list in another location of all of the items that match?
Option Explicit
Sub FindingColumn()
Dim Col1Rng As Range, Column1Search As String, foundCellCol1 As Range, lastRow As Long, lastFoundRow As Long
lastRow = Range("A100000").End(xlUp).Row
Set Col1Rng = ActiveSheet.Range("A1:A" & lastRow)
Column1Search = InputBox("Col 1 Criteria: ")
Set foundCellCol1 = Col1Rng.Find(What:="*" & Column1Search & "*")
While Not foundCellCol1 Is Nothing
If Not foundCellCol1 Is Nothing Then
Range("B" & Range("B100000").End(xlUp).Row + 1) = foundCellCol1.Value
Set Col1Rng = ActiveSheet.Range("A" & foundCellCol1.Row & ":A" & lastRow)
lastFoundRow = foundCellCol1.Row
Set foundCellCol1 = Col1Rng.Find(What:="*" & Column1Search & "*")
If foundCellCol1.Row = lastFoundRow Then Set foundCellCol1 = Nothing
End If
DoEvents
Wend
End Sub

Indentifier Under Cursor Not recognized - Excel Macro

I have a macro I am running to update a report table in Excel but I keep getting an error on this particular line of code:
totalFieldsStart = Left(totalFieldsStart, Len(totalFieldsStart) - 1) & ")"
Here is a look at the entire Macro:
Function AppnSOFFormulasState(fTL As Range, fBR As Range)
Dim final As Worksheet
Dim aCol As Integer 'index for appn column
Dim dCol As Integer 'index for div column
Dim mCol As Integer 'index for mdep column
Dim appn As String
Dim st As String
Dim div As String
Dim mdep As String
Dim stateAdd As String
Dim ntlAdd As String
Dim totalFieldsStart As String 'cells to total will be separated
Dim totalFieldsAFP As String 'cells to total will be separated
Dim totalFieldsOBS As String 'cells to total will be separated
Dim subFields As Range 'cells to subtotal will be contiguous
Dim c As Range 'cell iterator
Set final = ThisWorkbook.Worksheets(1)
final.Activate
aCol = final.Range("A1").Column
dCol = final.Range("B1").Column
mCol = final.Range("C1").Column
'set top left to be first October cell for APPN
appn = final.Cells(fTL.Row, aCol)
st = Range("state_select").address
totalFieldsAFP = "=sum("
totalFieldsOBS = "=sum("
Set fTL = fTL.Offset(0, 3)
For Each c In final.Range(fTL, final.Cells(fBR.Offset(-1, 0).Row, fTL.Column))
If Not IsEmpty(final.Cells(c.Row, dCol)) Then
'the first line will have nothing for div, so the range part of the next if will fail
On Error GoTo SkipFirst
If final.Cells(c.Row, dCol) = final.Range(div) & sTotal Then
c.Formula = "=sum(" & subFields.address & ":" & c.Offset(-1, 0).address & ")"
c.Offset(0, 1).Formula = "=sum(" & subFields.Offset(0, 1).address & ":" & c.Offset(-1, 1).address & ")"
totalFieldsAFP = totalFieldsAFP & c.address & ", "
totalFieldsOBS = totalFieldsOBS & c.Offset(0, 1).address & ", "
Else
SkipFirst:
On Error GoTo 0
Set subFields = c
div = final.Cells(c.Row, dCol).address
End If
End If
If Not IsEmpty(final.Cells(c.Row, mCol)) Then
mdep = final.Cells(c.Row, mCol).address
stateAdd = "left(" & st & ",2) &" & appn & "&" & div & "&" & mdep
ntlAdd = appn & "&" & div & "&" & mdep
'AFP
c.Formula = "=iferror(VLOOKUP(" & stateAdd & ",state_lookup_sof,3,FALSE),0)"
'Obs
c.Offset(0, 1).Formula = "=iferror(VLOOKUP(" & stateAdd & ",state_lookup_sof,4,FALSE),0)"
End If
Next c
totalFieldsStart = Left(totalFieldsStart, Len(totalFieldsStart) - 1) & ")"
totalFieldsAFP = Left(totalFieldsAFP, Len(totalFieldsAFP) - 1) & ")"
totalFieldsOBS = Left(totalFieldsOBS, Len(totalFieldsOBS) - 1) & ")"
final.Cells(fBR.Row, fTL.Column).Formula = totalFieldsAFP
final.Cells(fBR.Row, fTL.Offset(0, 1).Column).Formula = totalFieldsOBS
End Function

How to find two column Data If if find then third column to find the data

Please find the image you will we find all the information sorry for not able to explain in my word but i explain in picture please help me please request you
So i tried to follow your picture, I had the same issue and for that i use this function.
So you should put both codes in the same module. I also respect columns as you showed in the picture.
I hope it will help you.
EDIT:
Sub test()
Dim Lastrow As Long
Dim cell As Range
Dim rng As Range
Dim Lastrow2 As Long, Lastrow3 As Long
With ThisWorkbook.Worksheets("Sheet1")
Lastrow = Application.Max(.Cells(.Rows.count, "A").End(xlUp).Row)
.Range("B2:B" & Lastrow).Value = .Range("A2:A" & Lastrow).Value
For Each cell In .Range("B2:B" & Lastrow)
If cell.Value = "" Then
If rng Is Nothing Then
Set rng = cell
Else
Set rng = Union(rng, cell)
End If
End If
Next
If Not rng Is Nothing Then rng.Delete Shift:=xlUp
End With
Lastrow2 = Range("B" & Rows.count).End(xlUp).Row
Lastrow3 = Range("E" & Rows.count).End(xlUp).Row
For i = 2 To Lastrow2
Range("G" & i) = Range("B" & i) & " " & LookUpConcat(Range("B" & i), Range("D1:" & "D" & Lastrow3), Range("E1:" & "E" & Lastrow3), ",")
Next i
End Sub
Here the function:
Function LookUpConcat(ByVal SearchString As String, SearchRange As Range, ReturnRange As Range, _
Optional Delimiter As String = " ", Optional MatchWhole As Boolean = True, _
Optional UniqueOnly As Boolean = False, Optional MatchCase As Boolean = False)
Dim X As Long, CellVal As String, ReturnVal As String, Result As String
If (SearchRange.Rows.count > 1 And SearchRange.Columns.count > 1) Or _
(ReturnRange.Rows.count > 1 And ReturnRange.Columns.count > 1) Then
LookUpConcat = CVErr(xlErrRef)
Else
If Not MatchCase Then SearchString = UCase(SearchString)
For X = 1 To SearchRange.count
If IsError(SearchRange(X)) Then GoTo Continue
If MatchCase Then
CellVal = SearchRange(X).Value
Else
CellVal = UCase(SearchRange(X).Value)
End If
ReturnVal = ReturnRange(X).Value
If MatchWhole And CellVal = SearchString Then
If UniqueOnly And InStr(Result & Delimiter, Delimiter & ReturnVal & Delimiter) > 0 Then GoTo Continue
Result = Result & Delimiter & ReturnVal
ElseIf Not MatchWhole And CellVal Like "*" & SearchString & "*" Then
If UniqueOnly And InStr(Result & Delimiter, Delimiter & ReturnVal & Delimiter) > 0 Then GoTo Continue
Result = Result & Delimiter & ReturnVal
End If
Continue:
Next
LookUpConcat = Mid(Result, Len(Delimiter) + 1)
End If
End Function

concatenate cells when there are duplicates without using Transpose

I am using the following code - thanks #bonCodigo
Sub groupConcat()
Dim dc As Object
Dim inputArray As Variant
Dim i As Integer
Set dc = CreateObject("Scripting.Dictionary")
inputArray = WorksheetFunction.Transpose(Sheets(1).Range("A2:B7").Value)
'-- assuming you only have two columns - otherwise you need two loops
For i = LBound(inputArray, 2) To UBound(inputArray, 2)
If Not dc.Exists(inputArray(1, i)) Then
dc.Add inputArray(1, i), inputArray(2, i)
Else
dc.Item(inputArray(1, i)) = dc.Item(inputArray(1, i)) _
& "; " & inputArray(2, i)
End If
Next i
'--output into sheet
Sheets(1).Range("D2").Resize(UBound(dc.keys) + 1) = _
Application.Transpose(dc.keys)
Sheets(1).Range("E2").Resize(UBound(dc.items) + 1) = _
Application.Transpose(dc.items)
Set dc = Nothing
End Sub
A very elegant solution. Unfortunately, I am running into the limitation of using Transpose method. I have long strings that I would like to concatenate using the above code.
Any help will be appreciated.
Regards
This also uses a variant array but without the `Transpose`. It will ignore blank values to boot.
It runs by column, then by row
Sub Bagshaw()
Dim allPosts As Variant
Dim allPosts2 As Variant
Dim lngRow As Long
Dim lngCol As Long
Dim lngCnt As Long
Dim objDic As Object
Set objDic = CreateObject("Scripting.Dictionary")
allPosts = Range("A2:B5000").Value2
ReDim allPosts2(1 To UBound(allPosts, 1) * UBound(allPosts, 2), 1 To 1)
For lngCol = 1 To UBound(allPosts, 2)
For lngRow = 1 To UBound(allPosts, 1)
If Not objDic.exists(allPosts(lngRow, lngCol)) Then
If Len(allPosts(lngRow, lngCol)) > 0 Then
objDic.Add allPosts(lngRow, lngCol), 1
lngCnt = lngCnt + 1
allPosts2(lngCnt, 1) = allPosts(lngRow, lngCol)
End If
End If
Next
Next
Range("D2").Resize(UBound(allPosts2, 1)).Value2 = allPosts2
End Sub
Sub groupConcat()
Dim r As Range
Dim ro As Range
Dim myr As Range
Dim vcompt As Integer
vcompt = 0
Set ro = Range(Range("A2"), Range("A2").End(xlDown))
For i = Range("A2").Row To Range("A2").End(xlDown).Row
Debug.Print Range("A" & i).Address
Set myr = ro.Find(what:=Range("A" & i).Value, after:=Range("A2").End(xlDown), Lookat:=xlWhole, SearchDirection:=xlNext)
If myr Is Nothing Or myr.Address = Range("A" & i).Address Then
mystr = Range("A" & i).Offset(0, 1).Value
Set r = Range(Range("A" & i), Range("A2").End(xlDown))
Set myr = r.Find(what:=Range("A" & i).Value, Lookat:=xlWhole, SearchDirection:=xlNext)
If Not myr Is Nothing And r.Address <> Range("A2").End(xlDown).Address Then
Do While myr.Address <> Range("A" & i).Address
Debug.Print "r: " & r.Address
Debug.Print "myr: " & myr.Address
mystr = mystr & "; " & myr.Offset(0, 1).Value
Set myr = r.FindNext(myr)
Loop
End If
Range("D" & 2 + vcompt).Value = Range("A" & i).Value
Range("D" & 2 + vcompt).Offset(0, 1).Value = mystr
vcompt = vcompt + 1
End If
Next i
End Sub

Help with nested if/Loop VBA

I'm in the process of looping through an Excel spreadsheet and combining all the cells into a string, which I did. Now I need to format the string with XML tags before I send it for upload, and I'm having some difficulty working the tagging into the loop correctly. It seems like it is almost working, but a few of the tags are not going in the correct place. Any help would be much appreciated.
Code:
Public file As String
Sub locate_file()
Dim sheet1_95 As String
Dim theRange As Range
Dim strVal As String
Dim wb As Workbook
Dim counterDT As Integer
Dim counterSVR As Integer
Dim counterMB As Integer
Dim outputStr As String
'prompt user for location of other excel sheet'
file = Application.GetOpenFilename("Excel Files (*.xlsx), *.xlsx")
Set wb = Workbooks.Open(file)
Dim cell As Range
'initializing the xml string'
strVal = "<root>"
Sheets("DT").Activate
counterDT = 1
For Each cell In ActiveSheet.UsedRange.Cells
'this first if-block is just excluding the few header cells from the data collection'
If cell.Value <> "SKU" And cell.Value <> "P Number" And cell.Value <> "Month" _
And cell.Value <> "DP Dmd" And cell.Value <> "Vertical" Then
If cell.Column = "1" Then
strVal = strVal & "<item><sku>" & cell.Value & "</sku>"
ElseIf cell.Column = "2" Then strVal = strVal & "<pnum>" & cell.Value & "</pnum>"
ElseIf cell.Column = "3" Then strVal = strVal & "<month>" & cell.Value & "</month>"
ElseIf cell.Column = "4" Then strVal = strVal & "<forecast>" & cell.Value & "</forecast>"
Else: strVal = strVal & "<vertical>" & cell.Value & "</vertical>"
End If
counterDT = counterDT + 1
If cell.Row <> 1 Then
If counterDT Mod 6 = 0 Then
strVal = "<item>" & strVal & "<percent>" & category.percent(cell, "DT") & "</percent>"
Else: End If
Else: End If
End If
Next
strVal = strVal & "</root>"
So basically the problem is, this loop/nested if is printing like 30 "item" tags at the very beginning of the string and I'm not sure why.
For some other information, the Excel sheet is 6 columns, and will always be 6.
When I'm creating xml tags, I like to move the actual tagging into a separate function. The upside is that it ensures my tags match. The downside is that you don't "apply" the tags until the end. Tags like item and root are done after all the tags within them are done. Here's an example:
Sub locate_file()
Dim sVal As String
Dim sRow As String
Dim wb As Workbook
Dim sh As Worksheet
Dim lCntDT As Long
Dim rCell As Range
Dim rRow As Range
Dim vaTags As Variant
gsFile = Application.GetOpenFilename("Excel Files (*.xlsx), *.xlsx")
If gsFile <> "False" Then
Set wb = Workbooks.Open(gsFile)
Set sh = wb.Sheets("DT")
vaTags = Array("sku", "pnum", "month", "forecast", "vertical")
lCntDT = 1
For Each rRow In sh.UsedRange.EntireRow
sRow = ""
If rRow.Cells(1) <> "SKU" Then
For Each rCell In Intersect(sh.UsedRange, rRow).Cells
If rCell.Column <= 4 Then
sRow = sRow & TagValue(rCell.Value, vaTags(rCell.Column - 1))
Else
sRow = sRow & TagValue(rCell.Value, vaTags(UBound(vaTags)))
End If
Next rCell
lCntDT = lCntDT + 1
If rRow.Row <> 1 And lCntDT Mod 6 = 0 Then
sVal = sVal & TagValue("CatPct", "percent")
End If
sRow = TagValue(sRow, "item")
sVal = sVal & sRow & vbNewLine
End If
Next rRow
sVal = TagValue(sVal, "root")
End If
Debug.Print sVal
End Sub
Function TagValue(ByVal sValue As String, ByVal sTag As String) As String
TagValue = "<" & sTag & ">" & sValue & "</" & sTag & ">"
End Function

Resources