VBA - Loop through x items in blocks of 100 x times - vba

I've been struggling with this for a day now.
I have a list box that is populated with x items. Could be 1 - x
I need to take all the items in the list box and format them into a string
which I submit into an oracle database. I'm using INLIST on the SQL side and because of that I can only have a maximum of 100 items in my string.
So for example if I was to have 547 items in the listbox, I would iterate through all 547 items, but at every 100 I would submit into the database, returning my result into my collection class, finishing with the last 47.
here's what i have so far. There is some attempts to solve my problem in the code so if it's confusing i'll try to explain.
Public Function SearchBMS()
On Error GoTo HandleError
Dim rst As ADODB.Recordset
Dim sESN As String
Dim i As Integer
Dim x As Integer
Dim maxrec As Integer
Dim itemcnt As Integer
Dim iBlockCount As Integer
With frmEngineCampaignSearch.lstbxESNNumbers
itemcnt = .ListCount - 2
'iBlockCount = GetBlockCount(itemcnt)
x = 0
maxrec = 100
Debug.Assert itemcnt = 200
For i = 0 To itemcnt
For x = i To maxrec
MsgBox "test", vbOKOnly
i = i + 100
Next x
If i = itemcnt Then ' if I = last item than we put the closing parenthesis on our string
sESN = sESN & "'" & .list(i) & "'"
Else
sESN = sESN & "'" & .list(i) & "' , " ' otherwise there are more items so we seperate by comma
End If
If itemcnt <= 100 Then
Set rst = Nothing
'Set rst = rstGetCustomerInfo(sESN)
'LoadRSTToCollection rst
elseif
While x = maxrec
MsgBox "submit first 100", vbOKOnly
'Set rst = Nothing
'Set rst = rstGetCustomerInfo(sESN)
'LoadRSTToCollection rst
sESN = gC_sEMPTY_STRING
maxrec = maxrec + 100
Wend
x = x + 1
Next i
End With
HandleError:
If Err.Number > 0 Then
MsgBox Err.Number & ": " & Err.Description
End If
This function is to get the number of times I would have to perform the submission but i hit a road block on how to use it within the for loop
Public Function GetBlockCount(ByRef lItemCnt As Long) As Integer
Dim x As Double
If lItemCnt <= 100 Then
GetBlockCount = 1
Exit Function
ElseIf lItemCnt > 100 Then
x = Round(lItemCnt / 100)
If lItemCnt Mod 100 > 0 Then
x = x + 1
Else
GetBlockCount = x
Exit Function
End If
End If
End Function
Any help would be much appreciated.

I think you need to clean it out and make it more readable. Then look at it and the solution will be much clearer.
Here is a simple skeleton of what it should look like:
I = 100
Txt = Get100Requests(I)
Do While Txt <> ""
'use txt
I = I + 100
Txt = Get100Requests(I)
Loop
Function Get100Requests(FromItem As Integer) As String
If FromItem => frmEngineCampaignSearch.lstbxESNNumbers.ListCount Then Exit Function
Dim I As Integer
I + FromItem
Do While I < FromItem + 99 And I < frmEngineCampaignSearch.lstbxESNNumbers.ListCount
Get100Requests = Get100Requests & "'" & frmEngineCampaignSearch.lstbxESNNumbers.list(i) & "', "
I = I + 1
Loop
Get100Requests = Left(Get100Requests, Len(Get100Requests)-2)
Exit Function

Related

Type Mismatch in Dlookup

I'm getting a type mismatch in the Dlookup below. Note: the ID column in the Results2 Table is formatted as a Number.
If DLookup("[Result" & i & "]", "Results2", "[ID] = '" & newid & "'") <> Me.Controls("C" & 3 + column & "R" & i + j).Value Then
I've tried changing the newid from a string to an Integer or a Long, but I still get this error.
Full code for this Sub below, if more info is needed.
Private Sub BtnSave_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim rs3 As DAO.Recordset
Dim i As Integer
Dim j As Integer
Dim ans As Integer
Dim column As Integer
Dim colcnt As Integer
Dim newid As String
If IsNull(Me.Spindle3.Value) = False Then
colcnt = 3
ElseIf IsNull(Me.Spindle2.Value) = False Then
colcnt = 2
Else
colcnt = 1
End If
column = 1
Set db = CurrentDb
Set rs = db.OpenRecordset("Results")
Set rs2 = db.OpenRecordset("Results2")
Set rs3 = db.OpenRecordset("Results3")
Linestart:
j = 0
rs.AddNew
newid = rs![ID].Value
If Me.Result1.Value = "Fail" Or Me.Result2.Value = "Fail" Or Me.Result1.Value = "Fail" Then
If column = 1 Then
ans = MsgBox("This is a FAILING Result. Do you with to save it?", vbYesNo)
If ans = 7 Then GoTo Lineend
End If
ElseIf Me.Result1.Value = "Incomplete" Or Me.Result2.Value = "Incomplete" Or Me.Result2.Value = "Incomplete" Then
If column = 1 Then
ans = MsgBox("Testing is not finished for this part. Do you with to save and close now?", vbYesNo)
If ans = 7 Then GoTo Lineend
End If
End If
With rs
![PartNum] = Me.FilterPartNumber.Value
![INDNum] = Me.INDNum.Value
![DateTime] = Me.DateTime.Value
![HTLotNum] = Me.HTLotNum.Value
![Operator] = Me.Inspector.Value
![Spindle] = Me.Controls("Spindle" & column).Value
![TypeofCheck] = Me.InspType.Value
![OverallResult] = Me.Controls("Result" & column).Value
End With
rs2.AddNew
With rs2
![ID] = newid
![PartNum] = Me.FilterPartNumber.Value
![Plant] = Me.plantnum.Value
![DateTime] = Me.DateTime.Value
![HTLotNum] = Me.HTLotNum.Value
![Notes] = Me.Notes.Value
![Spindle] = Me.Spindle.Value
![TypeofCheck] = Me.InspType.Value
![OverallResult] = Me.Result1.Value
End With
rs3.AddNew
With rs3
![ID] = newid
![PartNum] = Me.FilterPartNumber.Value
![DateTime] = Me.DateTime.Value
End With
If IsNull(Me.HTLotNum.Value) = True Then
rs![HTLotNum] = "(blank)"
rs![HTLotNum] = "(blank)"
End If
For i = 1 To 90 Step 1
If i + j >= 90 Then
i = 90
GoTo Line1
End If
If IsNull(Me.Controls("C3R" & i + j).Value) = True Then
j = j + 1
End If
If i + j >= 90 Then
i = 90
GoTo Line1
End If
If IsNull(Me.Controls("C2R" & i + j).Value) = True Then GoTo Line1
rs("Char" & i) = Me!ListFeatures.column(1, i - 1)
rs("Desc" & i) = Me!ListFeatures.column(2, i - 1)
rs("Spec" & i) = Me!ListFeatures.column(3, i - 1) & " " & Me!ListFeatures.column(6, i - 1)
rs2("SC" & i) = Me!ListFeatures.column(4, i - 1)
rs2("Location" & i) = Me!ListFeatures.column(5, i - 1)
rs2("Result" & i) = Me.Controls("C" & 3 + column & "R" & i + j).Value
rs3("Coding" & i) = Me!ListCoding.column(1, i - 1)
Line1:
Next
rs.Update
rs2.Update
rs3.Update
For i = 1 To 90 Step 1
If i + j >= 90 Then
i = 90
GoTo Line1
End If
If IsNull(Me.Controls("C3R" & i + j).Value) = True Then
j = j + 1
End If
If i + j >= 90 Then
i = 90
GoTo Line1
End If
If DLookup("[Result" & i & "]", "Results2", "[ID] = '" & newid & "'") <> Me.Controls("C" & 3 + column & "R" & i + j).Value Then
MsgBox "Results not saved! Document results on paper and contact the database engineer regarding this error."
GoTo Lineend:
End If
Next
If column < colcnt Then
column = column + 1
GoTo Linestart
End If
Line2:
Forms![Landing Page]![LIstIncomplete].Requery
DoCmd.Close
Lineend:
End Sub
Per one of the comments, I updated the trouble line to the line below. I'm almost certain that was how I initially wrote this line and added the apostrophes as an attempt to fix.
If DLookup("[Result" & i & "]", "Results2", "[ID] = " & newid) <> Me.Controls("C" & 3 + column & "R" & i + j).Value Then
I had to fix one of my Goto's as well, one of them led to an infinite loop, but now everything is working as intended.
Thanks for the help!

How to find the first incident of any signature in a list/array within an email?

I want to give credit to an agent, if they're the one that sent the message, but only if their signature is at the top of the email.
Here is what I have. The search order is off. The code searches for one name at a time, and clear through the document. I need it to search for All names, the first one that hits in the body of the email.
Sub CountOccurences_SpecificText_In_Folder()
Dim MailItem As Outlook.MailItem
Dim strSpecificText As String
Dim tmpStr As String
Dim x As Integer
Dim Count As Integer
Dim HunterCnt As Integer
Dim SunmolaCnt As Integer
Dim RodriguezCnt As Integer
Dim MammedatyCnt As Integer
Dim MitchellCnt As Integer
Dim TannerCnt As Integer
Dim TAYLORCnt As Integer
Dim WilsonCnt As Integer
Dim WilliamsCnt As Integer
Dim GrooverCnt As Integer
Dim TyreeCnt As Integer
Dim ChapmanCnt As Integer
Dim LukerCnt As Integer
Dim KlinedinstCnt As Integer
Dim HicksCnt As Integer
Dim NATHANIALCnt As Integer
Dim SkinnerCnt As Integer
Dim SimonsCnt As Integer
Dim AgentNames(14) As Variant
AgentNames(0) = "Simons"
AgentNames(1) = "Skinner"
AgentNames(2) = "Mammedaty"
AgentNames(3) = "Hunter"
AgentNames(4) = "Sunmola"
AgentNames(5) = "Rodriguez"
AgentNames(6) = "Mitchell"
AgentNames(7) = "Tanner"
AgentNames(8) = "Taylor"
AgentNames(9) = "Wilson"
AgentNames(10) = "Williams"
AgentNames(11) = "Groover"
AgentNames(12) = "Tyree"
AgentNames(13) = "Chapman"
AgentNames(14) = "Luker"
x = 0
While x < ActiveExplorer.Selection.Count
x = x + 1
Set MailItem = ActiveExplorer.Selection.item(x)
tmpStr = MailItem.Body
For Each Agent In AgentNames
If InStr(tmpStr, Agent) <> 0 Then
If Agent = "Assunta" Then
HunterCnt = HunterCnt + 1
GoTo skip
End If
If Agent = "Sunmola" Then
SunmolaCnt = SunmolaCnt + 1
GoTo skip
End If
If Agent = "Rodriguez" Then
RodriguezCnt = RodriguezCnt + 1
GoTo skip
End If
If Agent = "Mammedaty" Then
MammedatyCnt = MammedatyCnt + 1
GoTo skip
End If
If Agent = "Mitchell" Then
MitchellCnt = MitchellCnt + 1
GoTo skip
End If
If Agent = "Tanner" Then
TannerCnt = TannerCnt + 1
GoTo skip
End If
If Agent = "Taylor" Then
TAYLORCnt = TAYLORCnt + 1
GoTo skip
End If
If Agent = "Wilson" Then
WilsonCnt = WilsonCnt + 1
GoTo skip
End If
If Agent = "Williams" Then
WilliamsCnt = WilliamsCnt + 1
GoTo skip
End If
If Agent = "Groover" Then
GrooverCnt = GrooverCnt + 1
GoTo skip
End If
If Agent = "Tyree" Then
TyreeCnt = TyreeCnt + 1
GoTo skip
End If
If Agent = "Chapman" Then
ChapmanCnt = ChapmanCnt + 1
GoTo skip
End If
If Agent = "Luker" Then
LukerCnt = LukerCnt + 1
GoTo skip
End If
If Agent = "Hicks" Then
HicksCnt = HicksCnt + 1
GoTo skip
End If
End If
Next
skip:
Count = Count + 1
Wend
MsgBox "Found " & vbCrLf & "Hunter Count: " & HunterCnt & vbCrLf & "Sunmola Count: " & SunmolaCnt & vbCrLf & "Rodriguez Count: " & RodriguezCnt & vbCrLf & "Mammedaty Count: " & MammedatyCnt & vbCrLf & "Mitchell Count: " & MitchellCnt & vbCrLf & "Tanner Count: " & TannerCnt & vbCrLf & "Taylor Count: " & TAYLORCnt & vbCrLf & "Wilson Count: " & WilsonCnt & vbCrLf & "Williams Count: " & WilliamsCnt & vbCrLf & "Groover Count: " & GrooverCnt & vbCrLf & "Tyree Count: " & TyreeCnt & vbCrLf & "Chapman Count: " & ChapmanCnt & vbCrLf & "Luker Count: " & LukerCnt & vbCrLf & " in: " & Count & " emails"
End Sub
InStr returns positional information. While it is difficult to find the first occurrence of an array member within the text (you would need to build and compare matches), you can find the first position of each name then find which came first.
For example (untested)
Sub CountOccurences_SpecificText_In_Folder()
Dim MailItem As Outlook.MailItem
Dim i As Long, x As Long, position As Long, First As Long
Dim AgentNames() As String
AgentNames = Split("Simons,Skinner,Mammedaty,Hunter,Sunmola,Rodriguez,Mitchell,Tanner,Taylor,Wilson,Williams,Groover,Tyree,Chapman,Luker", ",")
Dim AgentCount(LBound(AgentNames) To UBound(AgentNames)) As Long
For i = LBound(AgentCount) To UBound(AgentCount)
AgentCount(i) = 0
Next i
For Each MailItem In ActiveExplorer.Selection
x = 0
For i = LBound(AgentNames) To UBound(AgentNames)
position = InStr(MailItem.Body, AgentNames(i))
If x > 0 Then
If position < x Then
x = position
First = i
End If
Else
If position > 0 Then
x = position
First = i
End If
End If
Next i
AgentCount(First) = AgentCount(First) + 1
Next MailItem
For i = LBound(AgentNames) To UBound(AgentNames)
Debug.Print AgentNames(i) & " Count: " & AgentCount(i)
Next i
End Sub
The idea in the previous answer may be better implemented like this:
Option Explicit
Sub CountOccurences_SpecificText_SelectedItems()
Dim objItem As Object
Dim objMail As MailItem
Dim i As Long
Dim j As Long
Dim x As Long
Dim position As Long
Dim First As Long
Dim AgentNames() As String
AgentNames = Split("Simons,Skinner,Mammedaty,Hunter,Sunmola,Rodriguez,Mitchell,Tanner,Taylor,Wilson,Williams,Groover,Tyree,Chapman,Luker", ",")
ReDim AgentCount(LBound(AgentNames) To UBound(AgentNames)) As Long
For j = 1 To ActiveExplorer.Selection.Count
Set objItem = ActiveExplorer.Selection(j)
' Verify before attempting to return mailitem poroperties
If TypeOf objItem Is MailItem Then
Set objMail = objItem
Debug.Print
Debug.Print "objMail.Subject: " & objMail.Subject
x = Len(objMail.Body)
For i = LBound(AgentNames) To UBound(AgentNames)
Debug.Print
Debug.Print "AgentNames(i): " & AgentNames(i)
position = InStr(objMail.Body, AgentNames(i))
Debug.Print " position: " & position
If position > 0 Then
If position < x Then
x = position
First = i
End If
End If
Debug.Print "Lowest position: " & x
Debug.Print " Current first: " & AgentNames(First)
Next i
If x < Len(objMail.Body) Then
AgentCount(First) = AgentCount(First) + 1
Debug.Print
Debug.Print AgentNames(First) & " was found first"
Else
Debug.Print "No agent found."
End If
End If
Next
For i = LBound(AgentNames) To UBound(AgentNames)
Debug.Print AgentNames(i) & " Count: " & AgentCount(i)
Next i
End Sub

Displays the result many times in Mulitselect Listbox Search in VB6

I am creating a program in vb6 with ms access. while i am searching the database from multi select list box in vb it displays the results wrongly.
if i click the first item it shows one time
if i click second item it shows that item two times
it i click third item it shows that item three times.
how to solve this
i tried the below code
For i = List1.ListCount - 1 To 0 Step -1
If List1.Selected(i) = True Then
If str <> "" Then str = str & ""
If Val(List1.SelCount) = 1 Then
str = List1.List(List1.ListIndex)
Else
str = str & " or name= " & List1.List(List1.ListIndex)
End If
End If
Next i
If str <> "" Then
Set rs = db.OpenRecordset("select * from Customers where name= '" & str & "'")
display
End If
result
Kumar vasanth vasanth kannan kannan kannan
Try this:
Option Explicit
Private Sub Command1_Click()
Dim i As Integer
Dim str As String
For i = List1.ListCount - 1 To 0 Step -1
If List1.Selected(i) Then str = str & " or name = '" & List1.List(i) & "'"
Next i
str = Mid(str, 4)
If str <> "" Then
Set rs = db.OpenRecordset("select * from Customers where " & str)
display
End If
End Sub

Access-VBA For Loop Executes Only Once

I'm trying to measure the duration between two updates. there is already a table which keeps track of 'lastvalue', 'newvalue' and 'updatetime'. My way is to search for the entities which satisfy the conditions and assign related updatetimes to variables and then compute.
However, my for loops doesn't work they execute only once. I'm new to access-vba and use debug.prints to see how things change (they are permanent). Below is my code, thank you
Private Sub olcum()
Dim gs As Long
Dim db As Database
Dim rs As Recordset
Dim pt As Date
Dim ct As Date
Dim pc As String
Dim cc As String
Dim id As Integer
Dim i As Integer
Dim l As Integer
Dim k As Integer
'Dim a As Index
Dim strMessage As String
Set db = CurrentDb
Set rs = db.OpenRecordset("GecenSure", dbOpenSnapshot)
pc = "acilmasi bekleniyor"
cc = "onayda"
rs.MoveFirst
For i = 0 To (rs.RecordCount - 1)
strMessage = "Burada: " & (rs.AbsolutePosition + 1)
Debug.Print (strMessage)
'Set a = rs.AbsolutePosition
'Debug.Print (a)
id = rs.Fields("Kimlik")
rs.MoveFirst
For l = 0 To (rs.RecordCount - 1)
strMessage = "Burada: " & (rs.AbsolutePosition + 1)
Debug.Print (strMessage)
If (rs.Fields("Kimlik") = id) And (rs.Fields("PreviousCase") = pc) Then
pt = rs.Fields("UpdateTime")
Else
End If
For k = 0 To (rs.RecordCount - (1 + l))
strMessage = "Burada: " & (rs.AbsolutePosition + 1)
Debug.Print (strMessage)
'If (rs.Fields("Kimlik") = id) And (rs.Fields("CurrentCase") = cc) Then
'Debug.Print "rs.AbsolutePosition"
If (rs.Fields("Kimlik") = id) And (rs.Fields("PreviousCase") = cc) Then
ct = rs.Fields("UpdateTime")
Else
End If
'Else
'End If
rs.MoveNext
strMessage = "Burada: " & (rs.AbsolutePosition + 1)
Debug.Print (strMessage)
Next k
'bu prosedurle 2 kere ct atıyor.
rs.MoveFirst
For z = 0 To i
rs.MoveNext
strMessage = "Burada: " & (rs.AbsolutePosition + 1)
Debug.Print (strMessage)
Next z
Next l
gs = ct - pt
Debug.Print gs
'Debug.Print rs.Fields("CurrentCase")
rs.MoveNext
strMessage = "Burada: " & (rs.AbsolutePosition + 1)
Debug.Print (strMessage)
Next i
rs.Close
Set rs = Nothing
db.Close
MsgBox "Simdiki durumlar gosterildi"
End Sub
rs.RecordCount does not return the total number of records in a recordset; rather it returns the number of records that have already been accessed.
There are several options; option 3 is often considered the best, and is the method used in many Microsoft examples:
rs.MoveLast - prior to the loop; this is not a performant option
Query a SQL Count - prior to the loop, determine the number of records
Use a While or Do loop checking for rs.EOF
(see https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2007/bb243789(v=office.12)
An example of the Do loop:
Set rs = db.OpenRecordSet("GecenSure", dbOpenSnapshot)
Do Until rs.EOF
' do something
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
I suggest to use a structure like this:
If Not (rs.BOF And rs.EOF) Then ' if not completely empty
rs.MoveFirst ' start at the beginning
Do While Not rs.EOF ' while not at end
do something
increment i if necessary
' error checking if needed:
If i > ... Or SomethingUnwanted Then Exit Do
rs.MoveNext
Loop
End If
rs.Close

Sending Selected Items to a Cell

I am trying to get the items that I have and initiate all the separate items into its own respective cell.
With Me.selecteditems
For i = 1 To .ListCount - 1
If .Selected(i) Then
found = True
On Error Resume Next
str = ThisWorkbook.Sheets(9).Range("A1:Cells(i, 1)")
quantity = ThisWorkbook.Sheets(9).Range("A1:Cells(i, 2)")
On Error GoTo 0
End If
Next i
End With
This part of the below code, is supposed to put the items that come from the longer part of the code and put in the item, str, and the amount, quantity. I tried different ways and just recently I tried repeating how it was before, it doesn't come out that well. Also without the error it throws me:
Application-defined or Object-defined Error
The Whole Code:
Dim i As Long, j As Long, ii As Long
Dim found As Boolean
Dim str As String
Dim message, title, defaultval As String
Dim quantity As String
With Me.selecteditems
For i = 0 To .ListCount - 1
If .Selected(i) Then
found = True
For ii = 0 To .ColumnCount - 1
If str = "" Then
str = .List(i, ii) & vbTab
Else
If ii < .ColumnCount - 1 Then
str = str & .List(i, ii) & vbTab
Else
str = str & .List(i, ii)
End If
End If
Next ii
message = "How much" & vbCrLf & str & "?"
title = "Amount"
defaultval = "1"
quantity = InputBox(message, title, defaultval)
str = str & " x " & quantity & vbNewLine
End If
Next i
End With
With Me.selecteditems
For i = 1 To .ListCount - 1
If .Selected(i) Then
found = True
On Error Resume Next
str = ThisWorkbook.Sheets(9).Range("A1:Cells(i, 1)")
quantity = ThisWorkbook.Sheets(9).Range("A1:Cells(i, 2)")
On Error GoTo 0
End If
Next i
End With