Loop through range in one sheet and have custom formula for each cell. Put data into a new sheet [excel][vba][bloomberg] - excel

I'm not sure how descriptive my title is but below I will try to explain what I am trying to do.
I have a list of company Bloomberg tickers => maybe more than 100
This list of tickers is saved in say "Sheet1" "A:A"
For each ticker I have a Bloomberg (BDS) formula that returns a certain number of shareholders
The number of shareholders needs to be dynamic
The ticker of each company needs to be copied alongside the info gathered from BBG (as this is not provided by their formula)
This whole data should be in a new sheet let's say "Sheet2"
Below is the code I am using. It actually does what I need, however I am not able to make the output of my FOR loop to be in a new sheet. I also believe that the writing is not the most efficient so any help there would be great.
My current excel spreadsheet:
How it looks now
Sub Macro1()
'
' Macro1 Macro
'
Dim ticker As Range
Dim cell As Range
Dim start_row As Integer
Dim row As Integer
Dim top_investors As Integer
top_investors = 5
start_row = 2
Range("K2:U999999").ClearContents
Range("L" & start_row).Select
For Each ticker In Range("A2:A" & Cells(Rows.Count, 2).End(xlUp).row)
If Not IsEmpty(ticker) Then
ActiveCell.Formula = "=BDS(" & Chr(34) & ticker.Value & Chr(34) & ",""TOP_20_HOLDERS_PUBLIC_FILINGS"",""Endrow""," & Chr(34) & top_investors & Chr(34) & ",""Endcol"",""9"")"
For Each cell In Range("K" & start_row & ":" & "K" & start_row + top_investors)
row = start_row
Range("K" & row).Select
cell.Value = ticker.Value
row = row + 1
Next cell
start_row = start_row + top_investors
Range("L" & start_row).Select
End If
Next ticker
End Sub

Well, I guess you need to do something like:
Sub Macro1()
'
' Macro1 Macro
'
Dim ticker As Range
Dim cell As Range
Dim start_row As Integer
Dim row As Integer
Dim top_investors As Integer
Dim mySheet as Worksheet
top_investors = 5
start_row = 2
Sheets.Add.Name = "myNewSheet"
mySheet = ThisWorkbook.Sheets("myNewSheet")
Range("K2:U999999").ClearContents
Range("L" & start_row).Select
For Each ticker In Range("A2:A" & Cells(Rows.Count, 2).End(xlUp).row)
If Not IsEmpty(ticker) Then
mySheet.Range("define your Range").Formula = "=BDS(" & Chr(34) & ticker.Value & Chr(34) & ",""TOP_20_HOLDERS_PUBLIC_FILINGS"",""Endrow""," & Chr(34) & top_investors & Chr(34) & ",""Endcol"",""9"")"
For Each cell In (mySheet?.)Range("K" & start_row & ":" & "K" & start_row + top_investors)
row = start_row
mySheet.Range("K" & row).Select
cell.Value = ticker.Value
row = row + 1
Next cell
start_row = start_row + top_investors
Range("L" & start_row).Select
End If
Next ticker
End Sub
That won't work yet, but I guess you got the idea of working with "mySheet" and know better than me were to add it in your code. Maybe you need to google a little bit about the correct syntax.

If you have a recent Excel version (that has the LET spreadsheet function) then VBA is not strictly necessary for what you want to achieve.
For example, if you tickers are in the range A4:A7 on 'Sheet 1', you can collect all the data in 'Sheet 2':
The formula in Sheet2!A4: =Sheet1!A4
The formula in Sheet2!B4: =LET(data,BDS(A4,$B$2,"Array=TRUE"),s,SEQUENCE(1,$B$1),INDEX(data,s,1))
Then fill the formulae down as needed. The dynamic number of investors is in cell Sheet2!B1, but this can be hard-coded.
The main 'trick' is to use the "Array=TRUE" option in the BDS() call. This returns the data in a dynamic array, which can be indexed into.

Related

How do I move specific valued cells in VBA?

I am working with a dataset that contains both numbers and names. In the dataset, some numbers and names are displayed and instead of manually going through thousands of rows I tried to make a script but it doesn´t happen anything.
Here is the code:
Sub MoveCells()
Dim row As Long
For row = 2 To LastRow
If Range("C" & row).Value Like "*0*" Then
Dim i As Integer
For i = 1 To 2
Range("C" & row).Insert Shift:=xlToRight
Next
End If
Next
End Sub
I am trying to move the cell that has a 0 in it, and the cell to the right of it, one step to right.
E.g. Cells C4 & D4 to D4 & E4.
I've made some adjustments to your code which will acheive the outcome you described.
Private Sub MoveCells()
Dim TargetRow As Long
Dim LastRow As Long
Dim ColumnCValue As Variant
Dim ColumnDValue As Variant
With Sheets("Sheet1")
LastRow = .Cells(.Rows.Count, 3).End(xlUp).row
End With
For TargetRow = 2 To LastRow
If Sheets("Sheet1").Range("C" & TargetRow).Value Like "*0*" Then
ColumnCValue = Sheets("Sheet1").Range("C" & TargetRow).Value
ColumnDValue = Sheets("Sheet1").Range("D" & TargetRow).Value
Sheets("Sheet1").Range("D" & TargetRow).Value = ColumnCValue
Sheets("Sheet1").Range("E" & TargetRow).Value = ColumnDValue
Sheets("Sheet1").Range("C" & TargetRow).ClearContents
End If
Next
End Sub
Now we first assign a value to for LastRow and when the If...Then statement is true, assign the values of Column C and Column D to the respective variables. Then, write those values 1 row to the right and finally clear the contents from Column C.

Exce VBA how to generate a row count in that starts with specific row and stops at last row? Formula is flawed

So I have what might be a simple issue. I have a worksheet where I'm just hoping to generate a row count starting with cell A4. So A4 = 1, A5 = 2 , etc. The problem is I'm not sure how to configure this with the following goal:
1 - I'm hoping the count starts with cell A4 and ends the count at the final row with data.
The code I have below only works if I manually put A4 = 1, and also populates formulas past the last row unfortunately.
Please help if this is possible.
Sub V14()
With ThisWorkbook.Worksheets("DCT")
.Cells(5, 1).Resize(.Cells(.Rows.Count, 2).End(xlUp).Row - 1).Formula = "=IF(DCT!B5="""","""",DCT!A4+1)"
End With
End Sub
Write Formula to Column Range
The Code
Sub V14()
Const wsName As String = "DCT" ' Worksheet Name
Const tgtRow As Long = 4 ' Target First Row Number
Const tgtCol As String = "A" ' Target Column String
Const critCol As String = "B" ' Criteria Column String
' Define worksheet ('ws').
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(wsName)
' Define Last Non-Empty Cell ('cel') in Criteria Column ('critCol').
Dim cel As Range
Set cel = ws.Cells(ws.Rows.Count, critCol).End(xlUp)
' Define Target Column Range ('rng').
Dim rng As Range
Set rng = ws.Cells(tgtRow, tgtCol).Resize(cel.Row - tgtRow + 1)
' Define Target Formula ('tgtFormula').
Dim tgtFormula As String
tgtFormula = "=IF('" & wsName & "'!" & critCol & tgtRow _
& "="""","""",MAX('" & wsName & "'!" & tgtCol _
& "$" & tgtRow - 1 & ":" & tgtCol & tgtRow - 1 & ")+1)"
' Write Target Formula to Target Range.
rng.Formula = tgtFormula
' If you just want to keep the values:
'rng.Value = rng.Value
End Sub
I think you might just need an extra IF:
Sub V14()
With ThisWorkbook.Worksheets("DCT")
.Cells(4, 1).Resize(.Cells(.Rows.Count, 2).End(xlUp).Row - 1).Formula = "=IF(DCT!B4="""","""",IF(A3="""",1,SUM(DCT!A3,1)))"
End With
End Sub
Report any question you have or bug you have encountered. If, according to your judgment, this answer (or any other) is the best solution to your problem you have the privilege to accept it (link).
Dim target As String
Dim lastrow As Long
target = "A4"
lastrow = ActiveSheet.UsedRange.Rows.count
'for example
Range(target) = "1"
Range(target).Offset(1, 0) = "2"
Range(Range(target),Range(target).Offset(1, 0)).Select
Selection.AutoFill Destination:=Range(target & ":A" & lastrow + Range(target).Row - 1), Type:=xlFillDefault
You only got to change the target cell, this does the rest.

How to use variables in a VBA code using the sumif function

I download a data set that always has a different number of rows. I store two columns as variables, the imports and the months. Then I need to run a Sumif formula that sums the value of imports by the months. I am writing a Sumif formula that uses the two variables and references the cell to its left.
The cells however vary in location based on the changing size of the data set. So I write a code to select the last active cell on a column and select the cell 3 rows down.
When writing the formula with the variables and the cell its giving me an error. Please help sorry for any typos fist time doing this.
I select all the active cells in range D and store them as months, I do the same for the imports. Then using range I find the last active cell on column M, and use select the cell 3 rows down, where I wish to write my formula.
Please see my codes to see what am I doing wrong, I am a novice coder.
Sub Importaciones()
'
' Importaciones Macro
'
Dim LastRow As Long
LastRow = Range("L" & Rows.Count).End(xlUp).Row
Dim Months As Long
Months = Range("D2", Range("D2").End(xlDown)).Select
Dim Imports As Long
Imports = Range("M2", Range("M2").End(xlDown)).Select
Dim LastRowM As Long
LastRowM = Range("M" & Rows.Count).End(xlUp).Row
Range("M" & LastRowM + 3).Formula = "=sumif(" & Months & ", " &
Range("L" & LastRow + 3) & ", " & Imports & ")"
End Sub
For the formula to work and the sum of the month that I choose comes up
As per all the comments:
Sub Importaciones()
With Worksheets("Sheet1") 'Change to your sheet
Dim LastRow As Long
LastRow = .Range("L" & .Rows.Count).End(xlUp).Row
Dim Months As Range
Set Months = .Range("D2", .Range("D2").End(xlDown))
Dim Imports As Range
Set Imports = .Range("M2", .Range("M2").End(xlDown))
Dim LastRowM As Long
LastRowM = .Range("M" & .Rows.Count).End(xlUp).Row
.Range("M" & LastRowM + 3).Formula = "=sumif(" & Months.Address(0, 0) & ", " & .Range("L" & LastRow + 3).Address(0, 0) & ", " & Imports.Address(0, 0) & ")"
End With
End Sub

want to convert Excel formula into VBA code

I wanted to convert below formula to VBA code.
=C1&"`"&K1&"`"&L1&"`"&J1
=VLOOKUP(M1,Data!$A:$J,9,)
=SUMPRODUCT(SUMIF(B1:B,B1,G1:G))
Currently i have enter this formula in 1st row and than copying this formula till the last row used which is taking lot time to apply formula because it has more than million row.
LR1 = Sheets("CRIMS").UsedRange.Rows.Count
Sheets("CRIMS").Range("M1:P1").AutoFill Destination:=Sheets("CRIMS").Range("M1:P" & LR1)
is there any way to convert this formula into VBA code?
For first formula the easiest way would be:
Range("M" & i).FormulaR1C1 = "=RC[-10]&""`""&K&""`""&L&""`""&J"
But for vlookup I prefer dictionaries/collections! It is much much faster.
If You have source data in Data sheet and You want to put that to CRIMS sheet to column M:
Sub vlookup()
Dim names As Range, values As Range
Dim lookupNames As Range, lookupValues As Range
Dim vlookupCol As Object
Dim lastRow As Long
Dim lastRow2 As Long
Dim objekt as Object
With Sheets("Data")
lastRow = Sheets("Data").Cells(Rows.Count, 1).End(xlUp).row
Set names = Sheets("Data").Range("A1:A" & lastRow)
Set values = Sheets("Data").Range("I1:A" & lastRow)
End With
Set objekt = BuildLookupCollection(names, values)
With Sheets("CRIMS")
lastRow2 = 1000000
Set lookupNames = .Range("M1:M" & lastRow)
Set lookupValues = .Range("N1:N" & lastRow)
End With
VLookupValues lookupNames, lookupValues, objekt
Set objekt = Nothing
End Sub
Function BuildLookupCollection(categories As Range, values As Range)
Dim vlookupCol As Object, i As Long
Set vlookupCol = CreateObject("Scripting.Dictionary")
On Error Resume Next
For i = 1 To categories.Rows.Count
Call vlookupCol.Add(CStr(categories(i)), values(i))
Next i
On Error GoTo 0
Set BuildLookupCollection = vlookupCol
End Function
Sub VLookupValues(lookupCategory As Range, lookupValues As Range, vlookupCol As Object)
Dim i As Long, resArr() As Variant
ReDim resArr(lookupCategory.Rows.Count, 1)
For i = 1 To lookupCategory.Rows.Count
resArr(i - 1, 0) = vlookupCol.Item(CStr(lookupCategory(i)))
Next i
lookupValues = resArr
End Sub
Quotation Marks need to be doubled in VBA
Try this:
For i = 1 To LR1
Range("M" & i).Formula = "=C" & i & "&""`""&K" & i & "&""`""&L" & i & "&""`""&J" & i
Range("N" & i).Formula = "=VLOOKUP(M" & i & ",Data!$A:$J,9,)"
Next i
(replace column letters with actual target column)
As mentioned in the comments Looping in this case is highly inefficient.
Use this Code to insert the formulas all at once. It still takes some time for 1 Milion rows though.
Range("M1:M" & LR1).Formula = "=C:C & ""`"" & K:K & ""`"" & L:L & ""`"" & J:J"
Range("N1:N" & LR1).Formula = "=VLOOKUP(M:M,Data!$A:$J,9,)"

Loops and row references

The below code needs to run the =disvincenty formula on a loop, and the referenced cells $C$2,$D$2 need to go down one row each time in same column each time code block runs until ABF (Last row with data in column T.) then it exit's sub
For each row, it needs to run the formulas =Min and the two =small's in the same columns already referenced, but also dropping down one row at a time - the same as the =distvincenty, but values being pasted each time to preserve result.
So =distvincenty is looking at two criteria in cells next to each other on same row, compares to a list running down a column, applies the three other formulas to that row, and moves down.
Dim rng As Range
Dim row As Range
Dim cell As Range
Dim ABF As Integer
ABF = Sheet9.Range("T" & Rows.Count).End(xlUp).row
Set rng = Range("Q2:Q" & ABF)
For Each row In rng.Rows
For Each cell In row.Cells
Sheet9.Range("Q2").Formula = "=distVincenty($C$2,$D$2,$R2,$S2)/1609.344"
Sheet9.Range("Q2").Copy
Sheet9.Range("Q2:Q" & ABF).PasteSpecial xlPasteAll
Application.CutCopyMode = False
Sheet9.Range("E2").Formula = "=MIN(Q:Q)"
Sheet9.Range("H2").Formula = "=SMALL(Q:Q,2)"
Sheet9.Range("K2").Formula = "=SMALL(Q:Q,3)"
Next cell
Next row
UPDATE:
I now have this:
Dim ABF As Integer
Dim i As Integer
For i = 2 To Sheet9.Range("A" & Rows.Count).End(xlUp).row
ABF = Sheet10.Range("AC" & Rows.Count).End(xlUp).row
Sheet10.Range("AE3").Formula = "=distVincenty('Booking Workings'!$C$2,'Booking Workings'!$D$2,'User List'!$Z3,'User List'!$AA3)/1609.344"
Sheet10.Range("AE3").Copy
Sheet10.Range("AE3:AE" & ABF).PasteSpecial xlPasteAll
Application.CutCopyMode = False
Sheet9.Range("E" & i).Formula = "=MIN('User List'!AE:AE)"
Sheet9.Range("H" & i).Formula = "=SMALL('User List'!AE:AE,2)"
Sheet9.Range("K" & i).Formula = "=SMALL('User List'!AE:AE,3)"
Next i
End sub
The only problem I have is that each time this code runs, I need the $C$2 and $D$2 to change like the simpler formulas.
Can I do this?
Sheet10.Range("AE3").Formula = "=distVincenty('Booking Workings'!$C$"(I)",'Booking Workings'!$D$"(I)",'User List'!$Z3,'User List'!$AA3)/1609.344"
UPDATE
looks like this works:
"=distVincenty('Booking Workings'!$C$" & (i) & ",'Booking Workings'!$D$" & (i) & ",'User List'!$Z3,'User List'!$AA3)/1609.344"
This is hard to explain. Let me know if I'm close.
Sub Test()
Dim rng As Range
Dim row As Range
Dim cell As Range
Dim ABF As Integer
Dim arrValues
Dim count As Integer
ABF = Sheet9.Range("T" & Rows.count).End(xlUp).row
Set rng = Range("Q2:Q" & ABF)
arrValues = rng.Value
For Each cell In rng
Sheet9.Range("Q2:Q" & ABF).Formula = "=distVincenty($C$" & cell.row & ",$D$" & cell.row & ",$R2,$S2)/1609.344"
Sheet9.Range("E2").Formula = "=MIN(Q:Q)"
Sheet9.Range("H2").Formula = "=SMALL(Q:Q,2)"
Sheet9.Range("K2").Formula = "=SMALL(Q:Q,3)"
count = count + 1
arrValues(count) = cell.Value
Next cell
Sheet9.Range("Q2:Q" & ABF).Value = arrValues
End Sub

Resources