簡體   English   中英

Excel 如何轉換要用於 pivot 的表:在字段中使用列標題

[英]Excel how to transform a table to be used for pivot: use the column headers in a field

我在 Excel 中有一張表格,填寫如下

PROD         JAN-19     FEB-19    ...     ...

product1      123        098      ...     ...
product2      314        467      ...     ...

我需要使用 pivot 表中的數據,所以我想我應該使用 MMM-YY header 作為年份和月份字段中的數據以下列方式轉換數據模型。

 PROD          Year    Month     Data

 Product1       19      JAN       123
 Product1       19      FEB       098
 ...           ...      ...       ...

在實際表格的屏幕下方以及我想要實現的目標: 屏幕

是否有一種實用的方法可以在上傳表的數據模型上工作,或者作為最后一個選項 VBA?

通過Application.Index()進行數組轉換

這種方法首先將表值分配給一個數組,並最終使用Application.Index() function 的擴展功能將相同的數組轉換為所需的結構,從而維護產品名稱。

我不會假裝這是最有效的方法,但它清楚地證明了引用的 function - c.f 的可能性。 Application.Index function的一些特點

進一步說明:我假設所有月份數據都包括在內,即甚至是空值。

Sub Table2PivotBase()
' Purpose: Transform Table to Pivot base
' Method:  reorganize Datafield array of table using advanced features of Application.Index in [2]d)
' Note:    sheet references use the worksheet's CodeName property here
'~~~~~~~~~~~~ [0] Reference to table (address) ~~~~~~
Const MONTHSCOUNT& = 12, COLUMNOFFSET& = 1    ' number of months, column offset January = 1 (i.e. 2nd col)
With Sheet1
'a) Refer to table using the sheet's CodeName
    Dim rpt As ListObject
    Set rpt = .ListObjects("Table1")
Sheet1.CodeName
' ~~~~~~~~~~~ [1] Get Data ~~~~~~~~~~~~~~~~~~~~~~~~
'b) Assign table values in Sheet1 to 2-dim 1-based array
    Dim arr As Variant, yr&
    arr = .Range(rpt.Range.Address).Value2
'c) Extract current year from 1st month column in header (1+ coloffset 1 => 2nd column)
    yr = Val(Split(arr(1, 1 + COLUMNOFFSET) & "-", "-")(1))
End With

'~~~~~~~~~~~~~~ [2] Reorganize Data ~~~~~~~~~~~~~~~
'd) Redimension array preserving 1st column
    Dim arr2, ItemsCount&
    ItemsCount = UBound(arr) - IIf(rpt.ShowTotals, 1, 0)    ' exclude table totals from items count
    arr2 = Application.Index(arr, Application.Transpose(getRowsArr(ItemsCount, MONTHSCOUNT)), Array(1, 1, 1, 2))

'e) Redefine headers in 1st row
    Dim no&, headers
    headers = Array("Product", "Year", "Month", "Data")
    For no = 1 To 4
        arr2(1, no) = headers(no - 1)               ' headers are zerobased
    Next no
'f) Enter year, month & month data in a loop
    Const START& = 2
    Dim i&, mon&, ii&
    ii = START - 1
    For i = START To UBound(arr2)
            mon = (i - START) Mod MONTHSCOUNT + 1   ' 0 to 11 (omitting 1 caption row) + 1
            If mon = 1 Then ii = ii + 1             ' increment data row of arr1 in January

           'arr2(i, 1) has already been prefilled by section [2]d)
            arr2(i, 2) = yr
            arr2(i, 3) = Application.Text(DateSerial(yr, mon, 1), "mmm")
            arr2(i, 4) = arr(ii, mon + COLUMNOFFSET)
    Next i


'~~~~~~~~~~~~ ~[3] Write back pivot base to any sheet (via CodeName) ~~~~~~~~~~~
With Sheet2
    .Range("A:D") = vbNullString
    .Range("A1").Resize(UBound(arr2), UBound(arr2, 2)) = arr2
End With
End Sub

助手 function getRowsArr()


Function getRowsArr(ByVal ItemsCount, Optional ByVal n& = 12) As Variant()
' Purpose: return 1-dim 0-based array containing n row numbers per item + title row no 1
' Note:    allows restructuring the original array to contain all months data
    Const START& = 2                        ' data rang starts in 2nd row
    Dim tmp(), i&, ii&
    ReDim tmp(0 To (ItemsCount - 1) * n)    ' includes header row number 1 at tmp(0) - zerobound!
'1) fill temporary array
    tmp(0) = 1                              ' title row no equals 1
    For i = START To ItemsCount             ' row no 2 to ...
        For ii = 0 To n - 1                 ' repeat row number n times
            tmp((i - START) * n + ii + 1) = i
        Next ii
    Next i
'2) return Array(1,2,2,2,2,2,2,2,2,2,2,2,2,3,........3,4...,...) as function value
    getRowsArr = tmp
    'Debug.Print Left$(Join(tmp, ","), 65) & "..."
End Function



暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM