Why did I have to manually set the .value from the .text on losing focus in an unbound textbox - vba

I have an unbound textbox to accept the delete older than: number of days. It is in the report header. I set it to 30 days but I want the user to be able to change it. I was banging my head trying to figure out why entering 40 was not being accepted and it reverted back to 30 every time. I finally decided on using the lost_focus event to set .value to .text. That worked.
Further research showed that when the textbox get's focus text and value are both the same, 30 in my case. Changing the number in the text box to 40 shows the values of text at 40 and value at 30. Unless I specifically set Value to the value of text Access changes text to the value of value. This is different behavior than other places in Access such as forms.
Can anyone tell me why this might be? I can't find any setting that might do this. Is it because it's in a report header? what is the difference between this and every other text box I've ever used?

From a "best practices" viewpoint, Access Reports are not intended to be used interactively despite the ability to manipulate some unbound controls. Although workarounds can be implemented that function sufficiently well, such solutions are often incomplete and buggy and function differently depending on the active view: Report View vs. Print Preview. Appropriate design patterns include using Access Forms for specifying report options which then open the Report in a static configuration.
This may not satisfy the question "Why?" if seeking a deeper answer as to why Microsoft implemented inconsistent binding behavior in Access, or why they allowed interactive controls in reports at all if they don't behave the same way as in forms. But Access has plenty of other quirky behaviors that have no known/published explanation.
Regarding the priority of the Value property updating the Text property (and not vice versa): Value is the key field because it contains the actual data for the control (bound or unbound). Although it is natural to have a single control for both display and input (uh, that's how almost all controls work), the processes of displaying data and parsing user input are two distinct functions. The visual representation returned by the Text property can be manipulated using the various formatting properties, and technically could display an incomplete representation of the underlying Value data. If there are any conflicts between the stored Value property and the Text property, it is natural that the existing Value property has precedent.
My guess is that the automatic binding behavior was "relaxed" for reports to allow more flexible custom reporting output. First consider an Access Form in Datasheet view: An unbound Form control shows the same value for all records. Even if the control is edited while on a particular row, the updated value is displayed for all rows. The same control object is essentially repainted for each row and there is no concept of individual instances of the control that can hold different values. Bound controls have built-in code that repaint the control with data from the particular row, but there are still not multiple instances each "holding" the individual values. The visual output differs from an intuitive object-oriented paradigm where our minds what to assign each visual row its own in-memory instance of the controls--it just doesn't work like that in Access.
Unlike the Form behavior just described, the Report's Print Preview (and actual printed output) allows unbound controls to display different data per row using the Detail_Format() event. Within the Detail_Format() event, one can set the Value property of a control at which time the Text property is automatically updated according to various formatting properties. This update Text is then output for the current row. Perhaps (just guessing) that this behavior would not function properly if the Text property updated the value property. I suspect it would cause recursive events during report generation. Because reports are not meant to be interactive, relevant text-input parsing code was "disconnected" so that it doesn't behave like on a form.
All that explanation doesn't make Access any less frustrating nor remove its limitations, but at least learn to adapt and design things in the "Access-esque" way rather than fighting it.

your best bet is to design a form with the unbound combo boxes and have your data displayed in a subreport. I like to design my reports so that when values are updated the query for the recordsource of the report is generated doing this requires 2 queries to exist, one with all data possible and a filtered one as subreport recordsource. This will control the data for printing and also allow users to close or navigate away from the report and return to the data later.
Private Sub ComboBox1_AfterUpdate()
Dim Query1 as Object
Dim Temp_Name as Variant
Temp_Name = SubReport.SourceObject
SubReport.SourceObject = Empty
Set Query1 = Me.Form.Application.DBEngine.Workspaces(0).Databases(0).QueryDefs ("SubReport_Query")
Query1.SQL = "Select * Unfiltered_Query WHERE Field1 <= " ComboBox1 & ";"
SubReport.SourceObject = Temp_Name
End Sub

Related

VB.Net ComboBox (as Dropdown) not translating text to DisplayMember with Databinding

I inherited a fairly large project at work that is undocumented and written in VB (originally started pre .NET, ended around .NET 2). I'm in the process of updating / refreshing a lot of the code, but have run into an annoying issue that I haven't found the solution for yet. This system utilizes a UI, a Web Service, and a SQL DB.
Problem: I have a Databound Combobox (originally set to DropDownList - I'm changing it to DropDown, which is what started this mess - going back isn't an option) that is tied to a DataSet that comes from a Web Service. When a user types in the item they want manually, the data from the text field doesn't seem to associate itself with the DisplayMember, which forces the WS/SQL query to fail (it is sent a blank value when it's expecting a ValueMember). If the user types in a partial selection and then chooses the value they want from the DisplayMember list using the arrow keys or tab, the query goes off without a problem.
My Question: How do I get the text field to translate to the DisplayMember which will then properly tie itself to the ValueMember which will then allow the query to execute correctly? Sorry for making this sound complicated or convoluted; I'm sure the answer is easy and I'm just glazing over it.
The relevant bit of code is:
With cmbDID
If dtsLU.Tables.Contains(reqTable) = True Then
.DataSource = dtsLU.Tables(reqTable)
.DisplayMember = "zip"
.ValueMember = "gridID"
End If
End With
cmbDID.DataBindings.Clear()
cmbDID.DataBindings.Add("SelectedValue", dtsData, strDT & ".gridID")
I've tried changing "SelectedValue" to "Text", which almost works - but it directly translates to gridID and skips zip which ends up with an incorrect Web Service response since the zip and gridID field values are not synced (zip (DisplayMember) may be 5123 while gridID (ValueMember) may be 6047). I've tried changing "SelectedValue" to "SelectedIndex", and that got me no where.
Any help is greatly appreciated.
EDIT
To add some clarification to the process, the below pseudo code / description is roughly what happens. I could post the whole module, but I feel that would just muddy the whole question even more.
Private Sub A
FormAlpha is created with 1 ComboBox in the form of a DropDown
This DropDown is populated with a DataSet
DataBinding with a blank DataSet is added to the control to keep track of the users input
End Sub
lblSubmit_Click event is triggered on FormAlpha by the user after they have populated the DropDown with their data. lblSubmit_Click calls Private Sub Submit
Private Sub Submit
BindingContext(DropDown DataSet, tableName).EndCurrentEdit() is called
DataSet.HasChanges() is processed
If changes are present, changes are processed
HERE lies the problem
If the user has manually typed in the DropDown field, but not hit an arrow key or tab, then the DataSet registers a change, but returns a null value in all fields - it knows something was entered, but that data apparently didn't pass through the DataSet for the ComboBox (ListItems or SelectedIndex didn't change / fire I'm guessing). If the user selects the item with the arrow keys, the DataSet has the proper input (I'm assuming the Data was validated by the control at this point).
If the processed data is good, a value is entered into the database
If the processed data is bad (empty), an error is returned
End Sub
If the above can't be solved with what I've provided, but someone still knows a better way to handle this type of situation, I'm all ears. Rewriting the module isn't ideal, but fixing this problem is a necessity.
Alright, while this fix may not be ideal, it is a fix none the less.
The bare bones problem was that the text value of the DropDown wasn't causing the data to actually affect the SelectedIndex / SelectedValue of the control unless you interacted with it using the arrow keys or a mouse click. So, while the DropDown would read "1234", in reality the control saw "".
The fix I have in place for this is simply calling comboBox.text = comboBox.text whenever the user hits the submit button.

Microsoft Access 2013 Form Objects

I have a database that was create in Access 2010. We recently updated our systems to Access 2013. In Access 2010 I have no errors accessing a form object with
Form_frmName.txtFieldName.Value
However, when using Access 2013 I get a runtime 2424 error stating that "The expression you entered has a field, control, or property name that Microsoft Access can't find. I am accessing from a module.
The module sets these fields visible using
With Form_frmName
.txtFieldName.Visible = True
End With
before attempting to access them.
Has there been any changes in the way form objects are accessed between 2010 and 2013? Is this an issue others have faced?
In Response to #WayneGDunn's questions below
QUOTE:
I need to know exactly what and how you are using this.
1. You have a bound textbox named 'txtFieldName' on a form. As #brad asked, is there a subform, and if so, is this field on the subform?
2. You said the code is in a module, but is the code in the form where the field is defined?
3. Please explain where/what form 'frmQAtab' is (you said your form name was 'frmName', so what is the other, how related?)
4. Is the code in an event? Can you share the entire subroutine?
5. Have you tried creating a dummy query and using the builder to reference the field?
RESPONSE:
1. I have a form (frmMain) with multiple tabbed pages. frmName is one of those tabs, containing the bound field txtFieldName.
2. The module is run from the form the field is in.
3. My apologies frmQAtab is frmName, I just neglected to make that generic in my copy-paste.
4. The event is a button click. The button click runs a sub from a module. That sub makes visible the fields, runs a query based on user input (two date fields), populates the bound fields with the returned record set, then attempts to access them for processing (another query is run to process a complete other set of fields). To post the entire subroutine would be a bit more than I would ask you to chew on. This is legacy code I'm trying to fix, and it's rather large.
5. I have not tried a dummy query. Access is not my field (I'm mainly a C#, scripting, guy.) Is there some suggestions in this area you could give?
One of the following references to your fields should work. I created a form (named 'frmMain'), then created a Tab Control with two tabs. On the first tab, I inserted another form (named 'frm3197'). I also created a text box on the tab control named 'txtFieldName' AND in form 'frm3197'. From a button click on 'frmMain', the following will reference each of those fields.
Private Sub cmdButton1_Click()
Forms![frmMain]![txtFieldName] = Now()
Forms![frmMain]![frm3197].Form![txtFieldName] = Now()
End Sub

How to work around Access VBA error 3188

Having converted a number of fields in a table tblSource to Rich Text memos, I'm getting an error 3188 in the following circumstances.
Main form has a subform open (frmSource) bound to qrySource. qrySource pulls in some fields from tblSource and adds a calculated field which concatenates the (newly-minted) rich-text memo fields (SD1 to SD20) so that the result can be displayed in a single text box on frmSource called Citation.
If the user wishes to edit SD1 to SD20, they double-click on the Citation field and a modal form frmCitation opens up displaying the SD fields for editing. frmCitation is bound to qryCitation which pulls the SD fields and a couple of others out of tblSource. When finished, they close frmCitation. When SD1 etc were text fields, the tblSource record was updated successfully. However, now they're memo fields, I'm hitting VBA error 3188 ("Could not update; currently locked by another session on this machine.").
Searching on the Internet suggests that this is a common issue with Rich Text memos when a memo size exceeds 2k (limitation possibly due to Access edit buffer size?), so I'm looking for ways to work around it.
One option would be be to split tblSource into two tables tblSource and tblCItation with a one-to-one relationship between them, then base qrySource on tblSource and qryCitation on tblCitation, but that's fairly major surgery with knock-on effects in a number of other places in the application.
Another option is to limit the size of all the memo fields on this form (as per Rich text input into limited length text field in Access 2010), but there's one field for which that wouldn't be acceptable to the users.
Is there another technique I could explore?
Per the following MS Link: http://answers.microsoft.com/en-us/office/forum/office_2007-access/memo-field-could-not-update-currently-locked-by/d5c8163a-7ce5-484f-80d4-98c1a8c92160
near the bottom, they suggest the limit is 2,000 characters.
Not that it helps, but could you add code to the 'before update' to display what the new size should be wnen concatenated? May help to figure a solution...
Be sure to save the form before making any changes with:
If Me.Dirty Then Me.Dirty = False
Workaround 1: Try to update not a field of an underlaying query or table, but a field of the form's Recordset. For example:
With Me.Recordset
.Edit
!MemoField = "TEXT ADDED HERE <- " & !MemoField
.Update
End With
Workaround 2: If you need to update not form's Recordset, but any other Recordset, try to unbind the TexBox, make the update and then make the TextBox binded back again.
I had the same issue and I closed all other open tabs (tables, etc...) and tried again. That worked fine.
I had this problem years ago & was revisiting in case it as not an issue anymore, but seems it is.
I had a list/column form of emails inc a field with a large rft memo.
I wanted to click on a record to bring up the one email in single form
The only way I could get it to work was Open the Single form & immediately close the multi row form, on exiting the single had to load the list again using bookmarks etc. to return to where I wanted to be, a real pain.
Especially as like now I would like to be able to access the the list whilst still on the single form, hence the revisit, instead looks like I will have to save all the list'id somehow. Dooable but a lot more programming that I think should be necessary.

Gray out a form row's (detail's) button conditionally with VBA code

I have a standard form in MS-Access which lists a bunch of orders, and each row contains order no, customer, etc fields + a button to view notes and attached document files.
On request from our customer we should gray out the button btnAnm (or check or uncheck a checkbox) depending on a calculation from two queries to two other tables (a SELECT COUNT WHERE and a check if a text field is empty).
I've tried btnAnm_BeforeUpdate(...) and btnAnm_BeforeRender(...) and put breakpoints in the subs, but none of them trigger. The same if I use the control Ordernr instead of btnAnm.
I'd like a function in the Detail VBA code to be triggered for each "Me." (row) so to speak, and set the row's control's properties in that sub.
What do I do? I've looked at the help file and searched here.
*Edit: So I want to do something that "isn't made to work that way"? Ie. events are not triggered in Details.
As an alternative, could I base the value of a checkbox on each line on a query based on the 'Ordernr' field of the current row and the result of a SELECT COUNT from another table and empty field check?
Do I do this in the query the list is based on, or can I bind the extra checkbox field to a query?
A description of how to do this (combine a COUNT and a WHERE "not empty" to yes/no checkbox value) would be perfectly acceptable, I think! :)*
You cannot do much with an unbound control in a continuous form, anything you do will only apply to the current record. You can use a bound control with a click event so that it acts like a button.
Presumably the related documents have a reference to the order number that appears on your form, which means that you can create a control, let us call it CountOrders, with a ControlSource like so:
=DCount("OrderID","QueryName","OrderID=" & [OrderID])
The control can be hidden, or you can set it up to return true or False for use with a textbox, you can also use it for Conditional Formatting, but sadly, not for command buttons.
Expression Is [CountOrders]>0
You can also hide the contents and add a click event so that is acts in place of the command button. Conditional Formatting will allow you to enable or disable a textbox.
As I understand your question, you have a continuous form with as command button that appears on each row - and you'd like to enable/disable the button conditionally depending on the contents of the row.
Unfortunately you can't do that. It seems that you can't reference the individual command buttons separately.
Having wanted to do something similar in the past I came up with two alternate ways of setting up my interface.
Put a trap into the onClick code for the Button. Which is icky, because it is counter intuitive to the user. But it gets you that functionality now.
Move the command button (and editable fields) up into the form header, and make the rows read only. Your users then interact with the record only in the header, and select the record they want work with in the list below. As I recall this is known a Master-Detail interface.

VB in Access: Combo Box Values are not visible in form view but are visible through Debug.Print

Code in Form onLoad:
country_combo.RowSourceType = "Value List"
Code in a reset function:
Dim lListIndex As Long
With Me.country_combo
For lListIndex = .ListCount - 1 To 0 Step -1
.RemoveItem (lListIndex)
Next lListIndex<br/>
End With
Code to populate country combo:
*For n = 1 To numCountries*
*countryCombo.AddItem (countryRS.Fields("countryName"))*
*countryRS.MoveNext*
*Next n*
I'm having a problem that occurs AFTER the code to populate the country combobox runs. The values are there as I can run Debug.Print(countryCombo.Value) and it prints out the name of the selected country, but I can't see the values in the combobox at all. They're invisible, and as far as I know there is no visiblity property for specific items, unless I'm completely mistaken.
comboBoxError.png http://img110.imageshack.us/my.php?image=comboboxerror.png
I think you should probably use Access's GUI tools to do what you're looking for. In design mode, click on the field you are trying to populate, then click the "lookup" tab. You can then specify a table to populate the field with and your forms should automaticly update as well.
I've also seen what you describe here - as far as I can tell, it's a bug within Access (I was using 2007) that only occurs when you programatically mess with the contents of a combo box. It does not happen every time. The issue corrects itself if you highlight the text that is in the combo box.
I am experiencing a similar issue with Access 2003. Based on the selection of one combo box, the row source of a listbox is set to an SQL string Basically a SELECT DISTINCT [MyField_Selected] FROM MyTable. For some fields the values are visible in the list box and others it is not. The values are there however as I can access them via code. To make it more interesting it works fine in Access 2007.
Just found the resolution on another forum. Check the format property of the field(s) in question on the table. In my case, when Access 2007 created the table, it put an # format in there. I removed that and all works great!