I am having an issue changing runtime generated checkbox names in runtime generated groupboxes. I am using multiple groupboxes, and then taking all of the rows in a database and creating checkboxes for them. The checkbox names are as follows ""chkClass" & intGroupBoxNumber & intCurrentRow". Upon deletion of a groupbox, I renumber all of the current group boxes, and would like the checkbox names to change as well to the new groupbox number, if this makes any sense. My code is as follows:
strControlName = "grpGroup" & strIBResult
Try
intGroupBoxOldYLocation = Me.Controls(strControlName).Location
Me.Controls(strControlName).Dispose()
MessageBox.Show("Deleted: " & strControlName)
intRenameGroup = strIBResult + 1
Try
strControlName = "grpGroup" & intRenameGroup
strControlNewName = "grpGroup" & intRenameGroup - 1
Me.Controls(strControlName).Location = intGroupBoxOldYLocation
Me.Controls(strControlName).Text = "Group " & intRenameGroup - 1
Me.Controls(strControlName).Name = strControlNewName
MessageBox.Show("Changed: " & strControlName & " to: " & strControlNewName)
Do While intCurrentClassRow < intTotalClassRows
strCheckBoxOldName = "chkClass" & intRenameGroup & intCurrentClassRow
strCheckBoxNewName = "chkClass" & intRenameGroup - 1 & intCurrentClassRow
MessageBox.Show("Renaming: " & strCheckBoxOldName & " to: " & strCheckBoxNewName)
Me.Controls(strCheckBoxOldName).Name = strCheckBoxNewName
intCurrentClassRow += 1
MessageBox.Show("Renamed: " & strCheckBoxOldName & " to: " & strCheckBoxNewName)
Loop
intCurrentClassRow = 0
intRenameGroup += 1
intGroupBoxNewYIncrement = intGroupBoxOldYLocation.Y + Me.Controls(strControlNewName).Height + 50
Do
strControlName = "grpGroup" & intRenameGroup
strControlNewName = "grpGroup" & intRenameGroup - 1
Me.Controls(strControlName).Location = New Point(intCurrentXPosition, intGroupBoxNewYIncrement)
Me.Controls(strControlName).Text = "Group " & intRenameGroup - 1
Me.Controls(strControlName).Name = strControlNewName
Do While intCurrentClassRow < intTotalClassRows
strCheckBoxOldName = "chkClass" & intRenameGroup & intCurrentClassRow
strCheckBoxNewName = "chkClass" & intRenameGroup - 1 & intCurrentClassRow
Me.Controls(strCheckBoxOldName).Name = strCheckBoxNewName
intCurrentClassRow += 1
MessageBox.Show("Renamed: " & strCheckBoxOldName & " to: " & strCheckBoxNewName)
Loop
intCurrentClassRow = 0
intRenameGroup += 1
intGroupBoxNewYIncrement = intGroupBoxNewYIncrement + Me.Controls(strControlNewName).Height + 50
Loop
Catch ex As Exception
MessageBox.Show("Control: " & strControlName & " does not exist")
MessageBox.Show(ErrorToString)
End Try
Catch ex As Exception
'MessageBox.Show("Control: " & strControlName & " never existed")
MessageBox.Show("Please enter a valid group number to delete.", "Invalid Entry")
Exit Sub
End Try
I am pretty sure my trouble now exists at the Me.Controls(strCheckBoxOldName).Name = strCheckBoxNewName
The error is as follows: "Object reference not set to an instance of an object"
Is there a different method to reference that runtime generated groupbox?
Thanks. Sorry if this is confusing!
The form's Controls collection only contains the top-level controls that are placed directly on the form. If you load a control into a container control, such as a GroupBox, you must find it in that container control's Controls collection.
So, instead of doing this:
Me.Controls(strCheckBoxOldName).Name = strCheckBoxNewName
You should be doing something like this:
Me.Controls(strControlName).Controls(strCheckBoxOldName).Name = strCheckBoxNewName
I would temporarily comment out the try/catch blocks. Then the application will break at the offending statement and you won't have to be just "pretty sure" where the problem is. Then, check the values of the associated variables (highlight, shfit-F9). You'll probably find that one of the objects has a value of nothing. This causes the error message you mentioned.
Related
Is it possible to list the conditional formatting of all controls on a form? I'd like to be able to list out all existing conditions so that I can generate code to add/remove the existing conditions. I have inherited some complex forms and want to know what I'm dealing with and then generate some code to toggle the conditional formatting in areas where it is slowing down navigating a continuous form.
This Excel VBA example shows a similar format I'd like to have for Access.
https://stackoverflow.com/a/52204597/1898524
Only textboxes and comboboxes have Conditional Formatting.
There is no single property that can be listed to show a control's conditional formatting rule(s). Each rule has attributes that can be listed. Example of listing for a single specific control:
Private Sub Command25_Click()
Dim x As Integer
With Me.tbxRate
For x = 0 To .FormatConditions.Count - 1
Debug.Print .FormatConditions(x).BackColor
Debug.Print .FormatConditions(x).Expression1
Debug.Print .FormatConditions(x).FontBold
Next
End With
End Sub
The output for this example:
2366701
20
False
These are attributes for a rule that sets backcolor to red when field value is greater than 20.
Yes, code can loop through controls on form, test for textbox and combobox types, determine if there are CF rules and output attributes.
With some inspiration from #June7's example and some code from an article I found by Garry Robinson, I wrote a procedure that answers my question.
Here's the output in the Immediate window. This is ready to be pasted into a module. The design time property values are shown as a comment.
txtRowColor.FormatConditions.Delete
txtRowColor.FormatConditions.Add acExpression, acBetween, "[txtCurrent_Equipment_List_ID]=[txtEquipment_List_ID]"
With txtRowColor.FormatConditions.Item(txtRowColor.FormatConditions.Count-1)
.Enabled = True ' txtRowColor.Enabled=False
.ForeColor = 0 ' txtRowColor.ForeColor=-2147483640
.BackColor = 10092543 ' txtRowColor.BackColor=11850710
End With
You can test this sub from a click event on an open form. I was getting some false positives when checking the Boolean .Enabled property, even when I store the values into Boolean variables first. I don't know why and am researching it, but that is beyond the scope of this question.
Public Sub ListConditionalFormats(frmForm As Form)
' Show all the Textbox and Combobox controls on the passed form object (assuming the form is open).
' Output the FormatCondtion properties to the immediate window in a format that is
' suitable to be copied into VBA to recreate the conditional formatting.
' The design property value is shown as a comment on each condition property row.
Dim ctl As Control
Dim i As Integer
Dim bolControlEnabled As Boolean
Dim bolFormatEnabled As Boolean
On Error GoTo ErrorHandler
For Each ctl In frmForm.Controls
If TypeOf ctl Is TextBox Or TypeOf ctl Is ComboBox Then
With ctl
If .FormatConditions.Count > 0 Then
'Debug.Print vbCr & "' " & ctl.Name, "Count = " & .FormatConditions.Count
For i = 0 To .FormatConditions.Count - 1
' Generate code that can recreate each FormatCondition
Debug.Print ctl.Name & ".FormatConditions.Delete"
Debug.Print ctl.Name & ".FormatConditions.Add " & DecodeType(.FormatConditions(i).Type) _
& ", " & DecodeOp(.FormatConditions(i).Operator) _
& ", """ & Replace(.FormatConditions(i).Expression1, """", """""") & """" _
& IIf(Len(.FormatConditions(i).Expression2) > 0, ", " & .FormatConditions(i).Expression2, "")
Debug.Print "With " & ctl.Name & ".FormatConditions.Item(" & ctl.Name & ".FormatConditions.Count-1)"
bolControlEnabled = ctl.Enabled
bolFormatEnabled = .FormatConditions(i).Enabled
'Debug.Print bolControlEnabled <> bolFormatEnabled, bolControlEnabled, bolFormatEnabled
If bolControlEnabled <> bolFormatEnabled Then ' <- This sometimes fails. BS 2/9/2020
'If ctl.Enabled <> .FormatConditions(i).Enabled Then ' <- This sometimes fails. BS 2/9/2020
Debug.Print vbTab & ".Enabled = " & .FormatConditions(i).Enabled; Tab(40); "' " & ctl.Name & ".Enabled=" & ctl.Enabled
End If
If ctl.ForeColor <> .FormatConditions(i).ForeColor Then
Debug.Print vbTab & ".ForeColor = " & .FormatConditions(i).ForeColor; Tab(40); "' " & ctl.Name & ".ForeColor=" & ctl.ForeColor
End If
If ctl.BackColor <> .FormatConditions(i).BackColor Then
Debug.Print vbTab & ".BackColor = " & .FormatConditions(i).BackColor; Tab(40); "' " & ctl.Name & ".BackColor=" & ctl.BackColor
End If
If ctl.FontBold <> .FormatConditions(i).FontBold Then
Debug.Print vbTab & ".FontBold = " & .FormatConditions(i).FontBold; Tab(40); "' " & ctl.Name & ".FontBold=" & ctl.FontBold
End If
If ctl.FontItalic <> .FormatConditions(i).FontItalic Then
Debug.Print vbTab & ".FontItalic = " & .FormatConditions(i).FontItalic; Tab(40); "' " & ctl.Name & ".FontItalic=" & ctl.FontItalic
End If
If ctl.FontUnderline <> .FormatConditions(i).FontUnderline Then
Debug.Print vbTab & ".FontUnderline = " & .FormatConditions(i).FontUnderline; Tab(40); "' " & ctl.Name & ".FontUnderline=" & ctl.FontUnderline
End If
If .FormatConditions(i).Type = 3 Then ' acDataBar
Debug.Print vbTab & ".LongestBarLimit = " & .FormatConditions(i).LongestBarLimit
Debug.Print vbTab & ".LongestBarValue = " & .FormatConditions(i).LongestBarValue
Debug.Print vbTab & ".ShortestBarLimit = " & .FormatConditions(i).ShortestBarLimit
Debug.Print vbTab & ".ShortestBarValue = " & .FormatConditions(i).ShortestBarValue
Debug.Print vbTab & ".ShowBarOnly = " & .FormatConditions(i).ShowBarOnly
End If
Debug.Print "End With" & vbCr
Next
End If
End With
End If
Next
Beep
Exit_Sub:
Exit Sub
ErrorHandler:
MsgBox "Error #" & Err.Number & " - " & Err.Description & vbCrLf & "in procedure ListConditionalFormats" _
& IIf(Erl > 0, vbCrLf & "Line #: " & Erl, "")
GoTo Exit_Sub
Resume Next
Resume
End Sub
Function DecodeType(TypeProp As Integer) As String
' You heed this are there are 4 different ways to setup a CondtionalFormat
' https://vb123.com/listing-conditional-formats
Select Case TypeProp
Case 0
DecodeType = "acFieldValue"
Case 1
DecodeType = "acExpression"
Case 2
DecodeType = "acFieldHasFocus"
Case 3
DecodeType = "acDataBar"
End Select
End Function
Function DecodeOp(OpProp As Integer) As String
' You need this becuase equations can comprise of = > <> between
' https://vb123.com/listing-conditional-formats
Select Case OpProp
Case 0
DecodeOp = "acBetween"
Case 1
DecodeOp = "acNotBetween"
Case 2
DecodeOp = "acEqual"
Case 3
DecodeOp = "acNotEqual"
Case 4
DecodeOp = "acGreaterThan"
Case 5
DecodeOp = "acLessThan"
Case 6
DecodeOp = "acGreaterThanOrEqual"
Case 7
DecodeOp = "acLessThanOrEqual"
End Select
End Function
I have this procedure in visual basic that works for years in Visual Studio 2010 (2015) in windows 7 machine, but I change pc and now in Windows 10 Visual Studio 2017 it only works in debug mode. In runtime mode the procedure loop correctly for 2 time and exit with out error (exit code 0 on console).
In this procedure I loop in array of file information, read email in pdf file and send an email:
Private Sub elaboraFile(lDirectoryFile As String)
Dim i As Integer
Dim eMail, Denominazione, totaleFatt As String
For i = 0 To listaFatture.Length - 1
If File.Exists(lDirectoryFile & "\" & listaFatture(i).nomeFile) Then
' create a new PDF reader based on the PDF template document
Dim pdfReader As PdfReader = New PdfReader(lDirectoryFile & "\" & listaFatture(i).nomeFile)
Dim currentText As String
Dim strategy As New SimpleTextExtractionStrategy()
currentText = PdfTextExtractor.GetTextFromPage(pdfReader, 1, strategy)
currentText = Encoding.UTF8.GetString(ASCIIEncoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(currentText)))
Dim inizioEmail As Integer
Dim inizioDenomCompleta As String
inizioEmail = currentText.IndexOf("E-Mail: ")
If inizioEmail < 1 Then
'Errore indirizzo mail non trovato
listBoxErrori.Items.Add("mail non presente: " & listaFatture(i).nomeFile & " - " & listaFatture(i).denomParziale)
Else
inizioDenomCompleta = currentText.IndexOf(listaFatture(i).denomParziale)
eMail = currentText.Substring(inizioEmail + 8, inizioDenomCompleta - inizioEmail - 8 - 1)
If IsValidEmail(eMail) Then
'Estrazione denominazione Ditta
'inizio: valore di denomParziale
'fine: Spettabile
Denominazione = currentText.Substring(inizioDenomCompleta, currentText.IndexOf("Spettabile") - inizioDenomCompleta - 1)
ListBox1.Items.Add(listaFatture(i).nomeFile & " - " & eMail & " - " & Denominazione)
ListBox1.TopIndex = ListBox1.Items.Count - 1
Dim ldataFattura As String
ldataFattura = Strings.Right(listaFatture(i).dataFattura, 2) & "/"
ldataFattura = ldataFattura & listaFatture(i).dataFattura.Substring(4, 2) & "/"
ldataFattura = ldataFattura & Strings.Left(listaFatture(i).dataFattura, 4)
'Mail
Dim testoMail As String
testoMail = "Buongiorno <b>" & Denominazione & "</b>, <br />" & vbCrLf &
" <br />" & vbCrLf &
"Fattura nr <b>" & listaFatture(i).nrFattura & "</b> del <b>" & ldataFattura & "</b> <br />"
If SendMailAIM(eMail, "Invio fattura", testoMail, lDirectoryFile & "\" & listaFatture(i).nomeFile) = False Then
listBoxErrori.Items.Add("Errore invio mail - " & listaFatture(i).nomeFile & " - " & eMail & " - " & Denominazione & " - " & totaleFatt)
listBoxErrori.TopIndex = listBoxErrori.Items.Count - 1
End If
Else
listBoxErrori.Items.Add("mail errata: " & eMail & " nomefile:" & listaFatture(i).nomeFile & " - " & listaFatture(i).denomParziale)
End If
End If
pdfReader.Close()
pdfReader = Nothing
ResponsiveSleep(7000)
Try
File.Delete(lDirectoryFile & "\" & listaFatture(i).nomeFile)
Catch ex As Exception
listBoxErrori.Items.Add("Impossibile cancellare il file " & listaFatture(i).nomeFile)
End Try
ProgressBar1.PerformStep()
Else
listBoxErrori.Items.Add("Fattura non presente - " & listaFatture(i).nomeFile)
ProgressBar1.PerformStep()
End If
Me.Refresh()
Next
MsgBox("Elaborazione Terminata")
End Sub
I have the following code to check windows updates
Function CheckWinUpdates() As Integer
CheckWinUpdates = 0
Dim WUSession As UpdateSession
Dim WUSearcher As UpdateSearcher
Dim WUSearchResults As ISearchResult
Try
WUSession = New UpdateSession
WUSearcher = WUSession.CreateUpdateSearcher()
WUSearchResults = WUSearcher.Search("IsInstalled=0 and Type='Software'")
CheckWinUpdates = WUSearchResults.Updates.Count
Catch ex As Exception
CheckWinUpdates = -1
End Try
If CheckWinUpdates > 0 Then
Try
'Dim Update As IUpdate
Dim i As Integer = 0
For i = 0 To WUSearchResults.Updates.Count - 1
'Update = WUSearchResults.Updates.Item(i)
EventLog.WriteEntry("Item is type: " & WUSearchResults.Updates.Item(i).ToString, EventLogEntryType.Information, 85)
EventLog.WriteEntry("Deadline: " & WUSearchResults.Updates.Item(i).Deadline.ToString, EventLogEntryType.Information, 85)
EventLog.WriteEntry("Type: " & WUSearchResults.Updates.Item(i).Type.ToString, EventLogEntryType.Information, 85)
EventLog.WriteEntry("Released on: " & WUSearchResults.Updates.Item(i).LastDeploymentChangeTime, EventLogEntryType.Information, 85)
EventLog.WriteEntry("This windows update is required: " & WUSearchResults.Updates.Item(i).Title, EventLogEntryType.Information, 85)
'EventLog.WriteEntry("This windows update is required: " & Update.Title & vbCrLf & "Released on: " &
' Update.LastDeploymentChangeTime & vbCrLf & "Type: " & Update.Type.ToString & vbCrLf &
' "Deadline: " & Update.Deadline.ToString & vbCrLf & vbCrLf & "Item is type: " & Update.ToString, EventLogEntryType.Information, 85)
Next
Catch ex As Exception
EventLog.WriteEntry("Error while attempting to log required updates:" & vbCrLf & ex.Message, EventLogEntryType.Error, 86)
End Try
End If
WUSearchResults = Nothing
WUSearcher = Nothing
WUSession = Nothing
End Function
My intention with this is to a) get the number of windows updates that are applicable, and b) to look at what other properties are available, and more specifically see how many are older than a week or 2.
I know that UpdateSearcher doesn't allow to search by date, so I am looking to iterate through each item and then later report on each one.
At the moment my function does quite happily return the number of updtes, but when I try to get any of the properties I get "Object reference not set to an instance of an object".
Any ideas where I'm going wrong?
I got this working, turns it it doesn't like the deadline property, I don't know it comes up with "object reference not set", but for what I need it doesn't matter.
I do not understand where "Flag and Err05" (at the bottom of the codes)have been declared ? I have searched the entire project and can not found where the two parameters got declared. When I try to use the below codes in another project , i got the error message "Run time error : items not found in this collection " Any answers?
>Private Sub SanityCheck_Click()
>Dim St As String, WrnFlag As Boolean, j As Integer
>Dim RS As Recordset, RS1 As Recordset, i As Integer, WrongRootCauses As String
>Dim Err01 As String, Err02 As String, Err03 As String, Err04 As String
>WrnFlag = False
>If IsNull(Me.FactoryList) Then
> MsgBox "Select valid Factory before proceeding.", vbExclamation
>Else
> St = "SELECT Factory, Step1, Step2, Step3, Step4, DateColumn FROM [tbl >Factory] WHERE Allowed = True and Factory = """ & Me.FactoryList.Value & """"
> Set RS = CurrentDb.OpenRecordset(St, dbOpenSnapshot)
'-- 12NC codes check --
> St = "SELECT Count([" & RS!Step2 & "].PLANT) AS 12NC_chk " & _
>"FROM [" & RS!Step2 & "] " & _
> "WHERE (((Len(Trim(IIf(Left(Trim([12NC_CODE]),3)=""000"",Right>([12NC_CODE],Len([12NC_CODE])-3),[12NC_CODE])))) Not In (0,1,12)));"
' "WHERE (((Len(Trim([12NC_CODE]))) Not In (0,1,12)));"
> Set RS1 = CurrentDb.OpenRecordset(St, dbOpenSnapshot)
>If RS1.BOF And RS1.EOF Then
> Err05 = "+ No 12NC issues found."
>Else
> RS1.MoveFirst
> RS1.MoveLast
> If RS1![12NC_chk] = 0 Then
> Err05 = "+ No 12NC issues found."
> Else
> Err05 = "- " & RS1![12NC_chk] & " Incorrect 12NCs found!"
> WrnFlag = True
> End If
> End If
'--
> If WrnFlag = True Then **Flag** = vbCritical Else **Flag** = vbInformation
> MsgBox RS!Factory & " input data sanity check:" & vbCrLf & vbCrLf & " " & >Err01 & vbCrLf & " " & Err02 & vbCrLf & " " & Err03 & _
> vbCrLf & " " & Err04 & vbCrLf & " " & Err05 & vbCrLf & vbCrLf & IIf>>(WrongRootCauses = "", "", " Unknown ADP Root Cause(s):" & vbCrLf & WrongRootCauses), Flag
> RS.Close
>RS1.Close
>End If
>End Sub
Two posibilities
Unless the file have Option explicit in the top, you are not forced to explicitely declare variables. Which means that Flag and Err05 have indeed never been declared. VBA will just create them on the fly with a Variant type and an initial value of Nothing.
They might be global variables declared outside of any sub in another file. Try right clicking the variable and then click definition in the menu, Access will show you the way.
I run this little piece of code to do a kind of activity log window.
Sub writetolog(i As String)
Try
'outfile.Write(DateTime.Now.ToString("mm/dd/yyyy - H:mm:ss:fffffff") & "--->" & i & vbCrLf)
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ff") & " - " & i)
If String.IsNullOrWhiteSpace(i) = False Then LogLB.Items.Add(DateTime.Now.ToString("[" & "MM/dd/yy - HH:mm:ss:ff") & "] -- " & i) 'Else MsgBox(i & " is nothing!")
If LogLB.Items.Count >= 100 Then LogLB.Items.RemoveAt(0)
If LogLB.Items.Count > 0 Then LogLB.SelectedIndex = LogLB.Items.Count - 1
Catch ex As Exception
Console.Write(ex)
End Try
End Sub
So it works most of the time, but for some reason at seemingly random times I get a Null Exception and it points to the end of the line at
LogLB.Items.Count - 1
Why?