I have a macro running sheets in excel where the data being shown is connected to an external database. I am trying to have the data that is being shown refreshed as the data source is updated, all while the macro is running. To be clear, by "running" I mean the macro is displaying each sheet in the workbook for a number of seconds and just looping.
Here is the code:
Option Explicit
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As
Long) As Integer
Public Sub Switch()
Dim ws As Worksheet
Do
For Each ws In ThisWorkbook.Worksheets
ws.Activate
Application.Wait Now() + TimeValue("00:00:05")
If GetAsyncKeyState(vbKeyShift) Then Exit Sub
DoEvents
Next ws
Loop
End Sub
I have tried to insert ActiveWorkbook.RefreshAll just before 'Next ws' and I have also tried ThisWorkbook.RefreshAll in the same location.
As of now, when I am told the data has been updated, I stop the macro from running, which lets the data refresh, then I run the macro again. This is what I am trying to avoid having to do.
Thank you in advance for your help.
Thanks,
Derek
You can turn screen updating on or off during execution of your macro. The macro will run slower with it on.
Application.ScreenUpdating = True
Related
how I can run Formulas Calculate as last proces when WorkBook is opened ?
I mean when all data are already load, user gave permission to load external data from others WorkBook etc.
I already tryed with
Private Sub Workbook_Open()
Application.Calculate
End Sub
Private Sub Workbook_Open()
If Not Application.CalculationState = xlDone Then
Application.Calculate
End if
End Sub
When I run Excel file and click F9 (Calculate Formulas) then it's work.
How I can run Application.Calculate when all externals links(data from others workbook) are already loaded ? I think it could help
Thanks,
When you open the workbook use
Application.Calculation = xlCalculationManual
When you are about to close the workbook after completing all the work use
ThisWorkbook.Worksheets("wrkSheetName").Calculate
for each worksheet.
In Excel 2013 (Office 15) a combination of a shortcut and a very simple userform (for formatting) is sometimes causing the Active Workbook to disappear and another workbook to show for no reason (only happens sometimes, often after just having changed activeworkbook). I am trying to keep the current workbook window in the foreground while the formatting userform is shown but without success.
Here is my code:
Sub AssignKeys()
Application.OnKey "^%,", "MakeBlue"
End Sub
Sub MakeBlue()
frmFormat.Show
End Sub
frmFormat is a very simple and small form that only has one textbox where a formatting code is entered. It does work to restore the previously active workbook after hiding the modal form using this code:
Private Declare PtrSafe Function SetForegroundWindow Lib "USER32" (ByVal hWnd As LongPtr) As LongPtr
Public Sub MyAppActive(Handle As Long)
Dim lngStatus As LongPtr
lngStatus = SetForegroundWindow(Handle)
End Sub
Private Sub tbShortcut_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If tbShortcut.Text <> "xn" Then
Dim mySel As Range
Dim myWb As workBook
Dim myWnd As Window
Set myWnd = ActiveWindow
Set mySel = Selection
Set myWb = ActiveWorkbook
Debug.Print mySel.Address
Me.Hide
'mySel.Parent.Parent.Activate
myWb.Activate
myWnd.Activate
MyAppActive myWnd.hWnd
end if
end sub
So once the form is hidden, the original workbook window is restored. But while the userform is shown, the other unwanted Workbook window is displayed. Would be very greatful for any hints. Thank you!
The following seems to work most of the time. The OnTime seems to be necessary. I suspect the Microsoft bug is with the ribbon.
fsShow myUserForm
Sub fsShow(form As Object)
' Work around bug that form.show changes active window rather randomly
' (Only the displayed window is wrong, not the ActiveCell.parent.parent.)
Set fsActiveWindow = Application.ActiveWindow
form.Show
Application.OnTime Now(), "fsResetActiveWindowOnTime"
End Sub
Sub fsResetActiveWindowOnTime()
If Not fsActiveWindow Is Nothing Then
fsActiveWindow.Activate
Set fsActiveWindow = Nothing
End If
End Sub
However, I occasionally get a type mismatch error just by calling this, i.e. a userform is not an object(!). This whole area is buggy so I avoid using this method.
Sometimes just recreating a userform fixes the problem. It is not for all userforms. And I have not figured out a trigger.
Does anyone know the VBA Code that I need to use so that I can automatically “Refresh” and “Refresh All” using EPM (Hyperion) Smartiew? The “Refresh” function pulls the data into Excel on the active tab where the “Refresh” all function refreshes all tabs in the Workbook.
I’d like to create a simple macro attached to a command button in Excel and I’m not sure which VBA code to use.
I tried recording a macro where by I simply starting recording clicked refresh and stop recording although this did not work.
I tried this code just for the refresh:
Declare Function HypMenuVRefresh Lib "HsAddin.dll"() As Long
Sub MRetrieve()
X = HypMenuVRefresh()
End Sub
But received an error message saying that I had to update the declare method for use with a 64 bit system (I am using a 64 bit system).
Does anyone know how I could create this automatic Macro to refresh the data?
Any help would be much appreciated!
The declaration for x64 in VBA is not correct.
Try:
Private Declare PtrSafe Function HypMenuVRefresh Lib "HsAddin" () As Long
Sub refreshWS()
Dim Count, i As Integer
i = 1
Count = Worksheets.Count
Do While i <= Count
Sheets(i).Select
MsgBox Sheets(i).Name
Call HypMenuVRefresh
i = i + 1
Loop
MsgBox "done"
End Sub
Use the function calls that basically simulate pressing the buttons!
Refresh current worksheet
Declare Function HypMenuVRefresh Lib "HsAddin.dll" () As Long
lngReturn = HypMenuVRefresh()
Refresh All Worksheets
Declare Function HypMenuVRefreshAll Lib "HsAddin.dll" () As Long
lngReturn = HypMenuVRefreshAll()
*NOTE : Return value of 0 is 'OK'
HypRetrieveRange can refresh or update a range of information, there are also a number of other functions that might suit what you want depending on how much information you need to refresh. Did you import the entire smartview.bas file like they recommended?
Sub Refresh()
'
' Refresh Macro
' Macro recorded 8/12/2011 by joao-oliveira
'
Dim oBar As CommandBar
Set oBar = Application.CommandBars("Worksheet Menu Bar")
oBar.Controls("Hyperion").Controls("Refresh").Execute
End Sub
This worked for me. You'll be able to assign this macro to any button. Instead of using the refresh all function, I am using the HypMenuVRefresh function within each worksheet.
Sub refreshWS()
Dim Count, i As Integer
i = 1
Count = Worksheets.Count
Do While i < Count
Sheets(i).Select
Call HypMenuVRefresh
i = i + 1
Loop
MsgBox "done"
End Sub
Create a button and assign it a new subroutine. Use the call command to call the public function.
Sub RefreshHFM()
'
' RefreshHFM Macro
'
Call HypMenuVRefreshAll
'
End Sub
In my last post Auto refresh pivottables data in excel on first run, i found that on my first execution the query from the External data source is refreshed and takes approximately 1 min to execute. and in my second run, the pivot tables are updated.
Is there a solution (VBA code) to refresh both the External data source and pivot tables together within a time schedule (If suppose we set a timer) by clicking command button?
Under the connection properties, uncheck "Enable background refresh". This will make the connection refresh when told to, not in the background as other processes happen.
With background refresh disabled, your VBA procedure will wait for your external data to refresh before moving to the next line of code.
Then you just modify the following code:
ActiveWorkbook.Connections("CONNECTION_NAME").Refresh
Sheets("SHEET_NAME").PivotTables("PIVOT_TABLE_NAME").PivotCache.Refresh
You can also turn off background refresh in VBA:
ActiveWorkbook.Connections("CONNECTION_NAME").ODBCConnection.BackgroundQuery = False
I used the above answer but made use of the RefreshAll method. I also changed it to allow for multiple connections without having to specify the names. I then linked this to a button on my spreadsheet.
Sub Refresh()
Dim conn As Variant
For Each conn In ActiveWorkbook.Connections
conn.ODBCConnection.BackgroundQuery = False
Next conn
ActiveWorkbook.RefreshAll
End Sub
I think there is a simpler way to make excel wait till the refresh is done, without having to set the Background Query property to False. Why mess with people's preferences right?
Excel 2010 (and later) has this method called CalculateUntilAsyncQueriesDone and all you have to do it call it after you have called the RefreshAll method. Excel will wait till the calculation is complete.
ThisWorkbook.RefreshAll
Application.CalculateUntilAsyncQueriesDone
I usually put these things together to do a master full calculate without interruption, before sending my models to others. Something like this:
ThisWorkbook.RefreshAll
Application.CalculateUntilAsyncQueriesDone
Application.CalculateFullRebuild
Application.CalculateUntilAsyncQueriesDone
Auto Refresh Workbook for example every 5 sec.
Apply to module
Public Sub Refresh()
'refresh
ActiveWorkbook.RefreshAll
alertTime = Now + TimeValue("00:00:05") 'hh:mm:ss
Application.OnTime alertTime, "Refresh"
End Sub
Apply to Workbook on Open
Private Sub Workbook_Open()
alertTime = Now + TimeValue("00:00:05") 'hh:mm:ss
Application.OnTime alertTime, "Refresh"
End Sub
:)
I found this solution online, and it addressed this pretty well. My only concern is looping through all the pivots and queries might become time consuming if there's a lot of them:
Sub RefreshTables()
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Dim objList As ListObject
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
For Each objList In ws.ListObjects
If objList.SourceType = 3 Then
With objList.QueryTable
.BackgroundQuery = False
.Refresh
End With
End If
Next objList
Next ws
Call UpdateAllPivots
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
Sub UpdateAllPivots()
Dim pt As PivotTable
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
For Each pt In ws.PivotTables
pt.RefreshTable
Next pt
Next ws
End Sub
I have a worksheet that automatically gets updated with live stock price data. At the moment we have a very messy solution of copying periodically to the clipboard and manipulating the data from there.
Is it possible to instead automatically export data to CSV every time a price change is detected? I'm guessing it would involve VBA.
You can treat excel file as a data source and you may query it.
See google results: http://www.google.ro/#sclient=psy&hl=ro&q=excel+data+source+sql+query&aq=0&aqi=g1&aql=&oq=&pbx=1&fp=b0efac6ab816e29b
I will try to find a specific article for you.
I'd suggest the following strategy:
Fire up your worksheet and switch into "design mode"
Right-click the button which updates the stock info and try to find out to which macro the button is bound to
Open the VBA editor (ALT+F11)
Choose the "Workbook"-Section
From there select the "Open" Event/Method
Write a simple loop with a delay which calls the macro mentioned above periodically and programmatically save the excel-sheet as CSV
The code would be somthing like this (can't check it as I don't have access to excel right now):
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Sub Workbook_open()
Do While True
Call name_of_macro()
ActiveWorkbook.SaveAs Filename:= _
"c:\path/to/file.csv", FileFormat:=xlCSV _
, CreateBackup:=False
Sleep 10000 'Sleep 10 seconds
Loop
End Sub
This example is just intended to show a rough solution. As Jean-Francois pointed out, this piece of code will NOT update everytime a change is detected, it will update every 10 seconds, even if the data is still the same.
You can use an Application.OnTime to set up a function to get called on a regular basis.
The following function gets called by Excel every 30 seconds. Either call it once to kick off the schedule or just set Application.OnTime once when your worksheet opens to get it running.
Public Sub DoExport()
' do your export to CSV logic here
Application.OnTime Now + TimeValue("00:00:30"), "DoExport"
End Sub
This will do the trick:
Sub LoadNewValuesAndCheckForChange()
Dim rngMyValues As Range
Dim varBefore As Variant
Dim varAfter As Variant
Dim iRow As Long
Dim iCol As Long
Dim booValuesHaveChanged As Boolean
Set rngMyValues = Range("B4:D9") ' Or wherever your data is
varBefore = rngMyValues ' Save old values in an array
' Call the function that loads your new stock prices here...
varAfter = rngMyValues ' Get new values
' Loop through all cells to see if anything has changed.
booValuesHaveChanged = False
For iRow = LBound(varBefore, 1) To UBound(varBefore, 1)
For iCol = LBound(varBefore, 21) To UBound(varBefore, 21)
If Not varAfter(iRow, iCol) = varBefore(iRow, iCol) Then
' Change detected!
booValuesHaveChanged = True
End If
Next iCol
Next iRow
If booValuesHaveChanged Then
' Save .csv file with timestamp in filename
ActiveWorksheet.SaveAs _
Filename:="c:\myfile" & Format(Now, "yyyymmddhhnnss") & ".csv", _
FileFormat:=xlCSV
End If
End Sub