问题
I have a Pivot Table with more than 11,000 rows of data and 53 columns. I need a piece of code that very efficiently fetches data from a particular cell in the Pivot Table.
This is what the Pivot Table looks like:
I need to be able to fetch data from particular cells using the three (3) columns to the left as the conditions from picking the correct row and offset to the correct column by using the week numbers 1-50 at the top.
Here's a snippet of my current code (which works, but is probably highly inefficient since I need to this query about 48 times right now.
Dim oWB As Workbook: Set oWB = Workbooks.Open(tWB.Path & "\Telledata egeneide YTD.xlsx", ReadOnly:=True)
Dim oWS As Worksheet: Set oWS = oWB.Sheets("Telledata")
Dim pivotdata As Integer
Dim storeNo As Integer = 1101 'Example only - this can be anything between 1101 and 1199
Dim storeLoc As String = "0002" 'Example only - this value can be anything between 0001 and 0003
Dim materialGroup As Integer = 1120 'Example only - this can be anything between 1110 and 1899
Dim week as Integer = 11 'Example only - this can be anything between 1 and 50
pivotdata = Application.WorksheetFunction.CountIfs(oWS.Range("A:A"), storeNo, _
oWS.Range("B:B"), storeLoc, _
oWS.Range("C:C"), materialGroup, _
oWS.Range("C:C").Offset(0, week), ">4")
I'm looking for values that are higher than 4. As mentioned, the query at the end needs to be run up to 48 times as it currently stands, as the variables in the code snippet changes.
Example query:
storeNo: 1101
storeLoc: 0001
materialGroup: 1141, 1142, 1143, 1410, 1420, 1451, 1220, 1260, 1270, 1710, 1720, 1730
week: 11, 12
storeNo: 1101
storeLoc: 0002
materialGroup: 1141, 1142, 1143, 1410, 1420, 1451, 1220, 1260, 1270, 1710, 1720, 1730
week: 11, 12
As you can see, all the queries have to be run twice (for each storeLoc), plus I have to check two WEEK columns (the chosen week and the week after).
I've been thinking about a For / For Each loop, but not sure how to go about that...
回答1:
Here's one approach using a dictionary lookup based on the unique combinations of the 3 lookup columns:
(untested)
Sub Tester()
Dim pt As PivotTable, rngRows As Range, rngData As Range
Dim dict As Object, arrRows, arrData, r As Long, k
Set pt = ActiveSheet.PivotTables(1)
'https://peltiertech.com/referencing-pivot-table-ranges-in-vba/
Set rngRows = pt.RowRange 'get the rows range (includes headers)
Set rngRows = rngRows.Offset(1, 0).Resize(rngRows.Rows.Count - 1) 'exclude headers
arrRows = rngRows.Value '... get as 2D array
'create lookup based on the 3 columns
Set dict = CreateObject("scripting.dictionary")
For r = 1 To UBound(arrRows, 1)
k = Key(arrRows(r, 1), arrRows(r, 2), arrRows(r, 3))
dict(k) = r 'link the key to the row number
Next r
Set rngData = pt.DataBodyRange 'the data from the table
arrData = rngData.Value '... as 2D array
'now you can use the lookup to quickly locate the data you want
k = Key(storeNo, storeLoc, materialGroup)
If dict.exists(k) Then
weekVal = arrData(dict(k), WeekNum)
If weekNum < UBound(arrData, 2) Then
nextWeekVal = arrData(dict(k), WeekNum + 1)
End If
Else
'no match found
End If
End Sub
'create key by concatenating the values with "|"
Function Key(v1, v2, v3)
Key = Join(Array(v1, v2, v3), "|")
End Function
回答2:
Formula Solution
You can use INDEX & MATCH here to extract the value that corresponds to the row that fits your storeNo, storeLoc, materialGroup and the column that matches the week input.
=INDEX($A$1:$F$4,MATCH(1,($A$1:$A$4=H2)*($B$1:$B$4=I2)*($C$1:$C$4=J2),0),MATCH(K2,$A$1:$F$1))
Table Reference
Assuming a table (or pivot table) structure like below...
And a input table with target criteria like so...
Depending on your version of excel you may need to confirm this formula as array. To do that, enter the formula and confirm with CTRL + SHIFT + ENTER
来源:https://stackoverflow.com/questions/65352434/excel-vba-get-data-from-pivot-table-using-3-row-elements-and-1-column-element