Roh*_*han 3 excel vba excel-vba
我正在调试这段代码,但我不确定为什么这会返回false而不是true.
?Day(i)>salday(0)
False
?Day(i)
31
?salday(0)
20
?isnumeric(day(i))
True
?isnumeric(salday(0))
True
Run Code Online (Sandbox Code Playgroud)
Option Explicit
Option Compare Text
Sub genOP()
Dim wO As Worksheet
Dim i As Long, j As Long
Dim stDate, enDate, intVal, entR As Long, salDay, salAmt, stTime, enTime, dbMin, dbMax
Dim stRow As Long
Dim cet, curMn
'On Error Resume Next
Application.ScreenUpdating = False
stDate = STG.Range("B2"): enDate = STG.Range("B4")
intVal = Split(STG.Range("B3"), ","): entR = STG.Range("B5")
salDay = Split(STG.Range("B6"), "-")
salAmt = STG.Range("B7"): stTime = STG.Range("B8"): enTime = STG.Range("B9"): dbMin = STG.Range("B10"): dbMax = STG.Range("B11")
Set wO = ThisWorkbook.Sheets.Add
TEMP.Cells.Copy wO.Range("A1")
stRow = 19
curMn = Month(stDate)
For i = CLng(stDate) To CLng(enDate)
If stRow > 19 Then
wO.Rows(stRow & ":" & stRow).Copy
wO.Rows(stRow + 1 & ":" & stRow + 1).Insert Shift:=xlDown
Application.CutCopyMode = False
End If
cet = Trim(DESC.Range("A" & WorksheetFunction.RandBetween(2, DESC.UsedRange.Rows.Count)))
If STG.Range("B14") = "ON" Then
cet = cet & "Transaction amount " & Chr(34) & "&TEXT(H" & stRow & "," & Chr(34) & "#,##0.00" & Chr(34) & ")&" & Chr(34) & " GEL,"
End If
If STG.Range("B13") = "ON" Then
cet = cet & Chr(34) & "&TEXT(B" & stRow & "-1," & Chr(34) & "dd mmm yyyy" & Chr(34) & ")&" & Chr(34)
End If
If STG.Range("B12") = "ON" Then
cet = cet & " " & Format(stTime + Rnd * (enTime - stTime), "HH:MM AM/PM")
End If
If curMn = Month(i) And (Day(i) >= salDay(0) And Day(i) <= salDay(1)) Then 'Salary Day
cet = Trim(DESC.Range("A" & WorksheetFunction.RandBetween(2, DESC.UsedRange.Rows.Count)))
wO.Range("B" & stRow) = Format(i, "DD-MM-YYYY")
wO.Range("I" & stRow) = salAmt
wO.Range("L" & stRow) = MonthName(Month(i)) & "- Salome Baazov - " & "Geo" & " Ltd "
curMn = WorksheetFunction.EDate(i, 1)
Else
wO.Range("B" & stRow) = Format(i, "DD-MM-YYYY")
wO.Range("H" & stRow) = WorksheetFunction.RandBetween(dbMin, dbMax) + (WorksheetFunction.RandBetween(0, 1) * 0.5)
wO.Range("L" & stRow) = "=" & Chr(34) & cet & Chr(34)
End If
stRow = stRow + 1
i = i + intVal(WorksheetFunction.RandBetween(LBound(intVal), UBound(intVal))) - 1
Next i
wO.Rows(stRow).EntireRow.Delete
wO.Range("I" & stRow).Formula = "=SUM(I19:I" & stRow - 1 & ")"
wO.Range("H" & stRow).Formula = "=SUM(H19:H" & stRow - 1 & ")"
wO.Activate
Application.ScreenUpdating = True
STG.Range("B5") = stRow - 1
MsgBox "Process Completed"
End Sub
Run Code Online (Sandbox Code Playgroud)
因为你正在比较Variant
不同类型的两个(事后我们讨论了...... thx @MatsMug).比较Variants
不同类型,一个数字和一个String 时,比较结果是未定义的行为.
再一次是Variant异常.考虑一下这个MCVE:
Sub Test1()
Dim i, salday
i = CDate("5/30/2017")
salday = Split("20-20-20", "-")
Debug.Print Day(i), salday(0) ' 30 20
Debug.Print Day(i) > salday(0) ' False
Debug.Print Day(i) > CStr(salday(0)) ' True
' ^^^^
Debug.Print Val(Day(i)) > salday(0) ' True
' ^^^^
End Sub
Run Code Online (Sandbox Code Playgroud)
虽然salday(0)是String Variant
,明确地将其转换为String
与CStr
解决的问题.但是,如果没有转换,则比较失败.VBA没有隐式地将数字转换为字符串,反之亦然.它比较了两种不同类型的变体并返回了垃圾结果.
有关Variant诅咒的更多信息,请阅读For v = 1 to v和For v in v - 不同类型的行为
事实证明,使用CLng
或Val
强制数字比较是安全的方法,或CStr
强制文本比较.
进一步考虑这三个简单的例子:
Sub Test1()
Dim x, y: x = 30: y = "20"
Debug.Print x > y ' False !!
End Sub
Sub Test2()
Dim x As Long, y: x = 30: y = "20"
' ^^^^^^
Debug.Print x > y ' True
End Sub
Sub Test3()
Dim x, y As String: x = 30: y = "20"
' ^^^^^^
Debug.Print x > y ' True
End Sub
Run Code Online (Sandbox Code Playgroud)
如您所见,当两个变量(数字和字符串)都被声明为变体时,比较就是垃圾.当其中至少有一个是显式的时,比较成功!
Run Code Online (Sandbox Code Playgroud)Dim stDate, enDate
该指令声明了两个Variant
变量.他们被分配到这里:
Run Code Online (Sandbox Code Playgroud)stDate = STG.Range("B2"): enDate = STG.Range("B4")
假设[B2]
并[B4]
包含实际日期值,此时变量包含a Variant/Date
.那是因为这里隐含的代码如下:
stDate = STG.Range("B2").Value: enDate = STG.Range("B4").Value
Run Code Online (Sandbox Code Playgroud)
但你可能已经知道了.继续.
Run Code Online (Sandbox Code Playgroud)salDay = Split(STG.Range("B6"), "-")
salDay
也是隐含的Variant
.但是这条指令非常有用.这是隐式代码:
salDay = Split(CStr(STG.Range("B6").Value), "-")
Run Code Online (Sandbox Code Playgroud)
这会产生salDay
一个字符串数组.所以我们在这里:
Run Code Online (Sandbox Code Playgroud)?Day(i) 31 ?salday(0) 20
前面的前方空间31
是因为直接窗格总是留下负号的位置.salDay(0)
作为一个String
,没有领先的空间.那是你的线索.
Run Code Online (Sandbox Code Playgroud)?Day(i)>salday(0) False
随着salday(0)
是一个String
,我们在这里做一个字符串比较,如已经指出.除了31前面没有领先的空间; 隐式代码是这样的,因为类型Day(i)
是Integer
:
?CStr(Day(i)) > salDay(0)
False
Run Code Online (Sandbox Code Playgroud)
解决方案是salDay
完全摆脱:你不需要它.假设[B6]
还包含一个实际日期,您可以Integer
马上进入当天:
?Day(STG.Range("B6").Value)
Run Code Online (Sandbox Code Playgroud)
作为奖励,您可以将代码与工作表中基础日期值的字符串表示形式分离,因此更改NumberFormat
不会破坏您的代码.始终对待日期!
归档时间: |
|
查看次数: |
123 次 |
最近记录: |