Finding cellindex depending on cell content in excel - vba

Im in a bit of a hard spot at the moment, i've been searching the web for some weeks now whitout any luck. I hope some of you might have the answer however.
I want to search through a row for a cell with a specific numeric value. The row contains weeknumbers. When found i would like to be able to handle the cell like an object, or at least i need to know the coordiantes of the cell for further processing.
Furthermore, can that process be reversed. Meaning, can i get the value from say the next cell in the same row if i have the coordinates of the prior cell?
Example would be:
Search through row for the week number for this week.
Hopefully get the coordinates for the cell that contains the right number.
When i have that column, i want to find the content of the cells monday to friday for that week for every coworker
I doesnt matter if this i done by VBA or formulas.
Thanks a lot in advance.
Best regards Teambit

No need for VBA for this... you should be able to achieve it with formulae easily enough.
So, cell L3 has the formula:=ADDRESS(3,MATCH($B$1,$A$3:$N$3,0)). This will perform a MATCH on the week entered into cell $B$1 and find it in the range of weeks $A$3:$N$3. The ADDRESS function will return the cell address for where the week number is found, so $G$3 in my example.
Then the lower grid/table will display the working week for the current week. The OFFSET function is moving the cell address down 3 rows, then right 1, 2, 3, 4, or 6 rows for each day of the week. OFFSET will return a 0 for a blank, so the T function is ensuring we get a text equivalent, or blank instead of 0. I'm using INDIRECT to pass the OFFSET function the starting cell address, so it is using the value of our starting week cell ($G$3), instead of that cell ($L$1).
I've not put anything in to make this dynamic per worker, so it's always using row 3, but you can get a cell reference using ADDRESS from a VLOOKUP for a name and then plug that into the other formulae.

Check if this help u..
Sub SubOne()
Dim sh As Worksheet
Dim rw As Range
Dim iFoundIt As Range
Dim RowCount As Integer
' var to iterate trough rows
RowCount = 0
Set sh = ActiveSheet
For Each rw In sh.Rows
' iterate over all cells in first row
If sh.Cells(rw.Row, 1).Value = "ThisIsMySpecialValue" Then
' value is found, we save the cell for future options
Set iFoundIt = sh.Cells(rw.Row, 1)
Exit For
End If
RowCount = RowCount + 1
Next rw
Debug.Print (iFoundIt.Row)
Debug.Print (iFoundIt.Column)
End Sub

I know if i understand your question well, but if you have coordinates of cell and you wana e.g. next cell on left you can use something like this
Sub findWeek()
Dim targetSheet As Worksheet
Set targetSheet = Sheets("Sheet1")
Dim l As Long
Dim row As Long
row = 2
Dim myVal As String
myVal = "some name of week you looking for"
Dim resultCell As Range
With targetSheet
Do While .Cells(row, l).Value <> myVal
l = l + 1
Loop
resultCell = .Cells(row, l)
End With
End Sub
So i updated answer, try something like this. Just change sheet name, maybe row and even name which are you looking for. And in value resultCell you will have object of cell which you are looking for. And if you look at cell/range api you can get its coordinates etc...
So you can make it a function which will return range, or whatever you want... But always in value resultCell will be cell which you are looking for.
Maybe you will need to take care if week is not found ;) because this will stuck in loop, but its not that hard

Related

Excel Macro To Advance Date

I have a ton of excel sheets that each have 3 excel workbook tabs. On the last one there will be a ton of data but one column will be a date column with a bunch of different dates underneath. The date format will be MM/DD/YYYY. I need to advance each date ahead by 4 years.
I imagine that I will need to select the correct workbook, search for the particular column, and then loop to iterate through each value underneath that column to advance it, but the day itself needs to stay the same. For example, if its 10/05/2017, it needs to be 10/05/2021. Any suggestions or help would be great. Thank you in advance.
Thank you for the help, I realize I wasn't very helpful at all with my question. I'm very new to VB script and excel macros in general. I hadn't gotten how to search for the column itself as I would like it find the column no matter what the column value is (possibly search for a cell that says "Date" through the entire sheet?, I was just trying to add the 4 years to start with and couldn't find the function I needed. This is what I had from what I derived and seems like this is very wrong ha.
Do Until IsEmpty(ActiveCell)
Set ThisCell = ActiveCell
ThisCell = DateAdd("yyyy", 4, ColumnValueHere)
' Step down 1 row from present location.
ActiveCell.Offset(1, 0).Select
Loop
You'll be wanting the DateAdd function
Try something like this:
Sub AddDates()
Dim lastRow as integer
Dim theSheetImWorkingOn as worksheet
Dim theColumnNumberForTheDates as integer
theColumnNumberForTheDates = 5 ' change this to be the column number you want
Set theSheetImWorkingOn = Sheets("Put your sheet name here")
lastRow = theSheetImWorkingOn.Cells(1000000, theColumnNumberForTheDates ).End(xlUp).row
For x = 2 to lastRow ' assuming your data starts on row 2
theSheetImWorkingOn.Cells(x, theColumnNumberForTheDates) = DateAdd("yyyy", 4, theSheetImWorkingOn.Cells(x, theColumnNumberForTheDates))
Next x
End Sub

IF THEN VBA MACRO - Update one column if contents of another = 100%

I have a workbook with "Results" being sheet 3, this being the worksheet I want to use.
I have tried a few formulaes to try and add a macro to do the following:
I have column G with percentages. I then have column I where I would like there to be a result saying TRUE/FALSE where the contents of G are equal to 100%. Column G is formatted to percentage with two decimals.
Some considerations: I have my first row being a Hyperlink to another sheet, then my headings, then the first row of "results". I have 457 rows, if there is a measurement of the range, perhaps it could be on A?
I keep getting this error 9 with my range and have got a bit stuck.
Thanks in advance!
Sub PartialHits1()
Dim rng As Range
Dim lastRow As Long
Dim cell As Range
With Sheet3
lastRow = .Range("G" & .Rows.Count).End(xlUp).Row
Set rng = .Range("G1:G" & lastRow)
For Each cell In rng
If cell.Value = 100
Then
cell.Range("I1:I1").Value = 100
End If
Next
End With
End Sub
(I have hacked this a bit, just was trying to get it to set as 100 instead of the TRUE/FALSE Also was playing around near the Sheet 3 part as I got errors.)
RangeVariable.Range can refer only to a cell within RangeVariable, so you can't refer to column I in this way. Try: .Range("I"&cell.row)=100.
Also your criteria is probably wrong, if you have 100% in a cell it's actual value is 1.
And last question: why do you want to do this with VBA, it would be much more simple with worksheet function =IF(G3=1,100,"")

Excel Range Reference

Let me preface this question by saying I am not super technical so much of my verbiage may seem obscure..
On sheet1 I have three seperate horizontal ranges of cells (3 seperate series of steps):
A1:D1
A2:C2
A3:E3
On sheet two, I'd like to link to create live links to these ranges, such that if I change information on sheet1, it will be automatically reflected in sheet2.
The catch is, that on sheet2, I want the ranges to be listed after one another in one row, to create one long series of steps.
Range1-->Range2-->Range3 (all on one row)
How do I ensure that if I add an additional step to, say, the first range on sheet1, that on sheet 2, the new cell will be added and the following cells will all be pushed over to the right by one cell?
To accommodate ranges that might grow, start from the first cell and then find the last occupied cell with End(xlToRight). Once you've found all the range extents, you can combine them with an array UDF:
Function ConcatRanges(ParamArray ranges()) As Variant()
Application.Volatile
Dim ret() As Variant
ReDim ret(1 To 1, 1 To (Application.Caller.Columns.Count))
Dim RetIdx&, i&, cell As Range
RetIdx = 1
For i = 0 To UBound(ranges)
For Each cell in Application.Range(ranges(i), ranges(i).End(xlToRight))
ret(1, RetIdx) = cell.Value
RetIdx = RetIdx + 1
Next
Next
For RetIdx = RetIdx To UBound(ret, 2)
ret(1, RetIdx) = vbNullString
Next
ConcatRanges = ret
End Function
For your example, you'd call it like this:
=ConcatRanges(Sheet1!A1, Sheet1!A2, Sheet1!A3)

Change background color based on value and row count

I'm using VBA and I would like to ask for help with regards to the Excel I have created. I want to change the background color if a cell has value and if row count is even.
Here's my code:
Sub ChangeColor()
Dim rw as Variant
Dim rng As Range
Set rng = Range("B10:H10000")
For each rw In rng.Rows
If rw.Row Mod 2 = 0 And (I dont know what to put here) Then
rw.Interior.Color = RGB (183,222,232)
End If
Next rw
End Sub
And if I may ask how do I make the process of my application faster than normal since it will slow down because of the data that has been inputted (more or less 1000 + or almost 10k).
I already solved the row count is even, kindly help me for the value.
CF should be a lot quicker than VBA for this:
The formula I chose is:
=AND(ISEVEN(ROW()),B10<>"")

How to build non-consecutive ranges of rows based on cell contents?

I'm just getting started with VBA for Excel. I used VB and Java in college nearly ten years ago and was competent with it then, but am essentially starting over. (Um, not like riding a bike.)
I am trying to understand the methods to build a range that isn't just declared as A1:J34 or whatever. My Googling is challenged in that when searching for 'range' and terms that indicate what I seek, I get an avalanche of hits far more advanced than what I need, mostly hits that don't even address the basic summary info I need.
So, here's the basics of it:
Excel 2011 on Mac.
The sheet has data from A to M, down to 1309.
It's a repeating pattern of heading rows followed by data rows. Ugh. Seems like the person creating the sheet was more thinking about printing from the sheet than the organisation of the data. I need to clean it and 3 more like it up to use in a pivot table, and it's useless in this silly repeating layout.
Heading rows are as follows:
Last Name, First Name, then 10 date cells.
Data rows under the headings are the names, of course, and then a 1 or 0 for attendance.
Anywhere from 20 to 30 names under each heading. Then it repeats. And the dates change every few sets, picking up where the last set left off.
What I need to do right now:
I'm trying to assemble a range into a range variable by adding all the rows beginning with a specific value (in column A). In my case that value is the string "Last Name", so I can have the range variable holding all the cells in all rows that begin with "Last Name". This will then capture all the cells that need to be in date format. (I'm doing it so I can then make sure the date headings are all actually IN date format - because they are NOT all in date format now, many are just 'General' cells.)
My questions:
When telling a range object what it's range IS, how do you feed it cells/rows/columns that are not just a block defined by start and end cells entered by the person writing the code but based on row criteria? Eg: Create a Range that has rows 1, 34, 70, 93, and 128 from columns A to I based on presence of "First Name" in A.
What are the most common methods to do this?
Which of these is best suited to my need and why?
Here's a working example that demonstrates finding the "Last Name" rows, contructing a range object that includes all those rows, and then iterating through that object to search for non-date values. The code could be speeded up greatly by reading the data range into an array of variants and then searching the array for both the last name rows and the "bad dates" within those rows. This is especially true if you have a very large number of rows to check.
Sub DisjointRng()
Dim checkCol As String, checkPattern As String
Dim dateCols()
Dim lastCell As Range, usedRng As Range, checkRng As Range
Dim cell As Variant
Dim usedRow As Range, resultRng As Range, rngArea As Range
Dim i As Long, j As Long
checkCol = "A" 'column to check for "Last Name"
checkPattern = "Last*"
dateCols = Array(3, 5) 'columns to check for date formatting
With Worksheets("Sheet1")
'find the bottom right corner of data range; we determine the used range
'ourselves since the built-in UsedRange is sometimes out-of-synch
Set lastCell = .Cells(.Cells.Find(What:="*", SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, LookIn:=xlFormulas).Row, _
.Cells.Find(What:="*", SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, LookIn:=xlFormulas).Column)
Set usedRng = .Range("A1:" & lastCell.Address)
'the column of values in which to look for "Last Name"
Set checkRng = .Range(checkCol & "1:" & checkCol & usedRng.Rows.Count)
End With
'step down the column of values to check for last name & add
'add found rows to range object
For Each cell In checkRng
If cell.Value Like checkPattern Then
'create a range object for the row
Set usedRow = Intersect(cell.EntireRow, usedRng)
If resultRng Is Nothing Then
'set the first row with "Last Name"
Set resultRng = usedRow
Else
'add each additional found row to the result range object
Set resultRng = Union(resultRng, usedRow)
End If
End If
Next cell
For Each rngArea In resultRng.Areas
'if found rows are continguous, Excel consolidates them
'into single area, so need to loop through each of the rows in area
For i = 1 To rngArea.Rows.Count
For j = LBound(dateCols) To UBound(dateCols)
If Not IsDate(rngArea.Cells(i, dateCols(j))) Then
'do something
End If
Next j
Next i
Next rngArea
End Sub
You can use the Union operator, like this
Dim r As Range
Set r = Range("A1, A3, A10:A12")
or this
Set r = Union(Range("A1"), Range("A3"), Range("A10:A12"))
You can the iterate this range like this
Dim cl as Range
For Each cl in r.Cells
' code cell cl
Next
or this
Dim ar as Range
For each ar in r.Areas
' code using contiguous range ar
For each cl in ar.Cells
' code using cell cl
Next
Next