schema.ini 文件不适用于 MS Access
schema.ini file not working for MS Access
我有一堆 csv 文件,我通过 VBA 导入到 Access 中的表中。我在与导入的 csv 文件相同的目录中还有一个 schema.ini 文件。尽管字段在 ini 文件中被指定为双精度类型,但它们在 Access 中变成了文本类型字段。每当顶部的字段中有很多空值时,就会发生这种情况。如果我在前 10 个或 20 个字段中至少有一个非空值,该字段将变成数字类型。
经过一些研究,我的评估是 schema.ini 文件没有执行任何操作,Access 正在确定字段的数据类型,因为我看到的行为正是 Access 的默认行为(如果未使用 schema.ini 文件)。
所以这让我相信我的 schema.ini 文件有问题。
以下是我的 schema.ini 文件的示例,它与我正在导入的 5 个 csv 文件中的 3 个类似:
[ForClsDatedModel_2015 0702_1004-1254.csv]
ColNameHeader=True
Format=CSVDelimited
"Ticker"=TEXT
"WT Def BSS MF-WT"=INTEGER
"Cyc BSS MF-WT"=DOUBLE
"WT Cyc BSS MF-WT"=INTEGER
"Gr BSS MF-WT"=DOUBLE
"WT Gr BSS MF-WT"=DOUBLE
"NT BSS MF-WT"=DOUBLE
"WT NT BSS MF-WT"=INTEGER
"WT BSS (All Ts)"=DOUBLE
"No Cust Ind BSS MF-WI"=DOUBLE
"WI No Cust Ind BSS MF-WI"=DOUBLE
"BSS MF-AE"=DOUBLE
"BSS MF-AE Score"=DOUBLE
"Cross BSS"=DOUBLE
"Cross BSS Score"=DOUBLE
...etc....
"Avg Qtrly NIM"=DOUBLE
"Avg Qtrly PROFITS TO TOTAL LOANS"=DOUBLE
"yoy -0 PROFITS TO LL RESERVE GROWTH"=DOUBLE
"yoy -1 PROFITS TO LL RESERVE GROWTH"=DOUBLE
"yoy -2 PROFITS TO LL RESERVE GROWTH"=DOUBLE
"yoy -3 PROFITS TO LL RESERVE GROWTH"=DOUBLE
"Ann PROFITS TO LL RESERVE GROWTH"=DOUBLE
"Avg Qtrly PROFITS TO LL RESERVE Gr"=DOUBLE
"PROFITS TO LL RESERVE Gr"=DOUBLE
"WT PROFITS TO LL RESERVE Gr"=INTEGER
"WI PROFITS TO LL RESERVE Gr"=INTEGER
"WG PROFITS TO LL RESERVE Gr"=INTEGER
"Rk PROFITS TO LL RESERVE Gr"=INTEGER
[ForClsDatedModel_2015 0702_1-250.csv]
ColNameHeader=True
Format=CSVDelimited
"Ticker"=TEXT
"Fundamental Ticker"=TEXT
"Name"=TEXT
"Custom Industry"=TEXT
"Crescat Industry"=TEXT
"GICS Sector"=TEXT
"GICS Industry Group"=TEXT
"GICS Industry"=TEXT
"GICS Sub-Industry"=TEXT
"Russell Sector"=TEXT
"Currency Being Used"=TEXT
"Report CCY"=TEXT
"Market Status"=TEXT
"IU"=INTEGER
"GM"=INTEGER
"L_fs_S"=DOUBLE
"Or"=INTEGER
"LC"=DOUBLE
"JM"=DOUBLE
"Side"=DOUBLE
"Holding"=DOUBLE
"Theme"=INTEGER
...etc....
"1M Proj Adj Return"=DOUBLE
"Rk 1M Proj Adj Return"=DOUBLE
"3M Proj Adj Return"=DOUBLE
"Rk 3M Proj Adj Return"=DOUBLE
"6M Proj Adj Return"=DOUBLE
"Rk 6M Proj Adj Return"=DOUBLE
"1Y Proj Adj Return"=INTEGER
"Rk 1Y Proj Adj Return"=DOUBLE
"non-neg PE4QT"=DOUBLE
"non-neg PE4QF"=DOUBLE
"non-neg PCFO4QT"=DOUBLE
[ForClsDatedModel_2015 0702_1255-1505.csv]
ColNameHeader=True
Format=CSVDelimited
"Ticker"=TEXT
"WI EP MF-WI"=INTEGER
"WI MF-WI (All Ts)"=INTEGER
"Beta (10 yr or 5 yr)"=DOUBLE
"Rk Beta (10 yr or 5 yr)"=DOUBLE
"Vol30"=DOUBLE
"Rk Vol30"=DOUBLE
"Vol90"=DOUBLE
"Rk Vol90"=DOUBLE
...etc...
那个 schema.ini 文件有什么问题?谢谢!
我认为您的字段规范语法有误。
来自 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.
和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.
因此您可以像您一样省略 Col1=、Col2= 等,但 = 属于 Col(n) 和列名之间,而不是名称和类型之间。所以将 = 替换为 space.
此外,INTEGER 可能不是导入 Access 的有效数据类型 - 请改用 Short 或 Long。但我不确定。
编辑:我没有实际使用过这个(或者如果我用过,我忘记了),但是从我链接的参考资料来看它应该是:
[ForClsDatedModel_2015 0702_1004-1254.csv]
ColNameHeader=True
Format=CSVDelimited
"Ticker" TEXT
"WT Def BSS MF-WT" LONG
"Cyc BSS MF-WT" DOUBLE
或者如果这不起作用,请尝试包含 Coln - 大多数示例都包含它们,即使它是 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
我有一半的答案。我发现没有办法避免 schema.ini 文件中的 Col# 选项,尽管它在这里说:
https://msdn.microsoft.com/en-us/library/ms709353(v=VS.85).aspx
(如果你知道怎么做,post 一个答案,我会给你信用。)
除此之外,我想出了如何在文件顶部有一堆空值的字段上强制数据类型。
(请注意上面的 link 表示您可以使用 ColNameHeader=True
MaxScanRows=0 它将查看整个文件的格式。这对我不起作用。)
这是我的工作示例(我的回答)....
创建此 csv 文件并将其直接保存在您的 C 盘(无文件夹)并将其另存为 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 |
+-----------+----------+---------+
Anumber 字段中的大量 Null 值对此很重要。
在同一位置创建一个文本文件并保存 schema.ini,其中包含以下内容:
[test.csv]
ColNameHeader=True
MaxScanRows=0
CharacterSet=ANSI
Format=CSVDelimited
Col1="First Name" Char
Col2="Last Name" Char
Col3="Anumber" Double
然后 运行 MS Access 中的这段代码 VBA(对我来说是 2013):
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
并且将使用 test.csv 文件和 schema.ini 文件创建名为 "test" 的 table(在与 test.csv 文件相同的位置) 并且 "Anumber" 字段将被格式化为 "Number" 尽管字段顶部的所有 Null 值。如果您不使用 schema.ini 文件,"Anumber" 字段将被格式化为短文本类型。
编辑:将上面 Sub 中的 "C:\" 更改为您希望拥有 csv 文件和 schema.ini 文件的位置。
基本上有两种方法可以预先设置文本文件(.txt、.csv、.tab)导入到Access数据库中的数据列,这两种方法使用不同的VBA方法。
1.规格对象(保存在数据库中)
在这里,您使用 DoCmd.TransferText,其中一个参数是可选的规范名称(无扩展名或路径)。
DoCmd.TransferText(TransferType, SpecificationName, TableName, FileName,
HasFieldNames, HTMLTableName, CodePage)
要创建此规范对象,您只需手动导入一个示例文本文件一次,完成向导并在最后一节完成之前单击“高级”按钮,该按钮汇总了您刚刚指定的所有项目 -- 字段名称、长度、数据类型等。继续并通过单击对话框 window 上的另存为来保存整个摘要文件,并记住您为其指定的名称,即上面的规范参数。
事实上,保存规格后,您可以完全取消向导。 Import/Export 规格存储在可查询的访问系统 table,MSysIMEXSpecs 中,并且可以在 .accdb 文件的生命周期内使用和重复使用甚至覆盖(再次通过向导)。事实上,您甚至可以导入到其他数据库(在外部数据向导中单击高级)。
2。 Schema.ini文件(保存在数据库外)
此处,文本文件表现为外部 table,因为它包含可以 link 访问或通过记录集打开的架构,如 Microsoft.com 所述。现在需要一种解决方法,因为此外部文件不会使用导入方法自动执行。下面是 linked table 选项的修改,其中通过 Make-Table 查询(携带所有模式和结构和数据)创建本地 table。之后,linked table 被销毁(不是 table 本身只是 link)。将其调整到您的应用程序中,可能在按钮 OnClick 或表单 OnOpen 事件中或通过 AutoExec 宏从 VBA 模块调用(当数据库首次打开时)。
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
如上所述,我个人从不使用 schema.ini 文件,这甚至可能是一种过时的遗留方法,因为 Microsoft 支持不是最新的。规范提供了流畅的灵活性,因为它们与 import/export 过程集成在一起。此外,它们直接保存在数据库中,无需外部管理。
我有一堆 csv 文件,我通过 VBA 导入到 Access 中的表中。我在与导入的 csv 文件相同的目录中还有一个 schema.ini 文件。尽管字段在 ini 文件中被指定为双精度类型,但它们在 Access 中变成了文本类型字段。每当顶部的字段中有很多空值时,就会发生这种情况。如果我在前 10 个或 20 个字段中至少有一个非空值,该字段将变成数字类型。
经过一些研究,我的评估是 schema.ini 文件没有执行任何操作,Access 正在确定字段的数据类型,因为我看到的行为正是 Access 的默认行为(如果未使用 schema.ini 文件)。
所以这让我相信我的 schema.ini 文件有问题。
以下是我的 schema.ini 文件的示例,它与我正在导入的 5 个 csv 文件中的 3 个类似:
[ForClsDatedModel_2015 0702_1004-1254.csv]
ColNameHeader=True
Format=CSVDelimited
"Ticker"=TEXT
"WT Def BSS MF-WT"=INTEGER
"Cyc BSS MF-WT"=DOUBLE
"WT Cyc BSS MF-WT"=INTEGER
"Gr BSS MF-WT"=DOUBLE
"WT Gr BSS MF-WT"=DOUBLE
"NT BSS MF-WT"=DOUBLE
"WT NT BSS MF-WT"=INTEGER
"WT BSS (All Ts)"=DOUBLE
"No Cust Ind BSS MF-WI"=DOUBLE
"WI No Cust Ind BSS MF-WI"=DOUBLE
"BSS MF-AE"=DOUBLE
"BSS MF-AE Score"=DOUBLE
"Cross BSS"=DOUBLE
"Cross BSS Score"=DOUBLE
...etc....
"Avg Qtrly NIM"=DOUBLE
"Avg Qtrly PROFITS TO TOTAL LOANS"=DOUBLE
"yoy -0 PROFITS TO LL RESERVE GROWTH"=DOUBLE
"yoy -1 PROFITS TO LL RESERVE GROWTH"=DOUBLE
"yoy -2 PROFITS TO LL RESERVE GROWTH"=DOUBLE
"yoy -3 PROFITS TO LL RESERVE GROWTH"=DOUBLE
"Ann PROFITS TO LL RESERVE GROWTH"=DOUBLE
"Avg Qtrly PROFITS TO LL RESERVE Gr"=DOUBLE
"PROFITS TO LL RESERVE Gr"=DOUBLE
"WT PROFITS TO LL RESERVE Gr"=INTEGER
"WI PROFITS TO LL RESERVE Gr"=INTEGER
"WG PROFITS TO LL RESERVE Gr"=INTEGER
"Rk PROFITS TO LL RESERVE Gr"=INTEGER
[ForClsDatedModel_2015 0702_1-250.csv]
ColNameHeader=True
Format=CSVDelimited
"Ticker"=TEXT
"Fundamental Ticker"=TEXT
"Name"=TEXT
"Custom Industry"=TEXT
"Crescat Industry"=TEXT
"GICS Sector"=TEXT
"GICS Industry Group"=TEXT
"GICS Industry"=TEXT
"GICS Sub-Industry"=TEXT
"Russell Sector"=TEXT
"Currency Being Used"=TEXT
"Report CCY"=TEXT
"Market Status"=TEXT
"IU"=INTEGER
"GM"=INTEGER
"L_fs_S"=DOUBLE
"Or"=INTEGER
"LC"=DOUBLE
"JM"=DOUBLE
"Side"=DOUBLE
"Holding"=DOUBLE
"Theme"=INTEGER
...etc....
"1M Proj Adj Return"=DOUBLE
"Rk 1M Proj Adj Return"=DOUBLE
"3M Proj Adj Return"=DOUBLE
"Rk 3M Proj Adj Return"=DOUBLE
"6M Proj Adj Return"=DOUBLE
"Rk 6M Proj Adj Return"=DOUBLE
"1Y Proj Adj Return"=INTEGER
"Rk 1Y Proj Adj Return"=DOUBLE
"non-neg PE4QT"=DOUBLE
"non-neg PE4QF"=DOUBLE
"non-neg PCFO4QT"=DOUBLE
[ForClsDatedModel_2015 0702_1255-1505.csv]
ColNameHeader=True
Format=CSVDelimited
"Ticker"=TEXT
"WI EP MF-WI"=INTEGER
"WI MF-WI (All Ts)"=INTEGER
"Beta (10 yr or 5 yr)"=DOUBLE
"Rk Beta (10 yr or 5 yr)"=DOUBLE
"Vol30"=DOUBLE
"Rk Vol30"=DOUBLE
"Vol90"=DOUBLE
"Rk Vol90"=DOUBLE
...etc...
那个 schema.ini 文件有什么问题?谢谢!
我认为您的字段规范语法有误。
来自 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.
和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.
因此您可以像您一样省略 Col1=、Col2= 等,但 = 属于 Col(n) 和列名之间,而不是名称和类型之间。所以将 = 替换为 space.
此外,INTEGER 可能不是导入 Access 的有效数据类型 - 请改用 Short 或 Long。但我不确定。
编辑:我没有实际使用过这个(或者如果我用过,我忘记了),但是从我链接的参考资料来看它应该是:
[ForClsDatedModel_2015 0702_1004-1254.csv]
ColNameHeader=True
Format=CSVDelimited
"Ticker" TEXT
"WT Def BSS MF-WT" LONG
"Cyc BSS MF-WT" DOUBLE
或者如果这不起作用,请尝试包含 Coln - 大多数示例都包含它们,即使它是 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
我有一半的答案。我发现没有办法避免 schema.ini 文件中的 Col# 选项,尽管它在这里说: https://msdn.microsoft.com/en-us/library/ms709353(v=VS.85).aspx (如果你知道怎么做,post 一个答案,我会给你信用。)
除此之外,我想出了如何在文件顶部有一堆空值的字段上强制数据类型。
(请注意上面的 link 表示您可以使用 ColNameHeader=True MaxScanRows=0 它将查看整个文件的格式。这对我不起作用。)
这是我的工作示例(我的回答)....
创建此 csv 文件并将其直接保存在您的 C 盘(无文件夹)并将其另存为 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 |
+-----------+----------+---------+
Anumber 字段中的大量 Null 值对此很重要。
在同一位置创建一个文本文件并保存 schema.ini,其中包含以下内容:
[test.csv]
ColNameHeader=True
MaxScanRows=0
CharacterSet=ANSI
Format=CSVDelimited
Col1="First Name" Char
Col2="Last Name" Char
Col3="Anumber" Double
然后 运行 MS Access 中的这段代码 VBA(对我来说是 2013):
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
并且将使用 test.csv 文件和 schema.ini 文件创建名为 "test" 的 table(在与 test.csv 文件相同的位置) 并且 "Anumber" 字段将被格式化为 "Number" 尽管字段顶部的所有 Null 值。如果您不使用 schema.ini 文件,"Anumber" 字段将被格式化为短文本类型。
编辑:将上面 Sub 中的 "C:\" 更改为您希望拥有 csv 文件和 schema.ini 文件的位置。
基本上有两种方法可以预先设置文本文件(.txt、.csv、.tab)导入到Access数据库中的数据列,这两种方法使用不同的VBA方法。
1.规格对象(保存在数据库中)
在这里,您使用 DoCmd.TransferText,其中一个参数是可选的规范名称(无扩展名或路径)。
DoCmd.TransferText(TransferType, SpecificationName, TableName, FileName,
HasFieldNames, HTMLTableName, CodePage)
要创建此规范对象,您只需手动导入一个示例文本文件一次,完成向导并在最后一节完成之前单击“高级”按钮,该按钮汇总了您刚刚指定的所有项目 -- 字段名称、长度、数据类型等。继续并通过单击对话框 window 上的另存为来保存整个摘要文件,并记住您为其指定的名称,即上面的规范参数。
事实上,保存规格后,您可以完全取消向导。 Import/Export 规格存储在可查询的访问系统 table,MSysIMEXSpecs 中,并且可以在 .accdb 文件的生命周期内使用和重复使用甚至覆盖(再次通过向导)。事实上,您甚至可以导入到其他数据库(在外部数据向导中单击高级)。
2。 Schema.ini文件(保存在数据库外)
此处,文本文件表现为外部 table,因为它包含可以 link 访问或通过记录集打开的架构,如 Microsoft.com 所述。现在需要一种解决方法,因为此外部文件不会使用导入方法自动执行。下面是 linked table 选项的修改,其中通过 Make-Table 查询(携带所有模式和结构和数据)创建本地 table。之后,linked table 被销毁(不是 table 本身只是 link)。将其调整到您的应用程序中,可能在按钮 OnClick 或表单 OnOpen 事件中或通过 AutoExec 宏从 VBA 模块调用(当数据库首次打开时)。
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
如上所述,我个人从不使用 schema.ini 文件,这甚至可能是一种过时的遗留方法,因为 Microsoft 支持不是最新的。规范提供了流畅的灵活性,因为它们与 import/export 过程集成在一起。此外,它们直接保存在数据库中,无需外部管理。