Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 如何循环遍历字母和数字序列(I30112-J01111)_Excel_Vba - Fatal编程技术网

Excel 如何循环遍历字母和数字序列(I30112-J01111)

Excel 如何循环遍历字母和数字序列(I30112-J01111),excel,vba,Excel,Vba,我需要通过搜索字符串来找到多行(通常是156行) 示例字符串:“I30112”I代表九月(字母表中的第9个字母),30代表九月的第30天,112代表九月的第112个单位 我的用户会说,请从I30112开始查找下一个x单位。这意味着我将搜索I30112、I30113等,直到找到I30156。I30156之后的装置将为J01001。所以我需要找到从I30112到J01111的路径 如何从工作表的底部循环搜索,找到每个单元的最后一个引用?如果它们都是有序的,我可以找到一个,然后抓取下一个156,但不幸

我需要通过搜索字符串来找到多行(通常是156行)

示例字符串:“I30112”I代表九月(字母表中的第9个字母),30代表九月的第30天,112代表九月的第112个单位

我的用户会说,请从I30112开始查找下一个x单位。这意味着我将搜索I30112、I30113等,直到找到I30156。I30156之后的装置将为J01001。所以我需要找到从I30112到J01111的路径

如何从工作表的底部循环搜索,找到每个单元的最后一个引用?如果它们都是有序的,我可以找到一个,然后抓取下一个156,但不幸的是,它们的顺序并不总是正确的

谢谢大家!

---编辑---

我正在尝试使用ASC()方法。然而,考虑到我的用户输入是一个变量,我很难获得正确的字符。目前我有:

Dim Month As String  
Dim MonthChar As Integer  

Month = Left(UserForm1.TextBox1.Value, 1)  
MonthChar = Asc(Month)

然而,尽管Month是一个字符串,我还是得到了一个错误。如果我切换到Monthchar=Asc(“Month”),那么它总是从Month中获取M,而不是将其视为变量。

而您的问题没有给出在找到值后如何处理这些值的指示,将经过过滤的适当编码字符串集合收集到一个变量数组中,然后将它们推送到变量数组的标准中,这似乎是最方便的过程

Sub filter_for_encode_string()
    Dim str As String, enc As String, rw As Long
    Dim dt As Date, num As Long, dy As Long, ndy As Long, mn As String, nmn As String
    Dim v As Long, vFLTRs As Variant

    enc = "I30112"
    dt = DateSerial(Year(Date), Asc(Left(enc, 1)) - 64, Mid(enc, 2, 2))
    mn = Chr(Month(dt) + 64)
    dy = Day(dt)
    num = Val(Right(enc, 3))
    ndy = Day(dt + 1)
    nmn = Chr(Month(dt + 1) + 64)

    With Worksheets("Sheet4")
        If .AutoFilterMode Then .AutoFilterMode = False
        With .Cells(1, 1).CurrentRegion
            ReDim vFLTRs(0)
            For rw = 2 To .Cells(Rows.Count, 1).End(xlUp).Row
                str = .Cells(rw, 1).Value2
                If (Left(str, 1) = mn And Val(Mid(str, 2, 2)) = dy And Val(Right(str, 3)) >= num) Or _
                   (Left(str, 1) = nmn And Val(Mid(str, 2, 2)) = ndy And Val(Right(str, 3)) < num) Then
                    vFLTRs(UBound(vFLTRs)) = .Cells(rw, 1).Value2
                    ReDim Preserve vFLTRs(UBound(vFLTRs) + 1)
                End If
            Next rw
            If UBound(vFLTRs) Then ReDim Preserve vFLTRs(UBound(vFLTRs) - 1)

            .Columns(1).AutoFilter Field:=1, Criteria1:=(vFLTRs), _
                                   Operator:=xlFilterValues, VisibleDropDown:=False       
            With .Resize(.Rows.Count - 1, 1).Offset(1, 0)
                If CBool(Application.Subtotal(103, .Cells)) Then
                    'do something with the filtered range
                End If
            End With
            '.Columns(1).AutoFilter Field:=1
        End With
    End With
End Sub
有两种选择:

1。带阵列的标准环路



2。自动过滤和可见区域




我在工作表上有交互代码

考虑以下工作表(表4):

  • 列A中的单位字符串
  • 公式1c1
    =(code(RC[-1])-code(“A”)+1)*100000+值(右(RC[-1],LEN(RC[-1])-1))在B列中的等效数字
  • 动态命名范围
    MDU\u字符串

    =偏移量(Sheet4!$a$1,1,0,COUNTA(Sheet4!$a:$a)-1,1)
  • 2个静态命名范围:
    查找\u来自
    =Sheet4$E$1

    用于单位
    =Sheet4$G$1

  • E1上的数据验证:
现在进入第4页的工作表模块(问题已解决):

选项显式
私有子工作表_更改(ByVal目标作为范围)
选择案例目标
Case ThisWorkbook.Names(“Lookup_from”).refrestorange,ThisWorkbook.Names(“For_units”).refrestorange
设置过滤器目标
结束选择
端接头
专用子设置过滤器(ByVal目标作为范围)
昏暗的月亮和绳子一样长,像绳子一样慢
Dim oRng作为范围,lFrom作为长度,lTo作为长度,lCount作为长度,bStop作为布尔值
Dim lMonth为整数,lDay为整数,dNextDay为日期,iTry为整数
重置过滤器“删除自动过滤器”
Application.ScreenUpdating=False
如果不是空的(目标),那么
sLookup=thispoolk.Names(“Lookup_from”).refrestorange.Value
lUnits=thispoolk.Names(“用于单位”).refrestorange.Value
Debug.Print“Lookup”&lUnits&“from”&sLookup
Set oRng=ThisWorkbook.Names(“MDU字符串”).referestorange.Find(sLookup)
如果不是,那就什么都不是了
lFrom=oRng.Offset(0,1).值“数字等效”
lTo=lFrom
lCount=0
iTry=0
dNextDay=日期
bStop=False
'从查找开始,找到要显示的最后一个单元
做
调试。打印“查找lTo:&lTo&”(&lCount&”)命令
设置oRng=ThisWorkbook.Names(“MDU字符串”).refrestorange.Offset(0,1).Find(What:=CStr(lTo),LookIn:=xlValues,LookAt:=xlWhole)
如果oRng什么都不是
每月=lTo\100000
lDay=lTo\1000模100
dNextDay=DateSerial(年(日)、月、日+1)'移动到下一天
如果年(日期)=年(dNextDay),则
lMonth=月份(dNextDay)
lDay=天(dNextDay)
lTo=1个月*100000+1天*1000+1'第二天尝试001
Debug.Print“第二天尝试lTo:”&lTo
其他的
bStop=True
如果结束
iTry=iTry+1
如果iTry>2,则bStop=True
其他的
lTo=lTo+1'尝试下一个递增单位
iTry=0'重置尝试计数器
lCount=lCount+1
如果结束
bStop=(lCount>=lUnits)或bStop
循环到bStop
调试。打印“lFrom:&lFrom&vbTab&“lTo:&lTo”
'启动过滤器

并集(范围(“MDU字符串”)、范围(“MDU字符串”)。偏移量(0,1))。自动筛选字段:=2,标准1:=“>=”&lFrom,运算符:=xlAnd,标准2:=“首先构建一个来回转换日期的函数,然后构建一个变量数组,该数组包含开始和结束之间所有可能的变量,并使用该数组过滤值。如果这不是一个选项,则对数据进行排序,以便有机会找到起点和终点。提示:您可以使用
Asc(“J”)-Asc(“a”)+1
->
74-65+1=10
来确定月份。如果日期和单位编号有额外的列,然后,您可以应用自动筛选来显示结果,而不是循环数据。
Month
是一个函数,请避免将其用作变量名。使用
Dim sMonth作为字符串
。然后,我发现自己在数学上有一个错误。。。如果某一天只有2个单位,并且正在查找滚动到第2天的单位,则自动筛选功能无法正常运行…通过添加计数器和退出案例修复了搜索问题。
=AGGREGATE(14, 6, RIGHT(A2:INDEX(A:A, MATCH("zzz",A:A )), 3)/(LEFT(A2:INDEX(A:A, MATCH("zzz",A:A )), 3)="I30"), 1)
Option Explicit

Public Sub findUnitsArray()
    Const COL           As Long = 1      'A
    Const START_UNIT    As Long = 112
    Const CRIT          As String = "I30"

    Dim ws As Worksheet, ur As Range, v As Variant, i As Long
    Dim totalFound As Long, msg As String

    Set ws = ActiveSheet
    Set ur = ws.UsedRange
    v = ur.Columns(COL)

    For i = 1 To ur.Rows.Count
        If InStr(v(i, 1), CRIT) > 0 Then
            If Val(Right(v(i, 1), 3)) >= START_UNIT Then         'compare last 3 characters
                totalFound = totalFound + 1
                msg = msg & v(i, 1) & ", "
            End If
        End If
    Next
    MsgBox "Found " & totalFound & " units:" & vbCrLf & vbCrLf & Left(msg, Len(msg) - 2)
End Sub
Public Sub findUnitsAutoFilter()
    Const COL           As Long = 1     'A
    Const START_UNIT    As Long = 112
    Const CRIT          As String = "=I30**"

    Dim ws As Worksheet, ur As Range, ar As Range, cel As Range
    Dim totalFound As Long, msg As String

    Set ws = ActiveSheet
    Set ur = ws.UsedRange

    ws.AutoFilterMode = False
    With ur
        .AutoFilter
        .AutoFilter Field:=COL, Criteria1:=CRIT, Operator:=xlAnd
        For Each ar In .Columns(COL).SpecialCells(xlCellTypeVisible).Areas
            For Each cel In ar
                If Val(Right(cel.Value2, 3)) >= START_UNIT Then  'compare last 3 characters
                    totalFound = totalFound + 1
                    msg = msg & cel.Value2 & ", "
                End If
            Next
        Next
    End With
    MsgBox "Found " & totalFound & " units:" & vbCrLf & vbCrLf & Left(msg, Len(msg) - 2)
End Sub
Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
    Select Case Target
        Case ThisWorkbook.Names("Lookup_from").RefersToRange, ThisWorkbook.Names("For_units").RefersToRange
            SetupFilter Target
    End Select
End Sub

Private Sub SetupFilter(ByVal Target As Range)
    Dim lUnits As Long, sLookup As String
    Dim oRng As Range, lFrom As Long, lTo As Long, lCount As Long, bStop As Boolean
    Dim lMonth As Integer, lDay As Integer, dNextDay As Date, iTry As Integer

    ResetFilter ' Remove AutoFilter
    Application.ScreenUpdating = False
    If Not IsEmpty(Target) Then
        sLookup = ThisWorkbook.Names("Lookup_from").RefersToRange.Value
        lUnits = ThisWorkbook.Names("For_units").RefersToRange.Value
        Debug.Print "Lookup " & lUnits & " from " & sLookup
        Set oRng = ThisWorkbook.Names("MDU_String").RefersToRange.Find(sLookup)
        If Not oRng Is Nothing Then
            lFrom = oRng.Offset(0, 1).Value ' Number equivalent
            lTo = lFrom
            lCount = 0
            iTry = 0
            dNextDay = Date
            bStop = False
            ' Start from the Lookup_for, locate the last unit to show
            Do
                Debug.Print "Looking for lTo: " & lTo & " (" & lCount & ")"
                Set oRng = ThisWorkbook.Names("MDU_String").RefersToRange.Offset(0, 1).Find(What:=CStr(lTo), LookIn:=xlValues, LookAt:=xlWhole)
                If oRng Is Nothing Then
                    lMonth = lTo \ 100000
                    lDay = lTo \ 1000 Mod 100
                    dNextDay = DateSerial(Year(Date), lMonth, lDay + 1) ' Move to next day
                    If Year(Date) = Year(dNextDay) Then
                        lMonth = Month(dNextDay)
                        lDay = Day(dNextDay)
                        lTo = lMonth * 100000 + lDay * 1000 + 1 ' Try 001 on next day
                        Debug.Print "Try next day lTo: " & lTo
                    Else
                        bStop = True
                    End If
                    iTry = iTry + 1
                    If iTry > 2 Then bStop = True
                Else
                    lTo = lTo + 1 ' Try next incremented unit
                    iTry = 0 ' Reset trying counter
                    lCount = lCount + 1
                End If
                bStop = (lCount >= lUnits) Or bStop
            Loop Until bStop
            Debug.Print "lFrom: " & lFrom & vbTab & "lTo: " & lTo
            ' Activate the filter
            Union(Range("MDU_String"), Range("MDU_String").Offset(0, 1)).AutoFilter Field:=2, Criteria1:=">=" & lFrom, Operator:=xlAnd, Criteria2:="<" & lTo
            Set oRng = Nothing
        End If
    End If
    Application.ScreenUpdating = True
End Sub

Private Sub ResetFilter()
    Union(Range("MDU_String"), Range("MDU_String").Offset(0, 1)).AutoFilter Field:=2
End Sub