当前位置: 首页 > 知识库问答 >
问题:

使用VBA从Excel生成动态CSV

景靖琪
2023-03-14

我们要求用户可以隐藏/取消隐藏Excel列并在其中移动。用户单击generate CSV按钮后,我们希望列按特定顺序排列。例如,Col1、Col2、Col3是Excel第一行A、B、C列中的列标题。用户将Col2列移到了末尾,并隐藏了Col2:A、B、C列现在有标题:Col1、Col3、Col2(隐藏)

我们的CSV文件应该生成为:Col1,Col2,Col3。使用下面的代码,我们无法看到Col2,即使我们设法取消隐藏,我们如何知道用户在最后移动了Col2?

Public Sub ExportWorksheetAndSaveAsCSV()

Dim csvFilePath As String
Dim fileNo As Integer
Dim fileName As String
Dim oneLine As String
Dim lastRow, lastCol As Long
Dim idxRow, idxCol As Long
Dim dt As String

dt = Format(CStr(Now), "_yyyymmdd_hhmmss")
' --- get this file name (without extension)
fileName = Left(ThisWorkbook.Name, InStrRev(ThisWorkbook.Name, ".", -1, vbTextCompare) - 1)
' --- create file name of CSV file (with full path)
csvFilePath = ThisWorkbook.Path & "\" & fileName & dt & ".csv"
' --- get last row and last column
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
lastCol = Cells(1, Columns.Count).End(xlToLeft).Column
' --- open CSC file
fileNo = FreeFile
Open csvFilePath For Output As #fileNo
' --- row loop
For idxRow = 1 To lastRow
    If idxRow = 2 Then
        GoTo ContinueForLoop
    End If
    oneLine = ""
    ' --- column loop: concatenate oneLine
    For idxCol = 1 To lastCol
        If (idxCol = 1) Then
            oneLine = Cells(idxRow, idxCol).Value
        Else
            oneLine = oneLine & "," & Cells(idxRow, idxCol).Value
        End If
    Next

    ' --- write oneLine > CSV file
    Print #fileNo, oneLine  ' -- Print: no quotation (output oneLine as it is)
ContinueForLoop:
Next
' --- close file
Close #fileNo

End Sub

共有2个答案

公冶安怡
2023-03-14
  • 假设表(第一行是标题)是连续的(没有空行或空列),并且从单元格A1开始
Option Explicit

Sub exportToCSV()

    Const wsName As String = "Sheet1"
    Const TimePattern As String = "_yyyymmdd_hhmmss"
    
    Dim hCols As Variant: hCols = VBA.Array("Col1", "Col2", "Col3", "Col4")
    
    Dim wb As Workbook: Set wb = ThisWorkbook
    Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
    ' If the data is not contiguous, you might need something different here.
    Dim rg As Range: Set rg = ws.Range("A1").CurrentRegion
    
    Dim Data As Variant: Data = rg.Value
    Dim hData As Variant: hData = rg.Rows(1).Value ' For 'Application.Match'
    
    Dim rCount As Long: rCount = UBound(Data, 1)
    
    Dim cHeader As Variant
    Dim dHeader As Variant
    Dim cIndex As Variant
    Dim Temp As Variant
    Dim r As Long, c As Long
    
    For c = 0 To UBound(hCols)
        cHeader = hCols(c)
        dHeader = Data(1, c + 1)
        If cHeader <> dHeader Then
            cIndex = Application.Match(cHeader, hData, 0)
            If IsNumeric(cIndex) Then
                For r = 1 To rCount
                    Temp = Data(r, c + 1)
                    Data(r, c + 1) = Data(r, cIndex)
                    Data(r, cIndex) = Temp
                Next r
            End If
        End If
    Next c
    
    Dim TimeStamp As String
    TimeStamp = Format(CStr(Now), TimePattern)
    Dim BaseName As String
    BaseName = Left(wb.Name, InStrRev(wb.Name, ".") - 1)
    Dim FilePath As String
    FilePath = wb.Path & "\" & BaseName & TimeStamp & ".csv"
    
    Application.ScreenUpdating = False
    
    With Workbooks.Add
        .Worksheets(1).Range("A1").Resize(rCount, UBound(Data, 2)).Value = Data
        .SaveAs Filename:=FilePath, FileFormat:=xlCSV
        ' 'Semicolon users' might need this instead:
        '.SaveAs Filename:=FilePath, FileFormat:=xlCSV, Local:=True
        .Close
    End With
    
    ' Test the result in the worksheet:
    'ws.Range("F1").Resize(rCount, UBound(Data, 2)).Value = Data

    Application.ScreenUpdating = True
    
End Sub
马魁
2023-03-14

如果标头名称是固定的(只有位置不同),那么您将在标头上循环查找您想要的标头,并注意它们的位置:然后使用这些信息将单元格的值写入输出文件。

Public Sub ExportWorksheetAndSaveAsCSV()

    Dim csvFilePath As String
    Dim fileNo As Integer
    Dim fileName As String
    Dim oneLine As String
    Dim lastRow As Long
    Dim idxRow, idxCol As Long
    Dim dt As String, ws As Worksheet, hdr, arrCols, arrPos, i As Long, f As Range, sep
    
    
    Set ws = ActiveSheet 'or whatever
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
    
    'find all required columns
    arrCols = Array("Col1", "Col2", "Col3")
    ReDim arrPos(LBound(arrCols) To UBound(arrCols))
    For i = LBound(arrCols) To UBound(arrCols)
        'Note: lookin:=xlFormulas finds hidden cells but lookin:=xlValues does not...
        Set f = ws.Rows(1).Find(arrCols(i), lookat:=xlWhole, LookIn:=xlFormulas)
        If Not f Is Nothing Then
            arrPos(i) = f.Column
        Else
            MsgBox "Required column '" & arrCols(i) & "' not found!", _
                    vbCritical, "Missing column header"
            Exit Sub
        End If
    Next i
    'done finding columns
    
    fileName = Left(ThisWorkbook.Name, InStrRev(ThisWorkbook.Name, ".", -1, vbTextCompare) - 1)
    dt = Format(CStr(Now), "_yyyymmdd_hhmmss")
    csvFilePath = ThisWorkbook.Path & "\" & fileName & dt & ".csv"
    
    fileNo = FreeFile
    Open csvFilePath For Output As #fileNo
    
    For idxRow = 1 To lastRow
        If idxRow <> 2 Then
            oneLine = ""
            sep = ""
            'loop over the located column positions
            For idxCol = LBound(arrPos) To UBound(arrPos)
                oneLine = oneLine & sep & ws.Cells(idxRow, arrPos(idxCol)).Value
                sep = ","
            Next
            Print #fileNo, oneLine
        End If
    Next
    
    Close #fileNo ' --- close file

End Sub
 类似资料:
  • 本文向大家介绍使用Vue生成动态表单,包括了使用Vue生成动态表单的使用技巧和注意事项,需要的朋友参考一下 开需求会了,产品说这次需求的表单比较多,目前有18个,后期的表单可能会有增加、修改。我作为这次的前端开发,看到这样的需求,心里知道要这样搞不得把自己累死,首先表单居多,还会有变更,以后维护起来也让人心力憔悴。 于是我提议做动态表单,做一个表单的配置系统,在系统里配置表单类型、表单得字段、以及

  • 我是vba新手,我需要在工作表中取两个值。以下示例: B10=日期。。。。。。。。N10=:。。。。。。P10=2015年2月。。。。 B10的范围有日期,N10有冒号,P10有日期值,C10:O10有空单元格。 所以每次我不得不付出 选择。结束(xlToright)。选择。 如何动态地获取此值。 日期:2月15日日期:3月15日日期:4月15日日期:5月15日日期:6月15日日期:7月15日日期

  • 问题内容: 如何将两个正则表达式模式构造为一个? 例如,我有一个长模式,一个小模式,我需要在长模式前面放一个小模式。 这行不通。当我连接字符串时,所有的斜杠都消失了。 问题答案: 您必须使用: 当我连接字符串时,所有的斜杠都消失了。 如果您的模式中有反斜杠以转义特殊的正则表达式字符(如),则必须在字符串中使用两个反斜杠(因为是字符串中的转义字符):与相同。 因此,您的模式必须变为:

  • 本文向大家介绍excel-vba 始终使用“ Option Explicit”,包括了excel-vba 始终使用“ Option Explicit”的使用技巧和注意事项,需要的朋友参考一下 示例 在“ VBA编辑器”窗口中,从“工具”菜单中选择“选项”: 然后,在“编辑器”选项卡中,确保选中“需要变量声明”: 选择此选项将自动置于Option Explicit每个VBA模块的顶部。 小提示:到目

  • 问题内容: 嗨,我想遍历一个人对象列表,并在每个人的选项卡中显示数据。我试过了: 这是行不通的。任何帮助表示赞赏 PrimeFaces 3.x的tabView现在支持动态数量的选项卡,并增加了自己的迭代功能: 不幸的是,仍然不可能在同一个tabView中同时包含固定和动态选项卡(正如我想做的那样),甚至无法在不重建视图的情况下动态添加选项卡。幸运的是,当使用SessionScoped或CDI Co

  • 在本章中,我们来学习如何逐步编写一个简单的宏。 第1步 - 首先,在Excel 2016中启用“开发者”菜单。要完成这个设置,请点击左上角菜单:文件 -> 选项。如下图所示 - 第2步 - 点击“自定义功能区”选项卡并选中“开发工具”。然后点击“确定”。如下图所示 - 第3步 - “开发工具”功能区出现在菜单栏中。如下图所示 - 第4步 - 点击 “Visual Basic” 按钮打开VBA编辑器