Does anyone know how to retrieve the seed and increment of an auto increment field (aka COUNTER, or "AutoNumber" in the Access UI) in a Jet (MS Access) database?
I have enumerated all properties of the corresponding DAO.Field object, ADO.Field object, and ADOX.Column object, and have not been able to identify anything. Any method is acceptable, including whacky hacks of the MSys* tables or native method calls.
Background:
In Jet SQL, you can create an auto-incrementing column with a custom seed and increment with the DDL data type clause COUNTER(seed, increment), as in:
CREATE TABLE ODD_INCREMENTER (
ID_COL COUNTER(-52098, 42)
, TEXT_COL VARCHAR(50)
)
Which creates the following table (some data added for demonstration):
You can use ADOX
Dim cat As New ADOX.Catalog
Dim tbl As ADOX.Table
Dim col As ADOX.Column
Set cat.ActiveConnection = CurrentProject.Connection
Set tbl = cat.Tables("Table1")
Set col = tbl.Columns("AKey")
'Next autonumber
lngSeed = col.Properties("Seed")
Allen Browne has a fairly detailed reference: http://allenbrowne.com/ser-40.html
Consider using late binding instead of adding a reference.
You can get the increment in addition to the seed by inspecting its property.
Public Sub SeedAndIncrement(ByVal pTable As String, _
ByVal pAutonumField As String)
Dim cat As Object
Dim objColumn As Object
Set cat = CreateObject("ADOX.Catalog")
Set cat.ActiveConnection = CurrentProject.Connection
Set objColumn = cat.Tables(pTable).Columns(pAutonumField)
Debug.Print "Seed: " & objColumn.Properties("Seed")
Debug.Print "Increment: " & objColumn.Properties("Increment")
Set objColumn = Nothing
Set cat = Nothing
End Sub
Related
Currently I need to find a method to create an Access database in Visual C++ 2008, so that:
I can create the Access database in different formats, including Access 95/97 format, 2000 format, and 2007 accdb format.
I can create not only tables, but also other objects, including queries, reports, forms and macros in the Access database.
When adding a large volume of records into the tables, the method has a better performance.
I have searched online, and have found resourced such as this which lists some methods, however, as far as I know, DAO seems to be deprecated.
How about the other methods?
Thanks
As I have understood, you want to create database, objects in it, via calling some function and procedures. Best approach to my mind is to use DAO Library. Here is VBScript example:
Sub CreateDatabaseFile(ByVal strDbPath)
Dim wspDefault 'As Workspace
Dim dbs ' As Database
Dim dbEngine ' DAO DB Engine
Dim dbLangGeneral
dbLangGeneral = ";LANGID=0x0409;CP=1252;COUNTRY=0"
Set dbEngine = CreateObject("DAO.DBEngine.120")
Set wspDefault = DBEngine.Workspaces(0)
Set dbs = wspDefault.CreateDatabase(strDbPath, dbLangGeneral)
Dim s
s="CREATE TABLE tblCustomers (CustomerID INTEGER CONSTRAINT PK_tblCustomers PRIMARY KEY, " _
& " [Last Name] TEXT(50) NOT NULL, [First Name] TEXT(50) NOT NULL, Phone TEXT(10), Email TEXT(50), " _
& " Address TEXT(40)) "
dbs.execute s
dbs.Close
Dim AccessApp
Set AccessApp = CreateObject("Access.Application")
AccessApp.OpenCurrentDatabase strDbPath
Dim frm 'As Form
Dim ctlLabel 'As Control
Dim ctlText 'As Control
Dim intDataX 'As Integer, intDataY As Integer
Dim intDataY
Dim intLabelX 'As Integer, intLabelY As Integer
Dim intLabelY
' Create new form with tblCustomers table as its record source.
Set frm = AccessApp.CreateForm
'frm.Name = "MyForm"
frm.RecordSource = "tblCustomers"
' Set positioning values for new controls.
intLabelX = 100
intLabelY = 100
intDataX = 1000
intDataY = 100
' Create unbound default-size text box in detail section.
Dim acTextBox
acTextBox = 109
Set ctlText = AccessApp.CreateControl(frm.Name, acTextBox, , "", "", _
intDataX, intDataY)
ctlText.ControlSource = "Last Name"
Dim acLabel
acLabel = 100
' Create child label control for text box.
Set ctlLabel = AccessApp.CreateControl(frm.Name, acLabel, , _
ctlText.Name, "NewLabel", intLabelX, intLabelY)
Dim acButton
AccessApp.DoCmd.Save, frm.Name
' Restore form.
AccessApp.DoCmd.Restore
AccessApp.DoCmd.Quit
End Sub
Call CreateDatabaseFile("c:\test\a test database file.mdb")
How can I iterate a record set that returns a field of type field2?
Is there a way to tell how many objects are in the field2 type?
Let me describe the relevant aspects of my table:
The table fields has field NMR which contains a list of possible options a user can select in another table. In the Experiments table, the field NMR is a combobox with populates the options from the other table.
The way I do this is in the Experiments table design, I have set the field this way:
Now in one of my forms, I need to read the value in Experiments!NMR which can be a multiple selections allowed combobox. The recordset rs!NMR is of type Field2.
To get the values, you iterate using an integer (i.e. rs!NMR(0) would return the first selected option). The problem is I don't know how to get the field count and calling !NMR(i) where i is greater than the number of elements will invoke a Run time error '3265', Object doesn't exist in this collection.
Their exist a size method only returns the field width size (4?) and the documentation states this is the size of the data type within the field2 object.
There doesn't seem to be a count method associated with field2 as using !NMR.Count invokes runtime error 438, Object doesn't support this method.
Code:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim qry As String
qry = "SELECT * FROM Experiments"
Set db = CurrentDb
Set rs = db.OpenRecordset(qry, dbOpenSnapshot)
With rs
Do While Not .EOF
Dim i As Integer
For i = 0 to !NMR.Count ' or SOMETHING - this is the problem
' this is irrelevant, I need to know how to iterate the list
Next i
.MoveNext
Loop
End With
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
I've also tried logic control such as
Do While(!NMR(i) <> vbNullString) since the individual components are strings, but no luck. This issues the same 3265: Item isn't found error. Same for a loop with this check Do While Not IsNull(!NMR(i))
Is there a way to tell how many objects are in the Field !NMR?
You need to assign the complex Field2 to a Recordset2 object and loop through it.
Sub Whatever()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim rsComplex As DAO.Recordset2
Dim qry As String
qry = "SELECT * FROM Experiments"
Set db = CurrentDb
Set rs = db.OpenRecordset(qry, dbOpenSnapshot)
Do While Not rs.EOF
Set rsComplex = rs("NMR").Value
rsComplex.MoveLast
rsComplex.MoveFirst
Dim i As Integer
For i = 0 To rsComplex.RecordCount - 1 ' Asker modified
Debug.Print rsComplex(0)
rsComplex.MoveNext
Next i
rsComplex.Close
Set rsComplex = Nothing
rs.MoveNext
Loop
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
End Sub
This question already has answers here:
How do I create a decimal field in Access with Alter Table?
(3 answers)
Closed 6 years ago.
I am attempting to add a series of fields to a Access 2016 Table, but keep encountering the error:
Runtime error '3259'
Invalid field data type
I originally specified the data type as dbNumeric but changed it to dbDecimal to see if that made a difference. The solution given here for CreateFields did not solve my problem, though I did not try the SQL. It did not. Here is the code:
Sub BOD_Variables()
Dim myDBS
Dim myTable As TableDef
Dim myTableName As String
myTableName = "BOD_Data"
Set myDBS = CurrentDb
Set myTable = myDBS.TableDefs(myTableName)
Dim myField As Field
Dim myVariableNames As Variant
myVariableNames = Array("Blank_4_SampleVol", ... "BOD_ Concentration _OUT")
Dim iCount As Integer
For iCount = LBound(myVariableNames) To UBound(myVariableNames)
Debug.Print myVariableNames(iCount)
Set myField = myTable.CreateField(myVariableNames(iCount), dbDecimal) 'Originally specified dbNumeric for data type.
myTable.Fields.Append myField
Next
End Sub
I attempted to replace the call to the Array(index) with:
Set myField = myTable.CreateField("Blank_4_SampleVol", dbNumeric)
Still get the same error.
I tried specifying the length as discussed here, but that did not correct problem. Documentation on CreateField says it ignores field length when field type is dbNumberic.
Any ideas of what I am missing? Thanks in advance.
While it remains true that DAO does not seem to expose the required properties to create a Decimal field, even if we try using a DAO.Field2 object, the following ADOX code does create a Decimal field (tested with Access 2010):
Option Compare Database
Option Explicit
Sub AddNewDecimalField()
Dim cat As New ADOX.Catalog
cat.ActiveConnection = CurrentProject.Connection
Dim tbl As ADOX.Table
Set tbl = cat.Tables("MyTable")
Dim col As New ADOX.Column
col.Name = "MyNewDecimalField"
col.Type = adNumeric ' note: not adDecimal
col.Precision = 18
col.NumericScale = 8
tbl.Columns.Append col
End Sub
Or, we could just use a DDL query ...
CurrentProject.Connection.Execute _
"ALTER TABLE MyTable ADD COLUMN MyNewDecimalField DECIMAL(18,8)"
... as Andre suggests in his answer.
Follow the link in your linked question, and read the footnote #7 for DECIMAL:
[7] Not available in the Access query interface or DAO. Use ADO to Execute the DDL query statement.
So you'd use something like this:
strSQL = "ALTER TABLE myTable ADD COLUMN " & myVariableNames(iCount) & " DECIMAL (20,6);"
CurrentProject.Connection.Execute strSQL
Decimal fields have had (see comment below) their issues, see Avoid Using Decimal Field Size in Microsoft Access Tables
or http://allenbrowne.com/bug-08.html
Long or Double or Currency may be better options.
Part of a project I am working on is programmatically create a series of MDB files which will be the final deliverables. The specs from the client ask for some fields in the tables to have 3 decimal places.
I create the mdb files using python at first, and then to be able to alter the columns to DECIMAL (10,3), I use ADODB (C#, .NET 4.0) - as i couldn't find something suitable in Python. Problem though is that this will not be enough for the client. They want to open the MDB and in Design Mode to see the Decimal places for these fields to be set to 3. If they are not, the file is not accepted.
It has now taken me the best part of 3 days trying to come up with a solution. One likely candidate was DAO and the Field2 object but this object has so far eluded me. I am using the Microsoft DAO 3.6 Objects but Field2 doesn't seem to be part of the assembly. And dont even know if this will actually do what is required...
Does anyone know a way to do this? Don't care if its DAO, ADO, OLEDB or any other 3 letter acronym to be honest? How can I get from this:
to this - PROGRAMMATICALLY??
I can tell you how to do this in VBA/DAO, which may give you some ideas. You must append the property first:
sSQL = "create table testX (id counter, anumber decimal(10,3))"
CurrentProject.Connection.Execute sSQL
Dim db As Database
Dim tdf As TableDef
Dim fld As dao.Field
Set db = CurrentDb
Set tdf = db.TableDefs("testX")
Set fld = tdf.Fields("anumber")
'fld.Properties("DecimalPlaces") = 3
Set prp = fld.CreateProperty("DecimalPlaces", dbByte, 3)
tdf.Fields("anumber").Properties.Append prp
Public Sub DBF_SetDecPoints(ByVal DBNom As String, ByVal DBTab As String, ByVal Campo As String, ByVal NDEC As Short)
Dim DB As DAO.Database
Dim TD As DAO.TableDef
Dim FD As DAO.Field
Dim PP As DAO.Property
If DBF_Exists(DBNom, DBTab, Campo) Then
'Call DBF_SetProperty(DBNom$, DBTab$, Campo$, "Format", DaoText, "Fixed")
DB = DAOEngine.Workspaces(0).OpenDatabase(DBNom)
TD = DB.TableDefs(DBTab)
FD = TD.Fields(Campo)
PP = FD.CreateProperty("Format", DaoText, "Fixed")
On Error Resume Next
FD.Properties.Append(PP)
FD.Properties("Format").Value = "Fixed"
PP = FD.CreateProperty("DecimalPlaces", DaoByte, NDEC)
FD.Properties.Append(PP)
FD.Properties("DecimalPlaces").Value = NDEC
On Error GoTo 0
DB.Close()
End If
End Sub
What is the correct Access DDL query to add a Boolean datatype column to a table?
So far I've seen examples like the following...
ALTER TABLE MyTable ADD MyNewColumName BIT
but they do not seem to be 100% correct since
Access does not apply the checkbox control to the newly added column, and
the allowed values for that column seem to be 0 and -1
In access the Yes/No data type is a logical field that can display yes/no, true/false, or on/off. When you look at VBA code the true and false constants are equivalent to -1 and 0.
If you use this field to populate a check box it will function properly.
You may be able to Change your alter statement to use "YESNO" as such:
ALTER TABLE mytable ADD mynewcolumn YESNO
That should give you the desired check box in the access table column.
A DAO example.
''Requires reference to Microsoft DAO 3.6 Object Library
Dim tdf As DAO.TableDef
Dim fld As DAO.Field
Dim db As Database
Dim strSQL As String
Set db = CurrentDb
''Create a table ...
strSQL = "Create Table tblLTD (TheYesNoCheck YesNo, TheYesNoCombo YesNo)"
db.Execute strSQL
''It is now in the table collection, so ...
Set tdf = db.TableDefs("tblLTD")
''Change the way the YesNo fields display.
''A Checkbox
Set fld = tdf.Fields("TheYesNoCheck")
Set prp = fld.CreateProperty("DisplayControl", dbInteger, acCheckBox)
fld.Properties.Append prp
''A combobox
Set fld = tdf.Fields("TheYesNoCombo")
Set prp = fld.CreateProperty("DisplayControl", dbInteger, acComboBox)
fld.Properties.Append prp
''We will need a format
Set prp = fld.CreateProperty("Format", dbText, "Yes/No")
fld.Properties.Append prp
From: http://wiki.lessthandot.com/index.php/Add_a_Display_Control_(Checkbox,_Combobox)_to_a_YesNo_Field