简体   繁体   English

表格的四列(x,y,z,值)到矩阵表

[英]Table of four columns (x,y,z, value) to matrix table

I would like convert data that is in four columns to a matrix table. 我想将四列中的数据转换为矩阵表。 I've tried to use OFFSET function and it works but my data is too large (about 100,000 cells) and it crashed. 我试过使用OFFSET功能,它可以工作,但我的数据太大(大约100,000个单元格),它崩溃了。

So, I wound like to try to do this by macro, can you suggest how to do this? 所以,我想通过宏来尝试这样做,你能建议怎么做吗? Or you have any better suggestion that would be great. 或者你有更好的建议,那将是伟大的。

PS. PS。 I used OFFSET formula from this site here . 在这里使用了这个网站的OFFSET公式。

想象一下

Pivoted with Type above Gear for ROWS, Color for COLUMNS and Sum of Amount for Σ VALUES: 与ROWS上面的齿轮类型相对应,列的颜色和Σ值的总和:

SO24317683的例子

with the top row hidden, the Report Layout shown in Tabular Form, all subtotals and totals removed, the order of columns and of rows rearranged, empty cells set to show 0 , expand/collapse buttons hidden, Repeat All Item Labels set * , and borders added. 隐藏顶行,报表布局以表格形式显示,删除所有小计和总计,重新排列列和行的顺序,设置为显示0空单元格,隐藏展开/折叠按钮,重复所有项目标签集* ,以及边界添加。

In order to show the row of 0 s, I added Bus/Green/Manual to the source data (with a colour (Green) to avoid (blank) as an extra column). 为了显示0秒的行,我在源数据中添加了Bus / Green / Manual(使用颜色(绿色)以避免(空白)作为额外列)。


* not available in Excel 2007. To repeat item labels for versions earlier than Excel 2010 the standard practice is to copy the PT and Paste Special, Values and fill the blanks by selecting them with Go To Special, Blanks then = , Up, Ctrl + Enter . *在Excel 2007中不可用的版本重复项目标签比Excel 2010中的标准做法是将PT复制和粘贴特殊,价值与按转到特殊,选择它们填补空白早期空白,然后= ,上, 按Ctrl + 输入

Fun problem! 有趣的问题! Because you were having problems involving the size of your data, I tried to avoid using objects like dictionaries(I don't know how much a dictionary can hold). 因为您遇到涉及数据大小的问题,所以我试图避免使用字典之类的对象(我不知道字典可以容纳多少)。 Instead I created a program that keeps track of very little data, but ends up continuously reading/writing from the file: It'll be very slow, but it'll work for very large files. 相反,我创建了一个程序来跟踪非常少的数据,但最终不断地从文件读取/写入:它将非常慢,但它适用于非常大的文件。

Anyways, try copying and pasting the following code into a VBA module and then run it on your file. 无论如何,尝试将以下代码复制并粘贴到VBA模块中,然后在您的文件上运行它。 You may need to change some of the values for the rows and columns. 您可能需要更改行和列的某些值。

EDIT: I made it work for the example picture you gave, but it's a mess. 编辑:我让它为你给出的示例图片工作,但它是一团糟。 I'll try to make it clearer tomorrow (g2g) 我明天会试着让它更清楚(g2g)
EDIT: It's been updated! 编辑:它已被更新! Carefully commented etc, It'll be easy to modify however you like. 仔细评论等,无论你喜欢什么,都很容易修改。

Summary 摘要

  • Build matrix table below data table 在数据表下面构建矩阵表
  • Loop through the rows of the data table and add them to the matrix table 循环遍历数据表的行并将它们添加到矩阵表中
  • If the matrix table does not already have a row or column for the data, make it, else place in existing 如果矩阵表中没有数据的行或列,请创建它,否则放在现有数据中

Example: 例:
在此输入图像描述

Code: (SO got rid of the whitespace :( I think my post is too long) 代码:(SO摆脱了空白:(我认为我的帖子太长了)

'Start and end row of the original data
Private dataStartRow As Long
Private dataEndRow As Long

'The start row/column of the matrix
Private matrixStartRow As Long
Private matrixStartCol As Long

'How many rows/columns in the matrix
Private matrixRowLength As Long
Private matrixColLength As Integer

Public Sub makeMatrixTable()
    'Sets initial values for variables
    initializeValues
    'Builds table
    buildTable
End Sub

Private Function initializeValues()
    'The actual data probably begins on row 2, because row 1 is usually used for column titles
    dataStartRow = 2
    'Get last row of data
    dataEndRow = ActiveSheet.UsedRange.Rows.Count

    'By adding 2, we create a gap row between our new matrix table and the original data table
    matrixStartRow = dataEndRow + 2
    'The matrix values begin after column 2, because columns 1&2 are used for titles
    matrixStartCol = 2

    matrixRowLength = 0
    matrixColLength = 0
End Function

Private Function buildTable()
    Dim dataRow As Long
    Dim matrixRow As Long
    Dim matrixCol As Integer
    Dim value As String

    'The keys are the column/row titles
    'I'm using the work "key" because we're mimicking a dictionary object by only using a key once
    'in this case it's a little more complicated, as we have 3 keys (2 row keys, 1 column key)
    Dim rowKey1 As String, rowKey2 As String
    Dim colKey As String

    'loop through all rows containing data
    For dataRow = dataStartRow To dataEndRow
        'get keys from data
        rowKey1 = CStr(ActiveSheet.Cells(dataRow, 1).value)
        rowKey2 = CStr(ActiveSheet.Cells(dataRow, 3).value)
        colKey = CStr(ActiveSheet.Cells(dataRow, 2).value)

        'find if we have already created rows for the row keys, and if so return the row (else -1)
        matrixRow = rowExistsInMatrix(rowKey1, rowKey2)
        'find if we have already created a column for the column key, and if so return the row (else -1
        matrixCol = colExistsInMatrix(colKey)

        'Our matrix does not have a row with those row keys, so we must create one
        If matrixRow = -1 Then
            'increase the size of our matrix
            matrixRowLength = matrixRowLength + 1
            'get row that is not in use
            matrixRow = matrixStartRow + matrixRowLength
            'add the new keys to matrix
            ActiveSheet.Cells(matrixRow, 1).value = rowKey1
            ActiveSheet.Cells(matrixRow, 2).value = rowKey2
        End If

        'We don't have a column that matches the column key
        If matrixCol = -1 Then
            'increase size of matrix table
            matrixColLength = matrixColLength + 1
            'get column that is not in use
            matrixCol = matrixStartCol + matrixColLength
            'add new key to matrix
            ActiveSheet.Cells(matrixStartRow, matrixCol).value = colKey
        End If

        'get the value to be placed in the matrix from column 4
        value = CStr(ActiveSheet.Cells(dataRow, 4).value)
        'place value
        ActiveSheet.Cells(matrixRow, matrixCol).value = value

    Next dataRow
End Function

'Checks to see if the key from the data table exists in our matrix table
'if it does, return the row in the matrix table
'else return -1
Private Function rowExistsInMatrix(dataKey1 As String, dataKey2 As String) As Long
    Dim matrixRow As Long
    Dim matrixKey1 As String, matrixKey2 As String

    'loop through rows of matrix
    For matrixRow = matrixStartRow To matrixStartRow + matrixRowLength
        'get keys from matrix
        matrixKey1 = CStr(ActiveSheet.Cells(matrixRow, 1).value)
        matrixKey2 = CStr(ActiveSheet.Cells(matrixRow, 2).value)

        'do the keys match
        If dataKey1 = matrixKey1 And dataKey2 = matrixKey2 Then
            rowExistsInMatrix = matrixRow
            Exit Function
        End If
    Next matrixRow

    rowExistsInMatrix = -1
End Function

'Same as rowExistsInMatrix but loops through column titles
Private Function colExistsInMatrix(dataKey As String) As Long
    Dim matrixKey As String
    Dim matrixCol As Integer

    'loop through columns
    For matrixCol = matrixStartCol To matrixStartCol + matrixColLength
        matrixKey = CStr(ActiveSheet.Cells(matrixStartRow, matrixCol).value)

        'does a key match
        If matrixKey = dataKey Then
            colExistsInMatrix = matrixCol
            Exit Function
        End If
    Next matrixCol

    colExistsInMatrix = -1
End Function

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM