【问题标题】:Problem with list, decimals and thousands separators on VBAVBA 上的列表、小数和千位分隔符问题
【发布时间】:2022-07-01 03:13:16
【问题描述】:

我开发了一个 Excel 宏,它必须将工作表上的数据表(列 A 到 E 1)保存为 CSV 格式。它是如何工作的:对于表格的每个 lign,我遍历每个元素以将它们与一个新工作簿中的分号分隔符连接起来,我以 CSV 格式保存然后关闭(参见我帖子末尾的完整宏)。

Capture of my Excel file

由于我有来自世界各地的用户,分隔符设置可能会有所不同,因此此宏必须强制设置为:

  • 列表分隔符 = 分号
  • 千位分隔符 = 无或逗号
  • 小数分隔符 = 点

但是,我遇到了几个问题:

  • 如果 Windows 列表分隔符设置为分号,则带有分号的 CSV 格式可以正常工作,但如果它是例如逗号,则无法使用 SaveAs 函数强制分号 => 我决定创建“由通过在同一列中用分号连接元素来创建我的 CSV 文件。但是当以 CSV 格式保存此列时,我不知道为什么,每行都加上双引号,我不能把它们去掉(我不能重新搜索和替换它们,因为它们在文件打开时没有出现在 Excel 中)。

我发现避免该问题的唯一方法是使用参数 FileFormat:=xlTextPrinter 以文本格式保存文件。

如果您知道为什么会这样,我会全神贯注(是因为 ASCII 规范吗?)

For FiltersCount = 1 To Dialog.Filters.Count

        If Dialog.Filters(FiltersCount).Extensions = "*.txt" Then
            Index = FiltersCount
            Exit For
        End If
    Next

    With Dialog
        .FilterIndex = Index
        .Title = "Enregistrer sous... / Save as..."
        .Show

        If .SelectedItems.Count > 0 Then
            Path = .SelectedItems(1)
            ActiveWorkbook.SaveAs FileName:=Path, FileFormat:=xlTextPrinter, CreateBackup:=False, Local:=True

        Else
            MsgBox "Aucun emplacement ou nom n'a été défini. Merci de réessayer!" & Chr(10) & _
                                                                                            "No location or name has been defined. Please retry!"
        End If
    End With
  • 我的第二个问题是关于小数和千位分隔符。理论上应该可行的想法是更改用户设置(不是我所知道的最佳实践的一部分......)以强制设置我想要的设置(“。”=小数和“,=数千)。
'Save current separator parameters
 UseSystemSeparators = Application.UseSystemSeparators
 DecimalSeparator = Application.DecimalSeparator
 ThousandsSeparator = Application.ThousandsSeparator

 'Save separator parameters required by Data Management
 Application.UseSystemSeparators = False
 Application.DecimalSeparator = "."
 Application.ThousandsSeparator = ","

问题是,如果我的数据是十进制数,当我将它复制到我的新工作簿中时,即使已将十进制设置强制设置在某个点上,该点也会再次变为逗号。所以我的想法是用点搜索和替换逗号。但这就是它变得棘手的地方:根据用户设置,这可能与千位分隔符冲突。我不明白为什么这个点变成逗号,而这违背了我强制的设置,我发现避免这种情况的唯一方法是用“/”更改千位分隔符以确保没有冲突......但这不是我认为的最漂亮和最稳定的方式..

如果有人有任何想法,任何线索,那将非常有帮助!

最后,带来更多细节,这是我的完整宏和测试数据集:

Sub xlsToCSV()

    Dim Path As String
    Dim FileName As String
    Dim UseSystemSeparators As Boolean
    Dim DecimalSeparator As String
    Dim ThousandsSeparator As String
    Dim lastDataRowIndex As Long
    Dim Dialog As FileDialog
    Dim FiltersCount, Index As Integer
    Dim i As Integer, j As Integer, mergedData As String
    On Error GoTo errHandler

    Application.ScreenUpdating = False

    'Save current separator parameters
    UseSystemSeparators = Application.UseSystemSeparators
    DecimalSeparator = Application.DecimalSeparator
    ThousandsSeparator = Application.ThousandsSeparator

    'Save separator parameters required by Data Management
    Application.UseSystemSeparators = False
    Application.DecimalSeparator = "."
    Application.ThousandsSeparator = "/"

    lastDataRowIndex = calculateLastRowIndex("B", "C", "D", "E")

    Workbooks.Add

    For i = 2 To lastDataRowIndex

        For j = 1 To 4

            mergedData = mergedData & ThisWorkbook.Worksheets("Data").Cells(i, j) & ";"

        Next
        ActiveWorkbook.ActiveSheet.Cells(i - 1, 1) = mergedData & ThisWorkbook.Worksheets("Data").Cells(i, 5)

        ActiveWorkbook.ActiveSheet.Cells(i - 1, 1) = Replace(ActiveWorkbook.ActiveSheet.Cells(i - 1, 1), "/", "")
        ActiveWorkbook.ActiveSheet.Cells(i - 1, 1) = Replace(ActiveWorkbook.ActiveSheet.Cells(i - 1, 1), ",", ".")

        mergedData = Empty

    Next

    Application.DisplayAlerts = False

    'Save dialog / file forced as CSV
    Set Dialog = Application.FileDialog(msoFileDialogSaveAs)

    For FiltersCount = 1 To Dialog.Filters.Count
        If Dialog.Filters(FiltersCount).Extensions = "*.txt" Then
            Index = FiltersCount
            Exit For
        End If
    Next

    With Dialog
        .FilterIndex = Index
        .Title = "Enregistrer sous... / Save as..."
        .Show

        If .SelectedItems.Count > 0 Then
            Path = .SelectedItems(1)
            ActiveWorkbook.SaveAs FileName:=Path, FileFormat:=xlTextPrinter, CreateBackup:=False, Local:=True

        Else
            MsgBox "Aucun emplacement ou nom n'a été défini. Merci de réessayer!" & Chr(10) & _
                                                                                            "No location or name has been defined. Please retry!"
        End If
    End With

    ActiveWorkbook.Close

errHandler:

    'Restore current separator parameters
    Application.UseSystemSeparators = UseSystemSeparators
    Application.DecimalSeparator = DecimalSeparator
    Application.ThousandsSeparator = ThousandsSeparator

    Application.ScreenUpdating = True
End Sub

感谢您有勇气阅读这篇独白并祝您有美好的一天!

卡罗琳

【问题讨论】:

  • *大家好(我确定我在帖子的开头写了它,结果我没有,我保证我不粗鲁;))
  • 对于您的部分问题,将CSV另存为CSV,格式为您选择的区域;然后指示您的用户不打开csv。相反,他们应该导入 csv 文件并在此时定义csv 设置。此过程可以在 Power Query 中或使用 VBA 宏 自动完成导入任务。

标签: excel vba


【解决方案1】:

希望我已经正确理解了这一点。 我认为双引号是因为金额列中的逗号?它告诉它把它当作一个字符串而不是分隔它。 您不能只格式化列,而不是更改应用程序设置吗?

Columns("E:E").NumberFormat = "#,##0.00;-#,##0.00;""-""" - 或者在应用程序设置不同的情况下是否有效?

如果没有,如果允许我提供我的电子邮件地址,您能否将工作簿通过电子邮件发送给我?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-07
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2021-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多