我正在调试此代码,但我不确定为什么这会返回false而不是true。
?Day(i)>salday(0)
False
?Day(i)
31
?salday(0)
20
?isnumeric(day(i))
True
?isnumeric(salday(0))
True
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
答案 0 :(得分:6)
因为您正在比较两个不同类型的import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;
public class MainClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
PrintWriter writer = new PrintWriter("bigfile.txt", "UTF-8");
Random random = new Random();
for(int i = 0; i < 23695522; i++)
{
char[] word = new char[random.nextInt(8)+3]; // words of length 3 through 10. (1 and 2 letter words are boring.)
for(int j = 0; j < word.length; j++)
{
word[j] = (char)('a' + random.nextInt(26));
}
writer.print(new String(word) + ' ');
if (i % 10 == 0){
writer.println();
}
}
writer.close();
} catch (IOException e) {
// do something
}
}
}
(事后我们讨论了...... thx @MatsMug)。比较不同类型的Variant
,一个数字和一个字符串时,比较结果是未定义的行为。
再一次Variant anomalies。考虑一下这个MCVE:
Variants
虽然salday(0)是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
,但明确将String Variant
转换为String
解决了问题。但是,如果没有转换,则比较失败。 VBA没有隐式将数字转换为字符串,反之亦然。它比较了两种不同类型的变体并返回了垃圾结果。
有关变体诅咒的更多信息,请阅读For v=1 to v and For each v in v -- different behavior with different types
事实证明,使用CStr
或CLng
强制进行数字比较是一种安全的方法,或Val
强制进行文字比较。
进一步考虑这三个简单的例子:
CStr
正如您所看到的,当两个变量(数字和字符串)都被声明为变体时,比较就是垃圾。当其中至少有一个是显式的时,比较成功!
答案 1 :(得分:5)
Dim stDate, enDate
该指令声明了两个Variant
变量。他们在这里被分配:
stDate = STG.Range("B2"): enDate = STG.Range("B4")
假设[B2]
和[B4]
包含实际日期值,此时变量包含Variant/Date
。这是因为这里隐含的代码如下:
stDate = STG.Range("B2").Value: enDate = STG.Range("B4").Value
但你可能已经知道了。继续前进。
salDay = Split(STG.Range("B6"), "-")
salDay
也是一个隐含的Variant
。但是这条指令非常有用。这是隐含的代码:
salDay = Split(CStr(STG.Range("B6").Value), "-")
这使salDay
成为一个字符串数组。所以我们在这里:
?Day(i) 31 ?salday(0) 20
31
前面的前导空格是因为直接窗格总是留下负号的位置。 salDay(0)
是String
,没有领先的空间。那是你的线索。
?Day(i)>salday(0) False
如果salday(0)
为String
,我们会在此处进行字符串比较as was already pointed out。除了31之前没有领先的空间;隐式代码就是这样,因为Day(i)
的类型是Integer
:
?CStr(Day(i)) > salDay(0)
False
解决方案是完全摆脱salDay
:你不需要它。假设[B6]
还包含实际日期,您可以立即将这一天变为Integer
:
?Day(STG.Range("B6").Value)
作为奖励,您可以将代码与工作表中基础日期值的字符串表示形式分离,因此更改NumberFormat
不会破坏您的代码。总是把日期视为这样!