I have no experience writing VBA code but I can follow the logic.
Thank you for everyone's help in advance!
I found a VBA code that calculates a single field in a query (see pic). Because I have 10 fields I would need to create 10 separate functions: nPP1SURF, nPP2SURF, nPP3SURF ... ending with nPP0SURF.
Can I accomplish this with a single function?
Public Function UpdatePP1SURF(ByVal nPP1SURF As Integer) As String
If nPP1SURF = 1 Then
UpdatePP1SURF = "D"
ElseIf nPP1SURF = 2 Then
UpdatePP1SURF = "T"
ElseIf nPP1SURF = 3 Then
UpdatePP1SURF = "W"
ElseIf nPP1SURF = 4 Then
UpdatePP1SURF = "A"
Else
UpdatePP1SURF = "x"
End If
'Expr1: UpdatePP1SURF([nPP1SURF])
End Function
The logic for all 10 fields is the same.The vba functions I've seen that can accomplish what I want has the word "array" in it.
BRILLIANT! Works great Lee Mac!!
My concern is my other calculated fields are much more complex. Is my original function better suited to handle these IIf statements? For example:
IIf([xPSHF2] Between ([xPSHF_TOP]+1.1) And [xPSHF2]<([xPSHF_TOP]+10),"OR","x")
I greatly appreciate your help Lee Mac!!
I Googled "access select case statement" and I'll begin learning more about this type of coding. I see there is a IF-THEN-ELSE statement.
Cheers!
Since you have stated that the logic is to be the same for all fields, simply pass each of your fields to the function.
As noted in my comments, I would first suggest using a Select Case statement:
Function UpdateSURF(ByVal mySURF As Integer) As String
Select Case mySURF
Case 1: UpdateSURF = "D"
Case 2: UpdateSURF = "T"
Case 3: UpdateSURF = "W"
Case 4: UpdateSURF = "A"
Case Else: UpdateSURF = "x"
End Select
End Function
This may then be evaluated for any of your fields using expressions such as:
UpdateSURF([nPP1SURF])
UpdateSURF([nPP2SURF])
...
UpdateSURF([nPP0SURF])
Related
I would need support for that. I guess it's an easy one but i would like to get different approach if possible.
I have the following Function and i just want to return value. If possible within a string variable.
StrVal = "123 Test"
Function IsHaving(StrVal)
Set reg1 = New RegExp
reg1.Gloabl=True
reg1.IgnoreCase=False
reg1.Pattern="\d+"
Set mats = reg.Execute(StrVal)
For Each mat In mats
return mat.Value
Next
End Function
And then passing the value returned in another string
StrNum = IsHaving(StrVal)
I would like to do this way but i am not sure that in vb i can return from a loop for ( within the Function).
Some ideas on that ?
In my Access query, I have the query using a VBA function to figure the value that goes in the query field.
In the form, if the stringval textbox has a value, then I want to compute it, but if not, it should remain empty (null).
Function GetValue(stringval, numval)
Dim result
stringval= stringval & ""
result= IIf(stringval<> "", numval* 1.5, Null)
GetValue = Int(result)
End Function
Now, I have a form that uses this query, and on the form is a textbox that displays the query value. I want the value to be formatted with commas in the numbers for easy reading. Everything I've tried so far does not show any commas.
I've tried:
used Standard for the Format > Formatfor the textbox (in properties)
putting #,###.### in the textbox Format value
putting #,##0.0## in the textbox Format value
changing Data > Text Format but it only gives me Plain Text and Rich Text - no option for numbers.
returning a double from the function
Note: if I don't use a custom VBA function, and write the formula directly into the query, then it does display commas. But when I move the formula into the function then the commas are lost.
What do I do?
[update]
I tried Gustav's solutions and since they didn't work for me, I added those as items to my "what I've tried" list above.
Also, if I look at the query in datasheet view, the number values sort alphabetically instead of by the size of the value. When I used the forumulae directly in the query instead of using functions, it sorted by the value of the number. I hope this is a clue.
Numbers carries no format. A format is applied when displayed only.
But be sure to return a Double if not Null:
Function GetValue(stringval, numval)
Dim result
If stringval & "" <> "" Then
result = Int(CDbl(numval) * 1.5)
Else
result = Null
End If
GetValue = result
End Function
Then apply your Format to the textbox
#,##0.0##
Or force a formatted string to be returned:
If stringval & "" <> "" Then
result = Format(Int(CDbl(numval) * 1.5), "#,##0.0##")
Else
result = Null
End If
and skip formatting of the textbox.
The solution is this: the function has to be declared as a double.
That allows the query's datasheet view to know it is displaying numbers - and so you can set the field's format to Standard for the comma to display. This also allows the form to know it has a number and it will display the comma there, too. I knew it had to do with double, but didn't realize before that the function needed to be declared as such.
Function GetValue(stringval, numval) as double '<----THIS!!!!
Dim result
If stringval & "" <> "" Then
result = numval * 1.5
Else
result = 0 `<--can't return null here; use nz function in control source for textbox
End If
GetValue = int(result) 'to remove decimals
End Function
The problem I was having was in some of my functions I need to return double or null, because I wanted textboxes to remain blank if they contained no data. Now, at least I know how to make the numbers generated by functions to display commas.
And here is how to deal with the fact that you can't return null as the value of a double. The function is originally from here.
Put this function in a module so it is public, and then in the control source for the textbox, instead of just putting the field value, put Zn(fieldvalue). This works like a charm (although using functions in the control source seems to have a delay on the form display). This way you can keep the underlying value as a double and still get commas to display in both the form and the query whilst keeping the field blank if necessary.
Public Function Zn(pvar)
' Return null if input is zero or ""
If IsNull(pvar) Then
Zn = Null
ElseIf IsNumeric(pvar) Then
If pvar = 0 Then
Zn = Null
Else
Zn = pvar
End If
Else
If Len(pvar) = 0 Then
Zn = Null
Else
Zn = pvar
End If
End If
End Function
In short: I have a user-created function (gettargetTemp(targetTemp_input) with one input that, upon function evaluation, I would like to be able to call the function in an Access query (design view) criteria field and have it represent the criteria string that I want evaluated when the query is run.
i.e. targetTemp_input = 1450 - this value is assigned from a form (and can vary)
Access Query
Field: Pad Temp
Criteria: gettargetTemp("targetTemp_input")
Criteria possibilities:
- Records within 100 degrees of the targetTemp_input value which
typically in Access query design is: Between 1350 and 1550 Or Is Null
- All of the records
The code that makes sense to me is:
Public Function gettargetTemp(targetTemp_input)
If Forms![Parameter Confirmation].tempCheck = True Then
gettargetTemp = "Between " & (targetTemp_input - 100) & " AND " _
& (targetTemp_input + 100)
Else
End If
End Function
The outcome of this typically results in a data mismatch error from Access. Is there a way to accomplish what I'm trying to do? Or maybe do it better? I'm not a programmer, but I have a pretty good technical background.
At present, you're trying to have the VBA function form an expression that does the wanted test, rather than doing the test itself. You need to change that:
Function IsTempOK(Temp) As Boolean
Dim ParamForm As Access.Form, TargetTemp As Long
Set ParamForm = Forms![Parameter Confirmation]
If ParamForm.tempCheck Then
If IsNull(Temp) Then
IsTempOK = True ' or False, if that's what you want
Else
TargetTemp = ParamForm.TargetTemp ' or wherever this is defined
IsTempOK = (Temp >= TargetTemp - 100) And (Temp <= TargetTemp + 100)
End If
Else
IsTempOK = True
End If
End Function
In the query definition, the WHERE clause should now use IsTempOK, passing the Temp field as the parameter.
I want to know the Select Query for MS Access with case sensitive.
I have two values for VitualMonitorName as below
VCode VirtualMonitorName
Row 1 (1, 'VM1');
Row 2 (2, 'Vm1');
Here both values are different.
If I write
"SELECT VCode FROM VirtualMaster WHERE VirtualMonitorName like '" + Vm1 + "'";
It replies VCode = 1 Only.
You can use the StrComp() function with vbBinaryCompare for a case-sensitive comparison. Here is an example from the Immediate window to show how StrComp() works. See the Access help topic for more details.
? StrComp("a", "A", vbBinaryCompare)
1
? StrComp("a", "A",vbTextCompare)
0
StrComp() returns 0 if the first two arguments evaluate as equal, 1 or -1 if they are unequal, and Null if either argument is Null.
To use the function in a query, supply the vbBinaryCompare constant's value (0) rather than its name.
SELECT VCode
FROM VirtualMaster
WHERE StrComp(VirtualMonitorName, "Vm1", 0) = 0;
This approach is also available to queries from other applications if they use the newer Access Database Engine ("ACE") drivers. For example, the following C# code
string myConnectionString =
#"Driver={Microsoft Access Driver (*.mdb, *.accdb)};" +
#"Dbq=C:\Users\Public\Database1.accdb;";
using (OdbcConnection con = new OdbcConnection(myConnectionString))
{
con.Open();
using (var cmd = new OdbcCommand())
{
cmd.Connection = con;
cmd.CommandText =
"SELECT COUNT(*) AS n FROM [VirtualMaster] " +
"WHERE StrComp([VirtualMonitorName],?,?) = 0";
cmd.Parameters.AddWithValue("?", "Vm1");
cmd.Parameters.Add("?", OdbcType.Int);
var vbCompareOptions = new Dictionary<string, int>()
{
{"vbBinaryCompare", 0},
{"vbTextCompare", 1}
};
string currentOption = "";
currentOption = "vbBinaryCompare";
cmd.Parameters[1].Value = vbCompareOptions[currentOption];
Console.WriteLine(
"{0} found {1} record(s)",
currentOption,
Convert.ToInt32(cmd.ExecuteScalar()));
currentOption = "vbTextCompare";
cmd.Parameters[1].Value = vbCompareOptions[currentOption];
Console.WriteLine(
"{0} found {1} record(s)",
currentOption,
Convert.ToInt32(cmd.ExecuteScalar()));
}
}
produces
vbBinaryCompare found 1 record(s)
vbTextCompare found 2 record(s)
Check this out:
https://support.microsoft.com/kb/244693?wa=wsignin1.0
This article describes four methods of achieving a case-sensitive JOIN using the Microsoft Jet database engine. Each of these methods has advantages and disadvantages that should be weighed before choosing an implementation. The methods are:
StrComp
Case-Sensitive IISAM Driver
Hexadecimal Expansion
Binary Field
Using only built-in functions, add an additional custom column in the query design view:
location: InStr(1,[VCode],"VM1",0)
the zero parameter requests binary compare (case sensitive) when finding location of "VM1" within [VCode]
set the criteria in that column to >0 so only records with non-zero location in the vcode matching Like "*vm*" contain the exact VM1 string -
The WHERE clause looks like:
WHERE (((VirtualMaster.VCode) Like "\*vm*") AND ((InStr(1,[VCode],"VM1",0))>0));
Using at a simpler level of coding.
As a condition in a DCOUNT operation, checking on a Field (Column) that has to have the correct Case, and ignoring Blank States/Territories.
' lngcounter will count the all States
' or Territories Field ( Column) with this
' exact case value of 'Ohio'. ([ID] is an Autonumber ID field)
lngCounter = DCount("[id]", Trim(Me!tboDwellingTablename), "[State/territory],'Ohio',0) = 0")
This only does one letter:
MS-ACCESS SQL:
SELECT Asc(Left([Title],1)) AS t FROM Master WHERE (((Asc(Left([Title],1)))=105));
Title is the field you want to search
Master is the Table where Title field is located
105 Ascii code for character..
In this case only Title's that start with i not I
If you want to search for lower case "a" you would change the 105 to 97
I am trying to find the blank values and null values in a table. I am using Asc to assign the values of the table to a variable and then based on their ASCII values differentiating null and blank. But I am getting "runtime error 94: Invalid use of null" when the code tries to read the ASCII value of a null field.
When I have to deal with return values that can be either Null or zero-length string, I use a function that converts ZLS to Null:
Public Function varZLStoNull(varInput As Variant) As Variant
If Len(varInput) = 0 Then
varZLStoNull = Null
Else
varZLStoNull = varInput
End If
End Function
This takes advantage of the fact that the VBA Len() function treats a Null and a ZLS exactly the same so that you don't have to handle each case individually.
However, remember that if you use this in a WHERE clause, you'll be losing performance because it can't use the indexes. Thus, in a WHERE clause, you'd test for IS NULL or =""
SELECT MyField
FROM MyTable
WHERE MyField Is Null Or MyField = ""
That will be much more efficient. The varZLSToNull function is most useful when you're appending processed data to a field that has ZLS Allowed set to NO (as it should).
Another thing you should consider is changing your field so that it disallows ZLS, then running a query (using the WHERE clause above without the Is Null) to replace all the ZLS's with Nulls.
Of course, that assumes that your data is not distinguishing between Null and ZLS as meaning two different things (Null meaning "we haven't recorded any value here" and ZLS meaning "we have recorded an empty value here").
You can try the following user-defined function to test the table value:
Public Function text_test(str_in as Variant) As Long
' given input str_in, return -2 if input is Null,
' -1 if input is zero-length string; otherwise return 0
' use function Nz to test if input is Null and return -2,
' otherwise check non-null value with Len
' and return -1 if it is a 0-length string,
' otherwise return 0 for anything else
text_test = IIf(Nz([str_in], "null") = "null", -2, _
IIf(Len(str_in) = 0, -1, 0))
End Function
In the immediate window run a test with different inputs:
?text_test("fred");text_test("");text_test(Null);text_test(9);text_test(False)
Should return:
0 -1 -2 0 0
Note that you cannot use str_in as string in the function declaration since this will cause the same error you refer to in your question.
I think you should be using IsNull() to decide if a value is null.
https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-5034252.html
encapsulate your code inside a if statement and compare the string value to vbNullString like this:
If (Not (<string> = vbNullString) Then
if the string is NOT null execute your original code
if it is null add an Else block to execute what you need to do if the value is null
Yeah, it's an old thread, big deal...
This is the most concise way to test a value for Null and zero-length that I've seen:
FinalValue = IIf(Not Len(Nz(Value, "")) = 0, Value, Null)
How it might perform compared to David Fenton's excellent Function above, I do not know. I do know that the one-liner I present here and David's function do almost exactly the same thing. I suspect the one-liner might perform a bit better than a call out to a Function. On the other hand it makes use of an inclusive If, so it may in fact be slower. Who knows?
I use it in Class modules, mainly. For example, when creating a record with a DAO Recordset:
With rst
.AddNew
!JobCardID = IIf(Not m_JobCardID = 0, m_JobCardID, Null)
!ConstructionProjectID = IIf(Not m_ConstructionProjectID = 0, m_ConstructionProjectID, Null)
!MajorDisciplineID = IIf(Not m_MajorDisciplineID = 0, m_MajorDisciplineID, Null)
!ActivityDescriptorID = IIf(Not m_ActivityDescriptorID = 0, m_ActivityDescriptorID, Null)
!ActivityStatus = IIf(Not Len(Nz(m_ActivityStatus, "")) = 0, m_ActivityStatus, Null
'etc...
End With
In the above code, ActivityStatus is the relevant String.
Note: I never design a database with fields allowing zero-length strings. Repeat: NEVER.