可变搜索单元VBA

可变搜索单元VBA,vba,excel,Vba,Excel,我有以下专栏(1): 这需要变成两列 1 15 150 1500000 06700 1500000 07290 1500000 07500 2 22 220 2200000 00900 我最初的想法是: 创建额外的列 当找到长度为7位的数字时,通过行循环,在变量中注册单元格和值 将其下的值移动到B列,直到值的长度为5 从变量中保存的单元格开始,将值从变量复制到A列,直到A列不再为空 在上述过程之后,循环行并删除其中

我有以下专栏(1):

这需要变成两列

1   
15  
150 
1500000       06700
1500000       07290
1500000       07500
2   
22  
220    
2200000       00900
我最初的想法是:

  • 创建额外的列
  • 当找到长度为7位的数字时,通过行循环,在变量中注册单元格和值
  • 将其下的值移动到B列,直到值的长度为5
  • 从变量中保存的单元格开始,将值从变量复制到A列,直到A列不再为空
  • 在上述过程之后,循环行并删除其中A为长度7且B为空的行
由于我对VBA不熟悉,在我开始之前,我想验证一下,如果VBA宏在技术上可行,那么上述规则集是否会达到我的目的,以及它是否会导致意外行为


这段代码必须每月在一个新的大型excel文件上运行。

在编写了逻辑之后,记住了Jeeped的输入,我最终按照以下方式编写:

  • 强制将列A转换为文本
  • 创建额外的列
  • 获取包含数据的行数
  • 循环1:如果A列单元格长度为5,则将单元格移动到B列
  • 循环2:如果列A单元格长度为7,则将该值复制到变量
  • 循环2:如果列A单元格长度为0,则将变量粘贴到单元格中
  • 在上述过程之后,循环行并删除其中A为长度7且B为空的行。(性能反向循环)
欢迎您对下面发布的代码进行输入。我对各种可能的优化都持开放态度

    Sub FixCols()

    'First trim the numbers (text) with 2 methods. VBA trim and Worksheet formula trim
        Range("A:A").NumberFormat = "@"

        Dim Cell As Range
        For Each Cell In ActiveSheet.UsedRange.Columns("A").Cells
          x = x + 1
          Cell = Trim(Cell)
          Cell.Value = WorksheetFunction.Trim(Cell.Value)
        Next

    'Now insert empty column as B
        Columns("B:B").Select
        Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove

    'Determine rows with values for loop
        With ActiveSheet
        LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
        End With

    'Loops to move around the data

    Dim i As Long
    Dim CellValue As Long

        For i = 1 To LastRow
        'move items to column B
            If Len(Range("A" & i).Value) = 5 Then
                Range("A" & i).Select
                Selection.Cut
                Range("B" & i).Select
                ActiveSheet.Paste
            End If
        Next i

        For i = 1 To LastRow
            'if the row is a reknr we copy the value
            If Len(Range("A" & i).Value) = 7 Then
                CellValue = Range("A" & i).Value
            End If
            'Paste the reknr to the rows with item
            If Len(Range("A" & i).Value) = 0 Then
                Range("A" & i).Value = CellValue
            End If
        Next i

    'Reverse loop (performance) to check for rows to delete (reknr without item)
        i = LastRow
        Do
            If Len(Range("A" & i).Value) = 7 And Len(Range("B" & i).Value) = 0 Then
                Rows(i).Delete
            End If
            i = i - 1
        Loop While Not i < 1

    End Sub
Sub-FixCols()
'首先用两种方法修剪数字(文本)。VBA修剪和工作表公式修剪
范围(“A:A”).NumberFormat=“@”
暗淡单元格作为范围
对于ActiveSheet.UsedRange.Columns(“A”)单元格中的每个单元格
x=x+1
单元=修剪(单元)
Cell.Value=工作表function.Trim(Cell.Value)
下一个
'现在将空列插入为B
列(“B:B”)。选择
选择。插入Shift:=xlToRight,CopyOrigin:=xlFormatFromLeftOrAbove
'确定具有循环值的行
使用ActiveSheet
LastRow=.Cells(.Rows.Count,“A”).End(xlUp).Row
以
'循环以在数据周围移动
我想我会坚持多久
将单元格值设置为“长”
对于i=1到最后一行
'将项目移动到B列
如果Len(范围(“A”&i).Value)=5,则
范围(“A”和i)。选择
选择,剪
范围(“B”和i)。选择
活动表。粘贴
如果结束
接下来我
对于i=1到最后一行
'如果该行是reknr,则复制该值
如果Len(范围(“A”&i).Value)=7,则
CellValue=范围(“A”&i).值
如果结束
'将reknr粘贴到包含项的行
如果Len(范围(“A”&i).Value)=0,则
范围(“A”&i)。值=单元格值
如果结束
接下来我
'反向循环(性能)以检查要删除的行(不带项的reknr)
i=最后一行
做
如果Len(范围(“A”)和i.Value)=7且Len(范围(“B”)和i.Value)=0,则
第(i)行。删除
如果结束
i=i-1
循环而不是i<1
端接头
无论您的5位数字(c/w/前导零)是单元格格式为
00000
的真数字,还是看起来像带a的数字的文本,都应该能够从显示的文本中确定其修剪长度

下面的代码遵循您的逻辑步骤进行了一些修改;最明显的是它从A列的底部走到顶部。这是为了避免跳过已删除的行

Sub bringOver()
    Dim rw As Long, v As Long, vVAL5s As Variant, vREV5s As Variant

    'put the cursor anywhere in here and start tapping F8
    'it will help if you can also see the worksheet with your
    'sample data

    ReDim vVAL5s(0) 'preset some space for the first value

    With Worksheets("Sheet1")   '<~~ set this worksheet reference properly!
        'ensure a blank column B
        .Columns(2).Insert

        'work from the bottom to the top when deleting rows
        'or you risk skipping a row
        For rw = .Cells(Rows.Count, 1).End(xlUp).Row To 2 Step -1
            'determine the length of the trimmed displayed length
            'and act accordingly
            Select Case Len(Trim(.Cells(rw, 1).Text))
                Case Is < 5
                    'do nothing
                Case 5
                    'it's one to be transferred; collect it
                    vVAL5s(UBound(vVAL5s)) = .Cells(rw, 1).Text
                    'make room for the next
                    ReDim Preserve vVAL5s(UBound(vVAL5s) + 1)
                Case 7
                    'only process the transfer if there is something to transfer
                    If CBool(UBound(vVAL5s)) Then
                        'the array was built from the bottom to the top
                        'so reverse the order in the array
                        ReDim vREV5s(UBound(vVAL5s) - 1)
                        For v = UBound(vVAL5s) - 1 To LBound(vVAL5s) Step -1
                            vREV5s(UBound(vREV5s) - v) = vVAL5s(v)
                        Next v
                        'working With Cells is like selecting htem but without selecting them
                        'want to work With a group of cells tall enough for all the collected values
                        With .Cells(rw, 1).Resize(UBound(vREV5s) + 1, 1)
                            'move over to column B and put the values in
                            .Offset(0, 1) = Application.Transpose(vREV5s)
                            'make sure they show leading zeroes
                            .Offset(0, 1).NumberFormat = "[Color13]00000;[Color9]@"
                            'if there was more than 1 moved over, FillDown the 7-wide value
                            If CBool(UBound(vREV5s)) Then .FillDown
                            'delete the last row
                            .Cells(.Rows.Count + 1, 1).EntireRow.Delete
                        End With
                        'reset the array for the next first value
                        ReDim vVAL5s(0)
                    End If
                Case Else
                    'do nothing
            End Select
            'move to the next row up and continue
        Next rw
        'covert the formatted numbers to text
        Call makeText(.Columns(2))
    End With
End Sub

Sub makeText(rng As Range)
    Dim tCell As Range
    For Each tCell In rng.SpecialCells(xlCellTypeConstants, xlNumbers)
        tCell.Value = Format(tCell.Value2, "\'00000;@")
    Next tCell
End Sub
Sub-bringOver()
尺寸rw为长,v为长,vVAL5s为变型,vREV5s为变型
'将光标放在此处的任意位置,然后开始按F8键
'如果您还可以使用您的
"样本数据,
ReDim vVAL5s(0)'为第一个值预设一些空间

工作表(“Sheet1”)是一个有趣的项目,您已经编写了一个不错的软件规范,但它仍然是一个软件规范,不是一个免费的代码编写服务。开始使用宏录制器,然后回来编辑您的问题,以包括您在为更大的目的重新编写录制的代码时遇到的困难。感谢您的阅读,我不是在请求代码,也不是在审查代码。我在问我的逻辑是否有缺陷,我是否忘记了一个重要的步骤,一旦写了这个步骤,功能就会失效。我目前正在阅读并学习写上面的内容。你的逻辑可以工作,但可以优化。二维变量数组速度更快,行可以在一个片段中删除,而不是在多个小片段中删除。唯一突出的是你对长度的依赖。是将
00900
等格式化为文本还是将单元格编号格式化为
00000
以实现前导零?当你浏览这些行时,从底部开始,一直到顶部。它们确实被格式化为文本。我想你在我的逻辑中发现了一个有趣的缺陷。一旦我做了修剪,它就不再被认为是文本了。我需要保持领先的0。我在ActiveSheet.UsedRange.Columns(“A”).Cells x=x+1 Cell.Value=WorksheetFunction.Trim(Cell.Value)中使用Dim Cell作为每个单元格的范围。接下来取消上述操作,在修剪之前再次强制将其放入文本。有A、A和A。.Text是显示的文本,因此它可以是5个字符的文本字符串,也可以是格式为
00000
的数字。我第一次遇到这个问题,但那是因为我的数字格式仅为
00000
;一旦我把它们改成文本,一切似乎都很顺利。
Sub bringOver()
    Dim rw As Long, v As Long, vVAL5s As Variant, vREV5s As Variant

    'put the cursor anywhere in here and start tapping F8
    'it will help if you can also see the worksheet with your
    'sample data

    ReDim vVAL5s(0) 'preset some space for the first value

    With Worksheets("Sheet1")   '<~~ set this worksheet reference properly!
        'ensure a blank column B
        .Columns(2).Insert

        'work from the bottom to the top when deleting rows
        'or you risk skipping a row
        For rw = .Cells(Rows.Count, 1).End(xlUp).Row To 2 Step -1
            'determine the length of the trimmed displayed length
            'and act accordingly
            Select Case Len(Trim(.Cells(rw, 1).Text))
                Case Is < 5
                    'do nothing
                Case 5
                    'it's one to be transferred; collect it
                    vVAL5s(UBound(vVAL5s)) = .Cells(rw, 1).Text
                    'make room for the next
                    ReDim Preserve vVAL5s(UBound(vVAL5s) + 1)
                Case 7
                    'only process the transfer if there is something to transfer
                    If CBool(UBound(vVAL5s)) Then
                        'the array was built from the bottom to the top
                        'so reverse the order in the array
                        ReDim vREV5s(UBound(vVAL5s) - 1)
                        For v = UBound(vVAL5s) - 1 To LBound(vVAL5s) Step -1
                            vREV5s(UBound(vREV5s) - v) = vVAL5s(v)
                        Next v
                        'working With Cells is like selecting htem but without selecting them
                        'want to work With a group of cells tall enough for all the collected values
                        With .Cells(rw, 1).Resize(UBound(vREV5s) + 1, 1)
                            'move over to column B and put the values in
                            .Offset(0, 1) = Application.Transpose(vREV5s)
                            'make sure they show leading zeroes
                            .Offset(0, 1).NumberFormat = "[Color13]00000;[Color9]@"
                            'if there was more than 1 moved over, FillDown the 7-wide value
                            If CBool(UBound(vREV5s)) Then .FillDown
                            'delete the last row
                            .Cells(.Rows.Count + 1, 1).EntireRow.Delete
                        End With
                        'reset the array for the next first value
                        ReDim vVAL5s(0)
                    End If
                Case Else
                    'do nothing
            End Select
            'move to the next row up and continue
        Next rw
        'covert the formatted numbers to text
        Call makeText(.Columns(2))
    End With
End Sub

Sub makeText(rng As Range)
    Dim tCell As Range
    For Each tCell In rng.SpecialCells(xlCellTypeConstants, xlNumbers)
        tCell.Value = Format(tCell.Value2, "\'00000;@")
    Next tCell
End Sub