【问题标题】:Remove rows from output file .CSV从输出文件 .CSV 中删除行
【发布时间】:2020-09-11 23:24:58
【问题描述】:

有人可以看看这段代码吗?它将 .csv 文件合并到一个文件中。 我希望不要考虑每个 .csv 中的第一行,因为它是相关信息,我必须从新的合并文件中手动删除它。 我还想对新代码进行一些解释(我是 VBA 新手,但很想学习) 请问这样可以吗?

Option Explicit

#If VBA7 Then
    Private Declare PtrSafe Function OpenProcess Lib "kernel32" _
        (ByVal dwDesiredAccess As Long, _
        ByVal bInheritHandle As Long, _
        ByVal dwProcessId As Long) As Long

    Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" _
        (ByVal hProcess As Long, _
        lpExitCode As Long) As Long
#Else
    Private Declare Function OpenProcess Lib "kernel32" _
        (ByVal dwDesiredAccess As Long, _
        ByVal bInheritHandle As Long, _
        ByVal dwProcessId As Long) As Long

    Private Declare Function GetExitCodeProcess Lib "kernel32" _
        (ByVal hProcess As Long, _
        lpExitCode As Long) As Long
#End If


Public Const PROCESS_QUERY_INFORMATION = &H400
Public Const STILL_ACTIVE = &H103


Public Sub ShellAndWait(ByVal PathName As String, Optional WindowState)
    Dim hProg As Long
    Dim hProcess As Long, ExitCode As Long
    'fill in the missing parameter and execute the program
    If IsMissing(WindowState) Then WindowState = 1
    hProg = Shell(PathName, WindowState)
    'hProg is a "process ID under Win32. To get the process handle:
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, hProg)
    Do
        'populate Exitcode variable
        GetExitCodeProcess hProcess, ExitCode
        DoEvents
    Loop While ExitCode = STILL_ACTIVE
End Sub


Sub Merge_CSV_Files()
    Dim BatFileName As String
    Dim TXTFileName As String
    Dim XLSFileName As String
    Dim FileExtStr As String
    Dim FileFormatNum As Long
    Dim DefPath As String
    Dim Wb As Workbook
    Dim oApp As Object
    Dim oFolder
    Dim foldername

    'Create two temporary file names
    BatFileName = Environ("Temp") & _
            "\CollectCSVData" & Format(Now, "dd-mm-yy-h-mm-ss") & ".bat"
    TXTFileName = Environ("Temp") & _
            "\AllCSV" & Format(Now, "dd-mm-yy-h-mm-ss") & ".txt"

    'Folder where you want to save the Excel file
    DefPath = Application.DefaultFilePath
    If Right(DefPath, 1) <> "\" Then
        DefPath = DefPath & "\"
    End If

    'Set the extension and file format
    If Val(Application.Version) < 12 Then
        'You use Excel 97-2003
        FileExtStr = ".xls": FileFormatNum = -4143
    Else
        'You use Excel 2007 or higher
        FileExtStr = ".xlsx": FileFormatNum = 51
        'If you want to save as xls(97-2003 format) in 2007 use
        'FileExtStr = ".xls": FileFormatNum = 56
    End If

    'Name of the Excel file with a date/time stamp
    XLSFileName = DefPath & "MasterCSV " & _
                  Format(Now, "dd-mmm-yyyy h-mm-ss") & FileExtStr

    'Browse to the folder with CSV files
    Set oApp = CreateObject("Shell.Application")
    Set oFolder = oApp.BrowseForFolder(0, "Select folder with CSV files", 512)
    If Not oFolder Is Nothing Then
        foldername = oFolder.Self.Path
        If Right(foldername, 1) <> "\" Then
            foldername = foldername & "\"
        End If

        'Create the bat file
        Open BatFileName For Output As #1
        Print #1, "Copy " & Chr(34) & foldername & "*.csv" _
                & Chr(34) & " " & TXTFileName
        Close #1

        'Run the Bat file to collect all data from the CSV files into a TXT file
        ShellAndWait BatFileName, 0
        If Dir(TXTFileName) = "" Then
            MsgBox "There are no csv files in this folder"
            Kill BatFileName
            Exit Sub
        End If

        'Open the TXT file in Excel
        Application.ScreenUpdating = False
        Workbooks.OpenText Filename:=TXTFileName, Origin:=xlWindows, StartRow _
                :=2, DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
                ConsecutiveDelimiter:=False, Tab:=False, Semicolon:=False, Comma:=True, _
                Space:=False, Other:=False

        'Save text file as a Excel file
        Set Wb = ActiveWorkbook
        Application.DisplayAlerts = False
        Wb.SaveAs Filename:=XLSFileName, FileFormat:=FileFormatNum
        Application.DisplayAlerts = True

        Wb.Close savechanges:=False
        MsgBox "Your Excel file is here: " & vbNewLine & XLSFileName

        'Delete the bat and text file you temporary used
        Kill BatFileName
        Kill TXTFileName

        Application.ScreenUpdating = True
    End If
End Sub

谢谢

【问题讨论】:

  • 所以,这个(太)大代码必须将所有 csv 文件从一个特定文件夹中合并到一个“主”文件夹中,命名为“Current time.csv”,保存在 Documents 中,现在,你需要做同样的事情,但跳过每个文件的标题。这个假设是正确的吗? CSV 文件具有相同数量的列,我想它们看起来是用逗号分隔的。这也是正确的吗?

标签: excel vba csv export-to-csv


【解决方案1】:

你什么都不说,我必须离开办公室……请测试下一个代码。它假设我的上述假设(在评论中)是正确的。代码以某种方式进行了注释,以使您理解其含义。它使用标准的 VBA/VBScript 函数。没有 API 调用和 bat 文件...它从合并过程中排除了第一个 csv 行。

代码以易于理解的方式进行注释。如果有不清楚的地方,请随时要求澄清!

Sub testMeergeCSVFiles()
    Dim fullFilename As String, objFSO As Object, objTF As Object, arrIn As Variant
    Dim masterFullName As String, i As Long, strIn As String, strExt As String
    Dim finStr As String, foldName As String, wb As Workbook, xlsFullName As String

    masterFullName = Environ("TEMP") & "\" & Format(Now, "dd-mm-yy-h-mm-ss") & ".csv"
    xlsFullName = Application.DefaultFilePath & "\" & "MasterCSV " & _
                                Format(Now, "dd-mmm-yyyy h-mm-ss") & ".xlsx"
    foldName = GetFolderPath(ThisWorkbook.path & "\") ' it uses GetFolderPath function, starting from
                                                      ' ThisWorkbook path
    fullFilename = Dir(foldName & "\" & "*.csv") 'iterate in folder for csv files
    Do While fullFilename <> ""
        'If left(fullFilename, 9) = "TestMerge" Then 'only for testing reason (for me)
            Set objFSO = CreateObject("Scripting.FileSystemObject")
            Set objTF = objFSO.OpenTextFile(foldName & "\" & fullFilename, 1)
                strIn = objTF.ReadAll 'extract all the content of the file
            objTF.Close

            arrIn = Split(strIn, vbLf): sep = vbLf ' put the strinig in an array
            'start of modification__________________________________________
            If UBound(arrIn) < 1 Then arrIn = Split(strIn, vbCr): sep = vbCr
            If UBound(arrIn) < 1 Then arrIn = Split(strIn, vbCrLf): sep = vbCr
            Debug.Print "Sep: " & Len(sep), Asc(sep) ' adapted here...
            'end of modification____________________________________________

            For i = 1 To UBound(arrIn) ' build the string which excepts first row
                If arrIn(i) <> vbLf Then strExt = strExt & arrIn(i)
            Next i

            If finStr = "" Then 'Build the final string to be loaded in Master CSV
                finStr = strExt
            Else
                finStr = finStr & strExt
            End If
        'End If
        strExt = ""
        fullFilename = Dir  'reinitialize the loop
    Loop

    If finStr = "" Then Exit Sub 'happening in case of no csv files found in the folder
    Open masterFullName For Output As #1
        Print #1, finStr 'dropping the string in the master csv file
    Close #1
    'Opening the master file in Excel:
    Workbooks.OpenText fileName:=masterFullName, origin:=xlWindows, StartRow _
                :=1, DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
                ConsecutiveDelimiter:=False, Tab:=False, Semicolon:=False, Comma:=True, _
                Space:=False, Other:=False
    'Save csv file As Excel xlsx format:
    Set wb = ActiveWorkbook
    wb.SaveAs fileName:=xlsFullName, FileFormat:=xlOpenXMLWorkbook
    Kill masterFullName
    MsgBox "MasterCSV Excel file saved as " & xlsFullName
End Sub
Private Function GetFolderPath(Optional strPath As String) As String
Dim fldr As FileDialog, sItem As String

 Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
 With fldr
    .buttonName = "Select Folder"
    .Title = "Select .CSV files to be processed Folder"
    .AllowMultiSelect = False
    If strPath <> "" Then .InitialFileName = strPath
    If .Show <> -1 Then GoTo NextCode
    sItem = .SelectedItems(1)
 End With
NextCode:
 GetFolderPath = sItem
 Set fldr = Nothing
End Function

【讨论】:

  • 您好,感谢您对此感兴趣。是的,所有 .csv 文件都有相同的列数,只是行数不同。我试过这段代码,但在选择了 .csv 文件的文件夹后,它什么也没做。
  • Ups... 我忘了评论只有我使用的两行,以便对其进行测试。请刷新页面并再次测试。它只处理以“TestMerge”开头的 csv 文件名。我的测试文件夹中有更多 csv 文件,我想以某种方式选择具有相同结构的文件...
  • 它可以工作,但第一行和最后一行在从 A 到 ALO 的列中有数据。在第一行和最后一行之间一切正常。它看起来应该如何。一些数据被插入到第一行和最后一行,而不是单独的一行。
  • @Andrew Cm:当您说“ALO”时,这应该是指“ALO”列?如果是,这意味着列是双倍大小的?如果是,那些有问题的行有什么内容?相同的内容记录了两次,或者应该在问题的下面添加了一行?我问所有这些是为了了解您的 csv 文件是如何构建的。我的测试文件没有发生这种情况,它以 VbLf 字符(回车符)结尾,我将其删除,以避免两个连续的 csv 内容之间的间隙。你能在这里放一个链接来下载三个这样的 csv 文件吗?仅当回答不够时。
  • 数据应该在一行一个下一个,在第一行。请看图片,我不能共享文件,对不起imgur.com/oYWJBLw
猜你喜欢
  • 2011-05-03
  • 2020-07-18
  • 2018-08-15
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多