【问题标题】:schema.ini file not working for MS Accessschema.ini 文件不适用于 MS Access
【发布时间】:2015-08-26 22:44:09
【问题描述】:

我有一堆 csv 文件,我通过 VBA 将它们导入 Access 中的表中。我在导入的 csv 文件所在的目录中也有一个 schema.ini 文件。尽管在 ini 文件中将字段指定为双精度类型,但它们在 Access 中被转换为文本类型字段。每当顶部的字段中有很多空值时,都会发生这种情况。如果我在前 10 或 20 个字段中至少有一个非空值,则该字段将变为数字类型。

经过一些研究,我的评估是 schema.ini 文件没有做任何事情,而 Access 正在确定字段的数据类型,因为我看到的行为正是 Access 的默认行为(如果是 schema.ini)。 ini 文件未使用)。

这让我相信我的 schema.ini 文件有问题。

以下是我正在导入的 5 个 csv 文件中的 3 个的 schema.ini 文件的示例:

[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 文件有什么问题?谢谢!

【问题讨论】:

  • 检查拼写它 schcema.ini ,正如你在问题中提到的那样
  • 哈!我希望这很容易!只是问题中的一个错字。我现在就修。谢谢!

标签: ms-access vba schema


【解决方案1】:

基本上有两种方法可以预先设置将文本文件(.txt、.csv、.tab)导入 Access 数据库的数据列,这两种方法都使用不同的 VBA 方法。

1.规格对象(保存在数据库中)

在这里,您使用DoCmd.TransferText,其中一个参数是可选的规范名称(无扩展名或路径)。

DoCmd.TransferText(TransferType, SpecificationName, TableName, FileName, 
                    HasFieldNames, HTMLTableName, CodePage)

要创建此规范对象,您只需手动导入一个示例文本文件一次,完成向导并在最后一部分完成之前,单击“高级”按钮,该按钮汇总了您刚刚指定的所有项目--字段名称、长度,数据类型等。继续并通过单击对话框窗口上的另存为来保存整个摘要文件,并记住您给它的名称,即上面的规范参数。

事实上,一旦保存了规格,您就可以完全取消向导。导入/导出规范存储在可查询的 Access 系统表 MSysIMEXSpecs 中,并且可以在 .accdb 文件的生命周期内使用和重用,甚至覆盖(再次通过向导)。事实上,您甚至可以导入其他数据库(在外部数据向导中单击高级)。

2。 Schema.ini 文件(保存在数据库之外)

在这里,文本文件表现为一个外部表,因为它包含可以链接到 Access 或通过 Microsoft.com 中所述的记录集打开的架构。现在需要一种解决方法,因为此外部文件无法使用导入方法自动执行。下面是对链接表选项的修改,其中通过 Make-Table 查询(携带所有模式、结构和数据)创建本地表。之后,链接表被销毁(不是表本身,只是链接)。将此调整到您的应用程序中,可能在按钮 OnClick 或表单 OnOpen 事件中或通过 AutoExec 宏从 VBA 模块调用(当 db 首次打开时)。

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 支持不是最新的。规范提供了灵活的灵活性,因为它们与导入/导出程序集成在一起。此外,它们直接保存在数据库中,无需外部管理。

【讨论】:

  • 用你的#2 方式比我的回答有什么好处吗?似乎需要更多代码来做同样的事情。你的#1不是我的选择。谢谢!
  • 从技术上讲,您的解决方案是对#2 的简洁重写,但有很多方法可以给猫剥皮!很好奇为什么规格文件不是一个选项。代码会更少,因为只需要一行:DoCmd.TransferText!
  • 我现在走得太远了,无法将其引向不同的方向。感谢您的努力
【解决方案2】:

我有一半的答案。我发现没有办法避免 schema.ini 文件中的 Col# 选项,尽管它在这里说: https://msdn.microsoft.com/en-us/library/ms709353(v=VS.85).aspx (如果你知道怎么做,请发布答案,我会给你功劳。)

除此之外,我还想出了如何在文件顶部有一堆空值的字段上强制使用数据类型。

(请注意,上面的链接说您可以使用 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.csv 文件位于同一位置)创建一个名为“test”的表,并且“Anumber”字段将被格式化为“Number " 尽管字段顶部的所有 Null 值。如果不使用 schema.ini 文件,“Anumber”字段将被格式化为短文本类型。

编辑:将上面的 Sub 中的“C:\”更改为您想要保存 csv 文件和 schema.ini 文件的位置。

【讨论】:

    【解决方案3】:

    我认为您的字段规范语法是错误的。
    来自http://www.htmlgoodies.com/primers/database/work-with-text-file-data-using-the-microsoft-text-driver-creating-a-csv-data-file.html

    逐行理解 Schema.ini 文件

    第 5 行及以上:指定每列的名称、数据类型、宽度,如果 适用的。一般语法是

    Col(n)=<column name> <data type> <Width width>

    其中 n 是列在 CSV 文件中的位置,Width 是 仅对文本是强制性的。

    https://msdn.microsoft.com/en-us/library/ms709353%28VS.85%29.aspx

    下一个条目使用列号指定表中的字段 (Coln) 选项,对于以字符分隔的文件和 对于固定长度的文件是必需的。

    因此,您可以像以前一样省略 Col1=、Col2= 等,但 = 属于 Col(n) 和列名称之间,而不是名称和类型之间。所以用空格替换=。

    此外,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(n)="Cyc BSS MF-WT" DOUBLE ...引号和字面意思是“Col(n)”吗?我没有做固定宽度,也没有使用 Col# 选项。
    • 或者您的意思是:"Cyc BSS MF-WT" DOUBLE 如果是这样,VBA 中的 WritePrivateProfileString 不需要 ini 文件中的 = 吗?
    • 用例子编辑。
    • 这些都不起作用。我还尝试了 NUMBER 和 FLOAT 而不是 DOUBLE。我还尝试删除列名上的引号。我不明白。
    • 抱歉,那我没办法了。你必须继续研究。
    猜你喜欢
    • 2018-11-01
    • 1970-01-01
    • 2021-08-28
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多