Printing non-null fields only in MS Access 2003 report - ms-access

I am trying to generate a report whose source is a form and that only prints fields that are not null.
To do so I have two text-boxes for every field. They are both resizealbe (can shrink/grow).
The first text-box is for the caption, and its source is
=IIf([record] Is Null,"","Caption:")
The second is the record value itself. If record is null then the value of both text-boxes is "" and null and they do not appear nor take any space in the form.
Two question:
This doesn't seem like the smartest way to do it. Anyone has a better idea?
The report also contains check-boxes, and this method only works if I check/uncheck at least one check-box before I generate the report. Otherwise all captions appear anyway. This is very weird - anyone has any idea why it happens?

This will only work properly with Print Preview, not MS Access 2010 report or layout view. You will need Can Shrink on the control to close up the gaps. In Access 2010, "*_Label" is the default name assigned to labels of controls.
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
Dim ctl As Control
For Each ctl In Me.Controls
If ctl.ControlType = acLabel And ctl.Name Like "*_Label" Then
ctl.Visible = Not IsNull(ctl.Parent)
''Bound checkboxes are never null, so hide false
If ctl.Parent.ControlType = acCheckBox Then
ctl.Visible = ctl.Parent
ctl.Parent.Visible = ctl.Parent
End If
End If
Next
End Sub

Related

Access VBA - Turn off aggregation when opening form/sub-form

What I'm trying to do is, whenever a user opens a form (and the sub-form that opens by default), I want to search through all the columns (controls?) on the form, check to see if they are currently set to aggregate (sum, count etc.) with Access' built-in Totals row, and if so, set them to not aggregate.
The reason for this is there are several millions records that are stored, so when someone queries it down to 3-4 and turns on Sum, then closes it, when the next person opens it, it tries to sum millions of numbers and freezes up. The form displays the queried results from a table which is populated via SQL (I think, if that sentence makes sense). Here's what I have so far:
Private Sub Form_Load()
'this form_load is in the UserApxSub sub-form, for reference
Call De_Aggregate
End Sub
Private Sub De_Aggregate()
Dim frm As Form, con As Control
Set frm = Forms!UserAPX!UserApxSub.Form!
For Each con In frm.Controls
If con.ControlType = acTextBox Then
If con.Properties("AggregateType").Value <> -1 Then
'crashes on following line
con.Properties("AggregateType").Value = -1
End If
End If
Next con
End Sub
I have not so much experience in Access VBA (usually work in Excel VBA) so please forgive me if I'm entirely off the mark here. The command con.Properties("AggregateType").Value = -1 doesn't throw an error, but Access just straight-up crashes when reaching that line specifically.
I've tried a number of variations in the syntax with no success, and I've also tried looping through other elements of the file (tabledefs, querydefs, recordsets, etc.) as well to see if I'm trying to change the wrong value, but the controls on this subform are the only things in the entire .mdb file that results when I search for elements with the AggregateType property.
I switched out the line that errors with Debug.Print con.Name & " - " & con.Properties("AggregateType").Value and I can check, have nothing return anything other than -1, turn on aggregation in some column manually, and have it return the correct result (0 for sum for example), so I think I'm looking in the right place, just missing some key factor.
I've been working on this for a couple weeks with no success. Any way to fix what I have or point me toward the right direction would be greatly appreciated!
This is not necessarily the answer but I don't have enough reputation
to give a "comment"...
I tried your scenario and verified can change the property value as you are however I did not iterate through all controls and simply used an onDoubleClick event on a column to simulate.
I would suggest trying to fire your sub with Form_Open or Form_Current to see if the property is getting reset after your code has been called for some reason.
UPDATE:
You are referencing the "Subform" Object of your main Form:
Set frm = Forms!UserAPX!UserApxSub.Form!
Try referencing the actual UserApxSub FORM explicitly.
Something like Set frm = Forms!UserApxSub! (assuming UserApxSub is the name of the form)
then stick in the Form_Open of your main form:
Private Sub Form_Open(Cancel As Integer)
'// the following would set a single control only. You can add your loop through all controls
Me!{your control name}.Properties("AggregateType").Value = -1 '// set control in your main form
Form_UserApxSub!{your control name}.Properties("AggregateType").Value = -1 '// set control in your "sub" form
End Sub

Display only last characters in a textbox

I have an Access 2002 database/application where my clients can enter multiple information about their own clients, including a code which follow some rules.
However, when they view these information after they have been entered, I need to hide every characters in this code except for the 4 last characters. However, the agent needs to be able to edit this code if it needs to be modified.
So basically, I have 3 phases possible:
First time information are filled, empty data. The field must show the characters entered.
At a later date, the code must be hidden in some way to show only the last 4 characters. It can be with * or simply the last 4 characters, but the user must not be able to see what is before these.
The agent edit the code, the code must then be properly modified in the database. The characters must be shown.
I tried to show only the 4 last characters, however my database gets modified... So the code gets cut in the database.
I wrote the following function to obscure sensitive data. Its primary use is to discourage shoulder surfing. I'm not sure if it will meet your particular needs, but it is simple, straightforward and may help others who stumble upon this question.
'Use to hide data in sensitive fields (e.g., BirthDate, PhoneNum, SSN)
'Usage: Ctl OnEnter property: =ObscureInfo(False, Form.ActiveControl)
' Ctl OnExit property: =ObscureInfo(True, Form.ActiveControl)
' Form Open property: =ObscureInfo(True, [BirthDate], [HomePhone], [SSN])
Function ObscureInfo(HideIt As Boolean, ParamArray Ctls() As Variant)
Dim Ctl As Variant
For Each Ctl In Ctls
If HideIt Then
If IsNull(Ctl.Value) Then
Ctl.BackColor = vbWhite
Else
Ctl.BackColor = Ctl.ForeColor
End If
Else
Ctl.BackColor = vbWhite
End If
Next Ctl
End Function
Wow - I'm shocked that this hasn't been answered sufficiently. The best answer is to use an unbound text box in your form instead of a bound one. First you'll need to make your unbound text box populate the actual field. You'll do that in the AfterUpdate event.
Private Sub UnboundTextBox_AfterUpdate()
[MyField] = Me.UnboundTextBox
End Sub
Then you'll need to set an OnCurrent event to populate your unbound text box with the protected view whenever the agents view the record:
Private Sub Form_Current()
Me.UnboundTextBox = String(Len([MyField])-4, "*") & Right([MyField], 4)
End Sub
However, you also want to let your agents edit or view the full code later, if necessary. The best way to do this would be to set the OnEnter event for your unbound text box to pull the whole field value, so the agent can see and edit it - effectively the reverse of your OnUpdate event.
Private Sub UnboundTextBox_Enter()
Me.UnboundTextBox = Nz([Field1]) 'The Nz deals with Null errors
End Sub
I've used this with a field displaying SSN's and it works like a charm.

disable cells based on another cell

In Access 07 on a form: I need to disable two cells based on a dropdown. Another words, if the user picks "new" from the dropdown, two other cells get disabled. I beleive I will need to right-click the dropdown, build code, but I don't know the IF... script I need to use.
Say your form includes a combo box named cboMyField which is bound to a field named MyField in the form's record source, and two text boxes: txtField2 bound to Field2; and txtField3 bound to Field3.
You could check the combo's value and set the Enabled property of the two text boxes appropriately by calling a procedure in your form's code module.
Private Sub SetButtonStatus()
If Me.cboMyField = "new" Then
Me.txtField2.Enabled = False
Me.txtField3.Enabled = False
Else
Me.txtField2.Enabled = True
Me.txtField3.Enabled = True
End If
End Sub
Call that procedure from the form's On Current event so the text box status will be set as you navigate between rows.
Private Sub Form_Current()
SetButtonStatus
End Sub
Do the same for cboMyField's After Update event so the text box status will be updated based on a user change for cboMyField.
Private Sub cboMyField_AfterUpdate()
SetButtonStatus
End Sub
Edit, Trouble-shooting: Since you're using Access 2007. Put the database in a trusted location and run it from there. See Get started with Access 2007 security
Edit2:
Change the SetButtonStatus procedure temporarily to check whether it even runs, and how it sees the combo box value if it does run.
Private Sub SetButtonStatus()
MsgBox "SetButtonStatus"
MsgBox "Value of cboMyField is '" & Me.cboMyField & "'"
If Me.cboMyField = "new" Then
Me.txtField2.Enabled = False
Me.txtField3.Enabled = False
Else
Me.txtField2.Enabled = True
Me.txtField3.Enabled = True
End If
End Sub
Also add Option Explicit to the Declarations section (at the top) of your module. Then select Debug->Compile from the VB editor's main menu. That effort should tell us whether the code includes any names which VBA doesn't recognize.
Edit3: From private communication, the combo's bound field was numeric data type, so could never be equal to "new". Therefore every time the procedure ran, it set text box Enabled property to True.

Access 2010 VBA ControlSource Loop

I have multiple fields on a form that have no values associated with them until data is entered into that field. At which point those controls have the #Name? value. All I'm trying to do is hide the fields using a loop as opposed to writing If statements. Here is the code working with a single If statement to hide said field/fields.
If Not Me.txtField.ControlSource = "#Name?" Then
Me.txtField.ColumnHidden = True
End If
I can't seem to figure out how to hide multiple controls that have the #Name? flag. Any help would be appreciated.
Dim ctl As Control
Dim ctlError As String
ctlError = "#Name?"
For Each ctl In Me.Controls
If Not ctl.ItemsSelected(txtField) = ctlError Then
ctl.ColumnHidden = True
End If
Next ctl
EDIT:
On the main form there is a subform with a cross tab query. But the problem is results on the query are populated from a combobox. So I've added fields that are not yet available in the query to the subform and end up with #Name? Attached is a screenshot to better illustrate the issue.
There is a 90% chance I'm going about this process wrong, so it's a learning process right now.
It would be easier to address this question if you described the specific errors that are raised by your code. This answer assumes that the control in question is a TextBox.
"#Name?" means that a control's ControlSource refers to a field that is not in the form's RecordSource. For example, if your query has two fields (ID and BirthDate, for example) and your form has three controls, with ControlSource of "ID", "BirthDate", and "BirthCountry", then the control whose RecordSource is "BirthCountry" will show "#Name?". However, its Value is not "#Name?". Rather, calling the Value property raises error 2424 (with the rather unhelpful message "The expression you entered has a field, control, or property name that Microsoft Office Access can't find").
The only way I know to check for the string "#Name?" is through the control's Text property, which is only available when the control has the focus, so that's not much help. If you retrieve the value of the ControlSource property, you'll get "BirthCountry" (of course). So you could check all ControlSources on your form against the fields of the form's RecordsetClone (add error handling, please):
For Each ctl In Controls
If Not RecordSourceContains(ctl.ControlSource) Then
ctl.Visible = False
End If
Next
Function RecordSourceContains(strFieldName as String) As Boolean
Dim fld As Field
For Each fld In RecordsetClone.Fields
If fld.Name = strFieldName Then
RecordSourceContains = True
Exit For
End If
Next
End Function
You'll probably want to do some other bookkeeping. For example, you'd want to check for expression control sources (which begin with "=") because they won't be in the RecordSource. You'll also either need to handle error 438 (Object doesn't support this property or method) or check each control's type to make sure it has a ControlSource property.
In design view for the form, what does the field say for Control Source? It should be blank, meaning the form is unbound. If it's not, then that explains #Name.
More information: http://www.databasedev.co.uk/unbound-forms-add-data.html
Here is code I use to take care of that:
Sub setControl
'' You can use this in your loop
Call FieldEnable(subFrm, "boxQty", booSellSet)
End Sub
''----------------
Private Sub FieldEnable(subFrm As Access.Form, strCtlName As String, _
booEnableMe As Boolean)
On Error GoTo errHandler
subFrm(strCtlName).Enabled = booEnableMe
subFrm(strCtlName).Visible = booEnableMe
errExit:
Exit Sub
errHandler:
If Err.Number = 2164 Or Err.Number = 2165 Then ''control has the focus
Resume Next
Else
DoCmd.Hourglass False
Screen.Application.Echo True
MsgBox "Problem with control named " & strCtlName
Resume errExit
End If
End Sub
I have to adjust many fields on the form, so this is very reusable. I might be turning them "on" or "off"; this takes care of either. Let me know if you have questions.
It all boils down to this method for hiding the field:
Control.Enabled = False
Control.Visible = False
Delete the field Black from table.
And then make make again the Black field in your table.

Enabling field visibility from combo box selection in Access 2007

I have a form in Microsoft Access 2007 called System, and a combo box called Utility within this form. Below this is yet another combo box called Utility_FOO, and I have disabled its visibility by default. One of the options in Utilities is a checkbox labeled 'FOO.' I want Utility_FOO to become visible whenever FOO is selected.
I have tried creating a subroutine in Visual Basic that checks whether or not FOO is selected every time I select an item from the list (using onUpdate), but I cannot figure out how to check that specific entry. Is there a simple way to do this?
Thanks!
If your combo box is bound to a multi-valued field, examine its .Value property to determine whether FOO is among the selected (checked) items.
Private Sub Utility_AfterUpdate()
Call SetVisible
End Sub
Private Sub SetVisible()
Dim varItm As Variant
Dim blnVisible as Boolean
blnVisible = False
If Not IsNull(Me.Utility.Value) Then
For Each varItm In Me.Utility.Value
If varItm = "FOO" Then
blnVisible = True
Exit For
End If
Next varItm
End If
Me.Utility_FOO.Visible = blnVisible
End Sub
You may also want to do the same thing for the form's On Current event. If so, add this:
Private Sub Form_Current()
Call SetVisible
End Sub