Henry Simpson
hsimpson88 at hotmail.com
Fri Sep 12 22:29:05 CDT 2003
The question specifies that the call back is getting lists of fields from a 'couple of tables' hence the 'xxx' part of the table name should probably be interpreted as a placeholder for various specific table names which is why I suggested using multiple lists if using a RowSourceType of field list. In addition, you may note that the size of the array is redimmed progressively larger to include fields for a total of three tables. The field list rowsource is not an option if the fields of several table must be included in a single list. Another thing I see that is objectionable is that there are three calls to CurrentDb in the initialize procedure which causes three calls over a LAN to the backend file to refresh the database collections and each of these calls takes time as well. Had a database variable been dimensioned and set in a single call to CurrentDb, there could have been a minor improvement. Far bigger is the improvement from limiting the size of the recordsets by setting a condition that returns no records (numeric pk = -1 or Where False). Looking at this sample again, I also note that the recordset variable is set to nothing twice in the initialize procedure and once in the function's general exit (which happens many times as the list is created and filled). I understand the desire to kill the object in an error handler to ensure that a crash in the initialize procedure doesn't leave any surviving objects to hang on to resources and there is no problem setting a nothing object to nothing, however, i believe the best approach is to close a recordset object before setting it to nothing and attempting to close an object that hasn't been opened will trigger an error. That would require an on error resume next in the exit procedure (which is also slower than an error handler without the resume next). The two alternatives are to close and set to nothing in the initialize case and in the error handler only and not in the exit routine or, better yet, call an external procedure that sets a module level array for the list box or have a function return a static array (not static in the redim sense, but in the variable lifetime sense, Microsoft sucks with their careless terminology) and properly create and destroy any object variable in a procedure that will only run once. If the ultimate need is to display field names from multiple tables, the best proposition is to avoid the recordset object and just pull the field collections of the tabledefs. Whenever I use callbacks that require the creation and destruction of object variables, I call an external procedure to initialize a data array in order that I can write the cleanest error handler that will run where it belongs and give the clearest indication of the actual source of the error. I too agree that two minutes is intolerable and that even four seconds is bad but we do not know how much of the tab change time is attibutable to this portion of the code. In fact, four seconds could be stunningly fast depending on the LAN speed and how much data and the number and type of controls. All we really know is that there is a minute and fifty six seconds difference between two different network environments and the question implies that the listbox rowsource is somehow at fault. Obviously the form tab is LAN sensitive or, all things being equal, there would be no difference between LANs, so the solution is to cut down on calls from the FE to the data file. Multiple calls to CurrentDb, opening recordsets, pulling tables of data to get a field list and even setting them to nothing before resetting them cause LAN traffic. If the two minutes can be improved on, then so can the four seconds. Hen >From: "Charlotte Foust" <cfoust at infostatsystems.com> >Reply-To: Access Developers discussion and problem >solving<accessd at databaseadvisors.com> >To: "Access Developers discussion and problem >solving"<accessd at databaseadvisors.com> >Subject: RE: [AccessD] listbox with rowsource type (ala MS) >Date: Fri, 12 Sep 2003 08:05:44 -0700 > >IMO 4 seconds is too long to load each tab page as well. Your callback >routine is repeatedly opening and closing what looks like the same >recordset or else you pasted the same acLBInitialize case code in 3 >times. A field list as the rowsourcetype would be a faster way to get a >list of fields for a single table. > >Charlotte Foust > >-----Original Message----- >From: Sad Der [mailto:accessd666 at yahoo.com] >Sent: Friday, September 12, 2003 2:01 AM >To: Acces User Group >Subject: [AccessD] listbox with rowsource type (ala MS) > > >Hi group, > >i've got a problem. I'm using a tab control. On all >tabs i've got listboxes wich are filled with field >names of a couple of tables. These listboxes are >filled using the rowsource type thingy. This seems to >be the original MS-way-of-programming. > >Below I pasted the code. In the property RowSourceType >of the listbox I fill in the function name. > >When I programmed it it worked fine. The client is on >the desktop of the user and the BE is on our test >network. It took about 4 seconds to load each >tab-page. > >Now it's in production (on another network) and if a >switch between tab pages now takes almost 2 MINUTES!!! > >Any ideas how this is possible?? > >tia > >Sander >Private Function ListMeetVelden(fld As Control, id As >Variant, row As Variant, col As Variant, code As >Variant) As Variant > > Static strVelden() As String > Static lngRows As Long > Dim varRetVal As Variant > Dim oMeetTable As DAO.Recordset > Dim i As Integer > > On Error GoTo ListMeetVelden_Error > > Select Case code > Case acLBInitialize > ReDim strVelden(0) > 'fill array with fields. > Set oMeetTable = CurrentDb().OpenRecordset(Name:="tblxxxx", >Type:=dbOpenSnapshot, Options:=dbOpenForwardOnly) > With oMeetTable > For i = 0 To .Fields.Count - 1 > strVelden(UBound(strFields)) = "C_" & >.Fields(i).Name > ReDim Preserve strVelden(0 To >UBound(strVelden) + 1) > Next i > End With > > Set oMeetTable = Nothing > 'fill array with fields. > Set oMeetTable = CurrentDb().OpenRecordset(Name:="tblxxx", >Type:=dbOpenSnapshot, Options:=dbOpenForwardOnly) > With oMeetTable > For i = 0 To .Fields.Count - 1 > strVelden(UBound(strFields)) = "D_" & >.Fields(i).Name > ReDim Preserve strVelden(0 To >UBound(strFields) + 1) > Next i > End With > > Set oMeetTable = Nothing > 'fill array with fields. > Set oMeetTable = CurrentDb().OpenRecordset(Name:="tblxxx", >Type:=dbOpenSnapshot, Options:=dbOpenForwardOnly) > With oMeetTable > For i = 0 To .Fields.Count - 1 > strVelden(UBound(strVelden)) = "E_" & >.Fields(i).Name > ReDim Preserve strVelden(0 To >UBound(strVelden) + 1) > Next i > End With > > ReDim Preserve strVelden(0 To UBound(strVelden) >- 1) > > lngRows = UBound(strVelden) + 1 ' array is >0-based > varRetVal = lngRows > Case acLBOpen > varRetVal = Timer 'Unique ID for control > Case acLBGetRowCount > varRetVal = lngRows > Case acLBGetColumnCount > varRetVal = 1 > Case acLBGetColumnWidth > varRetVal = -1 'Default of -1 uses default >column width > Case acLBGetValue > varRetVal = strVelden(row) > Case acLBEnd > Erase strVelden > End Select > > ListMeetVelden = varRetVal > >ListMeetVelden_Exit: > Set oMeetTable = Nothing > Exit Function >ListMeetVelden_Error: > Set oMeetTable = Nothing > Call g_oGenErr.Throw("xxx.frmxxx", "tblxxxx") >End Function > > > >__________________________________ >Do you Yahoo!? >Yahoo! SiteBuilder - Free, easy-to-use web site design software >http://sitebuilder.yahoo.com >_______________________________________________ >AccessD mailing list >AccessD at databaseadvisors.com >http://databaseadvisors.com/mailman/listinfo/accessd >Website: http://www.databaseadvisors.com >_______________________________________________ >AccessD mailing list >AccessD at databaseadvisors.com >http://databaseadvisors.com/mailman/listinfo/accessd >Website: http://www.databaseadvisors.com _________________________________________________________________ Tired of spam? Get advanced junk mail protection with MSN 8. http://join.msn.com/?page=features/junkmail