我有一个代码生成随机包含8个字符的字符字符串(密码)。我的问题是只填充数字和字符。
1)我想在混音中包括特殊字符,并确保每个字符串中始终至少包含一个特殊字符。
2)我需要添加一个条件,即每个字符串始终包含至少一个大写字母,至少一个小写字母,至少一个数字。
这是我的代码,但是我无法弄清楚如何包括这些条件以使其按需工作。我已经尝试了很多谷歌搜索,使其专用于此代码,但无法弄清楚。你能请教吗?
Sub MakeRandom()
Dim J As Integer
Dim K As Integer
Dim L As Double
Dim iTemp As Integer
Dim sNumber As String
Dim bOK As Boolean
Range("G5:G148").Activate
Randomize
L = InputBox("Amount of Passwords:")
For J = 1 To L
sNumber = ""
For K = 1 To 8
Do
iTemp = Int((122 - 48 + 1) * Rnd + 48)
Select Case iTemp
Case 48 To 57, 97 To 122
bOK = True
Case Else
bOK = False
End Select
Loop Until bOK
bOK = False
sNumber = sNumber & Chr(iTemp)
Next K
ActiveCell.Value = sNumber
ActiveCell.Offset(1, 0).Select
Next J
End Sub
我将不胜感激。
答案 0 :(得分:0)
为什么不引入包含所有合法字符的长字符串,然后让您的算法从该字符串的随机位置中选择字符?这样,您可以轻松控制密码中的内容。
为确保条件成立,我将密码生成置于无限循环中,该循环仅在满足所有条件时结束。只要这实际上是可能的(也就是说,您的条件可以同时全部成立),则此循环最终将终止(由于大数定律)。
答案 1 :(得分:0)
我有一些可能对您有所帮助的东西。我使用不同的方法,但结果应该相似。我已根据您的限制进行了调整,但可能遗漏了一些东西。
我的工作原理是这样的:我有一个名为ChrSrc
的工作表,其中包含我希望能够包含在字符串中的所有字符。字符已分为四列。从A到D列是小写字母,大写字母,数字,特殊字符。
创建一个数组来存储字符并创建随机字符串。该数组包含3个“列”。第一个给出1到4之间的数字,以确定应该从哪一列获取其字符。前四个始终为1,2,3,4,以确保每种字符至少使用一次。随机填充其他4个(如果随机字符串较长则更多)。
然后在第二个“列”中填充实际字符以添加到随机字符串中。最后,第三个“列”用零填充。这些将用于跟踪随机字符串中使用了哪些字符。
一旦数组被填满,do while loop
用于随机选择字符的顺序。添加字符后,将数组中的零更改为1,以确保每个字符都使用一次。
最后,您的随机字符串位于变量RandomString
中,您可以将其写入单元格或对其进行任何操作。
如果您想一次创建多个字符串,建议您编写一个小的调用者子程序,该子程序调用此子程序的次数为x。或在其中添加一个循环和输入框。
希望有帮助。
Sub CreateString()
Dim StringArray() As Variant
Dim PositionCount As Long
Dim Lr As Long
Dim RandomString As String
Dim arrIndex As Long
Dim Loopcount As Long
Dim StringLength As Long
StringLength = 8
ReDim StringArray(1 To StringLength, 1 To 3)
For PositionCount = 1 To StringLength
If PositionCount > 4 Then
StringArray(PositionCount, 1) = Random(4)
Else
StringArray(PositionCount, 1) = PositionCount
End If
'lastrow for each character category, adjust as needed
Select Case StringArray(PositionCount, 1)
Case Is <= 2
Lr = 26
Case Is = 3
Lr = 10
Case Is = 4
Lr = 17
End Select
StringArray(PositionCount, 2) = ThisWorkbook.Sheets("ChrSrc").Cells(Random(Lr), StringArray(PositionCount, 1))
StringArray(PositionCount, 3) = 0
Next
Do While Len(RandomString) < StringLength
arrIndex = Random(StringLength)
If StringArray(arrIndex, 3) = 0 Then
RandomString = RandomString & StringArray(arrIndex, 2)
StringArray(arrIndex, 3) = 1
End If
Loopcount = Loopcount + 1
Loop
End Sub
Function Random(Max As Long)
Random = Int(Max * Rnd) + 1
End Function
答案 2 :(得分:0)
Activate
和Select
。在您的情况下,您可以创建一个随机字符串数组,然后将该数组写入工作表。数组的长度可以由InputBox
返回的值控制。L = InputBox("Amount of Passwords:", Type:=1)
,如果我正确阅读了文档,它将验证输入为数字。Long
而不是Integer
(因为Integer
现在已经转换为Long
了)。此外,在这种情况下,您将收到任意用户输入,Integer
类型将在32768处溢出。例如,如果您在InputBox
中输入32768(例如)或更大的数字,则会看到未处理的溢出错误。参考此答案(https://stackoverflow.com/a/57903244/8811778)中描述的方法:
Option Explicit
Private Function CreateRandomString(Optional ByVal lengthOfOutput As Long = 8, Optional ByVal minimumCountOfNumbers As Long = 1, Optional ByVal minimumCountOfLetters As Long = 1, Optional ByVal minimumCountOfSymbols As Long = 1) As String
Dim countRemaining As Long
countRemaining = lengthOfOutput - (minimumCountOfLetters + minimumCountOfNumbers + minimumCountOfSymbols)
Debug.Assert countRemaining >= 0
Const LETTERS_ALLOWED As String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
Const NUMBERS_ALLOWED As String = "0123456789"
Const SYMBOLS_ALLOWED As String = "!""£$%^&*()-_+[]{};:'@#" ' Change as necessary, I do not know what symbols you want included.
Dim toJoin() As String
ReDim toJoin(1 To 4)
toJoin(1) = GetRandomCharactersFromText(LETTERS_ALLOWED, minimumCountOfLetters, duplicatesAllowed:=False)
toJoin(2) = GetRandomCharactersFromText(NUMBERS_ALLOWED, minimumCountOfNumbers, duplicatesAllowed:=False)
toJoin(3) = GetRandomCharactersFromText(SYMBOLS_ALLOWED, minimumCountOfSymbols, duplicatesAllowed:=False)
' I arbitrarily pad the rest of the string with random letters, but you can change this logic.
toJoin(4) = GetRandomCharactersFromText(LETTERS_ALLOWED, countRemaining, duplicatesAllowed:=False)
Dim outputString As String
outputString = Join(toJoin, vbNullString)
' This step is meant to scramble the characters in the string.
' Otherwise, the returned string's structure would reflect the code above:
' • w letters, followed by x numbers, followed by y symbols, followed by z characters
' which stops it being pseudo-random.
outputString = GetRandomCharactersFromText(outputString, Len(outputString), False)
CreateRandomString = outputString
End Function
Private Function RandomBetween(ByVal lowerLimit As Long, ByVal upperLimit As Long) As Long
' Could use Application.RandBetween instead (maybe). But maybe there is some performance difference.
' https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/rnd-function
RandomBetween = Int((upperLimit - lowerLimit + 1) * Rnd + lowerLimit)
End Function
Private Function GetRandomCharactersFromText(ByVal someText As String, ByVal numberOfCharactersToGet As Long, Optional ByVal duplicatesAllowed As Boolean = True) As String
' Returns n characters from a given string. Characters are chosen pseudo-randomly.
' "duplicatesAllowed" controls whether a given index can be chosen more than once.
Dim chosenIndexes() As Long
ReDim chosenIndexes(1 To numberOfCharactersToGet)
Dim characterIndex As Long
For characterIndex = 1 To numberOfCharactersToGet
Do While True
Dim randomCharacterIndex As Long
randomCharacterIndex = RandomBetween(1, Len(someText))
If duplicatesAllowed Then Exit Do
If IsError(Application.Match(randomCharacterIndex, chosenIndexes, 0)) Then Exit Do
Loop
chosenIndexes(characterIndex) = randomCharacterIndex
Next characterIndex
Dim chosenCharacters() As String
ReDim chosenCharacters(1 To numberOfCharactersToGet)
For characterIndex = 1 To numberOfCharactersToGet
randomCharacterIndex = chosenIndexes(characterIndex)
chosenCharacters(characterIndex) = Mid(someText, randomCharacterIndex, 1)
Next characterIndex
GetRandomCharactersFromText = Join(chosenCharacters, vbNullString)
End Function
GetRandomCharactersFromText
函数完成。For K = 1 to 8
循环,并用ActiveCell.Value = CreateRandomString(lengthOfOutput:=8, minimumCountOfNumbers:=1, minimumCountOfSymbols:=1)
之类的东西替换(尽管您应该避免使用ActiveCell
,并且通常依赖于活动对象) 。