I have an excel file with 4 sheets. Each sheet contains a pivot table that connects to an Oracle database. I need all pivot tables to update automatically at 4 am. To do this I have a macro. The problem is the macro asks me to select a data source manually. Is there a way the macro select the data source automatically?
When I execute the macro, it shows me this window 4 times:
And then:
I need the macro select the one that is marked (PRODUCCION DWH).
This is the macro:
Sub Actualiza_Reporte()
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
ThisWorkbook.Save ' Guardamos el archivo
ThisWorkbook.Close ' Para cerrar el archivo
Application.Quit ' Para cerrar Excel
End Sub
I need to update the 4 sheets automatically, without asking me to select the data source.
Thanks and regards.
Besides using macros, you could also do it with power query which is included in Excel 2016 and higher by default:
Select Data, then New Query, then Databases, then Oracle and create a connection to Oracle.
Then you only need to set the refreshing intervall like this:
Click Data again, then Connections, then Settings, then Update after X minutes.
If you want control the exact time of the oracle power query update, just configure this macro:
Sub RefreshQuery()
Dim con As WorkbookConnection
Dim Cname As String
For Each con In ActiveWorkbook.Connections
If Left(con.name, 8) = "Query - " Then
Cname = con.name
With ActiveWorkbook.Connections(Cname).OLEDBConnection
.BackgroundQuery = False 'or true, up to you
.Refresh
End With
End If
Next
End Sub
Code found here: https://stackoverflow.com/a/38653892/11971785
Related
I wrote the following sub for a workbook containing 12 pivot tables (PT) in 6 sheets, all pointing to the same external source (another workbook). It works fine, except that if I wish to manually Refresh one pivot, Excel tells me I need to open the source file. If I then open the pivot's source file, the refresh works OK.
I would prefer to have the pivot cache refreshed in the background, like it once was. What am I missing ?
Sub ChangePivotSourceData(src As String)
Dim pt As PivotTable, wks As Worksheet, pc As PivotCache
'update #1 pt in PIVOT AF
Sheet2.PivotTables(1).ChangePivotCache ThisWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=src)
'adjust all others
For Each wks In ThisWorkbook.Worksheets
Debug.Print Now, wks.Name
For Each pt In wks.PivotTables
Debug.Print Now, pt.Name
pt.CacheIndex = Sheet2.PivotTables(1).CacheIndex
pt.RefreshTable
Next pt
Next wks
Debug.Print Now, "ChangePivotSourceData complete"
End Sub
The sub is called like this:
Workbooks.Open fn, False, True
shMenu.Range("c5").Value = fn
Application.Calculation = xlCalculationManual
'change source of ALL pivots
ChangePivotSourceData fn & "!feesIn" 'feesIn is a named range
Took me a few hours but I found a solution.
The problem is that - at first sight - you can't create a connection to an Excel range. You must have a whole sheet, or a table. In my case, the source data starts at B28 and could not be converted into a table. So I manually created the connection pointing to the whole sheet, bringing back of few rows of garbage. I then went the data/properties/definition, and
- I changed the Command type from Default to SQL
- I changed the Command text to a SQL statement like this: select * from [mySheet$b28:bt4000] where ccy is not null (note the required $ at end of sheet name)
Then I managed to get all pivots to point to that connection and finally I wrote a function to allow changing the connection source workbook name:
With ThisWorkbook.PivotCaches(1)
adoConn = Split(.Connection, ";")
adoConn(3) = "Data Source=" & fn
.Connection = Join(adoConn, ";")
.Refresh
'Debug.Print Now, .CommandText 'sql statement
End With
This way the refreshes are fast, and indeed I only need to refresh the connection to have all 12 PT updated.
I have a pivot table in my Sheet1 connected to external sources which is also an excel sheet. All i am trying to do is to get a date and time stamp whenever someone refreshes pivot table.
I get an error Object doesn't support this property or method.
Private Sub Refresh_Click()
Dim PT As PivotTable
Dim WS As Worksheet
For Each WS In ThisWorkbook.Worksheets
For Each PT In WS.PivotTables
PT.RefreshTable
WS.Sheets("Month-to-Date").Range("P5") = TimeValue(Now)
Next PT
Next WS
End Sub
The problem is that WS is a Worksheet and a Worksheet does not support another Worksheet as a property.
Worksheets are properties of Workbooks so
ThisWorkbook.Sheets("Month-to-Date").Range("P5") = TimeValue(Now)
Fixes the problem
There is a fancy built-in event in Excel VBA for this. In the worksheet of the pivot table, select the event PivotTableUpdate (Event Documentation):
As far as probably there would be more than 1 pivot tables on the worksheet, it is a good idea to check which one is the refreshed one, using its name:
Private Sub Worksheet_PivotTableUpdate(ByVal Target As PivotTable)
Select Case Target.Name
Case "PivotTable2"
Debug.Print "Write date somewhere "; Format(Now, "DD-MM-YYYY")
Case Else
Debug.Print "Not PivotTable2"
End Select
End Sub
"DateStamp" is obtained through Format(Now, "DD-MM-YYYY") and printed to the immediate window (Ctrl+G). Instead of printing there, it is a possible option to write it to a server or to a separate worksheet, getting the last cell of a row like this:
Case "PivotTable2"
Worksheets(2).Cells(lastCell, 1) = Format(Now, "DD-MM-YYYY")
So I have a ms query with a parameter (let's call it "qry_Accounting") and I linked this parameter to a field that is linked to a combobox. This way I can filter my data with the combobox.
I then created a Pivot Table based on the ms query. Normally, I should be able to see the data linked to the item selected in the combobox. I can see that when I change the item selected in the combobox the data changes in "qry_Accounting". I had to create a button, so that when I change the item selected and click on the button it will refresh the pivot table.
My problem is I always have the data from the previous selected item in my pivot table, and only that data. I really don't understand what happens. If I create a new pivot table it will have the correct data, but the behaviour continues when I change the item, I still always keep the previous data and I don't get the new data.
One more thing, If I manually refresh the table it will work. It will work even for multiple pivot tables when I refresh one of them if they are all linked to the same qry_Accounting table.
How can I have the correct data showing without asking the user to manually refresh all the time?
PS : I already changed the property "Number of items to retain per field" to "none".
Following some questions in the comment here is more of my code (When clicking on the button to apply the combobox change) :
Sub Button5_Click()
'If the buffer place (O4) is different from the combo linked cell (F4) then
'assign the value from F4 to O4.
'the table will then be updated because as soon as O4 value changes the
'table is updated (the parameter is taken from O4)
If Sheets("base_pivot").Range("O4").Value <> Sheets("base_pivot").Range("F4").Value Then
Sheets("base_pivot").Range("O4").Value = Sheets("base_pivot").Range("F4").Value
'We wait 5 seconds to avoid access denied problems
Application.Wait (Now + #12:00:05 AM#)
'we ask for a refresh of the pivot tables explicitely
RefreshPivotTables ActiveWorkbook
'we ask for a refresh of all data.
ActiveWorkbook().RefreshAll
End If
End Sub
Sub RefreshPivotTables Code
Sub RefreshPivotTables(wb As Workbook)
Dim ws As Worksheet
Dim pt As PivotTable
Dim pi As PivotItem
Dim pf As PivotField
For Each ws In wb.Worksheets
For Each pt In ws.PivotTables
pt.PivotCache().Refresh
pt.RefreshTable
Next
Next
End Sub
Other than that everything is automatic. The ms query has a parameter, so as soon as the O4 value is updated, the new data is loaded in the table.
So then the only thing to do it to refresh the pivottable.
Since I don't have your query ("Table_edu_ana_invoices_query4"), I tested the code below using an Access DB, and just wrote the Query in the code below (you will see in the code comments).
Let me know if you figure out how to modify the Query section to your needs.
Code
Sub RefreshPivotTables(wb As Workbook)
Dim ws As Worksheet
Dim pt As PivotTable
Dim ptCache As PivotCache
Dim pi As PivotItem
Dim pf As PivotField
Dim con As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim cmdCommand As ADODB.Command
'===== modify here to put your Connection String to your DB =====
con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Radoshits\Desktop\Database11.accdb"
'===== this is the String query I am using >> replace with yours =====
rs.Open "SELECT * FROM Table1", con, adOpenStatic, adLockReadOnly
For Each ws In wb.Worksheets
For Each pt In ws.PivotTables
' update Pivot Cache with Query settings
With pt.PivotCache
Set .Recordset = rs
.Refresh
End With
Next pt
Next ws
Set rs = Nothing
con.Close
Set con = Nothing
End Sub
So in the end I changed the way I do things since I couldn't make it work with MS query. I am now using excel 2016 query and no parameter anymore. The file is bigger, it is slower, but it works (I have over 100k lines in my data). I am using a slicer to filter the table. I am using VBA to update the slicer value to the value in the combo box. This way the pivottable get the correct data all the time. It seems pivot table has a problem when using MS query with a parameter, at least that is what I get from this experience. I'll probably try again in the future with another document.
Thanks for your help Shai Rado, I learned quite a few things a pivot tables and their cache :)
I am very new to VB coding and creating forms in Excel. I have created a very simple form in Excel that now captures user data and saves to a sheet within the Form's workbook. Is there a way to code the command button so that it will save the user data to separate workbook that is saved on a network server?
One way is open other workbook and insert data, for example
Sub ExtractData()
Dim nwb As Workbook
Set nwb = Workbooks.Open("\\Your\Server\Path\YourFile.xlsx")
With nwb.Sheets(1)
.Range("A1").Value = YourForm.Textbox1.Text
.Range("B1").Value = YourForm.Textbox2.Text
.Range("C1").Value = YourForm.Textbox3.Text
End With
nwb.Close True
End Sub
you can also use ADO to use Insert statement with TSQL, to create a connection see this
In Microsoft Excel, when refreshing my data sources (clicking "Refresh All" in the "Connections" block under the "Data" tab), it provides me with a message saying that it can't find the data source for a PivotTable - this is understandable, as I deleted the Sheet that contained the data.
The problem is now finding the specific PivotTable to delete it, as I don't want to receive the message every time I refresh my data sources.
Any ideas?
As a simple, one-off test, I think this will work for you. It displays a message and selects the offending pivot table. Just put this code in a module in the workbook with the pivot tables:
Sub FindDatalessPivot()
Dim ws As Excel.Worksheet
Dim pt As Excel.PivotTable
For Each ws In ThisWorkbook.Worksheets
For Each pt In ws.PivotTables
With pt
On Error Resume Next
.RefreshTable
If Err.Number <> 0 Then
ws.Activate
.DataBodyRange.Select
MsgBox .Name & " in " & ws.Name & " is disconnected."
End If
On Error GoTo 0
End With
Next pt
Next ws
End Sub
Of course, you could do this by hand as well, by refreshing each pivot table individually.
I also note, that at least in Excel 2010, when I Refresh All a dialog pops up telling me which pivot table isn't connecting.