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.
Related
Put the code I'm working with at the bottom.
I am trying to enter a set of formulas in a range with code. The formulas enter correctly, but they only calculate if I click on each cell, click on the formula box, and hit enter.
I've tried all suggestions I can find online, hence the last three lines of code. It's not a matter of the cells changing format, they remain General after the code runs. I'm completely stumped.
Sub ButtonTest()
Dim Number As Integer
Number = Range("M2").Value
Dim TestArray() As String
ReDim TestArray(0, 1 To Number)
Dim Values As Integer
Dim RangeValues As Integer
Dim Variable As Integer
Variable = 3
TestArray(0, 1) = "=1"
For Values = 2 To Number
TestArray(0, Values) = "=" & Cells(3, Variable).Address & "+1"
Variable = Variable + 1
Next Values
Range("C3:" & Cells(3, Number + 2).Address).Formula = TestArray
Application.Calculation = xlCalculationAutomatic
ActiveSheet.EnableCalculation = True
ActiveSheet.Calculate
End Sub
To enter a formula from an array use .FormulaArray rather than .Formula
Range("C3:" & Cells(3, Number + 2).Address).FormulaArray = TestArray
Not sure if I'm off the mark here, but I always had the impression that formulas couldn't be written to a Range in an array (as you would with values, for example). I believe you have to write one cell at a time.
There may be a method that can be called to convert array values to evaluated cells, but I don't know of it - be happy to hear if anyone can enlighten me though.
In the meantime, the code below gives an example of how your code could be made to work:
Dim iterationCount As Long, i As Long
Dim cell As Range
iterationCount = Sheet1.Range("M2").Value
Set cell = Sheet1.Range("C3")
cell.Formula = "=1"
For i = 1 To iterationCount
cell.Offset(, 1).Formula = "=" & cell.Address & " + 1"
Set cell = cell.Offset(, 1)
Next
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 & ")"
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/
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
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