For Loop: Skip to next line after X seconds - vb.net

Can someone help me with this code:
I have a dataGrid with 2 columns:
and what I want to do is use PStools' Psloggedon cmd to give me the name of every person logged in and append that result to the "LOGGED_IN" column but what is happening is that if there is no user logged into a PC, the process takes like 5 minutes to post an error message.
Now, what I want to do is that if .5 seconds has gone to just forget the row it's currently querying and move on to the next row, in the column?
here is the vb.net code i want to focus on:
Dim RowCount As Integer = datagridView1.RowCount
For i = 0 To RowCount - 2
'PERFORM PSLOGGEDON ROUTINE
Dim Proc1 As New Process
Proc1.StartInfo = New ProcessStartInfo("psloggedon")
Proc1.StartInfo.Arguments = "-l \\" & datagridView1.Rows(i).Cells(0).Value & ""
Proc1.StartInfo.RedirectStandardOutput = True
Proc1.StartInfo.UseShellExecute = False
Proc1.StartInfo.CreateNoWindow = True
Proc1.Start()
'INSERT RESULTS IN LOGGEN_IN COLUMN
datagridView1.Rows(i).Cells(1).Value = Proc1.StandardOutput.ReadToEnd
Next
Can someone please show me how to write the code to get that done?

Use Process.WaitForExit(int milliseconds) method.
Instructs the Process component to wait the specified number of milliseconds for the associated process to exit.
Return Value
Type: System.Boolean
true if the associated process has exited; otherwise, false.
You can then use Process.Kill to kill process if it did not exit in given time.
Something like
Dim RowCount As Integer = datagridView1.RowCount
For i = 0 To RowCount - 2
'PERFORM PSLOGGEDON ROUTINE
Dim Proc1 As New Process
Proc1.StartInfo = New ProcessStartInfo("psloggedon")
Proc1.StartInfo.Arguments = "-l \\" & datagridView1.Rows(i).Cells(0).Value & ""
Proc1.StartInfo.RedirectStandardOutput = True
Proc1.StartInfo.UseShellExecute = False
Proc1.StartInfo.CreateNoWindow = True
Proc1.Start()
If Not Proc1.WaitForExit(5000) Then
Proc1.Kill()
End If
'INSERT RESULTS IN LOGGEN_IN COLUMN
datagridView1.Rows(i).Cells(1).Value = Proc1.StandardOutput.ReadToEnd
Next

Related

vba excel If condition error on final iteration

I'm having the code takes the input from my checkboxes and grab data from the related worksheet. I ran it line by line and found out that it always gets a runtime error at the If statement on the final loop. Is there something wrong in my code?
Option Explicit
Private Sub UserForm_Initialize()
Dim counter As Long
Dim chkBox As MSForms.CheckBox
''''Add checkboxes based on total sheet count
For counter = 1 To Sheets.count - 2
Set chkBox = Me.Frame1.Controls.Add("Forms.CheckBox.1", "CheckBox" & counter)
chkBox.Caption = Sheets(counter + 2).Name
chkBox.Left = 10
chkBox.Top = 5 + ((counter - 1) * 20)
Next
End Sub
Private Sub cmdContinue_Click()
Dim Series As Object
Dim counter As Long
'''Clear old series
For Each Series In Sheets(2).SeriesCollection
Sheets(2).SeriesCollection(1).Delete
Next
''Cycle through checkboxes
For counter = 1 To Sheets.count - 2
''If the box is checked then
If Me.Frame1.Controls(counter).Value = True Then ''Error here on 4th iteration
''Add new series
With Sheets(2).SeriesCollection.NewSeries
.Name = Sheets(counter + 2).Range("$A$1")
.XValues = Sheets(counter + 2).Range("$A$12:$A$25")
.Values = Sheets(counter + 2).Range("$B$12:$B$25")
End With
End If
Next counter
Me.Hide
End Sub
Also, a second problem is it always run on the wrong loop. If i check box 2 it'll run data for the box 1 sheet, 3 run for 2, 4 run for 3, and 1 run for 4. Can anyone explain the reason behind this?
EDIT: So as VincentG point out below, adding an explicit name "checkbox" in there did the trick (i didn't know you could do that). Index 1 was probably taken by one of the buttons or the frame in the user form, causing it to get off set.
I guess your main problem comes from the fact that the controls have to be accessed starting from index 0. So to loop over all controls, you would do something like
For counter = 0 To Me.Frame1.Controls.Count - 1
Debug.Print counter; Me.Frame1.Controls(counter).Name
Next counter
So, when you stick to you code, I assume you have to change the if-statement to
If Me.Frame1.Controls(counter-1).Value = True Then

Excel vba: program takes a long time if status bar is renewed

I have a program that creates 100 000 objects of class Client, puts them into array and then goes through that array 100 times, each time assigning each Client a different random number through Rnd() function:
Main sub:
Sub start()
Dim i As Long
Dim j As Long
Dim clientsColl() As Client
ReDim clientsColl(1 To 100000) As Client
For j = 1 To 100000
Set clientsColl(j) = New Client
clientsColl(j).setClientName = "Client_" & j
Application.StatusBar = "Getting client " & j
DoEvents
Next
Dim tempCount As Long
Dim clientCopy As Variant
For i = 1 To 100
tempCount = 0
For Each clientCopy In clientsColl
tempCount = tempCount + 1
clientCopy.generateRandom
'Application.StatusBar = "Calculating " & i & ": " & tempCount & "/" & 100000 '(1)
'DoEvents
Next
Application.StatusBar = "Calculating " & i
DoEvents
Next
MsgBox ("done")
End Sub
Client class:
Option Explicit
Dim clientName As String
Dim randomNumber As Double
Public Sub generateRandom()
randomNumber = Rnd()
End Sub
Public Property Get getClientName()
getClientName = clientName
End Property
Public Property Let setClientName(value As String)
clientName = value
End Property
The problem is, the execution time depends on whether or not line (1) is commented out. If it's executed, the statusbar gets renewed, but the execution time is very slow. If it's not executed, the program gets done really fast.
Why does this happen?
VBA is fast enough as long as you stay within. Whenever you turn to Excel, it may get much slower because Excel makes thousands of operations every time it gets control. You may consider turning off a few more services of Excel like I do in my applications:
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.EnableEvents = False
ActiveSheet.DisplayPageBreaks = False
... and as far as I know DoEvents is the best way to make Excel update the status bar when you turn off automatic updates.
Another timesaving workaround can be to display only every 100th or 1000th message from within the inner loop.
when doing a progressbar or statusbar, you need to use it wisely.
Basically the progress info needs to be refreshed only every 0.1 seconds or so.
Knowing your max number of loops , and the time it takes, you might want to update the info only every (in your case) , let's say, 100 iterations of the loop.
This is done like this: if j mod 100=0 then application.statusbar="..." : doevents
Usually i even go further by using doevents less than my progressbar (second if j mod).

VB.NET - Unable to retrieve the first ID on a table using SELECT query

Good day everyone! After 3 years without using VB.NET I decided to use again for my project that not require web development.
this is my code (Reference: link)
cmdOLEDB.CommandText = "SELECT Price FROM tblPrice"
cmdOLEDB.Connection = cnnOLEDB
Dim rdrOLEDB As OleDbDataReader = cmdOLEDB.ExecuteReader
Dim priceList(18) As String
Dim i As Integer = 0
If rdrOLEDB.Read = True Then
While rdrOLEDB.Read()
priceList(i) = rdrOLEDB.GetValue(0)
i += 1
End While
txtPrice1.Text = priceList(0).ToString
cnnOLEDB.Close()
Else
MsgBox("Record not found.")
cnnOLEDB.Close()
End If
when I put this code in a MsgBox
MsgBox(rdrOLEDB.GetValue(0))
the result is "2" but I have 1 more data before that. It means the query retrieve the ID # 2 not the ID # 1. Here's the screenshot on my Access database
and when I use this code:
txtPrice1.Text = priceList(17).ToString
the result is 35.
You are skipping the first record because you call two times the Read method.
The first call reads the first record and returns true, then you enter the while loop extracting the info, but at this point you are on the second record.
If you want to check if there are rows then call HasRows
If rdrOLEDB.HasRows Then
While rdrOLEDB.Read()
priceList(i) = rdrOLEDB.GetValue(0)
i += 1
End While
txtPrice1.Text = priceList(0).ToString
cnnOLEDB.Close()
Else
MsgBox("Record not found.")
cnnOLEDB.Close()
End If
Please check with If condition , replace rdrOLEDB.Read with rdrOLEDB.hasrows
If rdrOLEDB.Hasrows= True Then
and check it again.

Inserting row second time in a loop gives me error, I need to stop macro, save document and restart it to insert the next

I have a VBA macro in excel that are searching for a value in a column and when it is found, it should insert a new, empty row and then continue to search for the next place to insert a new row.
It searches the cells in a column in a loop, it finds the value it's supposed to find and a new row is inserted. The loop resets and it searches the column again for a new value. However, when it finds this value, it does not give me a new row. An "out of memory" message pops up and the macro stops. At that time, I can't manually insert rows either untill I save my document. If I save it, I can re-run my macro and it runs one time without issues and then I get the same result.
I have tried all combinations in the recalculation-settings, I think. I have converted the whole code from using .Select, .Offset etc to use Cells() but the problem is the same. Only differense is that it runs a bit faster now.
This is a sample of the code giving me this issue:
Do While True
currentRow = 1
stringComparer = "PRM_" & prmNumber
Do While True
currentString = Cells(currentRow, parameterColumn)
If StrComp(currentString, stringComparer) = 0 Then
Cells(currentRow, parameterColumn).EntireRow.Insert
Exit Do
End If
currentRow = currentRow + 1
Loop
prmNumber = prmNumber + 1
Loop
Dim parameterColumn As Integer
Dim prmNumber As Integer
Dim Match As Boolean
Match = False
parameterColumn = 1
currentRow = 1
currentString = Cells(currentRow, parameterColumn)
' loop until you reach the end of the data
Do While currentString <> ""
'for each row, check for each of the parameters (I wasnt sure how many you have)
For prmNumber = 1 To 10
If StrComp(currentString, "PRM_" & CStr(prmNumber)) = 0 Then
Match = True
End If
Next
' if there is a match, insert a row and add 2 to the current row (to include the inserted row)
If Match Then
Cells(currentRow, parameterColumn).EntireRow.Insert
currentRow = currentRow + 2
Else
' if there isnt a match, only add 1
currentRow = currentRow + 1
End If
Match = False
currentString = Cells(currentRow, parameterColumn)
Loop

Reading excel rows and simultaneously processing it

I have an Excel sheet and its humongous.. Around like 200000 rows that needs to be processed.
All I have to do is read it and process them with a query on a DB2 table. I have written the program where its more than 8 hours to process 5000 rows.
Is there a way where I can simultaneously read the excel and execute the query. I want them to be independent of the process. I cannot use Parallel.for as reading and creating so many instance of threads is no advantage. ANy pipes and queues are of no use. THis is a dom method using and it does not read a row, it reads a string.. if there is a null value on the row, it executes the row and throws an null exception. I am well with Background workers and TPL's. Any idea or code would be appreciated. No DLL can be used apart from OPENXML
Ideally I do not want to add to array,, I want it in 2 diff variables and process them when read..
Read a row( only 2 columns, ignore other cols
create a thread to execute the row and in Parallel, execute the read row.
Merge into one single table.
display results.. Sounds simple but there are challenges.
.
Try
Using spreadsheetDocument As SpreadsheetDocument = spreadsheetDocument.Open(fileName, False)
Dim workbookPart As WorkbookPart = spreadsheetDocument.WorkbookPart
Dim worksheetPart As WorksheetPart = workbookPart.WorksheetParts.First()
Dim sheetData As SheetData = worksheetPart.Worksheet.Elements(Of SheetData)().First()
For Each r As Row In sheetData.Elements(Of Row)()
For Each c As Cell In r.Elements(Of Cell)()
Dim text As String
Try
text = c.CellValue.Text.ToString
Debug.Print(text.ToString)
If text IsNot Nothing AndAlso Trim(text).Length > 0 Then
Arr.Add(text.ToString)
End If
text = Nothing
j += 1
Catch
End Try
Next
text = Nothing
Next
End Using
Catch ex As Exception
MsgBox("Exception caught: " + ex.Message)
Debug.Print(ex.Message.ToString)
End
End Try
myArr = CType(Arr.ToArray(GetType(String)), String())
This is the process which is dividing the data into 2 parameters
For i As Integer = 2 To myArr.Count - 1 Step 2
If i And 1 Then
i = i - 1
Else
dstr = DateTime.FromOADate(Double.Parse(myArr(i).ToString())).ToShortDateString()
'Debug.Print(dstr.ToString & "----->" & i.ToString & "TCID--->" & myArr(i + 1).ToString)
DQueue.Enqueue(DateTime.FromOADate(Double.Parse(myArr(i).ToString())).ToShortDateString())
Tqueue.Enqueue((myArr(i + 1).ToString()))
TCArr.Add((myArr(i + 1).ToString()))
dc.Merge(ProcessQueryODBC(dstr, myArr(i + 1).ToString))
If dc.Rows.Count > 0 Then
dt.Merge(dc)
Else
nFound.Merge(CreateDT(dstr, myArr(i + 1).ToString()))
End If
End If
Next
Instead of opening a DB connection through ODBC. Can you export your data to a CSV file and then let DB2 perform the import?
somestring = "import from "myfile.csv" of DEL ...."
DoCmd.RunSQL somestring