Excel 如何循环遍历字母和数字序列(I30112-J01111)
我需要通过搜索字符串来找到多行(通常是156行) 示例字符串:“I30112”I代表九月(字母表中的第9个字母),30代表九月的第30天,112代表九月的第112个单位 我的用户会说,请从I30112开始查找下一个x单位。这意味着我将搜索I30112、I30113等,直到找到I30156。I30156之后的装置将为J01001。所以我需要找到从I30112到J01111的路径 如何从工作表的底部循环搜索,找到每个单元的最后一个引用?如果它们都是有序的,我可以找到一个,然后抓取下一个156,但不幸的是,它们的顺序并不总是正确的 谢谢大家! ---编辑--- 我正在尝试使用ASC()方法。然而,考虑到我的用户输入是一个变量,我很难获得正确的字符。目前我有: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,但不幸
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上的数据验证:
选项显式
私有子工作表_更改(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