【问题标题】:Export range with data to single CSV file将数据范围导出到单个 CSV 文件
【发布时间】:2016-02-03 23:57:30
【问题描述】:

使用 VBA 将包含 Excel 2010 数据的特定单元格范围导出到 CSV 的有效方法是什么?数据始终从单元格 A3 开始。范围的结尾取决于数据集(始终是 Q 列,但行结尾可能会有所不同)。它应该只从名为“内容”的工作表 2 中导出数据,并且单元格只需要包含“真实”数据,如文本或数字,而不是带有公式的空值。

单元格具有公式的原因是它们引用了工作表 1 和 3 中的单元格。公式使用正常引用和垂直搜索。

使用 UsedRange 将导出 Excel 使用的所有单元格。这可行,但它最终也会导出所有包含公式的空单元格,但没有数据导致输出 .csv 中出现大量不必要的分号(准确地说是 510)。

Sub SavetoCSV()
    Dim Fname As String
 Sheets("Content").UsedRange.Select
 Selection.Copy
 Fname = "C:\Test\test.csv"
    Workbooks.Add
    ActiveSheet.Paste
    ActiveWorkbook.SaveAs Filename:=Fname, _
    FileFormat:=xlCSV, CreateBackup:=False, local:=True
    Application.DisplayAlerts = False
    ActiveWorkbook.Close
    Application.DisplayAlerts = True
End Sub

一种解决方案可能是使用 Offset 或 Resize 更改 VB 代码中的 UsedRange。另一个可能是创建一个 RealRange 变量,然后选择复制它。

类似的问题被问了不止一次,比如hereherehere,我也看过 SpecialCells,但不知怎的,我无法让它按照我想要的方式工作.

我已经尝试了下面的代码,但它最终也从表 3 中添加了行。

 Sub ExportToCSV()
 Dim Fname As String
 Dim RealRange As String
 Dim Startrow As Integer
 Dim Lastrow As Integer
 Dim RowNr As Integer

 Startrow = 3
 RowNr = Worksheets("Content").Cells(1, 1).Value 'this cells has a MAX function returning highest row nr
 Lastrow = RowNr + 3
 RealRange = "A" & Startrow & ":" & "Q" & Lastrow

 Sheets("Content").Range(RealRange).Select
 Selection.Copy
 Fname = "C:\Test\test.csv"
    Workbooks.Add
    ActiveSheet.Paste
    ActiveWorkbook.SaveAs Filename:=Fname, _
    FileFormat:=xlCSV, CreateBackup:=False, local:=True
    Application.DisplayAlerts = False
    'ActiveWorkbook.Close
    Application.DisplayAlerts = True
End Sub

如果我看错了方向,请参考其他选项。

【问题讨论】:

    标签: vba excel csv


    【解决方案1】:

    如果我理解,您只想导出包含值的单元格。这将导致 csv 中包含不同数量的列。如果这确实是您想要做的,那么我认为最快的方法是将您的结果写入如下文件。这在大约 1 秒内运行了 20,000 行

    Dim Lastrow As Integer
    Dim RowNr As Integer
    Dim SourceSheet As Worksheet
    Const Fname As String = "C:\Test\test.csv"
    Const StartRow As Integer = 3
    Sub ExportToCSV()
    On Error GoTo errorhandler
    Set SourceSheet = Worksheets("Content")
        TargetFileNumber = FreeFile()
        Open Fname For Output As #TargetFileNumber 'create the file for writing
        Lastrow = SourceSheet.Cells(1, 1).Value + 3 'I would just use the used range to count the rows but whatever
        For r = StartRow To Lastrow 'set up two loops to go through the rows column by column
            Line = ""
            If SourceSheet.Cells(r, 1).Value <> "" Then 'check if there is a value in the cell, if so export whole row
                For c = 1 To 17 'Columns A through Q                
                    Line = Line & SourceSheet.Cells(r, c).Value & "," 'build the line                
                Next c
            Line = Left(Line, Len(Line) - 1) 'strip off last comma
            Print #TargetFileNumber, Line 'write the line to the file
        End If
        Next r
     GoTo cleanup
    errorhandler:
    MsgBox Err.Number & " --> " & Err.Description, vbCritical, "There was a problem!"
    cleanup:
    Close #TargetFileNumber
    End Sub
    

    【讨论】:

    • 谢谢,我收到一个错误 5--> 无效的过程调用或无效的参数,但它确实会产生输出 csv。在第一个循环中还添加了一个小注释符号'。我真的很喜欢这个结果,它实际上超出了预期,但我仍然有两个问题:1)在评论中你更喜欢使用 usedrange 来计算行数。你能告诉我怎么做吗? 2)如果它包含数据,我想保留整行。 A 列实际上是一个行号,因此如果 A 列有数据,则导出整行(A - Q 列)。如何做到这一点?
    • 1.我总是只使用 LastRow=Cells(65536,1).End(xlUp).Row 之类的东西。我猜这不是最佳实践,因为您的范围可以超出此范围,excel 能够处理超过一百万行只需选择一个那是你在工作表中使用过的数字..你也可以使用 Worksheet.UsedRange.Rows.Count (我认为),但我不使用它,因为它会在你的末尾拾取鬼行如果您没有删除这些行,则为实际数据。 2. 我将编辑帖子以检查 a 列中的值并导出整行
    • 在我的例子中,lastrow 不能超过大约 520 行数据,它实际上非常小,所以 LastRow=Cells(520,1).End(xlUp).Row 效果很好。感谢您在循环中进行编辑。我仍然得到 5 --> 无效的过程调用或参数,试图找出导致它的行,对此有什么想法吗?
    • 注释掉(在前面加上单引号)On Error GoTo errorhandler 行并运行,然后调试以找到导致错误的行
    • 找到导致问题的那一行,它是: Line = Left(Line, Len(Line) - 1) '去掉最后一个逗号。我把它注释掉了,它仍然有效,但在行尾显示了最后一个分隔符。我认为这对我来说现在还可以。感谢大家的帮助!
    猜你喜欢
    • 2017-03-27
    • 1970-01-01
    • 2017-10-16
    • 2014-08-07
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多