Office中国论坛/Access中国论坛

标题: 再谈批量导入CSV文件 [打印本页]

作者: 123shusheng    时间: 2013-4-7 15:29
标题: 再谈批量导入CSV文件
我在论坛里找到Grant版主的一篇例子,非常好.美中不足是在我的导入文件夹里有两类文件,都是CVS文件,但列数不同,两类文件在文件名上有区分,一个是以"N"结尾,一个是以"Y"结尾.
我的思路是:1.窗体1中列表框List1中的文件,默认值是全部导入同一个表(我再用查询将两类文件分开),不需要的文件人工点击取消.目前的问题是由于两类文件列数不同无法同时导入一个表.因为我的文件数量比较多,如果人工分两次导入不太方便.
2.如果不能将两类文件一次导入一个表内,能否根据文件名,将两类文件分别导入相应的表内.
请高手指点,谢谢![attach]51550[/attach]


作者: roych    时间: 2013-4-8 00:45
为什么不考虑把这两类文件分成两个文件夹,然后再选择不同的表来分别导入呢?批量的意思,往往是需要有些共性的。如果字段都不同了,怎么批量呢?
作者: 123shusheng    时间: 2013-4-8 07:28
roych 发表于 2013-4-8 00:45
为什么不考虑把这两类文件分成两个文件夹,然后再选择不同的表来分别导入呢?批量的意思,往往是需要有些共 ...

目我使用的是一个软件,它默认导出这两类文件在它的程序文件夹内,所以这两类文件是混在一个文件夹内,如果人工分到两个文件夹,因为文件数量较大,分拣起来比较麻烦
作者: 123shusheng    时间: 2013-4-8 07:46
这两类文件被默认导入到一个文件夹内,如果人工将它们分拣到两个文件夹内,因为文件数量较多,所以比较麻烦。能否在导入时,在文件名上做个筛选,分开导入到数据库的两个表里也行。
作者: 123shusheng    时间: 2013-4-8 10:34
为什么我的回复上不去
作者: 123shusheng    时间: 2013-4-8 10:37
因为我使用的软件导出的CSV文件,默认导入在程序所在的文件夹,并且两类文件混在同一个文件夹,如果人工分拣到两个文件夹,因为CVS文件数量较大,所以比较困难。
作者: 123shusheng    时间: 2013-4-8 22:25
为什么没人帮我,我尝试设两个按钮分别对应两个表,可以将两个类型的表分别导入两个表内,但窗体1中列表框List1中显示的是所有文件,必须在列表框List1中选择,比较麻烦。列表框List1中能不能分别显示以"N"结尾,和以"Y"结尾的文件.

作者: roych    时间: 2013-4-8 23:55
123shusheng 发表于 2013-4-8 22:25
为什么没人帮我,我尝试设两个按钮分别对应两个表,可以将两个类型的表分别导入两个表内,但窗体1中列表框L ...

加班刚回来……最近比较忙,周末吧。
作者: 123shusheng    时间: 2013-4-9 07:27
谢谢!,期待您的回复!
作者: aslxt    时间: 2013-4-11 09:09
本帖最后由 aslxt 于 2013-4-11 09:15 编辑

参考
[attach]51563[/attach]

只是一个按钮,导入到一张表,你用查询区别吧!
关键是根据文件名判断不同类型的表格的字段数量,根据不同的字段数量进行不同的追加操作(如果你的表都是一样的格式、命名方法)
另外,修正了你的一些错误。
作者: 123shusheng    时间: 2013-4-11 23:06
本帖最后由 123shusheng 于 2013-4-11 23:08 编辑

您的例子经过测试,我的两个表1个是10列,一个是13列,我将模块内n=13,提示运行时错误“3265”,在对应所需名称或序数的集合中,未找到项目。
另外,实现一个按钮,一张表导入后,能否默认将文件夹内所有CSV文件全部导入,不用的文件我人工消除,谢谢!
  If InStr(1, strFileName, "n") > 0 Then
     n = 13
   Else
     n = 13
   End If
   Set connA = CurrentProject.Connection
    conn.Open "Driver={Microsoft Text Driver (*.txt; *.csv)};" & _
              "DBQ=" & strFilePath & ";Extensions=asc,csv,tab,txtersist Security Info=False"   '打开数据链接关键
    With rs
        .CursorType = 2
        .LockType = 3
        .CursorLocation = 3
        .ActiveConnection = connA
    End With

    sqlcsv = "SELECT * FROM [TEXT;FMT=CSV;DELIMITED;HDR=YES;DATABASE=" & strFilePath & "].[" & strFileName & "]"
    Debug.Print sqlcsv
    rs.Open sqlcsv, connA
    rs.Move (0)         '移动到指定记录
    sql = "Select * From tbl_Export"
    rs1.Open sql, connA, 1, 3
    Do Until rs.EOF
        rs1.AddNew
        For i = 0 To n
            rs1.Fields(i + 0) = rs.Fields(i)
            'rs1(i + 1) = rs(i)
        Next
        rs.MoveNext
    Loop
    rs1.UpdateBatch
    rs1.Close
    rs.Close
    conn.Close
    Set rs = Nothing
    Set rs1 = Nothing
    Set conn = Nothing
End Function

作者: aslxt    时间: 2013-4-12 10:40
本帖最后由 aslxt 于 2013-4-12 11:02 编辑

If InStr(1, strFileName, "n") > 0 Then
     n = 13
   Else
     n = 13
   End If

第一个"n" 是判断表名称是否带有【n】这个字符,根据不同的情况处理第二个n的值:
If InStr(1, strFileName, "n") > 0 Then   '判断表名称是否带有【n】这个字符
     n = 13   '如果表名称是带有【n】这个字符,那么这个表的列数是多少,就填比列数少1的数:例如有13列,就“n=12”
   Else
     n = 13 '如果表名称不是带有【n】这个字符,那么这个表的列数是多少,就填比列数少1的数:例如有10列,就“n=9”
   End If

主要是按照你给的实例来搞的,实际情况变更后,你要修改。当然,access表也要增加同样的字段

作者: aslxt    时间: 2013-4-12 11:05
“另外,实现一个按钮,一张表导入后,能否默认将文件夹内所有CSV文件全部导入,不用的文件我人工消除...”
意思是未导入文件夹下的所有文件均默认全部导入,然后你再在access的表中人工消除已导入的并且确认不要的数据?
作者: 123shusheng    时间: 2013-4-12 15:45
本帖最后由 123shusheng 于 2013-4-12 15:49 编辑
aslxt 发表于 2013-4-12 10:40
If InStr(1, strFileName, "n") > 0 Then
     n = 13
   Else


感谢您的回复,太详细了,每条语句都有解释,收益匪浅,再次向您表示感谢!
按照您的指点,我的数据库也改好了,非常满意!
我默认是导入待导入数据文件夹里的所有CSV文件,现在需要在CSV窗体List1列表框内一个一个的选择文件,因为文件数量比较多,所以有点麻烦。但我发现其实按Shift键同时点击List1列表框内的最后一个文件,也可以做到全选,但是还是存在人差错,造成有文件没有导入,所以有点美中不足。
所以我想能否CSV窗体中List1列表框内默认是全部选中状态,有个别不需要的文件我在List1列表框内点击它,可以成为不选中状态(同List1列表框目前状态正好相反),然后点击导入按钮,导入我需要导入的CSV文件。
作者: aslxt    时间: 2013-4-12 19:57
Sub ShowFolderList(strFolderPath As String)    '向待导入数据列表矿添加数据的过程

    Dim i As Long
    Dim fso As Object
    Dim objFolder As Object
    Dim objFile As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set objFolder = fso.GetFolder(strFolderPath)

    Me.List1.RowSource = ""
    For Each objFile In objFolder.Files
        Me.List1.AddItem (objFile.Name)
    Next
    '**********添加以下三行
    For i = 0 To List1.ListCount
      List1.Selected(i) = True
    Next i
    '***************
    Set objFile = Nothing
    Set objFolder = Nothing
    Set fso = Nothing

End Sub

作者: 123shusheng    时间: 2013-4-12 22:27
太棒了,测试成功。我的问题在高手眼里,简直是张飞吃豆芽——小菜一碟。谢谢!
我在使用中还有一个问题,例子中的待导入数据和已导入数据两个文件夹,默认是在程序所在的文件夹内,实际使用不太方便,如何指定位置;如:  d:\程序\待导入数据; d:\程序\已导入数据
作者: ycxchen    时间: 2013-4-13 10:50
请教aslxt,如果批量导入EXCEL,如何写代码?
作者: 123shusheng    时间: 2013-4-13 22:23
aslxt 老兄的帮助下,我的窗体功能不断完善,非常感谢论坛里各位版主的大力帮助,你们的无私帮助,是我们后来者前进的动力。
我今天测试还有一个问题。因为我每天都会有一批CSV表。我每天把需要导入的表存放在待导入数据文件夹,同时导入数据文件夹中将导入数据文件夹中,将需要导入的表的前一天的CSV表从已移动到待导入数据文件夹,然后将这两日的文件同时导入数据库进行分析。
目前我在窗体中设了一个按钮,可以根据我今天要导入的表,自动将导入数据文件夹中符合要求的文件移动到待导入数据文件夹,可是窗体中List1文本框内文件数不能刷新,不能显示新移动来的文件。必须关闭窗体,然后再打开窗体,才能显示全部文件。请问怎么才能将List1文本框内文件数刷新一下,谢谢!
作者: 123shusheng    时间: 2013-5-2 17:08
自己顶一下,希望能得到高手的帮助
作者: efcndi    时间: 2013-5-9 08:11
看了这个例子 得到很多启发 谢谢了 但是有个疑问 如果需要导入的数据改成“01.002.01h
”为什么导入后变成了“3.001” 有人能帮我解答一下吗
作者: aslxt    时间: 2013-5-10 17:38
efcndi 发表于 2013-5-9 08:11
看了这个例子 得到很多启发 谢谢了 但是有个疑问 如果需要导入的数据改成“01.002.01h
”为什么导入后变成 ...

数据改成“01.002.01h”,是文件名改成,还是csv文件中的内容改成改成“01.002.01h
”导入后变成了“3.001”??
作者: aslxt    时间: 2013-5-10 18:01
是csv文件中的内容改成改成“01.002.01h”,导入后变成了“1.002”
作者: aslxt    时间: 2013-5-10 18:01
本帖最后由 aslxt 于 2013-5-10 18:22 编辑

具体原因有待勘察,实际上很多数据都有问题,甚至会出现乱码(某个字段),直接用查询可以得出这种现象:
SELECT *
FROM [TEXT;FMT=CSV;DELIMITED;HDR=YES;DATABASE=文件路径名].[ 含后缀的文件名]
例如:
源字段值                          查询得到的值
1.008.09更改                   ¥1
1.002.09h                        ¥1  
1.00好.09h                     # 错误
作者: aslxt    时间: 2013-5-10 18:30
[attach]51766[/attach]
查询结果
[attach]51767[/attach]
源数据
作者: aslxt    时间: 2013-5-10 19:28
本帖最后由 aslxt 于 2013-5-10 19:34 编辑

目前只能用逐行读取文本文件的方式可以保存数据的原样,参考代码如下:
Private Sub Command0_Click()
     Dim varItem As Variant
    With Application.FileDialog(3) 'msoFileDialogFilePicker
      .AllowMultiSelect = True       '允许选择多个文件
      .Filters.Clear
      .Filters.Add "CSV Files", "*.CSV"        '只显示CSV文件,可根据需要改变
      If .Show Then
        For Each varItem In .SelectedItems
          DR varItem
        Next
      End If
    End With
End Sub

Function DR(ByVal MYspath As String)
    Dim SQL, STR
    Dim i As Long
    Dim A
    Close #1
    i = 0
    Open MYspath For Input As #1
        Do While Not EOF(1)
            Line Input #1, STR    '   逐行读入
            i = i + 1
            A = Split(STR, ",") '这里不允许csv文件的数据设为千分位,文本字符间不能有半角逗号
            If i > 1 Then
                SQL = "INSERT INTO tbl_Export ( [VENDOR NO], [CUSTOMER NO], [INVOICE NO], [BL DATE], [MODEL NO], QTY, PRICE, AMOUNT ) VALUES (" & _
                      """" & A(0) & """" & "," & """" & A(1) & """" & ", " & """" & A(2) & """" & ", " & "#" & A(3) & "#" & "," & """" & A(4) & """" & ", " & A(5) & ", " & A(6) & ", " & A(7) & " )"
                Debug.Print SQL
                CurrentProject.Connection.Execute SQL
            End If
        Loop
    Close #1
End Function

作者: aslxt    时间: 2013-5-10 19:35
当然“SQL=....” 的语法要根据自己的表重新改过,才能实际运用
作者: efcndi    时间: 2013-5-12 10:02
aslxt 发表于 2013-5-10 19:35
当然“SQL=....” 的语法要根据自己的表重新改过,才能实际运用

谢谢 太厉害了 好好学习中
作者: efcndi    时间: 2013-5-12 10:46
aslxt 发表于 2013-5-10 19:35
当然“SQL=....” 的语法要根据自己的表重新改过,才能实际运用

再次感谢aslxt 可是我用您逐行读取的方式试了一下,问题还是没解决,还是会变成“1.002”之类的数据.
作者: aslxt    时间: 2013-5-12 10:48
本帖最后由 aslxt 于 2013-5-12 10:54 编辑

把你的实例贴上来(access【2007版本及以下】和csv文件)
或加我qq:853156456
作者: efcndi    时间: 2013-5-12 11:03
您稍等,我需要处理一下,有数据不能公开,我立刻处理
作者: efcndi    时间: 2013-5-12 11:17
实在对不起了 让您白等了 领导不让传 呵呵 不过问题解决了 我刚才数据弄错了 再次感谢aslxt 就是逐行读取速度慢了好多 有的时候超过10万行 感觉像死机了一样
作者: aslxt    时间: 2013-5-12 11:29
解决就好,“速度慢了好多 有的时候超过10万行 感觉像死机了一样
"可以做一个进度条,好看一些
作者: efcndi    时间: 2013-5-12 11:30
aslxt 发表于 2013-5-12 11:29
解决就好,“速度慢了好多 有的时候超过10万行 感觉像死机了一样
"可以做一个进度条,好看一些

谢谢 又学了很多




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3