Referring to a cell address/reference inside a formula - excel

I want to refer to the last cell that contains a text by its address (ex, C800) inside the MIN function. Can you help please?
Sub Set_Formula()
' -----------------------------
Dim lastRow As Long
Dim Lastcell As Range
Dim LC As String
Set Lastcell = Range("C:C").Find("*", Range("C1"), SearchDirection:=xlPrevious)
Set LC = Lastcell.Address()
'find last cell in the row
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
Dim r As Long
For r = 2 To lastRow
If (Cells(r, 3).Value <> "") Then
Range("E8") _
= "=MIN(C2:LC)" 'The MIN function
End If
Next
End Sub

It's not how I would do this, but :
Range("E8") _
= "=MIN(C2:" & LC & ")" 'The MIN function
End If
and, in your code, since LC is a string and not an object, be sure to remove the Set word.
That, of course, puts a static formula into E8.
So, if column C changes (more data added below LC, for example), you'll need to rewrite the formula to the worksheet.
If you prefer a formula that automagically adjusts to changing numbers of rows in column C, you can use:
=MIN(INDEX($C$2:INDEX($C:$C,LOOKUP(9.9E+307,$C:$C,ROW($C:$C))),0,1))
Edit: (Explanation of the formula)
The formula uses a feature of the LOOKUP function to find the last row. When lookup_value is greater than any value in lookup_array, LOOKUP will match the last value in lookup_array. Since we are using the optional result_vector argument, LOOKUP returns the value in the matching position which is that row number.
By using a very large number as lookup_value, one that is close to the maximum number allowed in Excel, we assure that there will not be a larger number in lookup_array
We then use the INDEX function to create an array that begins with C2 (or whatever you put in for a starting cell) and ends and Cn where n is the row number returned by the LOOKUP function.

Use the value for lastRow: Range("E8") = "=MIN(C2:C" & lastRow & ")"

Related

VBA inserting an arrray formula in R1C1 notation gets messed up

I have a function that inserts an array formula into a spreadsheet using R1C1 style notation. When the code inserts the formula into the spreadsheet, all the references get messed up. This confuses me because from what I saw online the .FormulaArray property of a range accepts both A1 and R1C1 style. This is the formula I want to insert:
AddArrayFunction "HUB_START", "=IFERROR(IF(INDEX(PACE!C10,MATCH(1,(PACE!C4=""New Hub"")*(PACE!C9=HubSummaryLTE!RC1),0))="""",""NO_DATE"",INDEX(PACE!C10,MATCH(1,(PACE!C4=""New Hub"")*(PACE!C9=HubSummaryLTE!RC1),0))),""NO_DATE"")", HubWS(Key) ' Make this an array formula
The double quotes are only there because of the way I pass the string to the function that actually inserts the formula down an entire column.
When the code writes to the Range.FormulaArray property, and I then go to the spreadsheet to look at the cell, it gives me this instead:
=IFERROR(IF(INDEX(PACE!R[8]C[-4],MATCH(1,(PACE!R[2]C[-4]="New Hub")*(PACE!R[7]C[-4]=HubSummaryLTE!R[-1]C[464]),0))="","NO_DATE",INDEX(PACE!R[8]C[-4],MATCH(1,(PACE!R[2]C[-4]="New Hub")*(PACE!R[7]C[-4]=HubSummaryLTE!R[-1]C[464]),0))),"NO_DATE")
I don't know why the references are getting messed up and I don't want to use A1 notation, any ideas?
Here's the calling code:
' HUB_START
AddArrayFunction "HUB_START", "=IFERROR(IF(INDEX(PACE!C10,MATCH(1,(PACE!C4=""New Hub"")*(PACE!C9=HubSummaryLTE!RC1),0))="""",""NO_DATE"",INDEX(PACE!C10,MATCH(1,(PACE!C4=""New Hub"")*(PACE!C9=HubSummaryLTE!RC1),0))),""NO_DATE"")", HubWS(Key) ' Make this an array formula
And here is the function definition:
Sub AddArrayFunction(FormulaTitle As String, FormulaText As String, WS As Worksheet, Optional Row As Long = 1, Optional Column As Integer = -1)
Dim LastRow As Long
LastRow = FindLastUsedRow(WS) ' WS.Cells(WS.Rows.Count, 1).End(xlUp).Row
Dim PasteCol As Integer
If Column < 0 Then
PasteCol = 1
Do Until WS.Cells(Row, PasteCol) = ""
PasteCol = PasteCol + 1
Loop
Else
PasteCol = Column
End If
If WS.Cells(Row, PasteCol) <> "" Then WS.Columns(PasteCol).Insert Shift:=xlShiftToRight
WS.Cells(Row, PasteCol) = FormulaTitle
WS.Range(WS.Cells(Row + 1, PasteCol), WS.Cells(LastRow, PasteCol)).FormulaArray = FormulaText
End Sub
The column with the header "HUB_START" has the formula that the code automatically puts in. The column next to it with no header, has the same exact formula, I just copied and pasted, then I did control shift enter just to test and it clearly works, so I don't know where the problem is coming from.

Using variable as column reference to autosum said column VBA

I'm really new to VBA and have been working section by section on a number of pieces of code to format a worksheet (I've been doing it piece by piece so that I understand how each works, and using a final macro to Call all the macros into one long process).
Issue is sometimes the worksheets I work with are not exported with columns in the same order from month to month (out of my control), thus to autosum a particular column I have to Find the column header, then autosum that column, but this makes the column letter(or number) completely variable. I know how to work with rows as variables, but I'm stuck on column. I've been scouring forums to try and find a concise explanation, but to no avail, yet.
This code DOES work for column Y specifically, but I'm trying to figure out how to get it to use a variable for the column.
For example, I'm using a separate Macro called "FindInvoiceColumn" to select the 1st cell in the column that contains the string "invoice_amount", then I'd like to use something like I wrote below to set "ColumnAddress" as the column value of that cell. As far as I know .Column returns the column number, which is fine, but I'm assuming I'd have to use with Cells() instead of Range(), I just don't know how to get here.
(Part of the code also shows Adding the word "Total" to the left of the cell containing the autosum value, and making both bold).
Here's what I have so far:
Dim Rng As Range
Dim c As Range
Set Rng = Range("Y" & rows.Count).End(xlUp).Offset(1, 0)
Set c = Range("Y1").End(xlDown).Offset(1, 0)
c.Formula = "=SUM(" & Rng.Address(False, False) & ")"
'Selects next empty row of column X to add "Total" label for sum of column Y'
Range("X" & Cells.rows.Count).End(xlUp).Offset(1, 0).Select
ActiveCell.FormulaR1C1 = "Total"
'Bolds Total and the Sum of invoices'
Range("X" & Cells.rows.Count).End(xlUp).Select
Selection.Font.Bold = True
Range("Y" & Cells.rows.Count).End(xlUp).Select
Selection.Font.Bold = True```
'The below is what I'd like to use to find the dynamic value of the column.'
'Finds cell in row 1 that contains column header "invoice_amount" and selects it'
Call FindInvoiceColumn
'Dim ColumnAddress As Integer
ColumnAddress = ActiveCell.Column
You can use .Address to get a column reference, such that:
Sub test()
Dim varCol As String
varCol = Columns(ActiveCell.Column).Address
Debug.Print varCol 'OUTPUTS $A:$A when I had cells(1,1) selected
End Sub
In the above example, I chose a single cell to A) find it's column reference, via .Column, and B) found the .address of said column.
You could also perform the sum on a defined range using .cells() notation, rather than .range() notation.
Sub test2()
Dim rng As Range
Set rng = Range(Cells(1, 1), Cells(2, 1))
Cells(3, 1).Formula = "=sum(" & rng.Address & ")"
End Sub
The above code ouputs:
Specific to using the .cells() notation, you can make your column reference a variable, e.g.:
dim r as long, c as long
r = 1
c = 4
debug.print cells(r,c).address `should output $D$1 (untested)
You can choose r or c to fit your needs.
And as always... avoid select/activate where possible!!!
Edit
Adding use of last row via code since comments are terrible:
dim col as long
col = 25 'Y
With sheets("name")
dim lastRow as long
lastRow = .cells(.rows.count,col).end(xlup).row
Dim rng As Range
Set rng = .Range(.Cells(1, 1), .Cells(lastRow, col))
end with
This is exactly why I mentioned the specifics abotu the notation after that section (use of r and c as variables).
I've used this code to set a column number if your header is in a variable position
Dim F As Object
ColumnAddress = 0
With ActiveSheet.Rows(1)
Set F = .Find(What:="invoice_amount", LookAt:=xlWhole)
If F Is Nothing Then
MsgBox "This is not a proper file"
' other code
Else
ColumnAddress = F.Column
End If
End With
You would then use Cells() in place of range to do further work with the result of ColumnAddress. Also, ColumnAddress should dim as Long, to be accurate.

How to select mutiple values from excel single cell

I have excel cell having multiple rows of data with image url.
Now I want to select all images having 1500 value. So basically I want to select row starting with http and ending 1500.jpg.
Please not that in my single cell values are also other than 1500.jpg.Sample data is given below
colorImages': { 'initial': [{"hiRes":"https://images-na.ssl-images-amazon.com/images/I/71GOT-L%2BOSL._UL1500_.jpg","variant":"MAIN","lowRes":null},{"hiRes":"https://images-na.ssl-images-amazon.com/images/I/716mECZ9JDL._UL1500_.jpg","thumb":"https://images-na.ssl-images-amazon.com/images/I/313QD20m4WL._SR38,50_.jpg","large""thumb":"https://images-na.ssl-images-amazon.com/images/I/313QD20m4WL._SR38,50_.jpg","large":"https://images-na.ssl-images-amazon.com/images/I/313QD20m4WL.jpg","main":{"https://images-na.ssl-images-amazon.com/images/I/71GOT-L%2BOSL._UY445_.jpg":[445,117],"https://images-na.ssl-images-amazon.com/images/I/71GOT-L%2BOSL._UY500_.jpg":[500,132],"https://images-na.ssl-images-amazon.com/images/I/71GOT-L%2BOSL._UY550_.jpg":[550,145],"https://images-na.ssl-images-amazon.com/images/I/71GOT-L%2BOSL._UY606_.jpg":[606,160],"https://images-na.ssl-images-amazon.com/images/I/71GOT-L%2BOSL._UY679_.jpg":[679,179],"https://images-na.ssl-images-amazon.com/images/I/71GOT-L%2BOSL._UY741_.jpg":[741,195],"https://images-na.ssl-images-amazon.com/images/I/71GOT-L%2BOSL._UY879_.jpg":[879,231]},
Assuming data is in Column A starting from Cell A2 and all the URLs ending with 1500.jpg needs to be displayed in adjacent columns i.e. same row Column B, Column C, Column D,.... then following might help.
Sub Demo()
Dim ws As Worksheet
Dim lastRow As Long, colIndex As Long
Dim rng As Range, cel
Dim X As Long, DotCount As Long
Dim Pat As String, EndPat As String, Parts() As String
Set ws = ThisWorkbook.Worksheets("Sheet3") 'change Sheet3 to your data sheet
With ws
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row 'get last row with data in Column A
For Each cel In .Range(.Cells(2, 1), .Cells(lastRow, 1)) 'loop through A2 to last cell with data in Column A
colIndex = 1
Pat = "*[!&-;?-[_a-z~=!" & Chr$(1) & "]."
EndPat = "[!&-;?-[_a-z~=!" & Chr$(1) & "]*"
Parts = Split(cel.Value, """") 'split cell value into an array
For X = 0 To UBound(Parts)
If Parts(X) Like "*?.?*" Then
DotCount = Len(Parts(X)) - Len(Replace(Parts(X), ".", ""))
If """" & Replace(Parts(X), "]", Chr$(1)) & """" Like Application.Rept(Pat, DotCount) & EndPat Then
Parts(X) = ""
ElseIf Right(Parts(X), 8) <> "1500.jpg" Then
Parts(X) = ""
Else
cel.Offset(0, colIndex) = Parts(X) 'display URL
colIndex = colIndex + 1
End If
Else
Parts(X) = ""
End If
Next X
Next cel
End With
End Sub
Derived this solution using Function URLs from here.
This is done easily via VBA, but am not expert in that. So I have done some thing for you,just follow the instruction , still it is apply to get only single search entry i.e. means in a cell its find only one 1500.jpg entry.
To get second entry in the same cell you need some effort via change or get substring from the G1 Cell string and repeat the step as explained again.
In A1 Cell, put 1500.jpg
In B1 Cell, put your actual string as you have above
In C1 cell, put formula "=SEARCH(A1,B1)", which find the search 1500 in string
In D1 cell, put formula "=MID(B1,1,C1)", which extract the substring
For E1 we need reverse the string via VBA code - Add Reversestr function (To add this function, see this link)
In F1 cell, put formula "=SEARCH(CHAR(34),E1)", which search " in above reverse string
In G1 cell, put formula "=MID(B1,C1-F1+1,C1)"
Finally you get the string in G1 Cell as "https://images-na.ssl-images-amazon.com/images/I/71GOT-L%2BOSL._1500.jpg"
For VBa formula, check this links
http://analystcave.com/excel-substring-vba-substring/

Stumped with WorksheetFunction.Match() in Excel

This is some VBA code I've written for Excel. I'm trying to match entries in Sheet1 with those in Sheet2. The structure of both sheets is as follows:
DATE | ID |
----- ----
Date1 ID1
Date2 ID2...
In my code, I loop through the rows of the first sheet, and set the values from each particular row as part of my MATCH() query, in hopes of finding these same values in the second sheet. When I do, I want MATCH() to return the row index it finds these values in, so I can use that same row to input further information from the first sheet. This query uses multiple criteria, as indicated by both the value and searchRange variables (I'm trying to use the multiple criteria via concatenation method, as seen in this article).
The problem is, I consistently get a WorksheetFunction.Match could not be used error. When I used one single criteria (the ID), the function worked. When I tried to use multiple ones, it failed, even though I followed the instructions seen in the previously linked article. Any suggestions or ideas to fix this would be appreciated.
Sub runComparison(Sheet1 As String, Sheet2 As String)
Dim rowCount As Variant, columnCount As Variant, information As Variant
Dim counter As Integer
Dim value As String, searchRange As String
Sheets(Sheet2).Select
'Array of the number of rows in both sheets
rowCount = Array(Sheets(Sheet1).Cells(Rows.count, "A").End(xlUp).row, Sheets(Sheet2).Cells(Rows.count, "A").End(xlUp).row)
'Array of the number of columns in both sheets
columnCount = Array(Sheets(Sheet1).Cells(1, Columns.count).End(xlToLeft).Column, Sheets(Sheet2).Cells(1, Columns.count).End(xlToLeft).Column)
'The range in which we will look for the date and the ID
searchRange = CStr(Range(Cells(2, 1), Cells(rowCount(1), 1)).Address & "&" & Range(Cells(2, 2), Cells(rowCount(1), 2)).Address)
counter = 2
Do Until counter = rowCount(0)
'Sets the search term equal to the current cell in Sheet1
value = Sheets(Sheet1).Cells(counter, 1) & "&" & Sheets(Sheet2).Cells(counter, 2)
' Attempts to set the cell in the 8th column in the same row in which the search term is found equal to a certain value from the search term's row
Cells(WorksheetFunction.Match(value, searchRange, 0), 8) = Sheets(Sheet1).Cells(counter, columnCount(0)).value
counter = counter + 1
Loop
End Sub
Edit: Here's some sample input
value = '7/14/2014&ESTUOUW1046465464'
searchRange = '$A2:$A298&$B2:B298'
UPDATED
Thanks for clarifying in comments. I removed my original answer as it pertains only to the regular "Match" function, and I see the reference/example and understand what you're trying to do now which involves an array formula.
Let's try this using Application.Evaluate which will avoid the need to put this formula in a cell. Using the example data from MS, I did this which seems to work:
Sub test()
Dim value As String
Dim srcRange As String
value = "D2&E2"
srchRange = "$A$2:$A$5&$B$2:$B$5"
Debug.Print Application.Evaluate("=MATCH(" & value & "," & srchRange & ",0)")
End Sub
Applying that in your code, I think would be like below. YOu will still want to Dim matchVal as Variant to hold the result of the formula evaluation, I think. Then do this:
Do Until counter = rowCount(0)
'Sets the search term equal to the current cell in Sheet1
value = Sheets(Sheet1).Cells(counter, 1) & "&" & Sheets(Sheet2).Cells(counter, 2)
'## Assign the result of the Match function to a variable
matchVal = Application.Evaluate("=MATCH(" & value & "," & searchRange & ",0)")
'## Check for errors, and handle as needed:
If IsError(matchVal) Then
'modify as needed, this highlight the cell with the non-matched value
' you might omit this line and simply ignore it, or you could
' display a MsgBox prompt, etc.
Sheets(Sheet1).Cells(counter, columnCount(0)).Interior.ColorIndex = 6
Else:
Cells(matchVal, 8) = Sheets(Sheet1).Cells(counter, columnCount(0)).value
End If
counter = counter + 1
Loop

Move values of cell to next column if integer

I haven't used formulas in Excel before. Currently, the values of my cells are misaligned. What I would like to do is move the values of column F to column G if they are numerical values. For instance, in the 7th row that is displayed in my image, I'd like to move 48 over to the adjacent cell to the right. Same with 3054, 5770, and 32. However, I DON'T want to move IsCallOnly because it is an alphanumerical value. How would I go about doing this? Thanks!
In cell G2, try:
=IF(ISNUMBER(F2),F2,"")
This will tell is to copy the adjacent cell if it is a number, but leave the cell blank if it is not.
I suggest, in H1 and copied down:
=IF(G1="",F1,G1)
this looks to see if G1 is empty and if it is, take F1, otherwise take G1.
However, the number values in ColumnF are copied rather than moved, though it could be arranged for 'move' rather than 'copy, if required, with a bit of fiddling.
Neither requires VBA but if that is obligatory then it would help if you would post the code you have tried so far.
I think you are asking to move only the numbers in column F to column G?, if so maybe the following will help.
Sub MoveMyNumbers()
MoveNumbers "XXX", "F"
End Sub
.
Function MoveNumbers(ShtName As String, ColLetter As String)
Dim ws As Excel.Worksheet
Dim ColNumber As Integer
Dim lRow As Long
Dim i As Long
Set ws = ThisWorkbook.Sheets(ShtName)
lRow = ws.Range(ColLetter & ws.Rows.Count).End(xlUp).Row
'Get Column Number from column letter
ColNumber = ws.Range(ColLetter & "1").Column
For i = 1 To lRow
If IsNumeric(Cells(i, ColNumber).Value) Then
Cells(i, (ColNumber + 1)).Value = Cells(i, ColNumber).Value
Cells(i, ColNumber).Value = " "
End IF
Next i
End Function

Resources