Pivot, dynamic data source - excel

I have a pivot chart which currently has the data source referring to my table.
Every week I run my code and a new row of data is appended to the bottom of my table.
The pivot does pick up this new data every week as it refers to the table, however, I want to take one less week each week So I have a years worth of data. So I want to include around rows.
Is there anyway to adjust my table to only include the years worth of rows?
Here is my sample data:
+----------+------------------+-----------------+
| week | stack | overflow |
+----------+------------------+-----------------+
| 12/20/17 | -142,335,432.00 | -41,641,109.88 |
| 12/27/17 | -105,428,220.20 | -47,448,990.63 |
| 1/3/18 | -88,520,154.56 | -24,858,774.97 |
| 1/10/18 | -42,033,431.10 | 14,573,779.35 |
| 1/17/18 | -66,101,748.16 | -8,670,735.22 |
| 1/24/18 | -75,871,649.12 | -18,000,154.21 |
| 1/31/18 | -77,027,686.63 | -11,784,198.64 |
| 2/7/18 | -96,720,126.71 | -52,219,288.98 |
| 2/14/18 | -119,118,554.60 | -34,743,350.28 |
| 2/21/18 | -116,529,554.70 | -20,774,072.93 |
| 2/28/18 | -86,871,998.53 | -25,993,521.20 |
| 3/7/18 | -90,351,387.27 | -21,259,727.05 |
| 3/14/18 | -77,968,076.28 | -51,609,924.29 |
| 3/21/18 | -120,805,352.60 | -40,338,490.97 |
| 3/28/18 | -92,247,583.62 | -14,525,648.04 |
| 4/4/18 | -70,821,451.36 | -35,866,864.46 |
| 4/11/18 | -82,694,486.66 | -59,009,729.82 |
| 4/18/18 | -79,034,094.39 | -64,231,312.42 |
| 4/25/18 | -63,415,815.16 | -28,612,265.37 |
| 5/2/18 | -80,372,191.96 | -53,375,611.61 |
| 5/9/18 | -72,619,415.73 | -50,642,469.19 |
| 5/16/18 | -109,654,240.70 | -45,762,784.43 |
| 5/23/18 | -100,407,366.50 | -39,577,966.11 |
| 5/30/18 | -105,794,095.80 | -65,071,199.59 |
| 6/6/18 | -83,630,201.98 | -60,981,969.88 |
| 6/13/18 | -104,644,821.50 | -63,754,760.71 |
| 6/20/18 | -75,229,424.33 | -55,803,681.24 |
| 6/27/18 | -65,237,135.62 | -54,693,832.65 |
| 7/4/18 | -60,025,672.33 | -44,367,918.60 |
| 7/11/18 | -30,172,175.09 | -28,392,163.28 |
| 7/18/18 | -20,687,864.39 | 24,300,285.63 |
| 7/25/18 | -40,476,447.03 | 4,850,881.09 |
| 8/1/18 | -31,211,625.05 | -67,887,918.30 |
| 8/8/18 | -29,736,938.87 | -32,905,703.80 |
| 8/15/18 | -74,934,647.91 | -65,611,884.73 |
| 8/22/18 | -25,220,747.20 | -7,019,746.86 |
| 8/29/18 | -24,608,552.13 | -8,065,633.97 |
| 9/5/18 | -30,119,599.95 | -26,225,633.08 |
| 9/12/18 | -29,836,379.12 | -10,045,560.95 |
| 9/19/18 | -61,281,567.61 | -58,427,878.27 |
| 9/26/18 | -47,418,209.59 | -33,451,409.22 |
| 10/3/18 | -41,321,336.46 | -25,112,764.44 |
| 10/10/18 | -1,241,932.51 | 21,814,274.35 |
| 10/17/18 | -19,791,273.66 | -12,199,449.75 |
| 10/24/18 | -20,501,406.84 | 1,225,387.11 |
| 10/31/18 | -64,116,464.30 | -5,308,628.21 |
| 11/7/18 | -83,657,672.02 | -19,922,992.91 |
| 11/14/18 | -112,704,007.53 | -32,939,535.69 |
| 11/21/18 | -71,969,954.54 | -51,335,709.79 |
| 11/28/18 | -79,668,484.56 | -67,887,918.30 |
| 12/5/18 | -44,134,343.99 | -32,905,703.80 |
| 12/12/18 | -71,700,079.84 | -65,611,884.73 |
| 12/19/18 | -82,238,011.30 | -74,725,620.20 |
| 12/26/18 | -59,385,932.41 | -54,947,256.94 |
| 1/2/19 | -42,717,830.26 | -31,110,199.14 |
| 1/9/19 | -11,029,444.63 | 7,309,440.90 |
+----------+------------------+-----------------+

Changing the source range for the pivot will be tricky as Excel does not allow non-contiguous cells to be used in pivot tables. Instead you can create the pivot by selecting entire column to account for all future entries.
Then the pivot can be manipulated to show a changing range as shown in the code below.
Hope that works for you.
EDIT
The code is updated below to include 50(can be changed) from the bottom.
Sub MovingPivot()
Dim ws As Worksheet
Dim dtTop As Date
Dim i As Integer, n As Long
Const NumWeeks = 50 'Change this to set weeks range
Set ws = ActiveSheet 'Set reference to your worksheet here
'reset the pivot filters
ws.PivotTables("Table1").PivotFields("Date").ClearAllFilters
'remove blank values
ws.PivotTables("Table1").PivotFields("Date").PivotItems("(blank)").Visible = False
'find the date entry in 50 places from bottom.
i = 0
For n = ws.PivotTables("Table1").RowRange.Count To 1 Step -1
If i = NumWeeks Then
dtTop = ws.PivotTables("Table1").RowRange.Cells(n).Value
Exit For
End If
i = i + 1
Next n
ws.PivotTables("Table1").PivotFields("Date").PivotFilters.Add2 Type:=xlAfterOrEqualTo, Value1:=Format(dtTop, "dd-mmm-yyyy")
End Sub

If you want to continue using a Pivot Chart, you can use the time line slicer to include/exclude data. You'll need to adjust the time line or filter manually after the data has refreshed. Or write VBA to set the filters.
A non-vba version that does not require slicers can also be achieved with a standard chart (not a pivot chart). Create named ranges with Offset functions that grab just the rows of data that you are interested in, then plug these range names into the standard chart. When new data is added to the table, the named ranges that feed the standard chart will also be updated.
If you need a step by step, take a look at https://peltiertech.com/Excel/Charts/DynamicLast12.html

Related

Find cell address of value found in range

tl;dr In Google Sheets/Excel, how do I find the address of a cell with a specified value within a specified range where value may be in any row or column?
My best guess is
=CELL("address",LOOKUP("My search value", $search:$range))
but it doesn't work. When it finds a value at all, it returns the rightmost column every time, rather than the column of the cell it found.
I have a sheet of pretty, formatted tables that represent various concepts. Each table consists of
| Title |
+------+------+-------+------+------+-------+------+------+-------+
| Sub | Prop | Name | Sub | Prop | Name | Sub | Prop | Name |
+------+------+-------+------+------+-------+------+------+-------+
| Sub prop | value | Sub prop | value | Sub prop | value |
+------+------+-------+------+------+-------+------+------+-------+
| data | data | data | data | data | data | data | data | data |
| data | data | data | data | data | data | data | data | data |
⋮
I have 8 such tables of variable height arranged in a grid within the sheet 3 tables wide and 3 tables tall except the last column which has only 2 tables--see image. These fill the range C2:AI78.
Now I have a table off to the right consisting in AK2:AO11 of
| Table title | Table title address | ... |
+---------------+-----------------------+-----+
| Table 1 Title | | ... |
| Table 2 Title | | ... |
⋮
| Table 8 Title | | ... |
I want to fill out the Table title address column. (Would it be easier to do this manually for all of 8 values? Absolutely. Did I need to in order to write this question? Yes. But using static values is not the StackOverflow way, now, is it?)
Based on very limited Excel/Google Sheets experience, I believe I need to use CELL() and LOOKUP() for this.
=CELL("address",LOOKUP($AK4, $C$2:$AI$78))
This retrieves the wrong value. For AL4 (looking for value Death Wave), LOOKUP($AK4, $C$2:$AI$78) should retrieve cell C2 but it finds AI2 instead.
| Max Levels |
+------------------+---------------+----+--+----+
| UW | Table Address | | | |
+------------------+---------------+----+--+----+
| Death Wave | $AI$3 | 3 | | 15 |
| Poison Swamp | $AI$30 | | | |
| Smart Missiles | $AI$56 | | | |
| Black Hole | #N/A | 1 | | |
| Inner Land Mines | $AI$3 | | | |
| Chain Lightning | #N/A | | | |
| Golden Tower | $AI$3 | | | |
| Chrono Field | #N/A | 25 | | |
The error messages for the #N/A columns is
Did not find value '<Table Title>' in LOOKUP evaluation.
My expected table is
| Max Levels |
+------------------+---------------+----+--+----+
| UW | Table Address | | | |
+------------------+---------------+----+--+----+
| Death Wave | $C$2 | 3 | | 15 |
| Poison Swamp | $C$28 | | | |
| Smart Missiles | $C$54 | | | |
| Black Hole | $O$2 | 1 | | |
| Inner Land Mines | $O$28 | | | |
| Chain Lightning | $O$54 | | | |
| Golden Tower | $AA$2 | | | |
| Chrono Field | $AA$39 | 25 | | |
try:
=INDEX(ADDRESS(
VLOOKUP(A2:A3, SPLIT(FLATTEN(D2:F4&"​"&ROW(D2:F4)), "​"), 2, ),
VLOOKUP(A2:A3, SPLIT(FLATTEN(D2:F4&"​"&COLUMN(D2:F4)), "​"), 2, ), 4))
or if you want to create jump links:
=INDEX(LAMBDA(x, HYPERLINK("#gid=1273961649&range="&x, x))(ADDRESS(
VLOOKUP(A2:A3, SPLIT(FLATTEN(D2:F4&"​"&ROW(D2:F4)), "​"), 2, ),
VLOOKUP(A2:A3, SPLIT(FLATTEN(D2:F4&"​"&COLUMN(D2:F4)), "​"), 2, ), 4)))
Try this:
=QUERY(
FLATTEN(
ARRAYFORMULA(
IF(
C:AI=$AK4,
ADDRESS(ROW(C:AI), COLUMN(C:AI)),
""
)
)
), "
SELECT
Col1
WHERE
Col1<>''
"
, 0)
Basically, cast all cells in the search range to addresses if they equal the search term. Then flatten that 2D range and filter out non-nulls.

VBA, Pivot formula to include last 52 weeks of data

I have a pivot that gets data from up to 2 years. I select all columns like Sheet!$A:$F.
How can I alter the formula to only include the previous 52 weeks from today?
Sample Data:
+-------------+
| 1-Jan-2019 |
| 2-Jan-2019 |
| 3-Jan-2019 |
| 4-Jan-2019 |
| 7-Jan-2019 |
| 8-Jan-2019 |
| 9-Jan-2019 |
| 10-Jan-2019 |
| 11-Jan-2019 |
| 14-Jan-2019 |
| 15-Jan-2019 |
| 16-Jan-2019 |
| 17-Jan-2019 |
| 18-Jan-2019 |
| 21-Jan-2019 |
| 22-Jan-2019 |
| 23-Jan-2019 |
| 24-Jan-2019 |
| 25-Jan-2019 |
| 28-Jan-2019 |
| 29-Jan-2019 |
| 30-Jan-2019 |
| 31-Jan-2019 |
| 1-Feb-2019 |
| 4-Feb-2019 |
| 5-Feb-2019 |
| 6-Feb-2019 |
| 7-Feb-2019 |
| 8-Feb-2019 |
| 11-Feb-2019 |
| 12-Feb-2019 |
| 13-Feb-2019 |
+-------------+
You can add a date filter to your PivotField.
With the DateSerial function you can subtract from today, e. g. 1 year (or 52 * 7 days or whatever).
With ActiveWorkbook.Worksheets("WSname").PivotTables("PTname").PivotFields("PFname")
.ClearAllFilters
.PivotFilters.Add2 _
Type:=xlDateBetween, _
Value1:=CStr(DateSerial(Year(Date) - 1, Month(Date), Day(Date))), _
Value2:=CStr(Date), _
WholeDayFilter:=True
End With

How to transpose repeating groups in excel?

I have an excel sheet with the following data structure
+-------------+-------------------------------+--+
| title | Dr. | |
| first_name | Adam | |
| last_name | Meyer | |
| email | adam.meyer#my-company.com | |
| phone | +49 (0)931-32187-0 | |
| fax | | |
| room | | |
| position | Direktor | |
| title | | |
| first_name | Judith | |
| last_name | Schmidt | |
| email | judith.schmidt#my-company.com | |
| phone | +49 (0)444-32131-1 | |
| fax | | |
| room | | |
| position | | |
| title | | |
| first_name | Claus | |
| last_name | Niemes | |
| email | claus.niemes#my-company.com | |
| phone | +49 (0)444-32131-2 | |
| fax | | |
| room | | |
| position | Verkäufer | |
| bio | xxxxxxxxxx | |
| title | Dr. | |
| first_name | András | |
| last_name | Cloon | |
| email | andrás.cloon#my-company.de | |
| phone | +49 (0)444-32131-1 | |
+-------------+-------------------------------+--+
Not all 450 Persons have values for all rows. Sometimes is missing the first row with the title for example.
I want to import these data into a mysql database.
I need this result:
I'm not an excel expert that's why I'm happy about every hint how to ease the preparation of the data for the import.
I know how to do the import.
Oh I see what you want now
Sub SortItOUt()
Dim t As Range
Dim r As Range
Set t = Sheets(2).Range("a2") 'I assume a blank second sheet to collect the data
Set r = Sheets(1).Range("a1") 'assume data starts in sheet 1
Do
Dim x As Long
For x = 0 To 7
r.Offset(x, 1).Copy t.Offset(0, x) 'copy and transpose
Next x
Set t = t.Offset(1, 0)
Set r = r.Offset(8, 0)
Loop Until r = ""
End Sub

Calculating frequecy (Min/Max/Average) of order placement in Excel

I need to analyze Weekly order frequencies over last 1 year period to find out what is the min/max/average frequencies of orders for each product.
whether it is new or old,system should calculate the first occurrence of the order in the year as the starting week of the order. Min order frequency is difference between successive ordering weeks. If the first order is in wk 3 and the second order is in wk6, implies the order frequency is 3 weeks (=>6-3). Orders can be at any week in the past 52 weeks. Average order frequency = (52 - First order week) / no of weeks that have orders.
Attaching the excel for better understanding the issue.
Original image
+---------+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+----------------+-------------------------+-----+-----------------------------------+--+
| Product | wk1 | wk2 | wk3 | wk4 | wk5 | wk6 | wk7 | wk8 | wk9 | wk10 | wk11 | wk12 | wk13 | wk14 | wk15 | wk16 | wk17 | wk18 | wk19 | wk20 | wk21 | wk22 | wk23 | wk24 | wk25 | wk26 | wk27 | wk28 | wk29 | wk30 | wk31 | wk32 | wk33 | wk34 | wk35 | wk36 | wk37 | wk38 | wk39 | wk40 | wk41 | wk42 | wk43 | wk44 | wk45 | wk46 | wk47 | wk48 | wk49 | wk50 | wk51 | wk52 | Order start wk | Order frequency (Weeks) | | | |
+---------+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+----------------+-------------------------+-----+-----------------------------------+--+
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Min | Max | Average | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (End wk - Start week)/No of times | |
| SKU 1 | | | | | | | | | y | | y | | y | | y | | y | | y | | y | | y | y | | | y | | y | | y | | y | | | | | | y | | y | | y | | y | | y | | y | | y | | 9 | 1 | 6 | 2.15 | |
| SKU 2 | | | | | | | y | | | | | | y | | | | | | y | | | | | | y | | | | | | y | | | | | | y | | | | | | y | | | | | | y | | | | 1 | 0 | 0 | 7.29 | |
| SKU 3 | | | | | | | | | | | | | | | y | | | | | | | | | | | | | | | | y | | | | | | | | y | | | | | | | | y | | | | | | 15 | 8 | 15 | 9.25 | |
+---------+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+----------------+-------------------------+-----+-----------------------------------+--+
So as mentioned #Barry Houdini solves the problem of finding the longest sequence of zeroes separated by ones elegantly here
You only have to change it slightly to check for repeated blank cells separated by 'y'. The only thing is that you don't want to include cells before the first 'y', and (although this isn't clear) may not want to include blank cells after the last 'y'.
The formula for MIN becomes
=MIN(IF((ROW(A$1:INDEX(A:A,COUNTA(B4:BA4)+1))>1)*(ROW(A$1:INDEX(A:A,COUNTA(B4:BA4)+1))<COUNTA(B4:BA4)+1),FREQUENCY(IF(B4:BA4="",COLUMN(B4:BA4)),IF(B4:BA4="y",COLUMN(B4:BA4)))))+1
and the formula for MAX becomes (the same)
=MAX(IF((ROW(A$1:INDEX(A:A,COUNTA(B4:BA4)+1))>1)*(ROW(A$1:INDEX(A:A,COUNTA(B4:BA4)+1))<COUNTA(B4:BA4)+1),FREQUENCY(IF(B4:BA4="",COLUMN(B4:BA4)),IF(B4:BA4="y",COLUMN(B4:BA4)))))+1
where you need to add 1 to make the results agree with the question because #Barry's formula counts numbers of blanks but OP wants interval between two successive y's. An array of ny+1 elements is generated where ny is the number of y's. This is because the FREQUENCY function returns an array with n+1 elements where n is the number of cut points (bins_array in documentation and because the column numbers of cells containing y are used as cut points so there are ny of them.
These are both array formulas and need to be entered with CtrlShiftEnter
The formula for the average is just
=(COLUMNS(B4:BA4)-MATCH("y",B4:BA4,0))/COUNTA(B4:BA4)

Excel VBA extrapolate values

I have a file that has data stored in it the following way (weekly data example)
+----------+----------+----------+----------+----------+----------+
| | WK1 | WK2 | WK3 | WK4 | WK5 |
+----------+----------+----------+----------+----------+----------+
| DT Begin | 29.12.14 | 05.01.15 | 12.01.15 | 19.01.15 | 26.01.15 |
| DT End | 04.01.15 | 11.01.15 | 18.01.15 | 25.01.15 | 01.02.15 |
| XData | 50 | 10 | 10 | 10 | 50 |
+----------+----------+----------+----------+----------+----------+
My problem ist to aggregate the XData on a monthly basis. For that I want to break the data down for days and then calculate the average.
Edit: I changed the table as it was not clear what I meant. This averages to ((50*4)+(10*21)+(5*50))/31 = 22.90
+------------+-------+
| Date | Value |
+------------+-------+
| 01.01.2015 | 50 |
| 02.01.2015 | 50 |
| 03.01.2015 | 50 |
| 04.01.2015 | 50 |
| 05.01.2015 | 10 |
| 06.01.2015 | 10 |
| 07.01.2015 | 10 |
| 08.01.2015 | 10 |
| 09.01.2015 | 10 |
| 10.01.2015 | 10 |
| 11.01.2015 | 10 |
| 12.01.2015 | 10 |
| 13.01.2015 | 10 |
| 14.01.2015 | 10 |
| 15.01.2015 | 10 |
| 16.01.2015 | 10 |
| 17.01.2015 | 10 |
| 18.01.2015 | 10 |
| 19.01.2015 | 10 |
| 20.01.2015 | 10 |
| 21.01.2015 | 10 |
| 22.01.2015 | 10 |
| 23.01.2015 | 10 |
| 24.01.2015 | 10 |
| 25.01.2015 | 10 |
| 26.01.2015 | 50 |
| 27.01.2015 | 50 |
| 28.01.2015 | 50 |
| 29.01.2015 | 50 |
| 30.01.2015 | 50 |
| 31.01.2015 | 50 |
+------------+-------+
| Average | 22.90 |
+------------+-------+
After having done this calculation I want to summarize the data as follows for the entire year:
+-------+-------+-------+------+------+
| | Jan | Feb | Mar | ... |
+-------+-------+-------+------+------+
| XData | 22.90 | 22.00 | 23.1 | ... |
+-------+-------+-------+------+------+
Being a newbie in Excel VBA, I have extreme trouble doing this.
I know how to get to the value of a cell (Range.Value) but not how to find data in a particular week (as WK1 is there for 2014 as well) Range.Find with a date other than the one in the cell itself does not seem to work.
Whar I am asking for is a way to approach this problem. My particular difficulties are to:
Find the data in the worksheet
split the week values into day values (see table above)
Copy the data or hold it in some sort of data structure
calculate the average (this should be ease then)
fill in the data on a monthly basis
As you can see, I have trouble even getting started - any hints would be greatly appreciated. Maybe I'm thinking of this entirely too complicated? Thank you!

Resources