MS Access VBA boolean values localization problem - ms-access

I build some SQL query strings in VBA in an MS Access Database (current Office 365 Access Version) and I ran into a weird localization problem with boolean values read from form controls: Me.MyBooleanControl returns "Wahr" (german "True") => the generated SQL fails.
I'm using a workaround now, wrapping each value request by a function to translate the values to -1/ 0 like suggested here, but I really like to know if there's a straight way to avoid this. I used the same code structure last year in another Access Database not running into the same problem - and I've absolutely no idea what's different (besides MS Office my have been updated).
Edit: I found the solution, see answer below.

Trying to reproduce the problem independently from the rest of my code, I nailed it down and found it to be my fault: I initialized the unbound checkbox as True which seemed to work fine, but causes the problem:
Private Sub Form_Load()
Me.UnboundCheckbox01 = True
Me.UnboundCheckbox02 = -1
End Sub
Private Sub ReadCheckBox()
Debug.Print Me.UnboundCheckbox01 ' returns localized value "Wahr"
Debug.Print Me.UnboundCheckbox02 ' returns -1 as expected
' after manually toggeling UnboundCheckbox01 to unchecked
' and back to checked again, the value returns as -1 too
End Sub
Sorry! Next time I'll honor the rules and provide some code - sometimes the question dissolves by just doing that...

I can't replicate this with my Danish localisation:
Me!UnboundCheckbox01 = True
Debug.Print Me!UnboundCheckbox01 ' returns String: "True"
However, it appears that you can assign just about any value of any data type to an unbound checkbox:
Me!UnboundCheckbox01 = "Martin"
Debug.Print Me!UnboundCheckbox01 ' returns String: "Martin"
Me!UnboundCheckbox01 = Now
Debug.Print Me!UnboundCheckbox01 ' returns Date like: 2020-03-29 13.45.23
I'm not sure if this is intended - even though the Value property is said to be of data type Variant:
CheckBox.Value property (Access)

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

MS Access 2010 Object Passing Value instead of Reference ... Sometimes

I have a small bit of code for a much larger MS Access database that likes to behave erratically. I can't say for sure, but it seems to change when I compile or recompile the database. Here's the code:
Private Sub FindCtls()
Dim DatType as String
Dim thisCTL as Control
DatType = Right(ActiveControl.Name, Len(ActiveControl.Name)-4)
For Each thisCTL In Me.Controls
If InStr(1, thisCTL.Name, DatType, 2) > 0 Then
Select Case Left(ThisCtl.Name,4)
Case "Sel_"
Set TgtCtls(0) = thisCTL
' A buncha other Cases
End Select
End If
Next thisCTL
End Sub
The problem is, when I step through the code, for some reason thisCTL is being passed as the value of the control, not the control itself. I've looked everywhere for this answer, that brought me to using the "Set" command instead of just putting TgtCtls(0) = thisCTL. That worked until I decompiled the DB and recompiled it. Made one change (changed the name of the first variable), compiled it again, and it worked. As I got into work today, someone told me that it was no longer working. Any ideas would be greatly appreciated.
Edit: I forgot to mention that TgtCtls is a form-wide array that was Dim'd at the top as such:
Option Compare Database
Dim TgtCtls(2) as Control

Wildcard in Access VBA

This is kind of a follow up question to this post: Access VBA recordset string comparison not working with wildcard but I don't have the rep to answer/comment on it to ask it in house. What I'm curious about is this line of code specifically:
If ![ACOD] = "*_X" Then '"$ICP_X" works
Debug.Print ![ACOD] 'For testing
'.Delete
End If
I want to know if this can be modified so that on a button click, it looks at all fields in a form with the field name of *_New (with the hope to catch all fields where the name ends in _New) and if they are not Null then confirm that the user wanted to make a the change indicated in the field. I was thinking of something along the lines like this:
If Not isNull(*_New.value) Then
If Msgbox ("Do you want to make these changes?",vbOKCancel, "Confirm Changes") = 1 Then
'### Do something with the record ###
End If
End If
EDIT
As of posting the above information, I did not have the Microsoft VBScript Regular Expressions Reference installed, currently I have version 5.5 (it was the latest version). With that installed (referenced?) and seeing the information from this site MS Access with VBA Regex, I'm wondering if it's better to do something like this:
Dim re As RegExp
Set re = New RegExp
re.IgnoreCase = True
re.Global = True
re.Pattern = "*_New"
If ##Not sure on syntax to match all fields## Then
Msgbox(##Same stuff as above MsgBox##)
End If
EDIT 2
Here's a sample case for my form I'm working on. Each of the fields to the right have names that end in _New. What I want to do is on the button click, to check and see what fields on the right have been filled in and ask the user if they want to confirm the changes to the record.
Not sure what you are trying to achieve but there is a way to access the control collection in a form. Here is a public function where you can loop through all controls and check its name.
Public Function FN_CONFIRM_CHANGES(iSender As Form)
Dim mCtl As control
For Each mCtl In iSender
If VBA.Right(mCtl.name, 4) = "_New" Then
Debug.Print mCtl.name & " is a match and its a " & VBA.TypeName(mCtl)
End If
Next mCtl
End Function
Call this function like
FN_CONFIRM_CHANGES Me 'Where me is referencing the form you are in.
You can modify the above code to return a boolean value to stop further execution if user decided not to save your changes or whatever logic you are trying to implement.

Access 2013:Trying to write macro to update form fields from a query result

I am trying to create a macro to update the value of a field in a form based off the results of a query.
I am entirely new to working with vba in Access so I apologize if I am asking a basic question.
I should mention, the "test" query returns exactly one result. It is essentially used similarly to a VLookup.
Currently My code is thus:
Private Sub UpdateBasic_Click()
Dim bucket As String
DoCmd.OpenQuery "test", acViewNormal, acReadOnly
'this line is meant to record the result of the query into a variable. It is not working but I haven’t found the right command to get it to pick up the data yet.
bucket = A1
DoCmd.Close acQuery, "test", acSaveNo
DoCmd.OpenForm "BasicData", acNormal, , , acFormEdit, acWindowNormal, "Global_ID = 'sdkfa'"
'this line is meant to update the value of the field on the form.
DoCmd.SetProperty testfield, acPropertyValue, bucket
End Sub
I am having no luck getting the SetProperty command to work at all. It is consistently telling me I have a data type mismatch regardless of whether I try to give it a variable like bucket or a value like 10. Error message is as follows:
Run-time error ‘2948’:
An Expression you entered is the wrong data type for one of the arguments.
Any and all help would be appreciated.
If you're simply trying to assign the result of a query to the value of a field in a form, I'd recommend a DLookup() function. You can use it like this (assuming the form's control is a textbox):
Me.TextBox.Value = DLookup("FieldName", "QueryName")
More elaborate solutions would involve recordsets, etc. but if you're looking for a quick, simple solution this should do just fine. Hope that helps!

Access Report won't allow me to refer to a field in VBA unless it's on the report in its own right

So, in an Access Form or Report a good way to show something dynamic on the screen that is more complex than =[UnitPrice]*[Quantity] is to drop into VBA.
e.g. in this simplified example, the underlying table for this Report has two fields ShowTax and TaxRate. By making a TextBox's control source =GetTaxInfo I get to introduce some complexity in VBA:
Public Function GetTaxInfo() As String
Dim result As String
If Me!ShowTax = 0 Then
result = "Tax included # " & Me!TaxRate
Else
result = ""
End If
GetTaxInfo = result
End Function
OK, this works ... so long as I have a field somewhere else that refers to TaxRate. Otherwise it just prints #Error. It's as if it needs to preload the field before it can be used in VBA code. It isn't the end of the world because I can have a bunch of fields in the report all set to not be visible, but it's untidy.
So is it the case that you can't refer to a field in VBA code backing a report unless you have already referred to the field in the conventional way as a field baked into the report?
I can't remember encountering this limitation before. Or is it that I have a corrupt report? (I have tried the usual compact/repair, export/reimport the Report etc)
Edit:
the weird thing is ... now it's working again. And - I'm pretty sure - there is no control in the report. which is why I was thinking it was a corruption in the report.
You'll need a control on the form/report.
If this is too messy, you could put the function in a Module and use in the RecordSource (based on a query). No sense burying all this logic in a report when it could be used in other places as well.
Public Function GetTaxInfo(ShowTax as Boolean, TaxRate as Single) As String
Dim result As String
If ShowTax = 0 Then
result = "Tax included # " & TaxRate
Else
result = ""
End If
GetTaxInfo = result
End Function
Then the control is set to this field in this report and others.