InStrRev Not Giving Correct Results - ms-access

I have an Access database where I'm importing book/journal publication data from JabRef in a CSV format.
When I import the data to Access one of the odd things that happens is that the page numbers are given two hyphens in between them, so the data in the "pages" column in Access would look something like "200--213"
I need to be able to count the number of pages that are referenced.
In order to do this I do the following in unbound text boxes on the form:
I find the length of the string in the "pages" column (have to rename the pages variable as it's a reserved name to pagesset): PLen = Len([pagesset])
I find the number of characters that happen from the left up to the "--": LPageVar = InStr([pagesset],"--")
I find the number of characters that happen from the right up to the "--": RPageVar = InStrRev([pagesset],"--")
I find the actual page number on the left side of the "--": LVal = Left([pagesset],[LPageVar]-1)
I find the actual page number on the right side of the "--": RVal = Right([pagesset],[RPageVar]-1)
I calculate the number of pages that appear: Pgcnt = RVal - LVal
Everything seems to work... except when the "InStrRev" hits an item that increments the number by the 10 or 100 spot, like this: "7--11", "7--23", or "92--101" as opposed to this: "102--123" or "103--110" (which causes no issues). When it hits these shorter pagethe RPageVar is too low by 1.
For each of these items on the right, RVal seems to drop the first character... so for "7--11" last page is reported as 1 or for "7--23" it would report the last page as 3 or "92--101" the last page is reported as 01. This causes these particular page counts to be negative.
Does anyone have an idea as to why I'm getting this behavior?

InStrRev() searches from the end of the string, but the location it returns is relative to the beginning of the string, not the end. So,
s = "this is a test--1"
Debug.Print InStrRev(s,"--")
displays 15, and
Right("this is a test--1",15)
is obviously not going to isolate the "1" at the end of the string. That would be done with
Mid(s,InStrRev(s,"--")+2)
or, in the case where there is only one instance of "--" in the string
Mid(s,InStr(s,"--")+2)
would also work.

Here is a different approach which is less confusing for me; not sure if it will be less confusing for anyone else, though.
? PageCount("200--213")
14
? PageCount("7--11")
5
Function PageCount(ByVal pIn As String) As Long
Dim astrPageRange() As String
astrPageRange = Split(pIn, "--")
PageCount = (Val(astrPageRange(1)) - Val(astrPageRange(0))) + 1
End Function

Related

Pulling One Element From A CSV File

I'm trying to write a function that will return the most recent 'closing' value in a csv file containing the data of a cryptocurrency. The csv file contains 6 columns and about 900 rows and I'm looking to only pull one element of the table.
However, I seem to faced a fair bit of difficulty in pulling this off for some reason. The function below returns values from the column I want, however it seems to be pulling values from the very bottom of the document (whereas I want the most recent values).
Also, just a side note to explain what I was attempting to do with the 'count'. Since I'm expecting the value I want to be located on the second row, I wanted my for loop to only iterate through two lines of the file. However, as the result of the function went on to reveal to me, as it currently stands with the counter I'm returning two values from the function.
I understand there must be a much less convoluted way of getting the information I need so am open to any solution to the problem. Though, that being said, I'd be really interested to see where I went wrong here as I'm fairly new to Python.
Thanks a lot!
def csv_to_close(csv_file):
with open(f"{csv_file}.csv", 'r') as csvfile:
csv_file = csv.reader(csvfile)
running = True
count = 0
while running == True:
if count < 2:
for column in csv_file:
close = column[4]
count += 1
else:
running = False
print(close)

Only Show specific word from a string

I'm currently learning Access 2016 since i find it works wonders with Excel.
However i'm trying to find the correct SQL code for detecting certain words in Long Text and only output these words not the text itself
Here is the setup
Fieldname: Type
Long Text
Cell Information
Cell1: Johan have a nice car
Cell2: Jane road a bike.
Cell3: Janes bike was red
Output
Cell1: car
Cell2: bike
Cell3: bike
I'm only interested in keeping certain words from these strings when the query is done, and they should be output to the same Fieldname, i have tried to locate this information for the most part of the day and my last hope of sanity was to check in here if someone has an idea of which function i should be using.
Thank you for your time
You will probably have to use VBA for this, depending on how big your list of words is, but one way to do it with SQL, assuming a relatively small and FIXED list of words:
IIF(<Mytext> LIKE '*car*','car',IIF(<Mytext> LIKE '*bike*','bike',''))
You could either read the values from a table or fill an array. Both would work, but I prefer table-driven code because, for something like this, adding new search terms would only require you to add them to your table.
So, what I would do is first create a new table called tblSearchTerms. In that table, create one field called SearchTerms, and put each of your terms (i.e. "Car", "Bike", etc...) in there, one per record.
Then set up a function in Access. Open a Module (either a new one or one you already have, as long as it's a Module), and enter this:
Function SearchExists(sString As String) As String
Dim db as Database
Dim rec as Recordset
Set db = CurrentDB
Set rec = db.OpenRecordset("Select SearchTerms from tblSearchTerms")
Do while rec.EOF = False
If InStr(1, sString, rec(0)) > 0 Then
SearchExists = "" & rec(0) & ""
Goto BugOut
Else
End If
Loop
SearchExists = "Not Found"
BugOut:
End Function
Now, what you do is create a query. In that query, you'll have one field to check to see if your search term exists. It will look something like this:
MySearchTerm: SearchExists([Cell1])
When you run your query, that field will either populate with one of the search terms (if it's found), or will return "Not Found".
This may require a bit of tweaking, because it's more for finding a search term in an Access table, so there's going to need to be some adjusting to make it work with Excel, but it's pretty close to what you need.

Access writng to wrong row number

4150
NRrows = RSNonResourceCosts.RecordCount ' Number of Rows in Non Resource Table
NRCols = RSNonResourceCosts.Fields.Count ' Number of Fields in NonResource Table
Dim CL(1 To 10) As Integer ' This is to count "filled rows" when spreadsheet is filled
Dim Header(1 To 10) As String
'-----------
'Find the Headers (Taken from Actual Table and not predefined as original)
For Each Recordsetfieldx In RSNonResourceCosts.Fields
If C > 0 Then
Header(C) = Recordsetfieldx.Name
End If
C = C + 1
Next Recordsetfieldx
4170
R = 0
'Write to worksheet
RSNonResourceCosts.MoveFirst
Do Until RSNonResourceCosts.EOF
For C = 1 To NRCols - 1
FieldName = RSNonResourceCosts.Fields(C).Value
If RSNonResourceCosts.Fields(Header(C)).Value <> "" Then
CL(C) = CL(C) + 1
WKS.Cells(200 + R, C) = RSNonResourceCosts.Fields(Header(C)).Value
End If
Next C
RSNonResourceCosts.MoveNext
R = R + 1
Loop
I attach code. Have solved part of original by defining Recordset. User can add column to Table. First part of code determines the headers. Second part determines values and writes to worksheet. The new Rows are appearing first on the worksheet and in wrong column. I tried attaching worksheet but it looked awful. Any help would be appreciated.
Two things:
1) The order your records is the order they are in the recordset. If you want them in a particular order, try sorting them (perhaps with an ORDER BY in the underlying SQL statement)
2) For the column issue: In the first bit of code, I don't see where C is initialized, but keep in mind the Headers and Fields both start with an index of 0, so if you set Header(1) = the first field's header (index 0), but then copy the data in the fields without shifting the index value, it will shift everything over by one column.
As an added note, you might want to consider what happens when you have more than 10 columns. Using fixed-length arrays means your code will break. You might want to read about using a dynamic array and ReDim.
I don't yet feel like I have completely grasped the entirety of the problem yet, but let me take a stab at it. From what I do understand, data is being written from your record set into excel (good), but it is going into the 'wrong row' (question title) and the 'wrong column' (question text).
From what I see, I don't know the purpose of FieldName = RSNonResourceCosts.Fields(C).Value, but I want to make sure that you understand that RSNonResourceCosts.Fields(C).Value is not necessarily equivalent to RSNonResourceCosts.Fields(Header(C)).Value. More than that, you are likely missing at least one column altogether in your output, or at least skipping over it accidentally. rs.Fields(0).name is the first 'column' in a recordset, but it is completely ignored in your code. Perhaps this is intentional, maybe it is a key field or something useless to you, but it is important that you are making that distinction intentionally. But, since I don't see where your code populates the headers in your worksheet, I wonder if 'wrong column' means every record has been shifted a column and your last column is sitting empty. That, coupled with the dubious omission of C being initialized as 0 (not 1, or anything else) in your above code, makes me concerned that Header(3) could possibly by field(1), or field(4), or I don't know. That would certainly also confuse the columns in your output, or at least make dependence on FieldName frustrating.
Another thing, really a shot in the dark: NRrows. I have had issues before, depending on how I create my recordset, of not getting the correct record count the first time. And, if I base the population of a worksheet, array, etc., on the number of rows and the records relative position in that number, my records get all sorts of wacky. Maybe you did this already, but since it isn't shown, I recommend a RSNonResourceCosts.movelast: RSNonResourceCosts.movefirst line before you define NRrows, just to be sure.
And last, if I am way off base here... then you really are going to have to show us the spreadsheet, even if it isn't your most beautiful work. We all know that if it were, you wouldn't be asking about it here... so set your pride aside, and be more specific as well as show us what the output looks like and how it should look.

In MS Access 2010 I'm trying to ignore a duplicate entry in a control

I want to ignore duplicate entries in specific text fields on a form. So, for example, I have 3 fields for seal entry. If the person scans a seal twice, it will ignore the duplicate and keep the focus on the field until a different number is entered. I cobbled together some code that works for the first and second entry, but not the third. When I debug it seems to be finding a duplicate number even though I'm entering in a different one.
Private Sub Seal2_AfterUpdate()
If Seal2.Value = Seal1.Value Or Seal3.Value Then
Seal2.Value = Null
Seal1.SetFocus
Seal2.SetFocus
End If
End Sub
Private Sub Seal3_AfterUpdate()
If Seal3.Value = Seal1.Value Or Seal2.Value Then
Seal3.Value = Null
Seal1.SetFocus
Seal3.SetFocus
End If
End Sub
You are treating the Or wrong. It's evaluating after the Seal2.Value = Seal1.Value.
So what you have done in that if statement is equivalent to
If (Seal3.Value = Seal1.Value) Or Seal2.Value Then
And since Seal2 has a value, it is evaluating to True
You want something more like:
If (Seal3.Value = Seal1.Value) Or (Seal3.Value = Seal2.Value) Then
Also, you seem to be setting focus to one field and then another. You probably want to only go to one unless you are trying to fire off triggers/events when you get/lose focus in each one; however, if you are doing that you might be playing with fire
In the end your if blocks probably want to look like this:
If (Seal2.Value = Seal1.Value) Or (Seal2.Value = Seal3.Value) Then
Seal2.Value = Null
Seal2.SetFocus
End If
and
If (Seal3.Value = Seal1.Value) Or (Seal3.Value = Seal2.Value) Then
Seal3.Value = Null
Seal3.SetFocus
End If
Finally, if you find that you have to expand beyond 3 fields, you may want take a slightly different approach that would be more scalable. E.g., Building up a list in memory, sorting and filtering it. But for 3 or 4 items you can get away with what you have already.

How to write a simple JQuery integer division function

My webpage displays realtime data that is updated every 10 seconds from our PI server(historian server). I was recently tasked to take two peices of data that are allready displayed on my page and divide them, displaying the new result on a graph. I have very little experience with AJAX/JQuery, so I was wondering if someone out there can lend me a hand?
Clarification:
Hypethetically-
Say I have "Number of Grades" and "Sum of Grades" displayed on my page as basic integers. They are updated every 10 seconds from the server. I want to take those two pieces of live data, divide them, and display the result (in this case it would be the overall average grade). So, my page will display Number of Grades, Sum of Grades, and Average Grade all updated in real time, every 10 seconds.
I am unclear as to whether JQuery can simply take those values off the server and perform division on them and return a value, or if other steps need to be taken to achieve this. I'm completely shooting in the dark here so sorry in advance for any vagueness or lack of required information.Thank you. Some example code is given below:
<span class = 'PIdata' data-tag = 'NumOfGrades' data-on_pi_change = 'NumOfGradeChange'></span>
<span class = 'PIdata' data-tag = 'SumOfGrades' data-on_pi_change = 'SumOfGradeChange'></span>
I want to display a value that divides NumOfGrades by SumOfGrades.
var sumOfGrades = parseFloat($.('#SumOfGradesId').text());
var numberOfGrades = parseFloat($.('#NumberOfGradesId').text());
var result = fn(sumOfGrades , numberOfGrades);
$.('#AverageGradeId').text(result);
This will set the required value.
Simple Maths with jQuery - division
The above link seems to have the answer to your question! Basically just access numbers by their id you set, get the value, parse them into integers or floats, perform your calculation, then store the value into the spot you would like it to appear!