use variable instead of table name - ms-access

First Thanks for your comments. The array for Names if the tables names like, Name1, Name2, Name3,.. but we have different names.
However, May I need to explain by other way to be understand.
What I want to do is compare old DataBase with new DataBase (Both in MS Access). Each has many tables (>20), and each table has many fields like “Number”, “ Name”, etc, and put the differences in “Output” Table.
Then to make code short as possible, I want to use Loop and use Variable refer to Tables names. I put all Tables Names in below table:
enter image description here
TablesNames
Old_DB_Tables_Names | New_DB_Tables_Names
Items_List | Items_List
Items_Price | Items_Price
Items_Specs | Items_Specs
Items_Size | Items_Size
Items_Warehouse | Items_Warehouse
Items_Spare | Items_Spare
Items_Quantity | Items_Quantity
:
: :
:
Dim TablesNames As ADODB.Recordset
Dim Items_List As ADODB.Recordset
Dim Items_Price As ADODB.Recordset
Dim Items_Specs As ADODB.Recordset
Dim Items_Size As ADODB.Recordset
Dim Items_Wearhouse As ADODB.Recordset
Dim Items_Spare As ADODB.Recordset
Dim Items_Quantity As ADODB.Recordset
:
:
Dim I as Integer
I=0
Table1=TablesNames.item("Old_DB_Tables_Names").value
Table2=TablesNames.item("New_DB_Tables_Names").value
While TablesNames .EOF=False
if Table1.fields(I) <> Table2.fields(I) then
Output.Fields.Item("Number").Value Table2.Fields.Item("Number ").Value
Output.Fields.Item("Name").Value Table2.Fields.Item("Name ").Value
:
:
End If
I=I+1
Wend
The issue VBA not accept statement [Table1.fields(I) <> Table2.fields(I)].
Is it: we can’t refer to a table by its name, and to any of its fields and get a value from a record in that field?
If you have anther way, Please let me know.

Ok, let's start with the first part:
Dim TablesNames As ADODB.Recordset
Dim Items_List As ADODB.Recordset
Dim Items_Price As ADODB.Recordset
Dim Items_Specs As ADODB.Recordset
Dim Items_Size As ADODB.Recordset
Dim Items_Wearhouse As ADODB.Recordset
Dim Items_Spare As ADODB.Recordset
Dim Items_Quantity As ADODB.Recordset
What it looks like you are trying to do from the rest of your code:
Bring all the information from each table into your code.
What you are actually doing:
Creating empty recordset variables, to store table data and then never storing any table data. i.e. TableNames, Items_List, etc. are all variables, and they currently have nothing to do with anything, at all, they are completely empty and have no meaning to the rest of your code in their current states.
Next we have:
Table1=TablesNames.item("Old_DB_Tables_Names").value
Table2=TablesNames.item("New_DB_Tables_Names").value
What it looks like you are trying to do from the rest of your code:
Store instances of your tables using the name of the table.
What you are actually doing:
Accessing the value of a field in the recordset TableNames and storing that value in a variable named Table1. From the name, I assume you are expecting this to be a TableDef, but you are using it as either a string or a value type, but I can't tell because I'm not seeing where you declared it. If you didn't declare it, you need to type "Option Explicit", without the quotes, at the top of every single one of your modules, right now, seriously, stop reading and go do that.
While TablesNames .EOF=False
If you had set the recordset of TableNames in your code, this will work, as long as you don't have a space before .EOF
if Table1.fields(I) <> Table2.fields(I) then
What it looks like you are trying to do from the rest of your code:
Access a field from the TableDef stored in the variable Table1.
What you are actually doing:
Nothing, since, from your code, Table1 is either a string or value type and there is no method nor property named "fields" for any string or value types, you aren't doing anything.
Finally we have
Output.Fields.Item("Number").Value Table2.Field`enter code here`s.Item("Number ").Value
Output.Fields.Item("Name").Value Table2.Fields.Item("Name ").Value
What?
All of this leads me to believe that you haven't grasped the syntactical structure of VBA. While many of us here would like to help you, in most cases, we aren't going to be able to just give you an answer that will work completely, with out some sort of modification by you.

Related

VBA Variables inside DoCmd.RunSQL

Just a question. Situation is as follows:
I have 15 make table queries that pulls data for a different submission clarification code that was used on a claim; i.e. Pull all claims where submission clarification code 5. As of right now I have a macro that will run all 15 queries, but each time I am required to type in the region I am filtering for due to the [What Region?] prompt I had put in the criteria field.
My question is:
Is it possible to use VBA to run all 15 queries using the DoCmd.RunSQL where I only have to type in the region number once and it will apply it to all queries?
My initial thoughts were I would have VBA prompt me for what region I'm filtering for, store that in a variable, and then use that variable in the SQL statement. But I'm not even sure if you can do that? Thanks in advance for any advice that may be given!
Update: So after reading a few threads, I created a mock database to try out some of the concepts and I think I might be on the right track?
Private Sub btnTest_Click()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim SQLString As String
SQLString = "SELECT tblEmployees.ID, tblEmployees.Last_Name, tblEmployees.First_Name, tblEmployees.SS_ID INTO Test" _
& "FROM tblEmployees" _
& "WHERE (((tblEmployees.ID)=[What number]));"
Set qdf = CurrentDb.QueryDefs("Query1")
qdf.Parameters(0).Value = InputBox("What is the ID Number")
qdf.Execute
qdf.Close
Set db = Nothing
Set qdf = Nothing
End Sub
So to apply this to the 15 queries I would just Dim other variables as DAO.QueryDef right? I'm note really sure i need the SQLString part either? Also, I noticed that when running this mock code it took quite a while for it to create the new table. Is this normal? Also also, the code will not run if the table it is creating already exists. Is there a way to just have the code replace the existing table with the new one? Kind of new to this VBA so thanks for your patience.
Short answer is yes, this is possible. Some keywords you want to familiarize yourself with are "parameters" which are the variables with the prompt and "Querydef" or query definition.
There are quite a few articles detailing how to pass parameter values to a query programmatically. Check out this page for a solid overview of how to accomplish this. Most notably, the last example uses an inputbox to prompt the user to provide the parameter value, which gets you close to what you need. (ie. cmd.Parameters(0).Value = InputBox("Enter a country name"))
Modified to your design, it might be best to create a string variable and ask for the parameter first, then use the variable in declaring the parameters individually, which would permit a single parameter submission that gets applied to all queries.
EDIT
I have adjusted your code to show you how to go about it. You will have to repeat the block for each query.
Private Sub btnTest_Click()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim strParamter As String
Set db = CurrentDb
strParamter = InputBox("What is the ID Number")
Set qdf = db.QueryDefs("Query1")
qdf.Parameters(0).Value = strParameter
qdf.Execute
qdf.Close
'Now move to next query
Set qdf = db.QueryDefs("Query2")
qdf.Parameters(0).Value = strParameter
qdf.Execute
qdf.Close
'...etc.
Set qdf = Nothing
Set db = Nothing
End Sub

Using access to refer to objects within access

I have a basic table in access with several populated fields. I would like to explore if there is a way, preferably through the GUI (or maybe through SQL), to add a field containing the name of the table itself. I see only the following data formats for fields: Short text, Long text, number, Date/time, Currency, Autonumber, Yes/No, OLE Object, Hyperlink, Attachment and Calculated. There is nothing pertaining to data object parameters themselves such as table, field or query names or parameters...
You can access the meta data of the database via VBA (Visual Basic for Applications) macros.
For example, this can show all table names:
Option Compare Database
Public Sub Test()
Dim database As DAO.database
Dim tableDef As DAO.tableDef
Set database = CurrentDb
For Each tableDef In database.TableDefs
MsgBox tableDef.Name
Next
End Sub

MS Access 2007: Runtime error 64224: Method 'Collect' of object 'recordset2' failed

I have been searching high and low for a workaround for this error, but since I haven't, I now turn to you for help. I am not (at all) an experienced programmer, so I hope this is not too basic a question to ask here, and that others can still benefit.
I am trying to set up a form, where I can register when one of our employees lends some stuff for a given period of time. I.e. from 21-12-2015 to 10-01-2016 employee n.n. lends a laptop. The form has two unbound textboxes TxtFraDato and TxtTilDato for the dates (from and to), and two unbound listboxes containing the name of the employee and the 'stuff' to be lend. The listboxes get their data from the tables:
Medarbejder (The employee):
- Navn: text (Primary key)
Materiale:
- Id: number (Primary key)
- ModelType: Text
I know that having a table like my Medarbejder-table is not at all pretty, and I have a fealing that this could be causing the problem, but this table is linked to a .txt-file created from a bat-file, and I have not been able to figure out, if there is another way to create such a link, that will give me a chance to give the table another primary key.
Finally, I have a button that on-click should save the record to the table "Udlaan":
Id: number (Primary key)
FraDato: date
TilDato: date
Medarbejder: text (lookup column)
Materiale: number (lookup column)
However, when I click the button, I get the runtime error 64224: Method 'Collect' of object 'recordset2' failed.
Private Sub btnSaveUdlaan_Click()
Dim db As Database
Dim rs As Recordset
Dim FraDato As Date
Dim TilDato As Date
Dim Medarbejder As String
Dim Model As Integer
Set db = CurrentDb
Set rs = db.OpenRecordset("Udlaan")
FraDato = Me.TxtFraDato.Value
TilDato = Me.TxtTilDato.Value
Medarbejder = Me.MAList.Column(0)
Model = Me.ModelList.Column(0)
AddUdlaan rs, FraDato, TilDato, Medarbejder, Model
rs.Close
db.Close
End Sub
The AddUdlaan:
Private Sub AddUdlaan(rs As Recordset, FraDato As Date, _
TilDato As Date, Medarbejder As String, Model As Integer)
' Adds a new record to a Recordset using the data passed
' by the calling procedure.
With rs
.AddNew
!FraDato = FraDato
!TilDato = TilDato
**!Medarbejder** = Medarbejder ß The debugger is pointing to this field
!Materiale = Model
.Update
End With
End Sub
Perhaps this is not at all the right way to solve by problem, so any help on this is much appreciated. But as it is, I would also be happy to lean something from the encounter with this error.
This is because the lookup field is a recordset of the recordset. Only Recordset2 can handle these.
Thus, what you should assign is the (hidden) Id of Medarbejder, in pseudo code:
!Medarbejder = <Id of recordset Medarbejder>
This can be done but - as already mentioned by #Parfait - do yourself a favour and get rid of the lookup fields. How "smart" they may seem, they will cause you nothing than trouble in the future.
As a start, change table Medarbejder to have an AutoNumber Id as the primary key.

Converting from Access to SQL Back End (Multi-Value Fields)

So I'm converting an access back-end to SQL. I've tried a few different tools (SSMA, Upsizing Wizard, and a simple import). I've found so far that the SSMA tool and importing seem to work the best, eliminating most of the work necessary for me. However, I'm running into one issue I can't figure out how to overcome.
Two fields allow multiple values (dropdown with check boxes). In converting these, it errors in a way that it not only doesn't carry all of the information over, but also grabs information from another field (and doesn't carry that information over).
I've tried forcing access to only accept the first value (and get rid of multi-values all together), but it won't let me.
Any ideas?
This should get you started. It will turn all those values which are selected in the multi select field into their own table. You will need to establish the relationships between the three tables to create a true many to many relationship after the fact.
Sub ExtractMultiValueFields()
Dim JoinTable As New DAO.TableDef
JoinTable.Name = "JoinTable"
With JoinTable
.Fields.Append .CreateField("MainTableId", dbInteger)
.Fields.Append .CreateField("JoinToValue", dbText)
End With
Dim joinRs As DAO.Recordset
CurrentDb.TableDefs.Append JoinTable
Set joinRs = CurrentDb.OpenRecordset("JoinTable")
Dim rs As DAO.Recordset
Dim childrs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("select * from table1")
Do While Not rs.EOF
Debug.Print rs("ID")
Set childrs = rs("col1").Value
Do While Not childrs.EOF
Debug.Print childrs("value") 'always "value"
joinRs.AddNew
joinRs("MainTableId") = rs("ID")
joinRs("JoinToValue") = childrs("value")
joinRs.Update
childrs.MoveNext
Loop
rs.MoveNext
Loop
End Sub

Why does a datasheet view show only 100 records when based on sorted and filtered adodb recordset

I have an access 2003 front end database with a form that allows users to see a sorted and/or filtered view of some data. The data is displayed in a sub-form.
The base data (loaded when the form is opened) is retrieved into a disconnected ADODB.Recordset object (static client side cursor). The sub-form's Recordset property is set to the disconnected recordset and all records are displayed.
Applying just a sort (in code) to the recordset object and then setting the sub-form to use the sorted recordset displays the data with the correct sort applied. The filter property is set to adFilterNone for this to work. All records are displayed (correct).
Applying just a filter (in code) to the recordset object and then setting the sub-form to use the filtered recordset displays the data with the correct filter applied. The sort property is set to an empty string for this to work. All records matching the filter are displayed (correct).
When both the sort property AND the filter property are set on the recordset, and that recordset is then set to the sub-form's Recordset property, only the first 100 matching records are displayed (incorrect). They are displayed in sort order. The underlying recordset object shows the correct record count for the filtered records, they just don't all display on the form.
Does anyone know why this is happening and if there is a way to get around this apart from creating a recordset using a new SQL string each time?
Thanks in advance.
What you are seeing with filtering and sorting is a known limitation of ADO recordsets.
Take a look at the list of ADO Cons listed on this page. Notice the one on the bottom:
http://www.utteraccess.com/wiki/index.php/Choosing_between_DAO_and_ADO
I couldn't find any documentation on MS's Support site about this so I don't know if it's a bug or simply a limitation. I'm assuming it's the latter.
FYI, I think MS has basically forgotten about ADO (classic). The last release of MDAC (which is how you obtain ADO) was 5/10/2005.
As far as a work-around for this problem, you can try using this function. It returns a new, filtered and sorted recordset. Just keep a big, full recordset handy and use this function to get a new one every time you do a sort/filter. This does increase your overall resource usage, especially memory.
I have used this function but it hasn't been fully tested to make sure it's bullet proof in every way. You might quickly find some bug or limitation with it. I actually had a note that it needed some kind of work but my note was unclear, I didn't have time to test it now, and I did find that I'm using this function in my production code so I think it's working.
Public Function GetFilteredRecordset(ByRef rsSource As ADODb.Recordset, _
ByVal sWhere As String, _
Optional ByVal sOrderBy As String, _
Optional ByVal LockType As ADODb.LockTypeEnum = adLockUnspecified) As ADODb.Recordset
Dim sOriginalOrderBy As String
sOriginalOrderBy = rsSource.Sort
Dim F As ADODb.Field
For Each F In rsSource.Fields
'Debug.Print F.Name
Next F
rsSource.Filter = sWhere
If sOrderBy <> "" Then
If Left(LCase(sOrderBy), 8) = "order by" Then sOrderBy = Trim(Right(sOrderBy, Len(sOrderBy) - 8))
rsSource.Sort = sOrderBy
End If
Dim rsF As ADODb.Recordset
Dim objStream As ADODb.Stream
'Create a New ADO 2.5 Stream object
Set objStream = New ADODb.Stream
'Save the Recordset to the Stream object in XML format
rsSource.Save objStream, adPersistXML
'Create an exact copy of the saved Recordset from the Stream Object
Set rsF = New ADODb.Recordset
rsF.Open objStream, , , LockType
rsSource.Filter = ""
rsSource.Sort = sOriginalOrderBy
'Close and de-reference the Stream object
objStream.Close
Set objStream = Nothing
Set GetFilteredRecordset = rsF
End Function
Another strange limitation of filtering ADO recordsets is that your OR keyword must always be on the top level. That is also documented in the link I posted above although I'm not sure if the examples given are accurate.