【问题标题】:Excel/VBA: Transpose and "Flush" TableExcel/VBA:转置和“刷新”表
【发布时间】:2012-12-14 08:11:49
【问题描述】:

我想自动化以下过程:

  1. 我要转置一个数据表。
  2. 然后“向左冲洗”。

行数和列数会随着时间的推移而增加。下面的截图应该能更好地解释(使用 SkyDrive):http://sdrv.ms/UdDu1o

我能想到的唯一方法是使用VBApastespecial-transpose 和大量do-while 语句在复制之前找到行的开头和结尾。我知道复制和粘贴往往会减慢 VBA 程序的速度 - 有没有人有更好的建议?

【问题讨论】:

  • 乍一看,同样可以在没有 VBA 的情况下实现。你能上传表格本身吗?
  • 刚刚想到(一边喝茶:))——看看两张表中的1685;在顶部表格中,它位于 Nov somethingNov something 的交集处;在 DESIRED OUTPUT 表中,它位于 Oct somethingNov something 的交集处 - 你在做什么似乎没有意义;或者您是否试图将结果转移到不同的周? **

标签: vba excel


【解决方案1】:

表格布局如下图所示。
电子表格示例:http://www.bumpclub.ee/~jyri_r/Excel/Transpose_and_flush_data.xls

输出列标题:=OFFSET($B$2;C15;$A16),从 C16 复制到右侧。
输出行标题:=OFFSET($B$2;0;$A17),从B17复制下来
辅助单元格:在 A 列输出表格数据行号,在第 15 行输出数据列号。

表格的数字部分可以用C17中的单个公式构建,向下和向右复制:

 =IF(B18="";"";OFFSET($B2;C$15;$A17))

Weeks 列以“x”结尾,以获得第一个数据列的空白单元格。

【讨论】:

  • +1 除非我必须使用 VBA,否则我会遵循这个示例 - OFFSET 是一个很棒的功能。
【解决方案2】:

您可以很简单地使用Variant Array

Sub Demo()
    Dim sh As Worksheet
    Dim rSource As Range
    Dim vSource As Variant

    Set sh = ActiveSheet
    ' set range to top left cell of table
    Set rSource = sh.Cells(1, 1) '<-- adjust to suit
    ' extend range
    '  this assumes there are no gaps in the top row or left column
    Set rSource = sh.Range(rSource.End(xlDown), rSource.End(xlToRight))
    With rSource
        ' remove Totals
        .Columns(.Columns.Count).Clear
        .Rows(.Rows.Count).Clear

        ' capture source data
        vSource = rSource
        ' clear old data
        rSource.Clear
        ' transpose and place data back
        sh.Range(.Cells(1, 1), .Cells(.Columns.Count, .Rows.Count)) = _
            Application.Transpose(vSource)
    End With
End Sub

【讨论】:

  • 漂亮的代码,但我刚刚对其进行了测试,结果似乎与 OP 结果集的所需模式不同 - 您的代码与 Copy-Pastespecial; Transpose 相同,但用户正在寻找的转置for 更复杂。
【解决方案3】:

好的 - 使用 Chris 的代码作为模板,实际上只是在转置之前添加了两行额外的代码以消除空白:

Sub ThisWorks()

Dim sh As Worksheet
Dim rSource As Range
Dim vSource As Variant

Set sh = ActiveSheet
' set range to top left cell of table
Set rSource = sh.Cells(5, 3) '<-- adjust to suit
' extend range
'  this assumes there are no gaps in the top row or left column
Set rSource = sh.Range(rSource.End(xlDown), rSource.End(xlToRight))
With rSource
    ' remove Totals
    .Columns(.Columns.Count).Clear
    .Rows(.Rows.Count).Clear
End With
'reset rSource
Set rSource = sh.Range(rSource.End(xlDown), rSource.End(xlToRight))

With rSource
    ' delete the blanks - not as tricky as you mentioned in OP!!
    .SpecialCells(Excel.xlCellTypeBlanks).Delete Excel.xlUp
    ' capture source data
    vSource = rSource
    ' clear old data
    rSource.Clear
    ' transpose and place data back
    sh.Range(.Cells(1, 1), .Cells(.Columns.Count, .Rows.Count)) = Application.Transpose(vSource)
End With

End Sub

在执行上述操作之前,我花了 90 分钟将头撞在砖墙上 - 我尝试将所有值添加到数组中,然后以正确的顺序将它们清空。如果你能看到如何让以下工作,请告诉我,因为我确信这是可能的!!...

Option Explicit
Option Base 1

Sub ThisDoesNOTwork()

Dim sh As Worksheet
Dim rSource As Range
Dim vSource As Variant

Set sh = ActiveSheet
' set range to top left cell of table
Set rSource = sh.Cells(5, 3) '<-- adjust to suit
' extend range
'  this assumes there are no gaps in the top row or left column
Set rSource = sh.Range(rSource.End(xlDown), rSource.End(xlToRight))
With rSource
    ' remove Totals
    .Columns(.Columns.Count).Clear
    .Rows(.Rows.Count).Clear
End With
'reset rSource
Set rSource = sh.Range(rSource.End(xlDown), rSource.End(xlToRight))

Dim tableWidth As Integer
tableWidth = rSource.Rows.Count

Dim numbers() As Variant
ReDim numbers(rSource.Cells.Count)

'add numbers into the array
Dim x, y, z As Integer
z = 1
For y = 1 To rSource.Columns.Count
    For x = 1 To rSource.Rows.Count
            numbers(z) = rSource(x, y)
            z = z + 1
    Next
 Next

' clear old data
rSource.Clear

'empty the array
Dim myValue
Dim i As Integer
Dim blanks As Integer
i = 0
blanks = 0

Dim c As Integer
For c = 1 To UBound(numbers)

        i = i + 1
        If numbers(i) = "" Then
            blanks = blanks + 1
        Else
            rSource.Cells(i) = numbers(c)
        End If

Next c
Debug.Print blanks

End Sub

【讨论】:

    【解决方案4】:

    我试图坚持使用数组(通常我喜欢反过来;-) 只有数值被转置,用户进行选择。命名范围"Vba_output" 应在工作表上预定义。

    Sub Transpose_and_flush_table()
    
    Dim source_array As Variant
    Dim target_array As Variant
    Dim source_column_counter As Long
    Dim source_row_counter As Long
    Dim blanks As Long
    
    Const row_index = 1
    Const col_index = 2
    
    source_array = Selection.Value
    ' source_array(row,column)
    
    ReDim target_array(UBound(source_array, col_index), UBound(source_array, row_index))
    
    For source_column_counter = _
        LBound(source_array, col_index) To UBound(source_array, col_index)
           blanks = 0
    
          'Count blank cells
          For source_row_counter = _
             LBound(source_array, row_index) To UBound(source_array, row_index)
               If source_array(source_row_counter, source_column_counter) = "" Then
                  blanks = blanks + 1
               End If
           Next
    
          'Replace blanks, shift array elements to the left
          For source_row_counter = _
             LBound(source_array, row_index) To UBound(source_array, row_index) - blanks
               source_array(source_row_counter, source_column_counter) = _
                 source_array(source_row_counter + blanks, source_column_counter)
          Next
    
          'Add blanks to the end
          For source_row_counter = _
            UBound(source_array, row_index) - blanks + 1 To UBound(source_array, row_index)
               source_array(source_row_counter, source_column_counter) = ""
          Next
    
          'Transpose source and target arrays
          For source_row_counter = _
             LBound(source_array, row_index) To UBound(source_array, row_index)
                 target_array(source_column_counter, source_row_counter) = _
                source_array(source_row_counter, source_column_counter)
          Next
    
    Next
    
    Range("Vba_output").Offset(-1, -1).Resize(UBound(target_array, row_index) + 1, _
      UBound(target_array, col_index) + 1) = target_array
    
    End Sub
    

    【讨论】:

      猜你喜欢
      • 2019-07-21
      • 2012-02-14
      • 1970-01-01
      • 2017-04-21
      • 2015-02-07
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      相关资源
      最近更新 更多