我有一組數據,目前有 39,000 行和 27 列。第一列是 ID 號碼。隨後的列對應於選舉,選舉日期位於第 1 行(單元格B1
- AA1
)。其餘儲存格填入與投票方法相對應的字母(如果沒有投票則為空)。我需要重新排列該表,使之共有三列:ID、日期和投票方法。例如:
目前表:
ID 05/2005 11/2005 03/2006 (etc., for 27 total columns)
2345 P V
3789 A V
4321 V A V
7890 I
我需要它看起來像這樣:
ID Date Voting Method
2345 05/2005 P
2345 11/2005 V
3789 11/2005 A
3789 03/2006 V
4321 05/2005 V
4321 11/2005 A
4321 03/2006 V
7890 11/2005 I
我認為這將需要 VBA 腳本,我嘗試將在網路上找到的腳本片段拼湊在一起(因為我從未學過 VBA),但我似乎無法讓它正常工作。也許Excel中已經存在這個函數?
這是我迄今為止正在使用的腳本:
Sub NewLayout()
For i = 2 To Cells.Find("*", [A1], , , xlByRows, xlPrevious).Row
For j = 0 To 26
If Cells(i, 3 + j) <> vbNullString Then
intCount = intCount + 1
Cells(i, 1).Copy Destination:=Cells(intCount, 10)
Cells(i, 2).Copy Destination:=Cells(intCount, 11)
[I think this one is wrong. It needs to copy the column name,
not the cell value, if there is a cell value.]
Cells(i, 3 + j).Copy Destination:=Cells(intCount, 12)
End If
Next j
Next i
End Sub
如果有人有任何建議,我將不勝感激!
答案1
使用 VBA,假設資料位於 Sheet1 中,從 A1 開始,且 Sheet2 存在:
Sub normalize()
Dim wks1 As Worksheet, wks2 As Worksheet
Dim iColCount As Integer, iRowCount As Integer
Dim i As Integer, j As Integer, k As Integer
Set wks1 = ActiveWorkbook.Sheets("Sheet1")
Set wks2 = ActiveWorkbook.Sheets("Sheet2")
iColCount = Application.WorksheetFunction.CountA(wks1.Range("1:1"))
iRowCount = Application.WorksheetFunction.CountA(wks1.Range("A:A"))
k = 1
For i = 2 To iRowCount
For j = 2 To iColCount
If wks1.Cells(i, j) <> vbNullString Then
wks1.Cells(i, 1).Copy Destination:=wks2.Cells(k, 1)
wks1.Cells(1, j).Copy Destination:=wks2.Cells(k, 2)
wks1.Cells(i, j).Copy Destination:=wks2.Cells(k, 3)
k = k + 1
End If
Next j
Next i
End Sub
Sheet2 中的結果:
2345 5/2005 P
2345 11/2005 V
3789 11/2005 A
3789 3/2006 V
4321 5/2005 V
4321 11/2005 A
4321 3/2006 V
7890 11/2005 I
答案2
為了完整起見,我現在展示我是如何做到這一點的沒有求助於VBA。我必須警告,下面的程式碼很複雜,很難有效地擴展。
讓我們假設以下初始條件:
表1
| A | B | C | D | …
---+----+---------+---------+---------+---
1 | ID | 05/2005 | 11/2005 | 03/2006 |
2 |2345| P | V | |
3 |3789| | A | V | …
4 |4321| V | A | V |
5 |7890| | I | |
… | …
表2
| A | B | C |
---+----+------+---------------+
1 | ID | Date | Voting method |
2 | #1 | #2 | #3 |
該單元格名為#1有以下公式:
=INDIRECT(ADDRESS(FLOOR((ROW(A2)-2)/27 + 2,0),1,,,"Sheet1"))
此公式的作用是將目前儲存格對應到 Sheet1 中的正確儲存格。這是在該函數的幫助下完成的FLOOR
。每當傳遞 27 行時,函數就會增加 1,從而將 Sheet2 中的行與 Sheet1 上的內容正確地映射。
此ADDRESS
函數根據數位輸入和工作表名稱建構對單元格的可用引用,同時該INDIRECT
函數檢索該引用指向的內容。
其餘的其他函數遵循相同的推理:使用輔助函數將當前單元格的座標映射到 Sheet1 上的正確單元格。
對於名為#2:
=INDIRECT(ADDRESS(1,MOD(ROW(A2)-2,27)+2,,,"Sheet1"))
在本例中,MOD
函數在 0 和 26 之間按順序交替,然後轉換為 2 到 28 之間的序列(換句話說,即帶有日期的單元格所在的位置)。
最後,對於名為#3:
=INDIRECT(ADDRESS(FLOOR((ROW(A2)-2)/27 + 2,0),MOD(ROW(A2)-2,27)+2,,,"Sheet1"))
它是之前使用的兩個序列的混合。原因是因為 ID 的內容有所不同(因此,來自儲存格的部分#1被呼叫)和日期(這是單元格中的部分#2進入)。
將這些函數輸入到正確的儲存格後,只需向下拖動,結果就應該很明顯,但有一個小問題:空票也會彈出。
不過,您可以過濾這些結果。選擇標題(在本例中A
為 Sheet2 上的行),然後前往「資料」>「篩選器」>「自動篩選器」(或您正在使用的 Excel 版本中的等效項)。點擊投票方法列上的下拉式選單並個性化排序以排除由零組成的結果。
答案3
我會為此使用 Power Query 插件。它不需要任何程式碼或複雜的功能。從頭開始,完成這項任務可能需要不到 5 分鐘的時間。
您可以從現有的 Excel 表格啟動查詢。然後,我將使用 Unpivot 命令根據您的需求轉換資料。
http://office.microsoft.com/en-au/excel-help/unpivot-columns-HA104053356.aspx
他們實作 Unpivot 的優點在於,它將接受新增的任何其他欄位(新日期)並處理它們,而無需對查詢定義進行任何更改。
我將根據需要重命名列並將結果傳遞到 Excel 表。