将Excel Grid Intersection数据规范化为平面列表

时间:2012-09-28 11:40:02

标签: excel excel-vba vba

我正在尝试获取Excel数据,这些数据使用网格/矩阵映射映射到非规范化的数据,以便我可以将数据输入数据库。

如何将网格中的数据从一个Excel工作表复制到另一个Excel工作表,如下所示。 enter image description here

我正在尝试这样的事情......但正如你所看到的,我离得很远!

Sub NormaliseList(mySelection As Range)
Dim cell As Range
Dim i As Long
i = 1
    For Each cell In mySelection
        If cell <> "" Then
                Sheets(2).Range("A" & i).Value = cell(cell.Row, 1).Value
                Sheets(2).Range("B" & i).Value = cell.Value
                Sheets(2).Range("C" & i).Value = cell(1, cell.Column).Value
                i = i + 1

    Next cell
End Sub

2 个答案:

答案 0 :(得分:1)

供参考。我更新了我的代码.. 只需添加代码,为该功能指定宏快捷方式即可 选择包含交叉点数据的范围(不是行和列数据) 运行宏(注意,工作表2将以标准化形式添加数据)

如果需要多个标题,我想我会合并成一列,然后在处理后执行“text to columns”。

Sub NormaliseList()
' to run - assign macro shortcut to sub - Select Intersection data (not row and column headings and run)
    Dim Rowname, ColumnName, IntValue As String
    Dim x, cntr As Integer
    Dim test As Boolean
    cntr = 0

For x = 1 To Selection.Count
    If Selection(x).Value <> "" Then
        cntr = cntr + 1
        Rowname = ActiveSheet.Cells(Selection.Cells(x).Row, Selection.Column - 1)
        ColumnName = ActiveSheet.Cells(Selection.Row - 1, Selection.Cells(x).Column)
        IntValue = Selection(x).Value
        test = addrecord(Rowname, ColumnName, IntValue, cntr)
     End If
  Next x
   End Sub

 Function addrecord(vA, vB, vC As String, rec As Integer) As Boolean
   'Make sure that you have a worksheet called "Sheet2"
   Sheets("Sheet2").Cells(rec, 1) = vA
   Sheets("Sheet2").Cells(rec, 2) = vB
   Sheets("Sheet2").Cells(rec, 3) = vC
 End Function

答案 1 :(得分:0)

我有两篇帖子,包括可用的代码和可下载的工作簿,在我的博客上用Excel / VBA执行此操作:

http://yoursumbuddy.com/data-normalizer

http://yoursumbuddy.com/data-normalizer-the-sql/

以下是代码:

'Arguments
'List: The range to be normalized.
'RepeatingColsCount: The number of columns, starting with the leftmost,
'   whose headings remain the same.
'NormalizedColHeader: The column header for the rolled-up category.
'DataColHeader: The column header for the normalized data.
'NewWorkbook: Put the sheet with the data in a new workbook?
'
'NOTE: The data must be in a contiguous range and the
'rows that will be repeated must be to the left,
'with the rows to be normalized to the right.

Sub NormalizeList(List As Excel.Range, RepeatingColsCount As Long, _
    NormalizedColHeader As String, DataColHeader As String, _
    Optional NewWorkbook As Boolean = False)

Dim FirstNormalizingCol As Long, NormalizingColsCount As Long
Dim ColsToRepeat As Excel.Range, ColsToNormalize As Excel.Range
Dim NormalizedRowsCount As Long
Dim RepeatingList() As String
Dim NormalizedList() As Variant
Dim ListIndex As Long, i As Long, j As Long
Dim wbSource As Excel.Workbook, wbTarget As Excel.Workbook
Dim wsTarget As Excel.Worksheet

With List
    'If the normalized list won't fit, you must quit.
   If .Rows.Count * (.Columns.Count - RepeatingColsCount) > .Parent.Rows.Count Then
        MsgBox "The normalized list will be too many rows.", _
               vbExclamation + vbOKOnly, "Sorry"
        Exit Sub
    End If

    'You have the range to be normalized and the count of leftmost rows to be repeated.
   'This section uses those arguments to set the two ranges to parse
   'and the two corresponding arrays to fill
   FirstNormalizingCol = RepeatingColsCount + 1
    NormalizingColsCount = .Columns.Count - RepeatingColsCount
    Set ColsToRepeat = .Cells(1).Resize(.Rows.Count, RepeatingColsCount)
    Set ColsToNormalize = .Cells(1, FirstNormalizingCol).Resize(.Rows.Count, NormalizingColsCount)
    NormalizedRowsCount = ColsToNormalize.Columns.Count * .Rows.Count
    ReDim RepeatingList(1 To NormalizedRowsCount, 1 To RepeatingColsCount)
    ReDim NormalizedList(1 To NormalizedRowsCount, 1 To 2)
End With

'Fill in every i elements of the repeating array with the repeating row labels.
For i = 1 To NormalizedRowsCount Step NormalizingColsCount
    ListIndex = ListIndex + 1
    For j = 1 To RepeatingColsCount
        RepeatingList(i, j) = List.Cells(ListIndex, j).Value2
    Next j
Next i

'We stepped over most rows above, so fill in other repeating array elements.
For i = 1 To NormalizedRowsCount
    For j = 1 To RepeatingColsCount
        If RepeatingList(i, j) = "" Then
            RepeatingList(i, j) = RepeatingList(i - 1, j)
        End If
    Next j
Next i

'Fill in each element of the first dimension of the normalizing array
'with the former column header (which is now another row label) and the data.
With ColsToNormalize
    For i = 1 To .Rows.Count
        For j = 1 To .Columns.Count
            NormalizedList(((i - 1) * NormalizingColsCount) + j, 1) = .Cells(1, j)
            NormalizedList(((i - 1) * NormalizingColsCount) + j, 2) = .Cells(i, j)
        Next j
    Next i
End With

'Put the normal data in the same workbook, or a new one.
If NewWorkbook Then
    Set wbTarget = Workbooks.Add
    Set wsTarget = wbTarget.Worksheets(1)
Else
    Set wbSource = List.Parent.Parent
    With wbSource.Worksheets
        Set wsTarget = .Add(after:=.Item(.Count))
    End With
End If

With wsTarget
    'Put the data from the two arrays in the new worksheet.
   .Range("A1").Resize(NormalizedRowsCount, RepeatingColsCount) = RepeatingList
    .Cells(1, FirstNormalizingCol).Resize(NormalizedRowsCount, 2) = NormalizedList

    'At this point there will be repeated header rows, so delete all but one.
   .Range("1:" & NormalizingColsCount - 1).EntireRow.Delete

    'Add the headers for the new label column and the data column.
   .Cells(1, FirstNormalizingCol).Value = NormalizedColHeader
    .Cells(1, FirstNormalizingCol + 1).Value = DataColHeader
End With
End Sub

你会这样称呼它:

Sub TestIt()
NormalizeList ActiveSheet.UsedRange, 1, "Name", "Count", False
End Sub