【问题标题】:Excel 2010 - VBA code to Write Formatted Numbers to CSVExcel 2010 - 将格式化数字写入 CSV 的 VBA 代码
【发布时间】:2015-03-31 21:35:28
【问题描述】:

我正在处理一个 5 表工作簿,其中表 5 上名为 ExportCSV 的按钮导出表 3 上的数据。更具体地说,该按钮运行一个 VBA 代码,该代码逐行检查前 3 个单元格数据。如果前三个单元格中的任何一个有数据,则选择整行。选择所有包含数据的行后,将数据逐行写入 CSV 文件(但文件本身以分号分隔)。

我遇到的问题是某些单元格格式被复制了,但有些没有。例如,使用 $ 为会计格式的单元格中的值格式正确,这意味着“$12,345,678.90”显示为“$12,345,678.90”。但是,格式为会计但没有 $ 的单元格中的值未正确写入 csv,这意味着“12,345,678.90”被写入“12345678.9”。

下面是有问题的宏。

Dim planSheet As Worksheet
Dim temSheet As Worksheet

Private Sub ExportCSV_Click()
    Dim i As Integer
    Dim j As Integer
    Dim lColumn As Long
    Dim intResult As Integer
    Dim strPath As String
    On Error GoTo Errhandler
    Set temSheet = Worksheets(3)
    i = 2
    Do While i < 1001
        j = 1
        Do While j < 4
            If Not IsEmpty(temSheet.Cells(i, j)) Then
                temSheet.Select
                lColumn = temSheet.Cells(2, Columns.Count).End(xlToLeft).Column
                temSheet.Range(temSheet.Cells(2, 1), temSheet.Cells(i, lColumn)).Select
            End If
            j = j + 1
        Loop
        i = i + 1
    Loop
    Application.FileDialog(msoFileDialogFolderPicker).InitialFileName = Application.ActiveWorkbook.Path
    Application.FileDialog(msoFileDialogFolderPicker).Title = "Select a Path"
    Application.FileDialog(msoFileDialogFolderPicker).ButtonName = "Select Path"
    intResult = Application.FileDialog(msoFileDialogFolderPicker).Show

    If intResult <> 0 Then
        'dispaly message box
        strPath = Application.FileDialog(msoFileDialogFolderPicker).SelectedItems(1)
    End If

    Dim X As Long, FF As Long, S() As String
    ReDim S(1 To Selection.Rows.Count)
    For X = 1 To Selection.Rows.Count
        S(X) = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(Selection.Rows(X).Value)), ";")
    Next
    FF = FreeFile
    FilePath = strPath & "\Data" & Format(Now(), "yyyyMMddhhmmss") & ".csv"
    Open FilePath For Output As #FF
    Print #FF, Join(S, vbNewLine)
    Close #FF

    Errhandler:
        ...Error Handling Code omitted

End Sub

我需要能够复制单元格的确切格式。将 no-$ 单元格转换为 $ 单元格将不起作用,因为没有 $ 的值将用于稍后在可以处理逗号但不是 $ 的过程中的计算,并且我无法更改代码稍后计算(专有插件进行计算。)此外,行具有混合内容,这意味着行中的某些值是文本而不是数字。

【问题讨论】:

  • 您将需要对For x = 1 to Selection.Rows.Count 循环进行大修。您必须对每行范围内的值数组进行逐个单元格迭代,并更新数组以包含 formatted 值(默认情况下,它将使用 .Value 完全不知道任何格式)。那有意义吗?如果是这样,请试一试,如果您遇到困难,我们会尽力提供帮助。
  • 这确实有些道理。我想我只是想看看是否有人知道不必这样做。
  • 对,我认为当您处理有条件地时,没有其他方法可以将需要写入的值更改为您现在正在执行的操作。从整个选择的行范围隐式转换为数组,然后您使用Join 函数将该数组强制转换为字符串,以便可以将其写入 FSO 文件。那里的隐式转换将使用行中每个单元格的.Value。相反,您需要从单元格的 .Text 属性构建数组,我认为一次只能完成一个单元格/值。
  • @DavidZemens 大修是对的。查看答案。

标签: vba excel csv


【解决方案1】:

我最终听从了 David Zemens 的建议,并彻底检查了 For X = 1 to Selection.Rows.Count 的部分,见下文。

For X = 1 To Selection.Rows.Count
    For Y = 1 To Selection.Columns.Count
        If Y <> Selection.Columns.Count Then
            If IsNumeric(temSheet.Cells(X + 1, Y).Value) Then
                If temSheet.Cells(X + 1, Y).Value = 0 Then
                    S(X) = S(X) & ";"
                Else
                    S(X) = S(X) & Replace(temSheet.Cells(X + 1, Y).Text, " ", "") & ";"
                End If
            Else
                S(X) = S(X) & Trim(temSheet.Cells(X + 1, Y).Text) & ";"
            End If
        Else
            If IsNumeric(temSheet.Cells(X + 1, Y).Value) Then
                If temSheet.Cells(X + 1, Y).Value <> 0 Then
                    S(X) = S(X) & Replace(temSheet.Cells(X + 1, Y).Text, " ", "")
                End If
            Else
                S(X) = S(X) & Trim(temSheet.Cells(X + 1, Y).Text)
            End If
        End If
    Next
Next

需要更多格式。它逐个单元格地进行,故意跳过工作表的第一行。某些单元格的.Text 属性在值之前或在 $ 和值之间返回空白空间,因此必须将其删除。 Trim 删除前导和结束空格,而Replace 替换导出中的所有空格。

【讨论】:

  • 干得好。如果性能是一个问题,您可以首先将整个行/范围.Value 放入一个数组中,然后对其进行迭代,而不是进行逐个单元格的迭代。它可能会更快,但在小型数据集上可能不明显。如果您有数千行,我可能会这样做。
  • 通常数据集不是那么大,但我运行了一个总共大约 2000 个的测试。选择大约需要 5-10 秒。出口是即时的。所以性能应该不是问题。感谢您朝正确的方向轻推。
  • 正确的导出应该是超级高效的,您使用优化的 I/O 功能一次打印整个文件。只是单元格迭代需要一些时间,但对于大多数人来说,5-10 秒是可以忍受的,所以我不会大惊小怪,除非它在未来成为问题 :) 干杯。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-18
  • 2021-01-27
  • 1970-01-01
  • 1970-01-01
  • 2019-02-19
  • 1970-01-01
  • 2017-10-24
相关资源
最近更新 更多