This function MRound does not exist in MS Access and you can't just install it.
I am trying to use the mround function in an Access
report. The function is not listed in the expression
builder box of built in functions. When I use the
calculation, for example, =mround([AmountDue],0.05), and
run the report, it asks for a parameter mround.
You could define your own in a public VBA Module, e.g.:
Function MRound(dblNum As Double, dblMtp As Double) As Double
MRound = dblMtp * Round(dblNum / dblMtp, 0)
End Function
Alternatively, add a reference to the Microsoft Excel Object Library to your VBA Project (Tools > References) and define the MRound function in a public VBA module as:
Function MRound(dblNum As Double, dblMtp As Double) As Double
MRound = Excel.WorksheetFunction.MRound(dblNum, dblMtp)
End Function
There is no MRound present in Access, so create your own rounding function.
However, never use Round for this, as it notoriously buggy. Thus, use plain math and the data type Decimal to avoid errors:
' Rounds a value by 4/5 to the nearest multiplum of a rounding value.
' Accepts any value within the range of data type Currency.
' Mimics Excel function MRound without the limitations of this.
'
' Examples:
'
' RoundAmount(-922337203685477.5808, 0.05) -> -922337203685477.6
' RoundAmount( 922337203685477.5807, 0.05) -> 922337203685477.6
' RoundAmount( 10, 3) -> 9
' RoundAmount(-10,-3) -> -9
' RoundAmount( 1.3, 0.2) -> 1.4
' RoundAmount( 122.25, 0.5) -> 122.5
' RoundAmount( 6.05, 0.1) -> 6.1
' RoundAmount( 7.05, 0.1) -> 7.1
' 2009-05-17. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function RoundAmount( _
ByVal Value As Currency, _
ByVal RoundValue As Currency) _
As Variant
Dim BaseValue As Variant
Dim Result As Variant
BaseValue = Int(Value / CDec(RoundValue) + CDec(0.5))
Result = BaseValue * RoundValue
RoundAmount = Result
End Function
This function will, for example, round this correctly:
Amount = RoundAmount( 122.25, 0.5)
Amount -> 122.50
For further information about precision rounding, refer to my project at GitHub:
VBA.Round
and the articles referred to herein.
Related
In MS Access I have a table with a Short Text field named txtPMTaskDesc in which some records contains numbers, and if they do, at different positions in the string. I would like to recover these numbers from the text string if possible for sorting purposes.
There are over 26000 records in the table, so I would rather handle it in a query over using VBA loops etc.
Sample Data
While the end goal is to recover the whole number, I was going to start with just identifying the position of the first numerical value in the string. I have tried a few things to no avail like:
InStr(1,[txtPMTaskDesc],"*[0-9]*")
Once I get that, I was going to use it as a part of a Mid() function to pull out it and the character next to it like below. (its a bit dodgy, but there is never more than a two-digit number in the text string)
IIf(InStr(1,[txtPMTaskDesc],"*[0-9]*")>0,Mid([txtPMTaskDesc],InStr(1,[txtPMTaskDesc],"*[0-9]*"),2)*1,0)
Any assistance appreciated.
If data is truly representative and number always preceded by "- No ", then expression in query can be like:
Val(Mid(txtPMTaskDesc, InStr(txtPMTaskDesc, "- No ") + 5))
If there is no match, a 0 will return, however, if field is null, the expression will error.
If string does not have consistent pattern (numbers always in same position or preceded by some distinct character combination that can be used to locate position), don't think can get what you want without VBA. Either loop through string or explore Regular Expressions aka RegEx. Set reference to Microsoft VBScript Regular Expressions x.x library.
Function GetNum(strS AS String)
Dim re As RegExp, Match As Object
Set re = New RegExp
re.Pattern = "[\d+]+"
Set Match = re.Execute(strS)
GetNum = Null
If Match.Count > 0 Then GetNum = Match(0)
End Function
Input of string "Fuel Injector - No 1 - R&I" returns 1.
Place function in a general module and call it from query.
SELECT table.*, GetNum(Nz(txtPMTaskDesc,"")) AS Num FROM table;
Function returns Null if there is no number match.
Well, does the number you want ALWAYS have a - No xxxx - format?
If yes, then you could have this global function in VBA like this:
Public Function GNUM(v As Variant) As Long
If IsNull(v) Then
GNUM = 0
Exit Function
End If
Dim vBuf As Variant
vBuf = Split(v, " - No ")
Dim strRes As String
If UBound(vBuf) > 0 Then
strRes = Split(vBuf(1), "-")(0)
GNUM = Trim(strRes)
Else
GNUM = 0
End If
End Function
Then your sql will be like this:
SELECT BLA, BLA, txtPMTaskDesc, GNUM([txtPMTaskDesc] AS TaskNum
FROM myTable
So you can create/have a public VBA function, and it can be used in the sql query.
It just a question if " - No -" is ALWAYS that format, then THEN the number follows this
So we have "space" "-" "space" "No" "space" "-" -- then the number and the " -"
How well this will work depends on how consistent this text is.
It is possible to create User Defined Functions in MySQL just as we do in excel, if Yes How to do the same.
Also, If above is possible then how do i correlate (have same usage) the MySql Function with my existing excel function pasted below:
Public Function HexToText(Text As Range) As String
Dim i As Integer
Dim DummyStr As String
For i = 1 To Len(Text) Step 2
If Val("&H" & (Mid(Text, i, 2))) > 31 Then DummyStr = DummyStr &
Chr(Val("&H" & (Mid(Text, i, 2))))
DoEvents
Next i
HexToText = DummyStr
End Function
Please note that my Hex Data also contains Null (00) probable causing error while using Unhex
One example Values in Hex Column:
596f757220496e7465726e6574206163636f756e7420776974682044484c2042524f414442414e44204e4554205b505d204c494d4954454420686176696e6720757365726e616d652020414a57414454524156454c2077696c6c20657870697265206f6e20323031362d31302d30332032303a30303a313620506c656173652
Error Result Achieved via above UnHex command :
��W"��FW&�WB66�V�Bv�F�D��%$�D$�B�UB��ĔԕDTB�f��rW6W&��R�tEE$dT�v���W��&R��#b��2#��b�V6R
Actual Result should have been something like:
Your Internet account with DHL BROADBAND NET [P] LIMITED having username AJWDTRAVEL will expire on 2016-10-03 20:00:16
I'm new to visual basic so forgive me in advance.
I'm trying to reference a data table from a module and I get “reference not a shared member requires object” error. I can’t figure out why.
Public Module myFuncs
Public Function get_name()
Dim lotto As Integer
Dim counter As Integer
Dim first As String
Dim last As String
Dim fullname As String
counter = Database11DataSet.Tbl_names.Rows.Count
lotto = Int((counter - 1 + 1) * Rnd() + 1)
Dim nameq = From n In Database11DataSet.Tbl_names.AsEnumerable()
Where n.ID = lotto
Select n
For Each n In nameq
first = n.first
Next
lotto = Int((counter - 1 + 1) * Rnd() + 1)
… 'does the same for the last name
Return fullname
End function
As you mentioned, your problems were on the lines that used:
Database11DataSet.Tbl_names
Within your code, Database11DataSet appears to be a type rather than an object; the only methods that can be called on a type are shared (or, depending upon the language, static). From http://en.wikipedia.org/wiki/Method_(computer_programming)#Static_methods:
Static methods neither require an instance of the class nor can they implicitly access the data (or this, self, Me, etc.) of such an instance. A static method is distinguished in some programming languages with the static keyword placed somewhere in the method's signature.
In your case, you should be able to resolve this by creating an instance of Database11DataSet at the top of your code, and then using that in place of the type:
Public Function get_name()
...
Dim data as new Database11DataSet()
counter = data.Tbl_names.Rows.Count
lotto = Int((counter - 1 + 1) * Rnd() + 1)
Dim nameq = From n In data.Tbl_names.AsEnumerable()
Where n.ID = lotto
Select n
...
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've tried googling, but with limited luck - what I want to do is use VBA to read in coordinates from a serial GPS dongle (or bluetooth Android phone mimicking the former), log a "visit" record, and find the nearest matching record on a table of our clients. Has anyone seen an opensource script that will allow this?
Thanks in advance.
PG
For the serial port data acquisition see the Serial Port Communications page at my web site. Then you can write records to a table using a SQL Insert query or a DAO Recordset with an AddNew. However finding the nearest matching record will likely require using of geometry to figure out the reading through the table looking for the closest location I'd have to refresh my memory as to the exact equations required.
I'm also thinking that to speed up the search you might want to index the latitude and longitude and start your search at nearby lat/longs. That is limit the initial record set to plus/minus, for example, 0.1 of a lat/long which, just guessing would be about 10 kms square.
Here's a rough rundown of what you will need to do.
Lookup Longitude & Latitude For Your Clients' Addresses:
I posted a question a while back on SO asking how to get GPS Coordinates for an address. You can see that question here. There's actually two functions there for you, one to use Google Maps API and another that uses rpc.geocoder.us. Take your pick. Just be aware that each of them having limitations. Google has licensing restrictions as well as maximum queries per day. Geocoder.us has a limit of one query every 15 seconds and I don't remember what their maximum queries per day is, if they even have a limit.
Obviously, you will need to retrieve the Longitude and Latitude for your addresses beforehand, and store this information along with the address. You could possibly try to come up with a zip code for the area and lookup the addresses by that but it could be horribly inaccurate in sprawling urban areas, especially if you have a lot of customers concentrated in a single zip code. You'll need to take Tony's advice here and query your GPS coordinate data using a between statement to get addresses in the near vicinity.
Get GPS Data from the GPS Device
As Tony has already pointed out, you'll need to use something like an ActiveX control, DLL, or API call to perform serial communications with your GPS Device. I have used MS's communication ActiveX control in the past for getting GPS data and it did work satisfactory.
I don't know where my code is to retrieve the incoming data from the GPS device. It's not exactly trivial if you have never programmed serial communications before. You usually have an OnComm event that fires on incoming data. If I remember correctly you loop until an EOF (End of File) code or bit is found which indicates the end of a data stream. If you use MS's Communications Control you can see some sample code here: http://support.microsoft.com/kb/194922
I think I had to use 4800 in my settings instead of 9600 but your requirements may be different depending what type of device you are using.
Extract The Right Data From Your Incoming GPS Data
Step two is to extract the data you need from the incoming GPS Data. You may even find that you have to change it to match the GPS Data you have stored (see below).
In my sample NMEA sentences (above), the Longitude and Latitude are both in the following format:
ddmm.mmmm
For some programs or API's you may have to convert it into Degrees.Degrees, or to word it another way, dd.dddd. The formula to convert it is:
dd.dddd = ddd + mm.mmmm/60
So, for example, if we want to convert my sample data above to exact Longitude and Latitude in degrees, here's what it would look like:
3731.9404 ----> 37 + 31.9404/60 = 37.53234 degrees
10601.6986 ----> 106 + 1.6986/60 = 106.02831 degrees
Here are some functions I wrote back in 2007 to extract certain parts of the data from the NMEA sentence:
Public Function ExtractLatitude(strNMEAString As String, Optional strNMEAStringType As String = "GPRMC") As String
'This function extracts the latitude from an NMEA string and converts it to Decimal Degrees (as a string).
'To use this function you must specify what string type you are passing in, either GPRMC or GPGGA
Dim aryNMEAString() As String
aryNMEAString() = Split(strNMEAString, ",")
Dim dblMinutes As Single, dblLatitude As Single
Select Case strNMEAStringType
Case "GPRMC"
'Latitude is the Number 3 place in the array (4th place in the string)
If aryNMEAString(2) = "A" Then 'A represents a valid string
dblMinutes = (CDbl(Mid(aryNMEAString(3), 3, 7)) / 60)
dblLatitude = CDbl(Left(aryNMEAString(3), 2)) + dblMinutes
ExtractLatitude = CStr(dblLatitude)
End If
Case "GPGGA"
'Latitude is the Number 2 place in the array (3rd place in the string)
If CDbl(aryNMEAString(2)) <> 0 Then 'If string is invalid it will be 0
dblMinutes = (CDbl(Mid(aryNMEAString(2), 3, 7)) / 60)
dblLatitude = CDbl(Left(aryNMEAString(2), 2)) + dblMinutes
ExtractLatitude = CStr(dblLatitude)
End If
End Select
End Function
Public Function ExtractLongitude(strNMEAString As String, Optional strNMEAStringType As String = "GPRMC") As String
'This function extracts the longitude from an NMEA string and converts it to Decimal Degrees (as a string).
'To use this function you must specify what string type you are passing in, either GPRMC or GPGGA
Dim aryNMEAString() As String
aryNMEAString() = Split(strNMEAString, ",")
Dim dblMinutes As Single, dblLongitude As Single
Select Case strNMEAStringType
Case "GPRMC"
'Latitude is the Number 3 place in the array (4th place in the string)
If aryNMEAString(2) = "A" Then
dblMinutes = (CDbl(Mid(aryNMEAString(5), 4, 7)) / 60)
dblLongitude = CDbl(Left(aryNMEAString(5), 3)) + dblMinutes
ExtractLongitude = CStr(dblLongitude)
End If
Case "GPGGA"
'Latitude is the Number 2 place in the array (3rd place in the string)
If CDbl(aryNMEAString(4)) <> 0 Then
dblMinutes = (CDbl(Mid(aryNMEAString(4), 4, 7)) / 60)
dblLongitude = CDbl(Left(aryNMEAString(4), 3)) + dblMinutes
ExtractLongitude = CStr(dblLongitude)
End If
End Select
End Function
Public Function ExtractSpeed(strGPRMC As String) As Integer
'Expects a GPRMC NMEA Sentence
Dim aryGPRMC() As String, dblSpeed As Double
aryGPRMC() = Split(strGPRMC, ",")
If aryGPRMC(7) <> "" Then dblSpeed = CDbl(aryGPRMC(7))
'Convert knots to MPH
ExtractSpeed = CInt(dblSpeed * 1.15077945)
End Function
Public Function ExtractHeading(strGPRMC As String) As Double
'Expects a GPRMC NMEA Sentence
Dim aryGPRMC() As String
aryGPRMC() = Split(strGPRMC, ",")
If aryGPRMC(8) <> "" Then ExtractHeading = CDbl(aryGPRMC(8))
End Function
Public Function ExtractSatelliteCount(strGPGGA As String) As Integer
'Expects a GPGGA NMEA Sentence
Dim aryGPGGA() As String
aryGPGGA() = Split(strGPGGA, ",")
ExtractSatelliteCount = CInt(aryGPGGA(7))
End Function