如何將Excel中的一行拆分為多行以進行資料庫管理

如何將Excel中的一行拆分為多行以進行資料庫管理

我有一組數據,目前有 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 表。

相關內容