0

我需要将一些 csv 文件导入 excel 2010 并创建一个非常简单但非常大的数据库。
整个故事将是 - 五列和数千行。
VBA 也很简单——将数据从一张纸复制到另一张纸——反之亦然。
但我需要关心内存需求,因为文件可能非常大。

Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim r1 As Range
Dim r2 As Range
Set ws1 = Sheets("01")
Set ws2 = Sheets("02")
Set r1 = ws1.Range("A1:B10") ' for example
Set r2 = ws2.Range("C5:D14")
r1.Copy Destination:=r2 'first way
r2.Value = r1.Value ' second way

这两种方法在内存/耗时范围内有什么区别吗?
在和我将有超过 10,000 行。文件的大小是多少?

4

2 回答 2

6

您可以利用 ADO 来查询文本文件,就好像它们是数据库表一样。这允许您编写 SQL 查询以从文本文件中提取数据。如果您愿意,您可以在任何文本文件甚至 .xls 文件中执行此操作。

这样做的代码/过程相当简单。您需要先引用 Microsoft ActiveX Data Objects 2.X 库,然后使用如下内容:

Dim cn as New ADODB.Connection
Dim rs as New ADODB.Recordset
Dim i as Integer

With cn
    .Provider = "Microsoft.Jet.OLEDB.4.0"
    .ConnectionString = "Data Source=C:\SomeFolder;" & _
                        "Extended Properties=""text; HDR=Yes;FMT=Delimited"""
    .Open

    With rs
        .Open "SELECT * from fileName.txt", cn

        'Loop through each row in query
        While Not (.EOF Or .BOF)
            'Loop through each column in row
            For i = 0 to .Fields.Count - 1
                Debug.Print .Fields(i).Value 'Print value of field to Immediate Window
            Next i

            .MoveNext
        Wend

        .Close
    End With

    .Close
End With

Set rs = Nothing
Set cn = Nothing

这将遍历您的文本文件并在您的 VBA 即时窗口中显示第一列的值。它还假定您的文件具有标题行。如果没有,那么您需要将ConnectionString 中的HDR更改为No

该代码将自动尝试并为您推断类型,但如果您遇到无法发现正确类型(例如前导零)的问题,那么您可以为您的文件明确定义模式。重要的是要注意,如果您采用架构路线,那么您的 ConnectionString 参数(如HDRFMT 将被忽略)。它们将保留注册表中定义的默认设置,除非您在架构定义中覆盖它们。可以在此处找到有关 schema.ini 文件的更多信息:http: //msdn.microsoft.com/en-us/library/windows/desktop/ms709353 (v=vs.85).aspx 。

这是另一个有用的链接:http: //msdn.microsoft.com/en-us/library/ms974559.aspx。这是 Microsoft Scripting Guys 撰写的一篇文章,也是我最初了解该过程的方式。

最后,如果您曾经对 .xls 文件使用此过程,那么您应该知道永远不要查询打开的 .xls 文件。OPEN .xls 文件存在严重的内存泄漏错误(更多信息:http: //support.microsoft.com/default.aspx ?scid=kb;en-us;319998&Product=xlw )。只要您查询 CLOSED .xls 文档,那么您就不应该有任何问题 =D。SQL FROM 子句中的语法有点不同,因为您必须针对特定工作表,但 IIRC 我链接的 Scripting Guys 文章解释了如何做到这一点。

于 2012-09-18T03:46:58.140 回答
2

这个代码块有一些我参与的项目的细节,但应该可以帮助你开始如何通过 VBA 导入 CSV 文件(有点清理):

Public Sub ImportCSV(strPath As String, strFile As String, strExt As String, wbDestination As Workbook, Optional wsDest As Worksheet, Optional strRange As String, Optional blHeaders As Boolean = True)
'imports given CSV file into given sheet at given range _
    defaults to comma separated delimiters

Dim wsDestination As Worksheet
Dim strFileName As String
strFileName = strPath & strFile & ".csv"


If wsDest Is Nothing Then Set wsDestination = wbDestination.Worksheets.Add(, wbDestination.Worksheets(wbDestination.Worksheets.Count)) Else: Set wsDestination = wsDest
If strRange = "" Then strRange = "$A$1"

With wsDestination.QueryTables.Add(Connection:="TEXT;" & strFileName, Destination:=wsDestination.Range(strRange))
        .FieldNames = False
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = False
        .AdjustColumnWidth = False
        .RefreshPeriod = 0
        .TextFilePromptOnRefresh = False
        .TextFilePlatform = 437
        .TextFileStartRow = 1
        .TextFileParseType = xlDelimited
        .TextFileTextQualifier = xlTextQualifierDoubleQuote
        .TextFileConsecutiveDelimiter = False
        .TextFileTabDelimiter = False
        .TextFileSemicolonDelimiter = False
        .TextFileCommaDelimiter = True
        .TextFileSpaceDelimiter = False
        .TextFileTrailingMinusNumbers = True
        .Refresh BackgroundQuery:=False
        .Delete
    End With

If Not blHeaders Then wsDestination.Range(strRange).EntireRow.Delete

End Sub
于 2012-09-17T21:17:16.360 回答