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

我需要通过search一个stringfind多行(通常是156)。

示例string:'I30112'我代表9月(字母表中的第9个字母),30代表9月的第30天,112代表9月30日的第112个单元。

我的用户打算说,请从I30112开始find下一个x单位。 这意味着我将searchI30112,I30113等,直到我到达I30156。 I30156之后的单位将是J01001。 所以我需要从I30112findJ01111。

如何从表单底部search循环,find每个单元的最后一个引用? 如果一切顺利,我可以find一个,抓下一个156,但不幸的是,他们并不总是正确的顺序。

谢谢!

– -编辑 – –

我正在尝试使用ASC()方法。 但是,鉴于我的用户input是一个variables,我很难得到正确的字符。 目前我有:

Dim Month As String Dim MonthChar As Integer Month = Left(UserForm1.TextBox1.Value, 1) MonthChar = Asc(Month) 

然而,尽pipeMonth是一个string,但我得到一个错误。 如果我切换到Monthchar = Asc(“Month”),那么它总是从月份获取M,而不是将其作为variables处理。

虽然你的问题并没有指出如何find它们的价值,收集适当的编码string过滤收集到一个变种数组,然后推入自动过滤方法的标准似乎是最方便的过程。

 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 

当你在一个月或一年的最后一天开始的时候,第二天会有一些杂耍。 由于今年没有规定,今年是用来确定29 – 2月是否是一个因素。

还有一些事情要处理。

  1. 获取编码的string进入例程。 目前这是分配与enc = "I30112"
  2. 没有提到一旦你找回了你想要做的事情。 我留下了一个注释区域,其中过滤的集合在With … End With语句中 。 之后立即有一个注释的代码行删除filter。 数据►分类和过滤►清除将做同样的事情。

你的叙述是指“通常156” 。 以下查找任何给定的编码的月份和date的最大“单位”代码。

 =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) 

几个选项:

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 

2.自动过滤和可见区域


 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 

在这里输入图像描述

我有工作表上的交互的代码。

考虑下面的工作表(Sheet4):
SampleWorksheet

  • 列A中的单位string
  • 由公式R1C1在列B中的等效数字
    =(CODE(RC[-1])-CODE("A")+1)*100000+VALUE(RIGHT(RC[-1],LEN(RC[-1])-1))
  • dynamic命名范围MDU_String
    =OFFSET(Sheet4!$A$1,1,0,COUNTA(Sheet4!$A:$A)-1,1)
  • 2个静态命名范围:
    Lookup_from=Sheet4!$E$1
    For_units=Sheet4!$G$1
  • E1上的数据validation:
    DataValid_E1

现在在Sheet4的工作表模块中(问题已解决):

 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 

这将允许您基于E1和G1中的更改​​进行交互式AutoFilter。 math后面的math可能会让人困惑,但是无论是当天或者当天的单位数量(最多999单位),它都可以使事物变得非常通用。

到12月底还没有testing到下一年的单位数量,所以应该留意一下。

样品结果:
SampleResults