vba Excel:宏将工作表导出为 CSV 文件,而无需离开我当前的 Excel 工作表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37037934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 10:23:50  来源:igfitidea点击:

Excel: macro to export worksheet as CSV file without leaving my current Excel sheet

excelvbaexcel-vbacsvexport-to-csv

提问by neves

There are a lot of questions here to create a macro to save a worksheet as a CSV file. All the answers use the SaveAs, like this onefrom SuperUser. They basically say to create a VBA function like this:

这里有很多问题要创建一个宏来将工作表保存为 CSV 文件。所有答案都使用 SaveAs,就像SuperUser 的这个一样。他们基本上说要创建一个这样的 VBA 函数:

Sub SaveAsCSV()
    ActiveWorkbook.SaveAs FileFormat:=clCSV, CreateBackup:=False
End Sub

This is a great answer, but I want to do an export instead of Save As. When the SaveAs is executed it causes me two annoyances:

这是一个很好的答案,但我想做一个导出而不是 Save As。当 SaveAs 被执行时,它会给我带来两个烦恼:

  • My current working file becomes a CSV file. I'd like to continue working in my original .xlsm file, but to export the contents of the current worksheet to a CSV file with the same name.
  • A dialog appears asking me confirm that I'd like to rewrite the CSV file.
  • 我当前的工作文件变成了 CSV 文件。我想继续处理我原来的 .xlsm 文件,但要将当前工作表的内容导出到同名的 CSV 文件中。
  • 出现一个对话框,要求我确认是否要重写 CSV 文件。

Is it possible to just export the current worksheet as a file, but to continue working in my original file?

是否可以仅将当前工作表导出为文件,但继续在我的原始文件中工作?

采纳答案by neves

Almost what I wanted @Ralph. Your code has some problems:

几乎是我想要的@Ralph。您的代码有一些问题:

  1. it exports just the hardcoded sheet named "Sheet1";
  2. it always export to the same temp file, overwriting it;
  3. it ignores the locale separation char.
  1. 它仅导出名为“Sheet1”的硬编码表;
  2. 它总是导出到同一个临时文件,覆盖它;
  3. 它忽略区域设置分隔字符。

To solve these problems, and meet all my requirements, I've adapted the code from here. I've cleaned it a little to make it more readable.

为了解决这些问题并满足我的所有要求,我修改了此处代码。我已经对其进行了一些清理以使其更具可读性。

Option Explicit
Sub ExportAsCSV()

    Dim MyFileName As String
    Dim CurrentWB As Workbook, TempWB As Workbook

    Set CurrentWB = ActiveWorkbook
    ActiveWorkbook.ActiveSheet.UsedRange.Copy

    Set TempWB = Application.Workbooks.Add(1)
    With TempWB.Sheets(1).Range("A1")
      .PasteSpecial xlPasteValues
      .PasteSpecial xlPasteFormats
    End With        

    Dim Change below to "- 4"  to become compatible with .xls files
    MyFileName = CurrentWB.Path & "\" & Left(CurrentWB.Name, Len(CurrentWB.Name) - 5) & ".csv"

    Application.DisplayAlerts = False
    TempWB.SaveAs Filename:=MyFileName, FileFormat:=xlCSV, CreateBackup:=False, Local:=True
    TempWB.Close SaveChanges:=False
    Application.DisplayAlerts = True
End Sub

There are still some small thing with the code above that you should notice:

上面的代码还有一些你应该注意的小东西:

  1. .Closeand DisplayAlerts=Trueshould be in a finally clause, but I don't know how to do it in VBA
  2. It works just if the current filename has 4 letters, like .xlsm. Wouldn't work in .xls excel files. For file extensions of 3 chars, you must change the - 5to - 4when setting MyFileName.
  3. As a collateral effect, your clipboard will be substituted with current sheet contents.
  1. .Close并且DisplayAlerts=True应该在 finally 子句中,但我不知道如何在 VBA 中做到这一点
  2. 仅当当前文件名有 4 个字母时才有效,例如 .xlsm。不适用于 .xls excel 文件。对于3个字符的文件扩展名,则必须更改- 5- 4设置MyFileName的时候。
  3. 作为附带效果,您的剪贴板将替换为当前工作表内容。

Edit: put Local:=Trueto save with my locale CSV delimiter.

编辑:Local:=True使用我的语言环境 CSV 分隔符保存。

回答by Ralph

@NathanClement was a bit faster. Yet, here is the complete code (slightly more elaborate):

@NathanClement 快一点。然而,这里是完整的代码(稍微详细一点):

Option Explicit

Public Sub ExportWorksheetAndSaveAsCSV()

Dim wbkExport As Workbook
Dim shtToExport As Worksheet

Set shtToExport = ThisWorkbook.Worksheets("Sheet1")     'Sheet to export as CSV
Set wbkExport = Application.Workbooks.Add
shtToExport.Copy Before:=wbkExport.Worksheets(wbkExport.Worksheets.Count)
Application.DisplayAlerts = False                       'Possibly overwrite without asking
wbkExport.SaveAs Filename:="C:\tmp\test.csv", FileFormat:=xlCSV
Application.DisplayAlerts = True
wbkExport.Close SaveChanges:=False

End Sub

回答by Craig Lambie

As per my comment on @neves post, I slightly improved this by adding the xlPasteFormats as well as values part so dates go across as dates - I mostly save as CSV for bank statements, so needed dates.

根据我对@neves 帖子的评论,我通过添加 xlPasteFormats 和 values 部分稍微改进了这一点,以便日期作为日期 - 我主要保存为 CSV 用于银行对帐单,因此需要日期。

Sub ExportAsCSV()

    Dim MyFileName As String
    Dim CurrentWB As Workbook, TempWB As Workbook

    Set CurrentWB = ActiveWorkbook
    ActiveWorkbook.ActiveSheet.UsedRange.Copy

    Set TempWB = Application.Workbooks.Add(1)
    With TempWB.Sheets(1).Range("A1")
        .PasteSpecial xlPasteValues
        .PasteSpecial xlPasteFormats
    End With

    'Dim Change below to "- 4"  to become compatible with .xls files
    MyFileName = CurrentWB.Path & "\" & Left(CurrentWB.Name, Len(CurrentWB.Name) - 5) & ".csv"

    Application.DisplayAlerts = False
    TempWB.SaveAs Filename:=MyFileName, FileFormat:=xlCSV, CreateBackup:=False, Local:=True
    TempWB.Close SaveChanges:=False
    Application.DisplayAlerts = True
End Sub

回答by Patrick Honorez

For those situations where you need a bit more customisation of the output (separator or decimal symbol), or who have large dataset (over 65k rows), I wrote the following:

对于需要对输出进行更多自定义(分隔符或十进制符号)或具有大型数据集(超过 65k 行)的情况,我写了以下内容:

Option Explicit

Sub rng2csv(rng As Range, fileName As String, Optional sep As String = ";", Optional decimalSign As String)
'export range data to a CSV file, allowing to chose the separator and decimal symbol
'can export using rng number formatting!
'by Patrick Honorez --- www.idevlop.com
    Dim f As Integer, i As Long, c As Long, r
    Dim ar, rowAr, sOut As String
    Dim replaceDecimal As Boolean, oldDec As String

    Dim a As Application:   Set a = Application

    ar = rng
    f = FreeFile()
    Open fileName For Output As #f

    oldDec = Format(0, ".")     'current client's decimal symbol
    replaceDecimal = (decimalSign <> "") And (decimalSign <> oldDec)

    For Each r In rng.Rows
        rowAr = a.Transpose(a.Transpose(r.Value))
        If replaceDecimal Then
            For c = 1 To UBound(rowAr)
                'use isnumber() to avoid cells with numbers formatted as strings
                If a.IsNumber(rowAr(c)) Then
                    'uncomment the next 3 lines to export numbers using source number formatting
'                    If r.cells(1, c).NumberFormat <> "General" Then
'                        rowAr(c) = Format$(rowAr(c), r.cells(1, c).NumberFormat)
'                    End If
                    rowAr(c) = Replace(rowAr(c), oldDec, decimalSign, 1, 1)
                End If
            Next c
        End If
        sOut = Join(rowAr, sep)
        Print #f, sOut
    Next r
    Close #f

End Sub

Sub export()
    Debug.Print Now, "Start export"
    rng2csv shOutput.Range("a1").CurrentRegion, RemoveExt(ThisWorkbook.FullName) & ".csv", ";", "."
    Debug.Print Now, "Export done"
End Sub

回答by nobilis

Here is a slight improvement on the this answer above taking care of both .xlsx and .xls files in the same routine, in case it helps someone!

这是对上面这个答案的轻微改进,在同一例程中同时处理 .xlsx 和 .xls 文件,以防它对某人有所帮助!

I also add a line to choose to save with the active sheet name instead of the workbook, which is most practical for me often:

我还添加了一行以选择使用活动工作表名称而不是工作簿进行保存,这对我来说通常是最实用的:

Sub ExportAsCSV()

    Dim MyFileName As String
    Dim CurrentWB As Workbook, TempWB As Workbook

    Set CurrentWB = ActiveWorkbook
    ActiveWorkbook.ActiveSheet.UsedRange.Copy

    Set TempWB = Application.Workbooks.Add(1)
    With TempWB.Sheets(1).Range("A1")
        .PasteSpecial xlPasteValues
        .PasteSpecial xlPasteFormats
    End With

    MyFileName = CurrentWB.Path & "\" & Left(CurrentWB.Name, InStrRev(CurrentWB.Name, ".") - 1) & ".csv"
    'Optionally, comment previous line and uncomment next one to save as the current sheet name
    'MyFileName = CurrentWB.Path & "\" & CurrentWB.ActiveSheet.Name & ".csv"


    Application.DisplayAlerts = False
    TempWB.SaveAs Filename:=MyFileName, FileFormat:=xlCSV, CreateBackup:=False, Local:=True
    TempWB.Close SaveChanges:=False
    Application.DisplayAlerts = True
End Sub

回答by OldUgly

As I commented, there are a few places on this site that write the contents of a worksheet out to a CSV. This oneand this oneto point out just two.

正如我评论的那样,这个站点上有几个地方可以将工作表的内容写入 CSV。这一一点只指出两个。

Below is my version

下面是我的版本

  • it explicitly looks out for "," inside a cell
  • It also uses UsedRange- because you want to get all of the contents in the worksheet
  • Uses an array for looping as this is faster than looping through worksheet cells
  • I did not use FSO routines, but this is an option
  • 它明确地寻找单元格内的“,”
  • 它还使用UsedRange- 因为您想获取工作表中的所有内容
  • 使用数组进行循环,因为这比循环工作表单元格快
  • 我没有使用 FSO 例程,但这是一个选项

The code ...

编码 ...

Sub makeCSV(theSheet As Worksheet)
Dim iFile As Long, myPath As String
Dim myArr() As Variant, outStr As String
Dim iLoop As Long, jLoop As Long

myPath = Application.ActiveWorkbook.Path
iFile = FreeFile
Open myPath & "\myCSV.csv" For Output Lock Write As #iFile

myArr = theSheet.UsedRange
For iLoop = LBound(myArr, 1) To UBound(myArr, 1)
    outStr = ""
    For jLoop = LBound(myArr, 2) To UBound(myArr, 2) - 1
        If InStr(1, myArr(iLoop, jLoop), ",") Then
            outStr = outStr & """" & myArr(iLoop, jLoop) & """" & ","
        Else
            outStr = outStr & myArr(iLoop, jLoop) & ","
        End If
    Next jLoop
    If InStr(1, myArr(iLoop, jLoop), ",") Then
        outStr = outStr & """" & myArr(iLoop, UBound(myArr, 2)) & """"
    Else
        outStr = outStr & myArr(iLoop, UBound(myArr, 2))
    End If
    Print #iFile, outStr
Next iLoop

Close iFile
Erase myArr

End Sub