I have a bunch of csv files that I import via VBA into tables in Access. I also have a schema.ini file in the same directory as the csv files that I am importing. Despite fields
There are essentially two ways to pre-set the data columns for text file (.txt, .csv, .tab) imports into an Access database, both of which use different VBA methods.
1. Specifications object (saved within the database)
Here, you use DoCmd.TransferText where one of the arguments is an optional specification name (no extension or path).
DoCmd.TransferText(TransferType, SpecificationName, TableName, FileName,
HasFieldNames, HTMLTableName, CodePage)
To create this specification object, you need to manually import an example text file just once, walk through the wizard and just before last section to finish, click the Advanced button which summarizes all items you just specified --field names, lengths, data types, etc. Go ahead and save that entire summary file by clicking Save As on the dialog window and remember the name you give it which is the specification argument in the above.
In fact, once specs is saved, you can cancel the wizard altogether. Import/Export specs are stored in the queryable Access system table, MSysIMEXSpecs, and can be used and reused even overwritten (via wizard again) for the life of the .accdb file. In fact, you can even import into other databases (clicking advanced in External Data wizard).
2. Schema.ini file (saved outside the database)
Here, the text file behaves as an external table since it contains schema which can be linked to Access or opened via a recordset as outlined on Microsoft.com. Now a workaround is needed since this external file does not automate with an import method. Below is a modification of the linked table option where a local table is created through a Make-Table query (carrying all schema and structure and data). Afterwards, the linked table is destroyed (not the table itself just the link). Adjust this into your application, possibly in a button OnClick or form OnOpen events or called from a VBA module via an AutoExec macro (when db first opens).
Function LinkSchema()
Dim db As DATABASE, tbl As TableDef
Set db = CurrentDb()
Set tbl = db.CreateTableDef("Linked Text")
tbl.Connect = "Text;DATABASE=c:\my documents;TABLE=csvFile_linked"
tbl.SourceTableName = "csvFile.csv"
db.TableDefs.Append tbl
db.TableDefs.Refresh
db.Execute "SELECT * INTO csvFile_local FROM csvFile_linked", dbFailOnError
db.TableDefs.Delete("csvFile_linked")
Set tbl = Nothing
Set db = Nothing
End Function
As described above, I personally never use the schema.ini file which might even be an outmoded legacy approach as Microsoft support is not up to date. Specs provide a fluid flexibility in that they work integrally with import/export procedures. Plus, they are saved directly in database without needing to manage them externally.
I have a half answer. I found no way to avoid the Col# option in the schema.ini file despite what it says here: https://msdn.microsoft.com/en-us/library/ms709353(v=VS.85).aspx (If you know how to do it, post an answer and I'll give you credit.)
Other than that I figured out how to force a data type on a field that has a bunch of null values at the top of the file.
(Note that the link above says you can use ColNameHeader=True MaxScanRows=0 and it will look at the entire file for a format. That didn't work for me.)
Here is my working sample (my answer)....
Create this csv file and save it directly on your C drive (no folder) and save it as test.csv:
+-----------+----------+---------+
| FirstName | LastName | Anumber |
+-----------+----------+---------+
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | |
| Robert | King | |
| Nancy | Davolio | 1.1 |
| Robert | King | 2.1 |
+-----------+----------+---------+
The large number of Null values in the Anumber field is important to this.
In the SAME LOCATION create a text file and save it has schema.ini with the following in it:
[test.csv]
ColNameHeader=True
MaxScanRows=0
CharacterSet=ANSI
Format=CSVDelimited
Col1="First Name" Char
Col2="Last Name" Char
Col3="Anumber" Double
Then run this code in MS Access VBA (2013 for me):
Sub ImportSchemaTable()
Dim db As DAO.Database
Set db = CurrentDb()
db.Execute _
"SELECT * INTO test FROM [Text;FMT=CSVDelimited;HDR=Yes;DATABASE=C:\;].[test#csv];", dbFailOnError
db.TableDefs.Refresh
RefreshDatabaseWindow
End Sub
And a table called "test" will be created using the test.csv file and the schema.ini file (in the same location as the test.csv file) and the "Anumber" field will be formatted as a "Number" despite all of the Null values at the top of the field. If you do not use the schema.ini file, the "Anumber" field will be formatted as a Short Text type.
Edit: Change "C:\" in the Sub above to where ever you want to have your csv file AND schema.ini file.
I think your syntax for field specifications is wrong.
From http://www.htmlgoodies.com/primers/database/work-with-text-file-data-using-the-microsoft-text-driver-creating-a-csv-data-file.html
Understanding the Schema.ini file line by line
Line 5 and above: Specify each column’s Name, Data type, Width if applicable. The general syntax is
Col(n)=<column name> <data type> <Width width>
Where n is the position of the column in the CSV file, and Width is mandatory only for Text.
and https://msdn.microsoft.com/en-us/library/ms709353%28VS.85%29.aspx
The next entry designates fields in a table by using the column number (Coln) option, which is optional for character-delimited files and required for fixed-length files.
So you can omit Col1=, Col2=, etc. as you did, but the = belongs between Col(n) and the column name, not between name and type. So replace the = by space.
In addition, INTEGER may not be a valid data type to import into Access - use Short or Long instead. But I'm not sure about that.
Edit: I haven't actually used this (or if I have, I forgot about it), but from the references I linked it should look:
[ForClsDatedModel_2015 0702_1004-1254.csv]
ColNameHeader=True
Format=CSVDelimited
"Ticker" TEXT
"WT Def BSS MF-WT" LONG
"Cyc BSS MF-WT" DOUBLE
or if that doesn't work, try including Coln - most examples include them, even if it's CSVDelimited:
[ForClsDatedModel_2015 0702_1004-1254.csv]
ColNameHeader=True
Format=CSVDelimited
Col1="Ticker" TEXT
Col2="WT Def BSS MF-WT" LONG
Col3="Cyc BSS MF-WT" DOUBLE