我有从另一个系统导出的excel表。我需要将其上传到数据库中,并且正在寻找一种规范化的方法。
目前的结构:
customerid date1 date2 date3 ... date85
1 1/1 1/4 2/4
2 3/1
3 4/1 4/12
需要转换为:
customerid date
1 1/1
1 1/4
1 2/4
2 3/1
3 4/1
3 4/12
我在Mac上并且拥有2016年的优秀成绩。我没有像电源枢轴这样的插件。
答案 0 :(得分:1)
您可以使用数据透视表向导(这不是附加组件,它是内置的Excel功能):
答案 1 :(得分:0)
假设customerid
在A1中,请在第2行的第2行中尝试(我没有!)
=OFFSET(A$2,INT((ROW()-2)/85),)
在另一栏中:
=OFFSET(B$2,INT(ROW()/85),MOD(ROW()-2,85),)
向下复制以适应,选择公式单元格,复制,粘贴特殊...,值顶部,然后过滤以删除另一个'柱。
请注意,如果在一张纸上执行此操作,因为删除行也可能会删除一些源数据。
添加标签。
答案 2 :(得分:0)
这就是我想出的结果,我希望VBA在Mac上没有太大的不同,然后它在PC上,否则这可能不起作用。
代码被公平评论,但可以随意询问是否有问题。
'Helper function to find the last Column
Public Function getLastColumn(strSheet, strColum) As Integer
Dim rng As Range
Set rng = Sheets(strSheet).Cells.Find(What:="*", _
After:=Sheets(strSheet).Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If rng Is Nothing Then
getLastColumn = 1
Else
getLastColumn = rng.Column
End If
End Function
'Helper function to find the lastRow
Public Function getLastRow(strSheet, strColum) As Long
Dim rng As Range: Set rng = Worksheets(strSheet).Range(strColum & "1")
getLastRow = Worksheets(strSheet).Cells(Rows.Count, rng.Column).End(xlUp).row
End Function
Public Sub Normalize_Table()
Dim LastRow As Long: LastRow = getLastRow("Sheet1", "A") ' First Parameter is the Sheet Name,
' Second is the column you want to count
Dim LastColumn As Integer: LastColumn = getLastColumn("Sheet1", "A")
Dim RowCounter As Long: RowCounter = 1 ' Starting Row
Dim RowID As Variant ' RowID, basically this is the repeated Column 1 value
Dim row As Object
Dim col As Object
Dim rng As Range: Set rng = Sheets("Sheet1").Range(Sheets("Sheet1").Cells(1, 1), _
Sheets("Sheet1").Cells(LastRow, LastColumn)) ' Get the range you want to Normalize to another sheet/range
'Iterate the range, go through each row, and each column
'Making a new row for each column value, only update the value
'of the first column when a start a new row
For Each row In rng.Rows
RowID = rng.Cells(row.row, 1)
For Each col In rng.Columns
'Assuming you want to add this to a new sheet, Let's say "Sheet2"
Sheets("Sheet2").Cells(RowCounter, 1) = RowID
If col.Column > 1 Then
Sheets("Sheet2").Cells(RowCounter, 2) = rng(row.row, col.Column)
RowCounter = RowCounter + 1
End If
Next
Next
End Sub
答案 3 :(得分:0)
这是一种VBA方法,即使在大型数据库上也应该非常快速地运行。 请注意,您必须按照该模块中的说明重命名类模块。
另请注意,您可能需要重命名wsSrc和wsRes - 包含源数据的工作表以及您希望结果的位置。
在常规模块的末尾附近还有一个区域,我做了一些基本的格式化。如果需要的话,你当然可以把它调整到漂亮的东西。
Option Explicit
'Rename cCustDTS
Private pID As String
Private pDT As Date
Private pDTs As Collection
Private Sub Class_Initialize()
Set pDTs = New Collection
End Sub
Public Property Get ID() As String
ID = pID
End Property
Public Property Let ID(Value As String)
pID = Value
End Property
Public Property Get DT() As Date
DT = pDT
End Property
Public Property Let DT(Value As Date)
pDT = Value
End Property
Public Property Get DTs() As Collection
Set DTs = pDTs
End Property
Public Function ADDdt(Value As Date)
pDTs.Add Value
End Function
Option Explicit
Sub NormalizeDates()
Dim vSrc As Variant, vRes As Variant
Dim wsSrc As Worksheet, wsRes As Worksheet, rRes As Range
Dim cCD As cCustDTS, colCD As Collection
Dim I As Long, J As Long, LineCount As Long
Dim LastRow As Long, LastCol As Long
Dim V As Variant, W As Variant
'Set Source and Results Worksheets and Ranges
Set wsSrc = Worksheets("sheet1")
Set wsRes = Worksheets("sheet2")
Set rRes = wsRes.Cells(1, 1)
'Get Source Data
With wsSrc
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
vSrc = .Range(.Cells(1, 1), .Cells(LastRow, LastCol))
End With
'Collect and organize the data
Set colCD = New Collection
For I = 2 To UBound(vSrc, 1) 'Skip the first row
Set cCD = New cCustDTS
With cCD
.ID = vSrc(I, 1)
For J = 2 To UBound(vSrc, 2)
If IsDate(vSrc(I, J)) Then
.DT = vSrc(I, J)
.ADDdt .DT
End If
Next J
colCD.Add cCD
LineCount = LineCount + .DTs.Count
End With
Next I
'Organize the data for output
ReDim vRes(0 To LineCount, 1 To 2)
vRes(0, 1) = "Customer ID"
vRes(0, 2) = "Date"
I = 0
For Each V In colCD
For Each W In V.DTs
I = I + 1
vRes(I, 1) = V.ID
vRes(I, 2) = W
Next W
Next V
'Write to the output sheet and format
Set rRes = rRes.Resize(rowsize:=UBound(vRes, 1) + 1, columnsize:=UBound(vRes, 2))
With rRes
.EntireColumn.Clear
.Value = vRes
With .Rows(1)
.Font.Bold = True
.HorizontalAlignment = xlCenter
End With
With .Columns(2)
.NumberFormat = "m/d"
End With
.EntireColumn.AutoFit
.Columns(2).ColumnWidth = .Columns(2).ColumnWidth * 2
End With
End Sub