MS Access query custom function accepting form text input as value - sql

G'day, everyone.
I've been banging my head against this question the whole day through today, and I haven't managed to find any answers, so I'd appreciate your help.
What I have:
An Access form containing a text field
A query which is the form's data source
A custom function called RegExp defined within a module
RegExp takes two values as input: string (obtained from a table) and pattern (obtained from the form). RegExp returns a boolean value which in turn thins out query results.
The function works perfectly fine and as expected, however, this is only the case when the user fills out the text field. If the field is left blank, no results are returned (and the function's not even getting called if that's the case).
So here's what that particular statement within the query looks like:
... AND (RegExp(tblRole.Description,Trim([Forms]![frmFindRole]![txtRegExp]))<>False) AND ...
(Basically, to sum it up, user types in a value into the text field which gets leading and trailing spaces trimmed off, converted to a regular expression inside a VBA module, and then query results get filtered based on what boolean value the function returns).
There is a number of controls on this form, and they worked prior to me adding that txtRegExp text field. Now the query only returns results if txtRegExp is filled out, and I have no idea why. I've tried adding more checks, but the query's too complicated already, and I haven't succeeded.
If additional code samples are required for an answer to be made, I'll be able to provide them tomorrow.
Thank you in advance.
P.S. Would Nz help? If yes, then how would I go about using it?

Based on the few explanations you gave in comments
Suppose that this is code triggered on the KeyUp event :
Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
Me.Requery
End Sub
Store the default SQL for your form's recordsource somewhere in a local variable. In this example I considered that you stored it in SQLdefault string.
Prior to requery, check if the textbox is empty and if yes change your form's recordsource SQL accordingly:
private SQLdefault as string
Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
Dim SQL As String
If Nz(txtRegExp, "") = "" Then
SQL = SQLdefault
SQL = Replace(SQL, "AND (RegExp(tblRole.Description,Trim([Forms]![frmFindRole]![txtRegExp]))<>False)", "")
Me.RecordSource = SQL ' Normally this is enought to requery, if not uncomment below
'Me.Requery
Else
Me.RecordSource = SQLdefault ' Normally this is enought to requery, if not uncomment below
' Me.Requery
End If
End Sub
In this example I just remove the SQL part containning :
AND (RegExp(tblRole.Description,Trim([Forms]![frmFindRole]![txtRegExp]))<>False)
Replace it by something else if that's not correct.
That's obviously not the most elegant solution but it's difficult to provide with the best solution with what you've shown.

I've managed to make it work by modifying my initial query to include a check for the value of txtRegExp.
I am still not entirely sure why it failed with a blank txtRegExp value. I have a feeling the RegExp function somehow didn't fire when provided with NULL as the second parameter.
I am very grateful to Thomas G for all the help he's provided.

Related

MS Access: Trim a leading character upon input into form field

I'm building an access database, and on my main form, I have a field called "PartNumber." I want to scan data (a part number) into this field using a USB scanner and barcode. However, the barcodes include a leading "P" that isn't actually in the part number, and only serves to identify what kind of object that number is assigned to. I would like to automatically remove that P when I initially scan the data, so that the database stores and displays the correct part number.
I thought about using a query with an expression involving mid() and len(), then setting the control of the form field to that field in the query. However, that won't let me change or input data in the form's table, so it's useless for any records not already in the table.
Any ideas are greatly appreciated. Thanks!
I would do this with VBA, in the AfterUpdate event of the textbox.
Private Sub PartNumber_AfterUpdate()
If Left(Me!PartNumber, 1) = "P" Then
' Remove the first character
Me!PartNumber = Mid(Me!PartNumber, 2)
End If
End Sub
Depending on how the barcode API VBA runs: update tables via SQL or updates current form record in VBA; updates in bulk or updates one at a time. Either way at end of bar code reading when updating field, simply use Replace() in VBA or SQL:
SQL:
UPDATE tablename SET fieldname = Replace(fieldname, 'P', '')
VBA:
Me.fieldname = Replace(Me.fieldname, 'P', '')

MS Access: referring to a subform textbox control element in VBA query definition

I have a subform with user input (text box), that can reach more than 255 chars and can have special characters. As I cannot assign it as a parameter to a vba query definition (only 255 characters will work), I thought about directly referencing the text box:
Insert into ...
Values (Forms!MainFormName!txt_MyTextField, ... )
does work in a query in the Access GUI, but not in a vba query definition specified with the following code:
Set query_definition = CurrentDb.CreateQueryDef("", SQLQuery))
"Forms!MainFormName!NameOfSubformNavigationElement!txt_MyTextField" does not work either as a reference, just in case you are wondering. Neither does "Forms!MainFormName!NameOfSubformNavigationElement.Form.txt_MyTextField"
How can I get what I want? The string can have any kind of special chars like ' and ". Is there no alternative than appending the user input into the sql query? Is there some built-in function to escape these values?
UPDATE: Added another example now that the environment is known.
To use the form field in an action query, create a public function that will return the desired field, then call that function from your query.
Public Function GetFormField() As String
GetFormField = Forms![MyMainForm]!MySub.Form.MyField
End Function
In your query, use something like:
WHERE ((([106thZip_code_database].zipcode)=GetFormField()));
The following is an example you could use in the Main form to reference a field in a subform. 'MySub' is the name of the control on the Main form - not the subform's object name.
Debug.Print Forms![MyMainForm]!MySub.Form.MyField
A good reference on this subject can be found at: http://access.mvps.org/access/forms/frm0031.htm

Count a specific word using a Function ans a Sub

In VB.net, I want to make a counting program using a Function and a Sub.
There is a textbox to input a date and a button to exercise the programme in Form1.
I have a txt file which was extracted from MS-Excel with sequential date of time at its column A.
And from that txt file, I want to count the number of date(Actually string) such as "18-Jun-12".
The answer showing the count should be in the format of msgbox in the Sub.
I really have no idea how to link a Function and a Sub using variable, because I am just beginner.
Any help will be gratefully accepted.
If the fields are delimited by comma you must be careful since the field itself could contain a comma. Then you cannot differentiate between the value and the delimiter. You either could enclose the fields with quotes to mask them. But then you should use an available CSV parser anyway.
If the values never contain comma and you want a simple solution use File.ReadLines or File.ReadAllLines to read the lines and String.Split to get all fields per line.
Here's a simple approach using a little bit of LINQ to count all lines which contain the searched date (as string):
Dim linesWithThatDate = From line in File.ReadLines("Path to File")
Where line.Split(","c)(0).Trim() = "18-Jun-12"
Dim count = linesWithThatDate.Count()
As an aside, if the user must enter a date you could use a DateTimePicker control instead. Then you should also use Date.Parse(line.Split(","c)(0).Trim()) or Date.TryParse to get a real date.

SSIS custom script: loop over columns to concatenate values

I'm trying to create a custom script in SSIS 2008 that will loop over the selected input columns and concatenate them so they can be used to create a SHA1 hash. I'm aware of the available custom components but I'm not able to install them on our system at work.
Whilst the example posed here appears to work fine http://www.sqlservercentral.com/articles/Integration+Services+(SSIS)/69766/ when I've tested this selected only a few and not all columns I get odd results. The script only seems to work if columns selected are in sequential order. Even when they are in order, after so many records or perhaps the next buffer different MD5 hashes are generated despite the rows being exactly the same throughout my test data.
I've tried to adapt the code from the previous link along with these articles but have had no joy thus far.
http://msdn.microsoft.com/en-us/library/ms136020.aspx
http://agilebi.com/jwelch/2007/06/03/xml-transformations-part-2/
As a starting point this works fine to display the column names that I have selected to be used as inputs
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
For Each inputColumn As IDTSInputColumn100 In Me.ComponentMetaData.InputCollection(0).InputColumnCollection
MsgBox(inputColumn.Name)
Next
End Sub
Building on this I try to get the values using the code below:
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Dim column As IDTSInputColumn100
Dim rowType As Type = Row.GetType()
Dim columnValue As PropertyInfo
Dim testString As String = ""
For Each column In Me.ComponentMetaData.InputCollection(0).InputColumnCollection
columnValue = rowType.GetProperty(column.Name)
testString += columnValue.GetValue(Row, Nothing).ToString()
Next
MsgBox(testString)
End Sub
Unfortunately this does not work and I receive the following error:
I'm sure what I am trying to do is easily achievable though my limited knowledge of VB.net and in particular VB.net in SSIS, I'm struggling. I could define the column names individually as shown here http://timlaqua.com/2012/02/slowly-changing-dimensions-with-md5-hashes-in-ssis/ though I'd like to try out a dynamic method.
Your problem is trying to run ToString() on a NULL value from your database.
Try Convert.ToString(columnValue) instead, it just returns an empty string.
The input columns are not guaranteed to be in the same order each time. So you'll end up getting a different hash any time the metadata in the dataflow changes. I went through the same pain when writing exactly the same script.
Every answer on the net I've found states to build a custom component to be able to do this. No need. I relied on SSIS to generate the indexes to column names when it builds the base classes each time the script component is opened. The caveat is that any time the metadata of the data flow changes, the indexes may change and need to be updated by re-opening and closing the SSIS script component.
You will need to override ProcessInput() to get store a reference to PipelineBuffer, which isn't exposed in ProcessInputRow, where you actually need to use it to access the columns by their index rather than by name.
The list of names and associated indexes are stored in ComponentMetaData.InputCollection[0].InputColumnCollection, which needs to be iterated over and sorted to guarantee same HASH every time.
PS. I posted the answer last year but it vanished, probably because it was in C# rather than VB (kind of irrelevant in SSIS). You can find the code with all ugly details here https://gist.github.com/danieljarolim/e89ff5b41b12383c60c7#file-ssis_sha1-cs

How to fit VERY long condition in conditional formatting

I have a very long condition, about 3,000 characters. Access has only space for about one tenth of that.
Is there some other way to set conditional formatting on a textbox besides through the dialogue, or can I do it in VBA and, if so, HOW?
I have conditional formatting on a bunch of textboxes that trigger when the report is opened.
Would be curious to know if the VBA approach worked?
Another idea: create a hidden field on the form and set it's value based on your 3000-character condition. If you are just trying to have 1 conditional expression, you could give this hidden field a false/true or 0/1 value; if you want mulitple conditions, you could give it a value of 0, 1, 2, or 3 corresponding to the conditions you want applied. In either case, your conditional expression test(s) is(are) now trivial: [HiddenFieldName]=ConditionValue
According to Access' Help topic, the FormatConditions Collection has methods (Add, Delete, Modify) which should allow you to adjust your FormatConditions with VBA code. I've never tried, so offer no opinion as to whether this would be a practical approach for you.
I also tried to find out if there is a capacity limit for the number of characters FormatConditions can accept. I didn't find anything there.
Yes, you can manipulate Format Conditions in VBA. There's a full detailed article knowledgebase article at http://support.microsoft.com/kb/304104.
Code snippet here showing a basic example. Refer to the above link to get the VBA for AddFormats:
Public Function HighLightForeignKeys(argFieldName As String, argFieldValue As Integer)
Dim FormatCondition As String
Dim CodeReception As Integer
FormatCondition = "[" & argFieldName & "] = " & ArgFieldValue
With Me.ID
.FormatConditions.Delete
.FormatConditions.Add acExpression, , FormatCondition
.FormatConditions(0).BackColor = 16510422
AddFormats Me.ID, Me
End With
End Function
I dont know if this is what you were after, since you mentioned there was only a tiny box to enter all of your conditional text. Others have shown you VBA solutions - since you asked if that was one way to achieve it.
I have always resorted to using the "zoom" feature which is accessible via the SHIFT-F2 keystroke. Is that what you were after? I think it goes back several Access versions too.
A good set of Access shortcut keystrokes is here:
http://www.joyedaniels.com/keys_access.htm