how to capture real time data in excel - excel

i have a cell (A1) linked to real-time data (=Tickers!Z12). i want to capture all of the price range in a five minute period. my issue is i'm trying to use the Worksheet_Change method but it wont update when the values change if the cell (A1) is formulated. it works fine if i manually change the values. but i need to capture values that are being generated by the formula and then copy & paste the values in column B everytime the values change. here's what i have so far.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.ScreenUpdating = False
Application.EnableEvents = False
If Range("A1").value <> Range("B2").value Then
Range("A1").Select
Selection.Copy
With ActiveSheet
LastRow = .Cells(.rows.Count, "B").End(xlUp).row + 1
.Cells(LastRow, 2).Select
Selection.PasteSpecial Paste:=xlPasteValues
End With
End If
Application.CutCopyMode = False
Application.EnableEvents = True
End Sub

Try using the Worksheet_Calculate event.
Also, I'm not sure you want to compare A1 to B2. Logic dictates you should be comparing it to the last cell in column B.
Also, using Activesheet is not a good idea, as the recalculation can happen when you are on any other sheet, and you don't want to write values on random worksheets.
And one more thing: don't use copy-paste ina macro. Just make .Value=.Value.
Private Sub Worksheet_Calculate()
Dim lngLastRow As Long
On Error Goto SkipAllThis
Application.ScreenUpdating = False
Application.EnableEvents = False
With Worksheets("Source") 'or whatever sheet has your code and stores your values
lngLastRow = .Cells(.Rows.Count, 2).End(xlUp).Row
If .Range("A1").Value <> .Cells(lngLastRow, 2).Value Then
.Cells(lngLastRow + 1, 2).Value = Range("a1").Value
End If
End With
SkipAllThis:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub

DRS,
Implement the sleep function as:
Declaring & Calling The Sleep API
Then afterward, capture your value. Just note the API is in milliseconds.
G.

Related

How to fill down functions in four columns to where the data in column A stops?

I am trying to fill down functions in four columns to where the data in column A stops, but by the time it gets to the fourth FillDown, it takes a very long time.
Is there any way to rewrite it more efficiently?
Range("D2").Select
ActiveCell.FormulaR1C1 = "=LEFT(RC[-1],2)"
Range(ActiveCell, ActiveCell.Offset(0, 0).End(xlDown)).FillDown
Range("E2").Select
ActiveCell.FormulaR1C1 = "=MID(RC[-2],7,2)"
Range(ActiveCell, ActiveCell.Offset(0, 0).End(xlDown)).FillDown
Range("Z2").Select
ActiveCell.FormulaR1C1 = "=IF(RC[-22]<>""SO"",RC[-22],RC[-12])"
Range(ActiveCell, ActiveCell.Offset(0, 0).End(xlDown)).FillDown
Range("AA2").Select
ActiveCell.FormulaR1C1 = _
"=IF(OR((RC[-22]=""17""),(RC[-22]<>""11""),(RC[-23]=""SO"")),""HQ"",""Remote"")"
Range(ActiveCell, ActiveCell.Offset(0, 0).End(xlDown)).FillDown
I see several issues here
You say ... to where the data in column A stops but are using .End(xlDown) on columns D, E, Z, AA. This may be filling the formula down to the botton of the sheet.
You don't need to Fill Down, simply apply the formula to a specified range
Select is not a needed
Consider this
Sub Demo()
Dim ws As Worksheet
Dim LastRow As Long
Set ws = ActiveSheet ' or specify the required sheet
With ws
' find where data in column A stops
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
If LastRow = 1 Then
' there is no data in column A
Exit Sub
End If
.Range(.Cells(2, 4), .Cells(LastRow, 4)).FormulaR1C1 = "=LEFT(RC[-1],2)"
.Range(.Cells(2, 5), .Cells(LastRow, 5)).FormulaR1C1 = "=MID(RC[-2],7,2)"
.Range(.Cells(2, 26), .Cells(LastRow, 26)).FormulaR1C1 = "=IF(RC[-22]<>""SO"",RC[-22],RC[-12])"
.Range(.Cells(2, 27), .Cells(LastRow, 27)).FormulaR1C1 = "=IF(OR((RC[-22]=""17""),(RC[-22]<>""11""),(RC[-23]=""SO"")),""HQ"",""Remote"")"
End With
End Sub
As #BigBen pointed out, you can avoid using .FillDown by just referencing the full range from the start. You can also avoid .Select at the same time by using functions like .Resize to reference larger ranges based on the current range.
Additionally, since your macro is writing formulas into cells, you can speed up the code by disabling the auto-calculation that happens whenever a cell is edited. It's also a good idea to disable any events that might be running from the Worksheet_Change procedure.
You can disable those two things using Application.Calculation = xlCalculationManual and Application.EnableEvents = False. After the code, you will want to return those two settings back to default with Application.Calculation = xlCalculationAutomatic and Application.EnableEvents = True
Here's an example of how to implement these suggestions:
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
With Range("D2")
.Resize(.End(xlDown).Row - .Row).FormulaR1C1 = "=LEFT(RC[-1],2)"
End With
With Range("E2")
.Resize(.End(xlDown).Row - .Row).FormulaR1C1 = "=MID(RC[-2],7,2)"
End With
With Range("Z2")
.Resize(.End(xlDown).Row - .Row).FormulaR1C1 = "=IF(RC[-22]<>""SO"",RC[-22],RC[-12])"
End With
With Range("AA2")
.Resize(.End(xlDown).Row - .Row).FormulaR1C1 = _
"=IF(OR((RC[-22]=""17""),(RC[-22]<>""11""),(RC[-23]=""SO"")),""HQ"",""Remote"")"
End With
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
I preserved the .End(xlDown) method since I don't know what your sheet looks and that may be the best method to match your data format.

Generate number upon macro execution and transfer it to another table where there is no existing data in another sheet

I am trying to generate a number in A1 in Sheet1 every time the Makro is executed. The number is a combination of the date and a number to be incremented. The final number is to be transferred to Sheet2 in column A where there is not yet data (in this case A1>A2>A3>....)
And this is my attempt in VBA but it does nothing.
Sub incrementInvoiceNumber()
Dim rng_dest As Range
Dim i As Long
Application.ScreenUpdating = False
Sheets("Sheet1").Range("A1").Value = WorksheetFunction.Text(Date, "YYYYMMDD") & WorksheetFunction.Text(Range("A1").Value + 1)
i = 1
Set rng_dest = Sheets("Sheet2").Range("A:A")
Do Until WorksheetFunction.CountA(rng_dest.Rows(i)) = 0
i = i + 1
Loop
Sheets("Sheet2").Range("A" & i).Value = Sheets("Sheet1").Range("A1").Value
Application.ScreenUpdating = True
End Sub
It's not so clear what exactly is making the code not working. I think its that some rages are not called by its parent sheet.
Besides, it's always better to avoid WorksheetFunction if you have VBA function that can do the same thing.
And, finding the last row can be done in a much better way by using End() method.
This is how:
Sub incrementInvoiceNumber()
Dim i As Long
Application.ScreenUpdating = False
Sheets("Sheet1").Range("A1").Value = _
Format(Date, "YYYYMMDD") & Format(Sheets("Sheet1").Range("A1").Value + 1) 'Make sure Sheet1 is the sheet with the value. Fix it if otherwise
With Sheets("Sheet2")
i = .Cells(.Rows.Count, 1).End(xlUp).Row
If Not IsEmpty(.Cells(i, 1)) Then i = i + 1
.Cells(i, 1).Value = Sheets("Sheet1").Range("A1").Value
End With
Application.ScreenUpdating = True
End Sub
Cells(Rows.Count, 1).End(xlUp) means the cell that you will reach if you start from the last cell in column A ("A1048576") and press Ctrl + Up Arrow.

Speed up VBA code on extracting relevant rows to new worksheet

I need to copy relevant rows to a new Excel worksheet. The code will loop through each row in the original worksheet and select rows based on relevant countries and products specified in the array into the second worksheet.
Private Sub CommandButton1_Click()
a = Worksheets("worksheet1").Cells(Rows.Count, 2).End(xlUp).Row
Dim countryArray(1 To 17) As Variant
Dim productArray(1 To 17) As Variant
' countryArray(1)= "Australia" and so on...
' productArray(1)= "Product A" and so on...
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
For i = 3 To a
For Each j In countryArray
For Each k In productArray
Sheets("worksheet1").Rows(i).Copy Destination:=Sheets("worksheet2").Range("A" & Rows.Count).End(xlUp).Offset(1)
Next
Next
Next
Application.CutCopyMode = False
Application.ScreenUpdating = False
End Sub
Each time I ran the code, the spreadsheet stopped responding in a matter of minutes. Would appreciate if someone could help me on this, thanks in advance!
Here are some pointers:
Remember to declare all your variables and use Option Explicit at the top of your code
Use With statements to ensure working with right sheet and not implicit activesheet or you may end up with wrong end row count
Only i contributes to the loop so you are making unnecessary loop work
Gather qualifying ranges with Union and copy in one go
Remember to switch back on screen-updating
Code:
Option Explicit
Private Sub CommandButton1_Click()
Dim unionRng As Range, a As Long, i As Long
With Worksheets("worksheet1")
a = .Cells(.Rows.Count, 2).End(xlUp).Row
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
For i = 3 To a
If Not unionRng Is Nothing Then
Set unionRng = Union(unionRng, .Cells(i, 1))
Else
Set unionRng = .Cells(i, 1)
End If
Next
With Worksheets("worksheet2")
unionRng.EntireRow.Copy .Cells(.Rows.Count, "A").End(xlUp).Row +1
End With
End With
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub

VBA Loop and copy regions from sheet to sheet

I am trying to loop down the column "Q" on my active sheet, find values that are in between 27 and 40 and then copy that cell along with a region around the cell noted by the (-1, -16) into a new sheet.
Right now I am just making the region bold to make sure that my loop is catching the right values and regions.
I"m new to VBA so if anyone can give me some pointers or advise on how to solve my problem I'd be very appreciative.
Sub Test2()
Application.ScreenUpdating = False
ActiveSheet.Range("Q13").Select
Let x = 0
Do While x < 500
If ActiveCell.Value >= 27 And ActiveCell.Value <= 40 Then
Range(ActiveCell, ActiveCell.Offset(-1, -16)).Select
Selection.Font.Bold = True
ActiveCell.Offset(2, 16).Activate
Else
ActiveCell.Offset(1, 0).Select
End If
x = x + 1
Loop
End Sub
Try below code :
Always set the ScreenUpdating property back to True when your macro
ends.Check this link
Avoid using Select/Activate in your code. Check this link
Always explicitly specify the sheet when working with more than one
sheet.
Avoid using ActiveCell,ActiveSheet and refer to them explicitly.
Sub Test2()
Application.ScreenUpdating = False
Dim lastRow As Long
lastRow = Sheets("sheet1").Range("Q" & Rows.Count).End(xlUp).Row
Dim rng As Range, cell As Range
Set rng = Sheets("sheet1").Range("Q1:Q" & lastRow)
For Each cell In rng
If cell.Value >= 27 And cell.Value <= 40 Then
Sheets("sheet1").Range(cell, cell.Offset(0, -16)).Copy Sheets("sheet2").Cells(Sheets("sheet2").Range("Q" & Rows.Count).End(xlUp).Row + 1, 1)
End If
Next
Application.ScreenUpdating = True
End Sub

Excel 2007, Copying rows from one sheet to another based on a value in 1 column

I'm trying to copy a range of rows where the rows chosen are based on the value in one cell.I want to do this for all rows containing the same value in a cell, then move on to the next value an append to the bottom of the first list.
Below is my attempt at explaining what I wish to achieve - hopefully the above will help explain more my dilemma. I have looked around for this but not quite found what I want. I thought it would be simple and probably is.
I receive a data dump with thousands of rows of data and 18 columns. Based on the value of column P "Contract" I want to copy entire rows into a new single worksheet workingdata. Not all the data will go into the workingdata worksheet.
The contract numbers are c1234, c1235, c2345 etc.
What i am after achieving is copying and sorting, so copy all the rows of data where contract number is c1234, in workingdata, then directly below it copy all rows where contract is c1235 and so on.
I thought I could select the range P:P and sort but to no avail.
Sheets("Data Dump").Select
Columns("P:P").Select
If Selection.Value = "C1234" Then
Selection.EntireRow.copy
I know I should post what i have tried, but it would be a pathetic, for some reason I just can't seem to get my head round this one.
Here's my latest effort - I know there are errors
Dim oWorksheet As Excel.Worksheet
Dim oRangeSource As Excel.Range
Dim oRangeDest As Excel.Range
Set oWorksheet = Worksheets("DataDump")
Set oRangeSource = oWorksheet.Range("p:p")
Set oRangeDest = Worksheets("workingdata")
If oRangeSource="CA0004000" Then Select.EntireRow
Selection.EntireRow.copy
Sheets("workingdata").Select.Paste
End If
latest effort but does not sort data or get rid of unwanted, I have to do a manual filter and sort which sorts of defeats the object of the macro
Sub copy()
'
' copy Macro
'
Dim rngContracts As Range: Set rngContracts = Sheets("DataDump").Range("P:P")
Dim wsData As Worksheet
Dim wsFound As Boolean: wsFound = False
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name = "Working Data" Then
Set wsData = ws
wsFound = True
Exit For
End If
Next ws
If wsFound = False Then
Application.CutCopyMode = False
ActiveSheet.Range("A1").EntireRow.copy
Set wsData = Sheets.Add(After:=Sheets(Sheets.Count))
wsData.Name = "Working Data"
wsData.Range("A1").EntireRow.PasteSpecial xlPasteAll, Transpose:=False
End If
Dim iCell As Range
For Each iCell In rngContracts
If iCell.EntireRow.Hidden = False Then
Application.CutCopyMode = False
iCell.EntireRow.copy
wsData.Range("P" & Rows.Count).End(xlUp).Offset(1, 0).EntireRow.PasteSpecial xlPasteAll, Transpose:=False
End If
Next iCell
Application.CutCopyMode = False
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
Latest attaempt - copies the data I need but does not sort:
Sub copytest()
'
' copytest Macro
'
Set MR = Sheets("data Dump").Range("P:P")
For Each cell In MR
If cell.Value = "CA000154" Then
cell.EntireRow.copy
Sheets("working data").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial
End If
If cell.Value = "CA000220" Then
cell.EntireRow.copy
Sheets("working data").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial
End If
If cell.Value = "CA000393" Then
cell.EntireRow.copy
Sheets("working data").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial
End If
If cell.Value = "CA000429" Then
cell.EntireRow.copy
Sheets("working data").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial
End If
Application.CutCopyMode = False
Next
End Sub
Record a macro to set filters on your data select one filter only.
Then, edit the code and loop through each filter copying the visible range on to your sheet. This must also sort your data as the filters are already sorted.
Also, take a look at creating filter arrays in the Excel VBA help with regards to using them to sort.

Resources