Why is this error causing a loop instead of exiting the function? - ms-access

I was casting around SE and the web yesterday looking for a way to concatenate specific fields from multiple records together as part of a query/report structure in my Access database. I found this SE question which led me to Allen Browne's ConcatRelated() function here. After getting off on the wrong foot by naming the module the same as the function, I got it working as desired.
However, On my initial attempt to use it in a query, I made a dumb mistake and fed it parameters that equated to "WHERE Employee = " & [Employee] instead of the correct'WHERE Employee = ' & [Employee] & "'" necessary to evaluate as a string. This resulted in the expected 3464 (data type mismatch) runtime error but with Allen's modifications it showed the actual string that caused the error. No surprise, I'll just click ok and go fix the SQL. I was surprised to find that didn't work. As soon as I clicked away the msgbox it would come back again. I used Ctrl+Break to stop the code but clicking End caused it to go right back to the same error rather than actually ending the Function. The only way I could stop the loop was by clicking Debug which drops me into the code as expected but I couldn't get out of the code to change the original Query. Hitting reset caused the error to pop again and put me right back in the loop.
I eventually got out of it by commenting everything out of the Error Handler and telling it to Exit Function. I knew that most likely was only masking the problem so I added a counter and had it increment every time the error handler was called then checked the value in the Immediate window. Sure enough, it would go up by 10 or more each time I clicked somewhere in the query.
What I don't understand is what is causing the error to loop. Err_Handler should dump it out of the function on the first error since there's nothing telling it to attempt to Resume and it specifically directs it to Exit_Handler which resets a couple variables and then does Exit Function. Even directly putting Exit Function in Err_Handler still causes multiple increments to the my error counter. Further experimenting with Debug highlights the line Set rs = DBEngine(0)(0).OpenRecordset(strSql, dbOpenDynaset). I don't know that it helps that much since it's the first line after the function constructs the value of strSql. Commenting it out caused the next line to be highlighted.
I know why caused the initial error (my mistake) and that's an easy fix. I'm more interested in the unintended result of the mistake and the loop it created.
tl;dr
What would cause this error to loop instead of exiting or breaking?
Why would it seem to occur a finite number of times if error handling calls an immediate exit but adding something like msgbox first seems to loop infinitely, or at least until I got tired of clicking.
Is there a way to circumvent this in the code so that it actually stops after the fist error?
I initially was using a table with 600+ records but then experimented further with a small table of only 10 records.
Small Table Query SELECT TestEmpHistory.Employee, ConcatRelated("EmpGroup", "TestEmpHistory", "Employee = " & Employee) AS CompliedNames
FROM TestEmpHistory to reproduce the error.
The table TestEmpHistory is in the following format:
ID(AutoNum)|Employee|EmpGroup| Other fields not referenced in the query
ID|Employee | EmpGroup|
1 |Employee1| G&A
2 |Employee1| Sales
3 |Employee2| CSR
4 |Employee2| G&A
5 |Employee3| CSR
6 |Employee3|Programming
7 |Employee3| G&A
8 |Employee4| CSR
9 |Employee4| CSR
10|Employee4| Programming
I'm using Access 2016

Without reading the whole post, I'm guessing the reason you're in a loop is because it's running this code for every row returned by the query. The only way to get out of this is, when you break into the code temporarily comment it all out so that the query can complete without generating the error for every row. Once this has completed, you can go back and correct your query design before un-commenting the function code and trying again.

Related

RTweet new lookup_users continued excess error

I was using R's RTweet lookup_users to successfully pull data on 6 IDs
test<-c("ID1","ID2","ID3","ID4","ID5","ID6")
detail_followers <- lookup_users(users=test,
parse=TRUE,
token=[bearer_token here],
retryonratelimit=TRUE,
verbose=TRUE)
Update: I created a loop so I could get more visibility on the run, which made it profoundly slow. This would be tolerable, except for two new problems. First, some lookup_user are missing the "profile_banner_url" variable. I built a function to check for this problem and insert a NULL value for those users missing it, further slowing the run.
Finally, many users in this set appear to be bots, as they are deleted within 24 hours of my having just pulled them from the API. The error provided from lookup_users is "Error: $ operator is invalid for atomic vectors". is.atomic eval is not useful, because the fault occurs when lookup_user is called. There are far too many of these fake/suspended/deleted users for manual prompts.
These may be issues with the new RTweet from GitHub.

Me syntax working instead of writing full control adress. Why?

I am kind of new to VBA programming in Access and I have banged upon strange thing. I have system of myListbox (multi-choice, two of them in testing regime, planning 5 total) to filter myReport contained in subform container by selected items in those listboxes.
Switching "On" filter works kind of fine (I will address it in different question after doing some research first), but switching filter off turned out to be problem. I was getting error message described here.
Managed to find a workaround. Since I have myReport bound to control in parent form, I am not switch off filter, instead I am changing it to resemble the bound field criteria, after that switch it off.
Code:
Forms![myForm]![myReport].Report.Filter = "((sourceQuery.fieldForBoundControl)=Forms![myForm]![boundControl])"
Me.FilterOn = False
but if I try this:
Forms![myForm]![myReport].Report.Filter = "((sourceQuery.fieldForBoundControl)=Forms![myForm]![boundControl])"
Forms![myForm]![myReport].Report.FilterOn = False
...or any other combination, or simply turning it off, I get error messages and procedure termination. Why?
Is my solution correct for future working of the app or I my setting myself for another Access trap?

Show MessageBox if no records for report

I already asked a Question Here.
My this question is just a step ahead to same problem.
I have a delphi code which works perfectly for calling report.
But, now I wanted to show a MessageBox before opening rpt file.
I tried to query it separately for record count and then decide for MessageBox. But, this solution is having a worst case where a aprticular report's query itself takes 3 mins to execute and then again querying while opening rpt it takes 30 sec to load (in second query it takes less time may be because of some data may present in buffer/temp place,etc.).
qPODPhy.close;
qPODPhy.SQL.clear;
qPODPhy.SQL.text :='select * from ViewName';
qPODPhy.Open;
If qPODPhy.RecordCount < 1 Then
MessageBOx('No data To Display...');
Else
Begin
crRep.Somproperties := Initialization
.
.
.
CrRep.SQLQuery := qPODPhy.SQL.text;
crRep.action := 1
End
My Question is :
How can I show a MessageBox if no record is going to present for particular view's output.
OR
Is there a method where I can open the dataset of .rpt file in delphi code and just check the count of records and make the decision? In short, is there some property of crystalreport component which can do this?
You can do a select count(*) separately, that is much faster.
Or maybe select only one record: SELECT TOP 1 ....
And, as RBA suggested, you can try putting that SELECT COUNT in a stored procedure for even more speed.
Just experiments with these methods to see if/when you've gained enough speed.
Are you pushing the data ? You can probably use ReadRecords method of the ReportDocument and check Rows.Count property. If the report is retrieving the data the you can use the NoData event of ReportDocument.

"No current record" after Cancel in combo_BeforeUpdate

I'm trying to prevent circular (or even cascading) references in my data, and it seems it's only working part of the time.
In Access 2007, I have the following table:
create table mfr (
mfr_id Autonumber,
mfr_nm Text(255),
mfr_is_alias_for_id Long Integer
)
I'm importing a bunch of data from Excel, and the mfr_nm is one of the columns from the worksheet. I can't control how data gets entered into Excel, so I want a way of capturing alternate spellings as being "really" same thing. So far, so good (I think...).
Now I've built a form off of this table. I've got a ComboBox for the alias--again, so far, so good. However, when I add this code to the BeforeUpdate event, things get "interesting" (error handling omitted):
If Not IsNull(cboMfrAlias) Then
If Not IsNull(DLookup("mfr_is_alias_for_id", "mfr", "mfr_id=" & cboMfrAlias)) Then
MsgBox """Alias for"" must not also be an alias.", vbExclamation
Cancel = True
End If
End If
This works exactly as I expect it to when the form is in Form View, but if I'm in Datasheet View my MsgBox is immediately followed by an Access-generated "No current record" error that is not caught by error handling within the BeforeUpdate sub.
Can I catch this error? Where?
Your dropdown list should filter out entries that are aliases. In other words, don't display a choice the user can't make.
You'd do this by simply eliminating from the dropdown the choices where mfr_is_alias_for_id Is Not Null.
I've implemented this in various guises and it works fine.
I'm addressing the "No Current Record" error part of your question, from so long ago. After checking google for an answer, I found this link which was helpful. However, instead of using NZ() to transform the troublesome binary field in an aggregate query, I used troublesomefield: IIF([troublesomefield] IS NULL,NULL,[troublesomefield]) and this worked to banish the error. So my solution is only a small variation on the original answer I found, but it gets around the error and let you keep nulls if you want to...

How to insert a Please Wait form while a query is running

I want to display a "Please Wait" form while a 60+ second query is running. I have the query and the form made (easy enough), except the macro won't bring them together. Here is my autoexec macro:
SetWarnings=False
Open Wait Form
Run the query & Display Results
Close Wait Form
The problem is that I can only see the outline of my wait form while the maketable query is running. I can only guess that the macro doesn't wait for the form to completely load before going to the next step.
And just for fun:
The Wait form has a Timer that shows the number of seconds elapsed. How do I run the query while still allowing the form to update itself at the same time?
-------Update----------
Repaint only updates the background color before moving on to the query. I also tried 6 repaints in a row with no difference (I thought that might get around the bug you people mentioned). The form is very simple. A single text box that uses "loading" for the control source and a timer function (disabled for the moment). Here is my macro in slightly greater detail:
SetWarnings=False
Open Wait Form (modal=yes, popup=no)
Repaint the form
Open a maketable query (this query saves alot of time)
Close Wait Form
Open the display query
Firstly, you just need to Repaint the wait form after it is shown for it to show correctly, it's just a bug in VBA that sometimes causes forms not to be displayed properly even if they are drawn at the correct point in the code.
Secondly, if you set the wait form's ShowModal property to false then you will be able to update it through your routine. I use a public function that takes a 0-100 argument to update a progress bar. This works best in a loop where you can normally calculate the number of loops remaining and provide an accurate guide to the elapsed progress, but even when performing a series of operations you can time and pass suitable values through to the progress form so that the user is kept informed. This works better than most Windows progress bars!
The first problem is easy to solve, try putting me.Repaint before the query runs, sometimes access can get a bit lazy with screen painting and you have to force it.
As for the other thing that is a bit more complicated. You would have to execute the query asynchronously. You can do this in ADO by adding the adAsyncExecute option when executing the query. You would then catch the finishing event to tell the users the query is done
Here is a link on the Microsoft knowledge base http://support.microsoft.com/kb/262311
If you are using an Action Query you can track the number of executed rows by using a vba-function which returns the same value that was passed to it. Of course you have to know the total number of rows, to know when the query is done or display progress (This can often be achieved relatively fast using a lightweight counting query*).
'first some global vars to keep track of the number
Dim lngCurrentRow as Long
Dim lngTotalRows as Long 'We assume lngTotalRows have been set elsewhere
'Here is the function
Public Function UpdateProgress(FieldValue as Variant) as Variant
lngCurrentRow = Nz(lngCurrentRow, 0)
If (lngCurrentRow >= lngTotalRows) then
MsgBox "Query Done!"
Else
'Do stuff to show progress
End If
lngCurrentRow = lngCurrentRow + 1
End Function
For displaying the progress I have used an Unbound form, with an empty textfield with transparent background (progressFrame) and a label (progressLabel) which has a blue background and is placed behind the textbox to the left. For each call to UpdateProgress you can then set the width of the label:
progressLabel.Width = progressFrame.Width * (lngCurrentRow / lngTotalRows)
*: F.ex. if the query is based on one table, with some added data, so that the number of records the query will produce is equal to that of the table, a count can be done on the table alone so that it will be faster..
I hope this was helpful, or at least inspiring :)
I had the same issue with a pop up form which took a few seconds before it displayed the text which informs the user that something is processing so please wait. I added the line of code below after the code which opens the form and before the next bit of code which runs the update queries (which takes a while hence the need to inform the user that something was processing)
DoCmd.RepaintObject acForm, "frmMyForm"
Works perfectly for me.