i am new to access and i am debugging someone's database
how do i know if i am using ADO?
i have stuff in a listbox, how do i use the .GetRows method to put the recordset into a two-dimensional array?
Do you have a reference to the ADO libraries (In a code window, under Tools->References: Microsoft ADO Ext x.x For DLL and Security, Microsoft ActiveX Data Objects x.x Library) Have you set the recordset to an ADO recordset?
You will find details of GetRows here: http://www.w3schools.com/ado/met_rs_getrows.asp
You can use it like GetString, as illustrated in a reply to your previous post.
EDIT
You do not have to have a reference to the ADO libraries to use ADO, but it can be easier. To use ADO without the libraries (late binding), try something like:
Dim cn As Object
Dim rs As Object
Set cn=CreateObject("ADODB.Connection")
Set rs=CreateObject("ADODB.Recordset")
cn.Open strConnect ''Any suitable connection string
rs.Open strSQL, cn ''Any suitable SQL string
As others mentioned, to check if the using ADO, you as a general rate ruled can look in your code. However what's probably confusing you and not has been explained is that it's ONLY in your coding practices do you choose ADO or DAO.
For the rest of the application (ie: BUILT IN OBJECTS) you will use the concept of what's called linked tables. These linked tables handle all of the connection strings and all of the internal workings for you. There's no additional effort required on the user's part when they're developing the application. For all of these internal objects, you don't choose a particular data object type (ADO or DAO).
What this means is that for filling data into forms, data into reports, data into listbox, data into combox boxes etc. you DO NOT write code, and YOU DO NOT use connection strings. And you DO NOT HAVE a choice of ADO or DAO. What this means is that when you look at a combo box or list box or form, you'll get off the confused really fast if you start looking for some type of connection string or asking if that combo box is based on ADO or DAO (hint: you as a genera rule don't have a choice in this matter: all of these object and how they work are handled automatically for you internally inside of a MS access). What this means is all you have to do supply the given object with some SQL, and you're done.
So, all of these objects will as a rule work from your linked tables in access. Once these linked tables are set up, then you build forms, or reports, or list box is based on these linked tables. As a result a as mentioned, you'll not be choosing ( or even have to bother) with DAO or ADO when working with these objects.
The choice of ADO or DAO We'll generally only come into play in your actual code that opens a record set or query directly. Most of the code in a form can be based on referencing the controls or objects such as an combo box that exist on that form. Once again the choice of ADO or DAO it not relevant, and you don't have control over that aspect.
For example, if you wanted to use code to setup the values for a combo box, you would use the following code: (we assume the combo box is a two column combo box, 1st column is id (hidden) and 2nd column company name.
The VBA code to fill or setup the combo box via sql is:
Me.Mycombobox.RowSource = "select id, CompnayName from tblCustomers"
That is it!
Notice how there's no connection strings, no record sets, you just shoved some clean SQL right into the combo box row source and away you go.
Now of course the above assumes you have a linked table called "tblCustomers". You can see/view those tables in the tables tab.
( By the way our combo boxes and listbox is allow more than two columns, to hide columns you set the format lengthy equal to zero for that column. That way you can still access the data in your code, but not have that column displayed in the list box).
So the choice of ADO/ADO is often not an issue. Note that even when you do choose ADO or DAO in your code, you as a general rule should use the built in table objects and this again will not have to bother with an connection string built in code. There are some exceptions here, but let's keep this general for the time being.
The above should clear up a lot of your questions about how come you can't see or tell how the form is using DAO or ADO ( the answer is you don't bother with this, and the answers you don't have a choice, and the answer is this is all automatically handled internally for you by MS access)
2.i have stuff in a listbox, how do i use the .GetRows method to put the recordset into a two-dimensional array?
For what reason do you want to do the above? There is VERY little reason to pull data from a listbox into a array. You have the list box ALREADY loaded up with data, so why then waste time loading this data into an array? For what reason would you do this?
You can reference the data in that listbox, but you might want explain what you're trying to accomplish here. There's no need to pull the data out of the listbox, but you can use code in a form to look at value(s) selected in the listbox, and do a useful things with those selections made. Again, to work with the selected data from that listbox, you don't need an array, you don't need connection strings, and you don't need to write a whole bunch of code to repeat what is our data currying and is available inside of that form (hint: the data inside of that list box is available for you as a collection).
So you don't need a record set, you don't need to write a whole bunch of code nor do you need some connection strings. And you don't need nor want to pull that data from that list box into an array, it's simply not required and is completely overkill. Simply stay what you're trying to do with that listbox, and we'll come up with a solution that's likely only a couple of lines of code.
As mentioned, look at that data tab of a listbox, and take a look at the SQL used to fill that listbox. Does that sql run correctly, and furthermore check of the number of columns specified in the listbox matches the number of columns you have in your SQL that set for that list box in the data tab. Funny things can happen if the number of columns don't match the settings for the number of columns in the listbox.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 11 months ago.
Improve this question
My question: Why would a SQL string function properly as a query but not as the RecordSource of a report?
I apologize for the lengthy background, but I think the context in which this issue is arising is probably helpful. In Access 2019, I have a MainQuery that is based upon multiple other queries, some of which are parameter queries. So, MainQuery itself does not contain any parameters as part of its definition, but because its "constituent queries" contain parameters for which the user is prompted, running MainQuery prompts the user for said parameter values. Note that I call them "constituent queries" because they are all standalone query objects in my database as opposed to true subqueries within MainQuery.
MainQuery is the RecordSource of MainReport. Of course, upon opening MainReport, the user is prompted for the parameters that allow MainQuery (i.e. all its constituent queries) to run. Naturally, the user must reopen or refresh MainReport and supply different parameter values each time to see a different set of data inside MainReport.
This arrangement has worked well for years and continues to work, but I recently decided I wanted to increase the functionality of the database by allowing the user to print out multiple MainReport reports (for different records) in rapid succession.
The strategy I used was to consolidate MainQuery and all of its constituent queries into one big, complex MasterQuery made up of legitimate subqueries defined inside of it. The parameters for which the user used to be prompted each time the MainQuery was run were replaced with a simple string place holder, and the entire body of the MasterQuery is saved in a SQL_Table so that my VBA code can access it. Now, the user can select the records for which he or she wishes to print on a form designed for this purpose. Then, upon clicking a button, my VBA code gathers the user's choices, retrieves the template SQL string from the SQL_Table, and for each record that the user wants to print, replaces the string place holders in the SQL string (previously known as the parameters) and assigns the RecordSource of MainReport to that SQL string.
As I was working on this project for the last week or so, I was able to get this process to work very beautifully and successfully. But, as I continued developing it, I ended up making several additions and alterations to the MainReport and MasterQuery to improve the functionality of the database.
So, the current state of affairs is that I am successfully passing the SQL string to the RecordSource property of the report, but the problem is that Access tells me there is an error in the SQL string, and it will not actually run the report. Instead, the report stays in DesignMode and will not go into Report View. The error message says,
Syntax error in query. Incomplete query clause
In attempting to diagnose the problem, I took the exact same SQL string (I literally copied and pasted it from the RecordSource property of report into the SQL View of a blank query), and to my surprise, the query runs beautifully. It returns the result set that I expect to see. As a bonus, I even saved the query as Query1 and set the RecordSource of MainReport to Query1, and even this works!
I don't understand this behavior. I might expect that either they both work with the same SQL string or they both don't work, but I don't understand why they might behave differently; and this is the crux of my question.
So, why would a SQL string function properly as a query but not as the RecordSource of a report?
Thanks in advance for anyone who might have any ideas!
Well, since the query in its raw form will not run, and you fully pointed out that you "replace values in that query?
And since you ALSO point out that you are replacing the reports query source (and you MIGHT WANT to show and explain how you doing that?
So, given that you EACH TIME are going to modify the raw query? Then obvislity if you modify it for one time, then the values in that report (the critera) will have be changed. So, it ALSO not clear how you deal with that issue??
In most cases, becuase the query in its raw format has "values" that you going to replace, then in theory those values need to be "known" so you can repalce them.
Thus, as a general apporach for the above?
I save the raw query in the querybuilder, but then MAKE A COPY of that query, make the critera replacments and then SAVE that query to a 2nd query - a query that the report is based on.
So, say we have a simple query and report.
qryHotelsS (I put a "s" on such querys - means "source"
qryHotels (the final fixed up and changed query).
So, say I have this:
SELECT * FROM tblHotels WHERE City = '#City' ORDER BY HotelName.
So, I now might have some really nice prompt form, or form that allows the person to enter the city criteria, and then hit a view report button.
The code would thus look like this:
Dim strSQL As String
Dim strCity As String ' for test - the value would no doubt come
' from a very nice form wiht a text box, and
' button to launch the report.
strSQL = CurrentDb.QueryDefs("qryHotelsS").SQL
strCity = "Calgary" ' as noted, this would be some text box value on
' a nice report form
strSQL = Replace(strSQL, "#City", strCity)
CurrentDb.QueryDefs("qryHotels").SQL = strSQL
DoCmd.OpenReport "rptHotels", acViewPreview
So, we grab our "source" query, replace the values we want, and then save the query to a query that the report is based on, and then simple launch that report.
I mean, it really comes down to how your replacing and setting up the query now? The REALLY nice feature of above? You can run the code (comment out the open report command above). Once you run the above code, then you are rather free to open up the report and do further design and tweaking of the report, and since it has a valid query source, then you are free to design, change and setup the report any way you want. (since it has a valid sql query source).
so, adopt the idea of a having two queries for the report. The "source" query - with some values that you replace in VBA code. I just out of the blue used '#City', so I use # signs, and you can roll your own quite much anyway you want. You could even leave in the [] and have your VBA replace the [], but I like using # signs for this. And it works well even for dates.
eg:
WHERE InvoiceDate = ##InvoiceDate#
So, in code, you can just replace #InvoiceDate with a date string, but the delimiters (#) don't need to be added.
Edit: Why some query can't work in code?
Well, if you can take that string, shove it (save it) into a query, and then run the report on that query, then this can work.
However, there is a SIGNFICANT difference to use the DAO object model, and shoving sql into a reocrdset vs that of basing a form, or query on the same source.
Remember, the DAO recordset object does NOT allow and does NOT know about forms! Expressions etc., and they can't be used.
And if you introduce ANY VBA function into the sql? Once again, you cannot use the DAO querydef object.
The pure data engine (DAO) can be used from vb6, vb.net, c# etc. The data engine thus does not allow for example forms! expressions, and it ALSO does not allow use of custom VBA functions in that sql.
So, basing a reprot on a saved query def? No problem, both forms! expresisons, and even VBA functions can be contained in the sql query.
However, if you attempt to use the SAME query, and shove it into a DAO recordset? Then the so called "expression" service. (the system that resolves forms! expresions, and resolves VBA function calls) cannot be used.
That is due to the fact that the data base engine (JET/ACE) does not know about VBA, does not know aobut forms!, and it is a stand alone data engine, and a data engine NOT limited to being used with Access, but as noted can be used from FoxPro, vb.net, c#, vb6 etc. So, a pure DAO data engine call does not have nor allow forms! expressions, and as noted does not even allow you to have VBA expressions. It has to be 100% valid JET ONLY sql syntax. So, while some functions exist in JET sql, a good number of VBA ones are NOT allowed.
The JET database engine thus does NOT even know nor even assume that a forms! object exists, can be open, or closed, and the same goes for VBA functions used in that sql - in fact they can't be used.
So, if you put such expresisons in a query, and use from MS-ACCESS? Then the query can be run from the UI, can be used as a data source to a report, but in pure VBA code, setting the same query to a DAO recordset object will fail.
So, it probably better to either:
Figure out if you have any VBA functions used in the sql
Figure out if you have any forms! expressions used in the sql
And then remove the above.
However, you might have a bit of a difficult time working through that messy sql, so you can then just shove that query string into a querydef ojbect (save it into the .SQL property as I did above), and then simple base the report on that saved query as opposed to trying to create a DAO recordset object in code, and using that for the forms reocrdsource, which as I point out above can't use forms! or VBA functions - and has to be pure valid JET/ACE syntax without such expressions.
I have a SQL Server that is ODBC into my Access which is being utilized as my front end. I created a column in SQL with a BIT data type and created a checkbox with the yes/no data type that uses my SQL Column as its control source. When I go into my form and try to change anything in there and update my tables, I get a writing error and it wont let me append the updates I'm trying to make. As soon as I delete the bit data type, and the check box, then I am able to again append information to my form. Does anyone know a solution or a way I could utilize the Boolean check boxes to report to my SQL Database so that I could track progress of an order, but still be able to append my records? Also if anyone knows why this is happening I would appreciate the information just for my own notes and understanding.
this image shows the column created in SQL Server
This image shows what it looks like in the ODBC table in Access
This image shows the control source I picked which is from a query that utilizes the names of the form comboboxes, text boxes, and hopefully check boxes
This is image shows what happens after I try to update and and close
Thanks
haven't done this for a long time, but the problem could be related to the numbers that are stored. yes/no in access = -1/0, in sqlsrvr = 1/0 (or similar). you could use an INT field in sqlsrvr which will then store whatever access sends (-1 or 0), or keep the BIT but don't use yes/no in access - create a custom yes/no table where yes=1 and no=0 (or whatever BIT needs) and use the custom table as a lookup table for that field which, when updated will send the appropriate value. hope that's all relevant and makes sense.
So I have been messing around with this and after a few other problems running through SQL, Cabinet Vision (our drafting software with a ancient access database) and crystal reports I came to realize that Access cannot accept null values.
So in my SQL Bit data type column I set the default value as 0 and didn't allow nulls. now it records all my check boxes as true or false. and I no longer have a write conflict.
This most commonly arises when a db is developed in Access and at some later date the tables are exported via ODBC to SQLServer. The Checkbox controls on the Access forms were probably placed there using the 'Available Fields' button on the Access 'Design' ribbon. Before getting into complicated solutions with T-SQL modifications to metadata etc, try simply deleting the checkbox control from the problem Access form. Insert an unbound checkbox to replace it, then use the the Properties dialog to set the relevant SQLServer field as the control source for that checkbox. Usually works.
I'm using MS Access 2007 as a front end and have all linked tables in SQLServer 2008 R2 backend.
In a form in Access I am trying to execute the FIND button either in the ribbon or by creating a button on the form with the expressed purpose of looking for records with a specific value in a particular field.
When I complete the entry in the FIND window, I click on Find Next. In some cases, the record(s) is found immediately. In others, it can go for hours only to report that it can't find anything (when I know it should).
The table I am looking in has approximately 99,000 records in it. It doesn't seem to matter whether or not the field is indexed.
Is there something I'm doing wrong, or is Access unable to handle this? Also, is creating a stored procedure with handling multiple search requests and passing the info to Access the answer?
The find methods are known to be slow with ODBC data sources. Here is what the Access 2007 Recordset.FindFirst Method help topic says:
When working with Microsoft Access database engine-connected ODBC databases and large dynaset-type Recordset objects, you might discover that using the Find methods or using the Sort or Filter property is slow. To improve performance, use SQL queries with customized ORDER BY or WHERE clauses, parameter queries, or QueryDef objects that retrieve specific indexed records.
Futhermore, binding an Access form to a record source of 99K records is a performance challenge. Use a query as the form's record source, and design the query to return only one or a few rows.
Give the user an option to choose a different set of rows, and modify the form's record source property to reflect the user's choice.
This depends on the type of search you need and on the data type of the column (field) to be searched. For example, if I have a text data type in an indexed column and I search using Start of field or Whole field, it will be quite fast, however, if I search for Any part of field, it may well fall over. In other words, if Access can use an index for the search, it will work, even on quite a large table, otherwise, you may be best with a stored procedure, though I doubt that will be fast without an index, either.
I'm in the process of converting a MS Access 2000 database to MySQL, while still using Access for the front end.
I've come across a problem where some forms get the data from fields in MS Access tables. IE, the "Control Source" value is set to a specific field, and when the form is run, its creates the required number of Textboxes to match the number of entries in the table and populates them with the data from the tables.
Now I'd like to be able to set the Control Source of the Textbox to call a VBA function, which get's the data from MySQL, and populates the textbox with the entries in MySQL table. I'm not sure how this is achieved, or if its even possible.
So could I just create a VBA function and set it in the Control Source property for the Textbox, or do I need a more complicated solution ?
You do not need any code for the text boxes to display. Simply use a linked table to MySql, and the form should function as before. There is little if any reason I can think of here to dump the use of bound forms and bound controls.
I have a form which will generate a report for mailing.
The form opens a recordset with all the fields needed. I'm wandering how can i pass this recordset to the report, so that i don't need to open the same recordset once again.
Similarly, sometimes i also want to pass recordset between forms (no main/sub form relation), how can i do this?
Another little question, when i open a form in datasheet view, it's always very big. How can i limit its size when opening?
Thanks!
EDIT:
To be clearer, say i have "FORM", when the user hit a button on it, "Report" will be open. I want "Report" to use the recordset that is already created(opened) in "FORM".
Also on "FORM", there is a textbox, filled by users, i want also to show it on the "Report".
EDIT2:
I tired but cannot passe the recordset, nor populating a field in my report from a textbox on my form, very annoying ..
You should be able to accomplish this by simply passing the correct SQL statement to your report. This can be done using the Opening Arguments.
Assuming that you really do want the identical set of records on your report as you see on your form, what you need to do depends on how you have opened your form, or how you are filtering your form. You could indeed use an identical DAO Recordset object and set your reports Recordset object to a copy or clone of the Form's Recordset object. However, this might not be necessary to get the results your look for.
Solution #1
If your form uses a query or SQL statement you can use this solution.
Code on your form:
DoCmd.OpenReport "rptReportName", acViewPreview, , , acWindowNormal, Me.RecordSource
Code on your report:
Private Sub Report_Open(Cancel As Integer)
Me.RecordSource = Nz(Me.OpenArgs, "")
End Sub
Solution #2
Use this solution if your form is using the form's filter property to filter down to the correct set of records. I'm assuming you then want to pass that filter condition on to the report. You'll need to configure the report so that it uses the same RecordSource as your Form (or it must at least contain the table/fields that will be included in your filter statement). The problem is that passing the recordsource of your report to your form doesn't pass any filter that you might have set on the form.
DoCmd.OpenReport "rptReportName", acViewPreview, , Nz(Me.Filter, ""), acWindowNormal
As a final note, it is not possible to set a Report's recordset property. You can assign a Recordsource as I've already shown (a recordsource is a tablename, a queryname, or an SQL statement) but you cannot use the Recordset property unless the database is an Access Data Project, which I don't recommend using at all.
Edit1
It wasn't clear from the original post what problem the OP was trying to solve. I incorrectly assumed he was having trouble getting the same records to show on his report as what he has on his form. It appears that rather the OP is concerned about making two trips to the server to retrieve records.
Because you cannot set the Recordset value on an Access report, your best option might be to create a local Access table and simply use it as a temp table. I don't know what size your recordset typically is. If it's quite large (5000+ records) this solution may not be a good idea. One problem I can think of is that it will cause your front-end database application file to bloat over time unless you have the file setup to run Compact and Repair on close.
I think the worry about two trips to the server is unwarranted.
If you were using a Jet/ACE back end, Jet would cache the data locally, and there wouldn't be a re-retrieval unless the data had changed (in which case I think you'd probably want the up-to-date data, no?).
With a server database, the server itself is likely to cache the results, particularly if the SQL statement used is identical in both cases.
This looks to me like a case of premature optimization.
Well If I have understand from your question you need to manipulate the data in a table by knowing/unknowing the record set number.
If that is then you need to reform the mentality of how to access data in a table, because to promote the record set number in your list is not the quite right way, usually we promote the data and the record numbers are hidden.
So when you read your table try to pass your fields into variables for later use or pass them directly to your list view.
The way of accessing the table to get each data it comes from another process which always varied.
But even when you want to keep the record numbers for later use try to declare a name as public variable as ArrayList() then when you read from table you may use the 'Variable'.add(RecordNumber) .
So when you need to access a particular number take the reading line number from your list view by calling VariableName(ListViewLineNumber)
Please inform me if this solution comes closely to you issue solution.