PivotCache Refresh - Cell formula return #Value - vba

I have a pivot table created from external data source(access) that contain number of records for each hour on a weekly basis for an average period of 3 months. Just beside this pivot table, I've created a column that calculates the average number record for each hour for a day. (A week here is just 5 days - sat & sun don't count).
To achieve the above, I have created a UDF that counts the number of weeks from the pivot data field (Week_Ending). To ensure the code don't count ghost or non-existent weeks, I have used the pivotcache refresh in the UDF. This works perfectly, except it now gives #value (A value used in the formula is the wrong data type) in the cells where I expect the daily average. I have found no issue with the cell formula and works if a single week is selected from the field "Week_Ending" instead of ALL.
I have attached the code and cell function and an image of the issue.
Cells formula in Cell E6 and it is similar upto cell E29 (Hourly cell reference is incremented by 1 for each cell)
=IF($E$4=1,GETPIVOTDATA("CountOfCase_Id",$A$4,"HOURLY",A6)/5,GETPIVOTDATA("CountOfCase_Id",$A$4,"HOURLY",A6)/($E$4*5))
Vba UDF function
Option Explicit
Function WeekCount(InputVal As Variant) As Integer
Dim book1 As String, PivotName As String
book1 = ThisWorkbook.Name
With Workbooks(book1).ActiveSheet
If InputVal = "(All)" Then
PivotName = .PivotTables(1).Name
.PivotTables(PivotName).PivotCache.MissingItemsLimit = xlMissingItemsNone
.PivotTables(PivotName).PivotCache.Refresh
WeekCount = .PivotTables(PivotName).PivotFields("WEEK_ENDING").PivotItems.Count
Else
WeekCount = 1
End If
End With
End Function
I appreciate any help. Excel version is 2003.

The problem turned out to be with
.PivotTables(PivotName).PivotCache.Refresh
in the UDF and not fixed with Application.Volatile. However #GSerg’s solution without p.update seems to have worked.

Related

return number of unique dates on another sheet in the same workbook

I have a project for work where I am trying to calculate the total number of days an employee worked, with data from one sheet feeding the number calculated on the same sheet, or another sheet in the same workbook.
There are several rows of data for each work day, and so I am looking to calculate the total number of unique dates for each employee separately. If the data is isolated to one employee then I can use:
=SUM(IF(FREQUENCY(B:B,B:B)>0,1))
to calculate the number of work days. I have tried using several additional formulas to get the value I'm looking for, including:
=SUMPRODUCT((TEXT('Data'!$A$1:$A$100, "yyyymm")="201804")*('Data'!B$1:$B$100="John Doe"))
AND
=SUMIFS(IF(FREQUENCY('Sono Detail'!$B:$B,'Sono Detail'!$B:$B)>0,1),'Sono Detail'!$E:$E,'(Test) Sono Report Card 1.0'!$B$3)
Neither of these worked.
This isn't a code solution (yet), but I'm posting this answer to illustrate the data you can derive from a pivot table based on the sample you provided.
In the first arrangement of fields, you can see that the pivot shows how many procedures were performed on each day for each employee. This includes an overall total number of procedures for each employee for the time period. So "Employee 1" performed 14 procedures on 1-March, and so on.
If I change the Values field of the pivot, I can show the total time (in DAYS) that each employee spent performing procedures. So in the table below, Employee 1 worked 0.15833 Days on 1-March. This translates to 288 minutes (or 3.8 hours).
VBA code to traverse the pivot table would then identify each employee and how many days they worked and can access other summative data as well.
If you can use VBA macros, then try this:
in cell L3 type:
=WorkingDaysCount(B:B,C:C,K3)
Do similarly for the other employees in L4, L5, and L6.
Then use this code below in a new code module
Option Explicit
Public Function WorkingDaysCount(ByRef Dates As Range, ByRef EmployeeRange As Range, ByVal Employee As String) As Integer
Dim ct As Integer 'counter
Dim i As Long
'for looping
Dim EmployeeDates() As Date 'array to track which dates are already counted
ReDim EmployeeDates(0) 'create initial
'loop through all the cells
For i = 1 To Dates.Count
If (EmployeeRange(i) = Employee) Then 'if the employee is equal to the employee in that range
If (Not (IsInArray(Dates(i), EmployeeDates))) Then 'if the date hasn't already been counted
EmployeeDates(UBound(EmployeeDates)) = Dates(i) 'add the date
ReDim Preserve EmployeeDates(UBound(EmployeeDates) + 1) 'add another element to the array for the next one
End If
End If
Next i
WorkingDaysCount = UBound(EmployeeDates) 'since ubound is 0-based this is the total count of dates
End Function
Private Function IsInArray(valToBeFound As Variant, arr As Variant) As Boolean
'DEVELOPER: Ryan Wells (wellsr.com)
'DESCRIPTION: Function to check if a value is in an array of values
'INPUT: Pass the function a value to search for and an array of values of any data type.
'OUTPUT: True if is in array, false otherwise
Dim element As Variant
On Error GoTo IsInArrayError: 'array is empty
For Each element In arr
If element = valToBeFound Then
IsInArray = True
Exit Function
End If
Next element
Exit Function
IsInArrayError:
On Error GoTo 0
IsInArray = False
End Function

For Next loop with two statements - Copy & Paste

I have a workbook with 2 worksheets, the 1st having a large range of data and formulas and the 2nd containing two empty tables to be populated with specific date from sheet1. Sheet1 has a column of dates Range("DK7:DK39") that range from 5/1/1986 to 5/1/2018. Any time the first date is changed in this column ("DK7"), all of the other dates in the following years will auto-update to the same day in the given year. With these changes, two separate columns will be repopulated with new data that is determined based on date-specific data.
I am trying to run a code that will loop through a range of days for which I need data (5/1 through 8/28), changing the value of cell("DK7") to each date in that range. However, I need the loop to also copy and paste data from the two data columns ("DS7:DS38") & ("DT7:DT38") into the two tables on sheet2 which have the years 1986-2017 as the y-axis column and 5/1 through 8/28 as the x-axis row. I have figured out how to loop the date through the Cell("DK7") but can't figure out the copy & pasting into the 2nd worksheet in respective year / date columns. Any help greatly appreciated, thanks.
Private Sub CommandButton1_Click()
Dim i As Date
For i = ("5/1/1986") To ("8/28/1986")
Range("DK7").Value = i
Worksheets(1).Range("DS7:DS38").Copy
Worksheets(2).Range("D4:E36").PasteSpecial
Next i
End Sub
This is a good way to loop through the dates:
Public Sub TestMe()
Dim i As Date
For i = DateSerial(1986, 5, 1) To DateSerial(1986, 8, 28)
Debug.Print i
Next i
End Sub
Make sure you are using DateSerial() function as there is a big difference between date formats around the world.

VBA Function. Running Cumulative Costs across multiple sheets

Long time, first time.
I am creating a sheet for workover rigs in Oil and Gas field work. Each sheet is identical in structure but represents a different day of work. I have buttons that add and subtract sheets as new days are required, which complicates my main problem:
I need to create a function that calculates the cumulative cost of various categories up to that sheet in the workbook. I need a way to reference the cell adjacent to the cell containing the function (containing the current day's cost), as well as the previous sheet's cumulative cost (or each previous sheet's daily cost, in the same cell one sheet back) to create a new cumulative value. I want each sheet's cumulative to be cumulative up to that day.
A subroutine would be much more conducive to this, but I do not want someone to have to click a button to generate a cumulative in these cells. It needs to automatically calculate as information is added.
What I have so far is below. The sheets are named by the numbered day on the job (1,2,3,4 etc) and Cell AD7 in each sheet contains the value of the current day on the job as well. Basically what I need is a way to extract and use the address of the input cell "daily".
Function Cat_Cum(daily)
Dim day, i As Integer
day = Cells(7, 30)
For i = 1 To day
If i = 1 Then
Cat_Cum = Sheets(i).Cells(daily.Address)
Else
Cat_Cum = Sheets(i).Cells(daily.Address) + Cat_Cum
End If
Next i
End Function
Recap worksheet structure:
2 columns: daily cost, cumulative cost.
Each sheet is identical in structure.
Cumulative should be the total of each previous sheet's daily value in that same cell.
Thanks for the help!
IIUC you want your UDF to be like this:
Public Function Cat_Cum(daily As Range)
Cat_Cum = daily.Value2
If Application.caller.Parent.Name = "1" Then Exit Function
Cat_Cum = Cat_Cum + _
Worksheets(CStr(Application.caller.Parent.Name - 1)).Range(Application.caller.Address).Value2
End Function
so in each worksheet named "1", "2", "3" etc.., in the cumulative column you type, =Cat_Cum(A2) in row 2 and fill down. Replace the column of the daily stuff in place of A if it is another column.

Translating results by day to results by week with excel vba

In my excel sheet I have an varying number of dates in column A with associated totals for each date in column B. The dates are somewhat random but I want to find the sum of the associated totals per week. I'm new to vba and I'm having a bit of trouble figuring out how to calculate the totals per week.
The psudo code for what I'm thinking is:
buttonClicked()
Dim sum As Integer, tempDate As Date, current As Date, i As Integer, j As Integer, match As Boolean
sum = 0
tempDate = Range("A1").Value
current = tempDate
For i = 1 To Rows.Count
for j = 0 to 7
tempDate = addDate(d, i, tempDate)
If cell(i,1).Value = tempDate Then sum = sum + cell(i, 2).Value
match = true
Break
End If
Next j
If match = true Then tempDate = current
Else
`next open space in column D is current
current = tempDate
`next open space in column E is sum
sum = 0
Next i
end
Please let me know if there's any better way to solve this problem other than iterating through the entire list and counting 7 days ahead. I should note that A1 is already assumed to be a sunday and I'm not sure how the commented out lines should be implemented. I would be very grateful for any advice at all.
In other column assign the corresponding Year.WeekNumber to each row using the following formula:
=CONCATENATE(YEAR(A1),".",TEXT(WEEKNUM(A1),"00"))
The totals per Year.Week can be obtained using a SUMIF formula or via a PivotTable. The PivotTable can be auto resize if you use a Dynamic Range as DataSource
If you are looking for a series of 7 row sums from column B, then this formula using native worksheet functions should do.
=SUM(INDEX(B:B, (ROW(1:1)-1)*7+1):INDEX(B:B, (ROW(1:1)-1)*7+7))
Fill down to catch successive week periods.
      
If you can supply a starting date (e.g. =MIN(A:A)) and add 7 to it in successive rows, then the weekly starting date could be a reference point for a SUMIFS function. In E9 as,
=SUMIFS(B:B,A:A, ">="&D9,A:A, "<"&D9+7)
Fill down as necessary.
If a VBA solution is necessary, that logic can be brought into a VBA sub or function.

VBA Excel - Summing a range of cells based on result in a different range of cells

I am attempting create a forecasting function in excel using based on a set of preregistered historical data. I am new to VBA and I am unable to make this function.
I have three Ranges:
Range 1 lists every day in a year. All cells are formatted in the form of "date".
Range 2 on a different sheet named "C" also lists every day in a year. All cells are formatted in the form of "date".
Range 3 on sheet "C" contains the dollar value actualized in the specific date of the year mentioned in Range 2.
Requirement:
The function should take 3 different variables which are the three different ranges. The Function should first "LOOKUP" the month and year of the selected cell and match it with the month of and (year -1) of the cells in Range two.
Accordingly, The cells in Range 3 on the same row in which the "LOOKUP" matches with Range 2 should sum up and then divide by the count of cells counted.
So far I have been able to create a function named MNAME.
Function MNAME(x As Variant) As String
Dim CurrentMonth As Date
CurrentMonth = x
MNAME = MonthName(Month(CurrentMonth), True)
End Function
But I am failing to nest the lookups and sum up the values.
you dont need VBA.
Read Up on the SUMPRODUCT() function - Here is a good explanation
to summarise your problem you want to find out:
if the year of the cells in Range2 is the same as YEAR(reference_cell)-1
--> IF(YEAR(reference_cell)-1=YEAR(Range2))
if the month of the cells in Range2 is the same as MONTH(reference_cell)
--> IF(MONTH(reference_cell)=MONTH(Range2))
where 1. IS TRUE and 2. IS TRUE, sum corresponding cells in Range3
--> =SUMPRODUCT(--(YEAR(reference_cell)-1=YEAR(Range2))*--(MONTH(reference_cell)=MONTH(Range2))*Range3)