Excel/VBA - How do I use BloombergUI .Subscribe to pull BDS? - vba

I am running into a problem where Bloomberg formulas do not load while the VBA is running. I would like to use the BloombergUI to resolve it.
Colin Legg's response here works for pulling BDP data, but I cannot get it to work for BDS formulas. Does anybody know how to modify the code?
Dim xlCalc As XlCalculation Sub Test1()
'early bound - reference to Bloomberg
'save the calculation setting and then set to automatic
xlCalc = Application.Calculation
Application.Calculation = xlCalculationAutomatic
Sheet1.Range("C2:H4").Formula = "=BDP($B2,C$1)"
BloombergUI.RefreshAllStaticData
Application.OnTime Now + TimeValue("00:00:02"), "HardCode" End Sub Sub HardCode()
Sheet1.Range("C2:H4").Value = Sheet1.Range("C2:H4").Value
Application.Calculation = xlCalc End Sub

I think you're looking for something like one of these:
Excel Bloomberg API callback in macro
VBA to refresh Bloomberg data not running in proper order
If you need to use the values returned by Bloomberg in VBA, you need to wait for all the values to return first.

Related

ThisWorkbook.RefreshAll doesn't trigger for some people

I have an Excel workbook which refreshes data on startup. After the refresh is finished the rows which don't contain data are being hidden. The refresh is started when a worksheet is activated. I've added the same code in a Before_Print function to ensure the data has had enough time to load. The data is coming from a SQL Server database. But these problems have also existed when I was using Access as a backend.
For 9 out of 10 people the code I have written works. For the people from who it doens't work there happens nothing on startup. The entire 'ThisWorkbook' doesn't seem to be working for them. I think it's due to some difference in settings or something. What could be the problem here? These people have macro's enabled
Here the code which triggers when the worksheet is activated:
Private Sub Worksheet_Activate()
ThisWorkbook.RefreshAll
Application.CalculateUntilAsyncQueriesDone
Dim r As Range, c As Range
Application.ScreenUpdating = False
Set r = Range("H99:H142")
For Each c In r
If Len(c) = 0 Then
c.EntireRow.Hidden = True
Else
c.EntireRow.Hidden = False
End If
Next c
Application.ScreenUpdating = True
End Sub
The code that tirggers this on startup:
Private Sub RefreshSheet()
Worksheets("-").Activate
Worksheets("DPM").Activate
End Sub
Sub Workbook_Activate()
Application.OnTime Now + TimeValue("00:00:01"), "ThisWorkbook.RefreshSheet"
End Sub
Thanks in advance,

VBA getting error Active method of Worksheet class failed

I tried to look for answers but am not finding anything that has worked so far. I have some code that works for some people and doesn't work for others (using same version of Excel) when running this code:
Private Sub Workbook_Open()
Application.ScreenUpdating = False
Application.ExecuteExcel4Macro "SHOW.TOOLBAR(""Ribbon"",False)"
Application.DisplayFormulaBar = False
Sheets("Discount").Activate
ActiveSheet.Unprotect Password:="01"
ActiveSheet.Range("G14:O15,O18:O19,D29:I29,D31:I31,D33:I33,D35:I35,D37:I37").ClearContents
ActiveSheet.Shapes("Option Button 31").ControlFormat.Value = xlOn
OptionButton31_Click
Application.ScreenUpdating = True
End Sub
The error shows up at Sheets.("Discount").Activate
the spelling of the worksheet is correct. I also tried
Private Sub Workbook_Open()
ActiveWorkbook.Unprotect Password:="01"
Application.ScreenUpdating = False
Application.ExecuteExcel4Macro "SHOW.TOOLBAR(""Ribbon"",False)"
Application.DisplayFormulaBar = False
ThisWorkbook.Sheets("Discount").Activate
ActiveSheet.Unprotect Password:="01"
ActiveSheet.Range("G14:O15,O18:O19,D29:I29,D31:I31,D33:I33,D35:I35,D37:I37").ClearContents
ActiveSheet.Shapes("Option Button 31").ControlFormat.Value = xlOn
OptionButton31_Click
ActiveWorkbook.Protect Password:="01"
Application.ScreenUpdating = True
And still getting the error. I am having a hard time figuring it out because it works for me every time, but doesn't for other people.
Solution 1:
Instead of Sheets.("Discount").Activate write Sheets("Discount").Activate and it should work. E.g., remove the dot.
Solution 2:
If this does not work, try to make sure that this sheet is visible. E.g. write before the line with the error the following:
Sheets("Discount").Visible = True
In general, in VBA try to avoid ActiveSheet, ActiveWorkbook, ActiveCell -
How to avoid using Select in Excel VBA
As noted by #Mat's Mug, consider using Worksheets("Discount").Visible, when you refer to Worksheets, because the Sheets collection contains Charts as well.
Try using:
Sheets("Discount").Visible
Sheets("Discount").Select
If this doesn't work, let me know and I'll see if there's anything else I can recommend. If you make a note of any error messages, this may help. Also, try running it with screenupdating not turned off as the person above suggested - then you will see if there's a specific action that's making it fall over.

Run VBA function with a button

I defined a VBA function that returns a filesize. Now I want to invoke it with a button that's calling a different macro. My expectation is that after running the macro it'll invoke my function at the very end. My problem is that when I put a formula into a cell it will return a current filesize only the moment I enter the formula. When I edit the file, save it and reopen, the =wbksize() will still display the filesize from before my edits.
So the purpose of this macro run by a button is to refresh the filesize value. Here's my attempt to do it.
function:
Function wbksize()
myWbk = Application.ThisWorkbook.FullName
wbksize = FileLen(myWbk)
End Function
refresh:
Worksheets("Sheet2").Range("K1").Calculate
The above doesn't seem to work :/
Function works fine, but refreshing should call function.
Function wbksize() As String
myWbk = Application.ThisWorkbook.FullName
wbksize = Str(FileLen(myWbk))
End Function
Sub Refresh()
Worksheets("Sheet2").Range("K1") = wbksize
End Sub
This may or may not help you in your situation....LINK
I have never needed to use this on excel but it maybe what your looking for, you can set custom functions as 'VOLATILE' which forces excel to run them whenever ANYTHING get calculated, again i have never needed to use this so i cannot comment on any drawbacks or anything but it looks like it may work in your case.
I've tested these, and they both work fine. It depends on what you want your trigger to be: Changing the worksheet, or performing a Calculate on the worksheet.
Put either of these in your Worksheet. The first will trigger on Calculate, the second on Change.
Private Sub Worksheet_Calculate()
Dim lFileLength As Long
Application.EnableEvents = False 'to prevent endless loop
lFileLength = FileLen("\\MyFile\Path\AndName.XLS.XLS")
ThisWorkbook.Sheets("Sheet1").Range("A1").Value = CStr(lFileLength)
MsgBox "You changed THE CELL!"
Application.EnableEvents = True
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim lFileLength As Long
Application.EnableEvents = False 'to prevent endless loop
lFileLength = FileLen("\\MyFile\Path\AndName.XLS")
ThisWorkbook.Sheets("Sheet1").Range("B1").Value = CStr(lFileLength)
MsgBox "You changed THE CELL!"
Application.EnableEvents = True
End Sub

VBA - Wait for formulae dependant on PivotTable to update before proceeding

As per the title, looking to wait for formulae dependent on PivotTable to update before proceeding.
The set up (in Excel 2010 workbook):
PivotTable constructed with
One xlDataField (unchanging),
Several xlRowFields (unchanging), and
One xlPageField (for changing via VBA, to increase speed of data retrieval)
Two-dimensional range (columns x rows) populated using formulae (including GetPivotData derived from the above PivotTable)
Processing (via VBA):
The above mentioned xlPageField is changed (expecting the values in
the above mentioned range are updated)
Two-dimensional range “read” into a Variant for further processing via VBA
The process is falling over between the steps 3 and 4. The range values are not updated before being read into a Variant. It could be the PivotTable is not updating, the formulae dependant on the PivotTable are not updating, or both.
Solutions attempted to date (from various StackOverlow threads or external websites):
PivotTables("*name*").PivotCache.BackgroundQ‌​uery = False (Getting Excel VBA to wait for external workbook links to refresh before continuing). Results in Run-time error '1004'.
Activeworkbook.RefreshAll
DoEvents (Wait until ActiveWorkbook.RefreshAll finishes - VBA) No impact.
And a mix of:
ThisWorkbook.RefreshAll
DoEvents
PivotTables("*name*").RefreshTable
DoEvents
Application.Calculate
DoEvents
Do Until Application.CalculationState = xlDone
DoEvents
Loop (Wait until Application.Calculate has finished)
Any guidance would be appreciated.
Requested code (truncated)
Dim AllocationRange As Variant
Dim SwitchHistory As PivotTable
Sub Main()
InitialisePublicVariables
'For each member
GetMemberSwitchHistory
Dim Allocations As New Dictionary: Set Allocations = GetDictionary("Allocations")
// further processes
'Next member
End Sub
Private Sub InitialisePublicVariables()
Set SwitchHistory = Sheets("All Switches (clean)").PivotTables("SwitchHistory")
AllocationRange = Range("AllocationRange")
End Sub
Private Sub GetMemberSwitchHistory()
Dim MemberAccountNumber As String: MemberAccountNumber = Range("MemberAccountNumber").Value
SwitchHistory.PivotFields("Member Account Number").CurrentPage = MemberAccountNumber
SwitchHistory.RefreshTable
DoEvents
End Sub
Regards
Shannon
Can you refactor your code so that you can use the PivotTableUpdate event on the Worksheet to operate on the Pivot after it is updated?
Private Sub Worksheet_PivotTableUpdate(ByVal Target As PivotTable)
Debug.Print "Pivot table updated - do stuff..."
End Sub
You can also use the PivtoTableChangeSync event (this may be more appropriate as it discerns changes more).
Private Sub Worksheet_PivotTableChangeSync(ByVal Target As PivotTable)
Debug.Print "Pivot table change sync..."
End Sub
More information on this event can be found here:- https://msdn.microsoft.com/EN-US/library/office/ff838251.aspx

VBA un-protect sheet, run sub, then re-protect sheet?

Here is my issue, I have subs that work when I tested them with the sheet unlocked, but when I locked the sheet to protect certain cells from being selected or deleted/altered, the subs error out. So I need to add a part to my sub that unlocks, runs the main code, then re-locks the sheet.
I am looking for something like this
Sub Example ()
Dim sample as range
set sample as range("A3:Z100")
Application.ScreenUpdating = false
UN-PROTECT CODE
'Existing sub code here
RE-PROTECT CODE
Application.ScreenUpdating = True
End Sub
I am however unaware on what the code to achieve this should look like. I have tried researching and all I found was incomplete code that based on the comments, didn't work all the time. I did find a suggestion to upon error, have an error handler re-protect the sheet, but not sure how to write this either. Any suggestions?
Oh, and the people who will be using this sheet will not have access to the sheet password. I plan to have the module its self password protected and the subs attached to buttons. So placing the Sheet unlock password in the sub would be ok if it is needed.
Posting my original comment as an answer.
If you use the macro recorder and then protect & unprotect sheets, it will show you the code.
EDIT: Added the below.
If you attempt to unprotect a sheet that is not protected you will get an error. I use this function to test if a sheet is protected, store the result in a Boolean variable and then test the variable to see if a) the sheet must be unprotected before writing to it and b) to see if the sheet should be protected at the end of the proc.
Public Function SheetIsProtected(sheetToCheck As Worksheet) As Boolean
SheetIsProtected = sheetToCheck.ProtectContents
End Function
Do you need it to remove passwords? This worked for me
Sub macroProtect1()
Sheet1.Unprotect Password:="abc"
'Enable error-handling routine for any run-time error
On Error GoTo ErrHandler
'this code will run irrespective of an error or Error Handler
Sheet1.Cells(1, 1) = UCase("hello")
'this code will give a run-time error, because of division by zero. The worksheet will remain unprotected in the absence of an Error Handler.
Sheet1.Cells(2, 1) = 5 / 0
'this code will not run, because on encountering the above error, you go directly to the Error Handler
Sheet1.Cells(3, 1) = Application.Max(24, 112, 66, 4)
Sheet1.Protect Password:="abc"
ErrHandler:
Sheet1.Protect Password:="abc"
End Sub
had a similar problem and found this code on the web:
Sub protectAll()
Dim myCount
Dim i
myCount = Application.Sheets.Count
Sheets(1).Select
For i = 1 To myCount
ActiveSheet.Protect "password", true, true
If i = myCount Then
End
End If
ActiveSheet.Next.Select
Next i
End Sub
Sub Unprotect1()
Dim myCount
Dim i
myCount = Application.Sheets.Count
Sheets(1).Select
For i = 1 To myCount
ActiveSheet.Unprotect "password"
If i = myCount Then
End
End If
ActiveSheet.Next.Select
Next i
End Sub
Note that it is designed to protect / unprotect all sheets in the workbook, and works fine. Apologies, and respect, to the original author, I can't remember where I found it (But I don't claim it)...
The most common object that is Protected is the Worksheet Object This make it possible to preserve formulas by Locking the cells that contain them.
Sub Demo()
Dim sh As Worksheet
Set sh = ActiveSheet
sh.Unprotect
' DO YOUR THING
sh.Protect
End Sub
Here's my very simple technique for situations that don't require a password (which are most situations that I run into):
Dim IsProtected As Boolean
IsProtected = SomeWkSh.ProtectContents: If IsProtected Then SomeWkSh.Unprotect
'Do stuff on unprotected sheet...
If IsProtected Then SomeWkSh.Protect
You can, of course, simplify the syntax a bit by using a With SomeWkSh statement but if the "Do stuff..." part refers to properties for methods of a larger, spanning With statement object, then doing so will break that functionality.
Note also that the Protect method's Contents parameter defaults to True, so you don't have to explicitly specify that, although you can for clarity.