简体   繁体   中英

VBA, how to insert a dynamic / relative cell reference into a .formulaArray method?

I have the following code:

  With Sh.Range("A1:A" & LastRow + 1).Offset(0, 4)
    .FormulaArray = "=MAX(IF(A2:A" & LastRow + 1 & "= ** , D2:D" & LastRow + 1 & "))"
    .Value = .Value
  End With

In the place where I have **, I would want a dynamic cell reference. If I was using .formulaR1C1, I would have inserted RC[-1], but I can't use that with a .formulaArray.

Does anyone know how I can insert a relative cell reference that would change as the formula being pasted within the range?

Thank you

EDIT # 1

The whole code looks like this:

Sub RemoveDuplicates_SumMarketValue()
Dim Sh As Worksheet
Dim LastRow As Long
Dim Rng As Range



Set Sh = Worksheets(1)

Sh.Columns(6).Insert

LastRow = Sh.Range("A65536").End(xlUp).Row

With Sh.Range("A1:A" & LastRow).Offset(0, 5)
    .FormulaR1C1 = "=IF(COUNTIF(R1C[-5]:RC[-5],RC[-5])>1,"""",SUMIF(R1C[-5]:R[" & LastRow & "]C[-5],RC[-5],R1C[-1]:R[" & LastRow & "]C[-1]))"
    .Value = .Value
End With
Sh.Columns(5).Delete
Sh.Rows(1).Insert



Sh.Columns(5).Insert

With Sh.Range("A1:A" & LastRow + 1).Offset(0, 4)
    .FormulaArray = "=MAX(IF(A2:A" & LastRow + 1 & "= A1 , D2:D" & LastRow + 1 & "))"
    .Value = .Value
End With



Set Rng = Sh.Range("E1:E" & LastRow + 1)

With Rng
    .AutoFilter Field:=1, Criteria1:="="
    .SpecialCells(xlCellTypeVisible).EntireRow.Delete

End With

End Sub

This purpose of this code, is too look though a sample of data and

  1. find duplicates
  2. sum up values in 5th column associated with duplicates
  3. remove duplicate rows (except the one that carries the sum from 5th column)

Now I also want it to have the max value from column 4th of all the duplicates to be retained in the final version, but I can't get the array formula to reference the row correctly.

EDIT : Try pasting this inside the "ThisWorkbook" code sheet :

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim Sh As Worksheet
Dim LastRow As Long
Dim Rng As Range

Set Sh = Worksheets(1)

LastRow = Sh.Range("A65536").End(xlUp).Row

With Sh.Range("A1:A" & LastRow).Offset(0, 5)
    .FormulaR1C1 = "=IF(COUNTIF(R1C[-5]:RC[-5],RC[-5])>1,"""",SUMIF(R1C[-5]:R[" & LastRow & "]C[-5],RC[-5],R1C[-1]:R[" & LastRow & "]C[-1]))"
    .Value = .Value
End With

With Sh.Range("A1:A" & LastRow + 1).Offset(0, 4)
    .FormulaArray = "=MAX(IF(A2:A" & LastRow + 1 & "= A1 , D2:D" & LastRow + 1 & "))"
    .Value = .Value
End With

'This section you might want to remove from this routine
Set Rng = Sh.Range("E1:E" & LastRow + 1)

With Rng
    .AutoFilter Field:=1, Criteria1:="="
    .SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With

End Sub

It basically is the same as your function, but it doesn't remove the columns or add any rows. What will happen is everytime one of your cell's content changes, this macro will run automatically, updating the formulas in the cells.


The closest you can get to achieving that, is having a macro in the background that will be running everytime a change is made to the sheet. If you have tens of thousands of rows, or a REALLY slow computer, this may not be the ideal solution. If this is not the case, however, you may find it very easy to get your code to work with very little changes.

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)

    'Update your formula here with the new content/reference 
    '  (your code + some changes to update where the last row is)

End Sub

Paste this inside the "ThisWorkbook", and simply place your code inside it.

This is what I came up with to solve the issue of the .formulaArray not accepting RC cell reference notation. I just used a loop to insert the array formula into each cell and reference the target row by using the loop variable i.

Code:

Sub RemoveDuplicates_SumMarketValue()
Dim Sh As Worksheet
Dim LastRow As Long
Dim Rng As Range
Dim targetcell As Range




Set Sh = Worksheets(1)

Sh.Columns(6).Insert

LastRow = Sh.Range("A65536").End(xlUp).Row

With Sh.Range("A1:A" & LastRow).Offset(0, 5)
    .FormulaR1C1 = "=IF(COUNTIF(R1C[-5]:RC[-5],RC[-5])>1,"""",SUMIF(R1C[-5]:R[" & LastRow & "]C[-5],RC[-5],R1C[-1]:R[" & LastRow & "]C[-1]))"
    .Value = .Value
End With
Sh.Columns(5).Delete
Sh.Rows(1).Insert



Sh.Columns(5).Insert

For i = 2 To LastRow + 1


Cells(i, 5).FormulaArray = "=MAX(IF(A2:A" & LastRow + 1 & "= A" & i & " , D2:D" & LastRow + 1 & "))"
Cells(i, 5) = Cells(i, 5).Value

Next
Sh.Columns(4).Delete


Set Rng = Sh.Range("E1:E" & LastRow + 1)

With Rng
    .AutoFilter Field:=1, Criteria1:="="
    .SpecialCells(xlCellTypeVisible).EntireRow.Delete

End With

Sheets(1).Cells(1, 4) = "Price" Sheets(1).Cells(1, 5) = "market value"

End Sub

So what this code does, loops for duplicates in Col 1, sums up associated values in col 5 and picks the max associated value in col 4.

Could you use, where you fill a cell and replicate it,

L = LastRow + 1
With Sh.Range("A1:A" & L).Offset(0, 4)
  .Cells(1,1).FormulaArray = "=MAX(IF(A$2:A$" & L & "=A1,D$2:D$" & L & "))"
  .FillDown
  .Value = .Value
End With

Handling A1 vs R1C1 style is easy, with Application.ConvertFormula

Need to be careful about Row/Col Abs/Rel referencing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM