【问题标题】:Saving worksheets to CSV with Excel Formulas intact将工作表保存为 CSV,并保持 Excel 公式不变
【发布时间】:2012-03-18 12:02:55
【问题描述】:

我完全在 VBA for Excel 中工作。我的解决方案必须完全是程序化的,而不是用户驱动的。解决方案的要求是用户启动一个宏来获取工作簿并将 8 个工作表保存到单独的 CSV 文件中,保留公式并丢弃公式分辨率。我有一组表(sht),我遍历并保存它们。下面的代码完美地做到了这一点。

For i = LBound(sht) To UBound(sht)
    If (SheetExists(csv(i))) Then
        Sheets(sht(i)).SaveAs _
                fullpath & csv(i) & ".csv", _
                FileFormat:=xlCSV, _
                CreateBackup:=False
    End If
Next i

其中 fullpath 包含文件保存位置的完整路径,我编写了一个布尔函数来测试工作簿中是否存在工作表。

问题:

我需要 CSV 文档来包含 Excel 公式,而不是公式的计算结果。公式的结果可以丢弃。 The Microsoft website 说:

如果单元格显示公式而不是公式值,则公式将转换为文本。所有格式、图形、对象和其他工作表内容都将丢失。欧元符号将转换为问号。

这意味着 SaveAs 函数可能永远不会做我想让它做的事情,但我需要一些方法来创建文件。理想情况下,我也希望保持 Excel 能够完整地转义 CSV 单元格。 CSV 文件将由可以根据需要正确解析 Excel 函数的 Java 和 SQL 程序读取。

【问题讨论】:

  • 你将如何处理合并的单元格?如果公式包含换行符怎么办 - 是否应该在导出之前将其删除?你需要处理数组公式吗?
  • 您可以在运行 SaveAs 之前尝试激活每个工作表并添加 ActiveWindow.DisplayFormulas = True
  • @蒂姆·威廉姆斯。非常聪明。比我的建议好。
  • @TimWilliams 完美。像魅力一样工作。找出规范细节的方法。如果您回复了真正的解决方案,我会将其标记为已接受。
  • 此外,几乎所有的公式都是工作表引用,因此没有进行重大处理。没有数组数据,CSV 可以通过用双引号包围单元格来转义包含逗号的单元格,也可以转义嵌入的双引号。

标签: excel csv excel-formula vba


【解决方案1】:

您可以尝试依次激活每个工作表,然后添加

ActiveWindow.DisplayFormulas = True

在调用 SaveAs 之前。

【讨论】:

    【解决方案2】:

    您需要执行类似的操作将公式逐个单元格地导出到 csv 文件中,而不是将每个工作表另存为 CSV 文件,从而去除公式

    这段代码和我在Generate a flat list of all excel cell formulas的回答类似

    对于三张工作簿,它将创建名为

    的文件

    C:\temp\output1.csv
    C:\temp\output2.csv
    C:\temp\output3.csv

    VBA(添加分隔符转义)

    Const sFilePath = "C:\temp\output"
    Const strDelim = ","
    
    Sub CreateTxt_Output()
    Dim ws As Worksheet
    Dim rng1 As Range
    Dim X
    Dim lRow As Long
    Dim lCol As Long
    Dim strTmp As String
    Dim lFnum As Long
    Dim lngCnt As Long
    Dim strOut As String
    
    lFnum = FreeFile
    For Each ws In ActiveWorkbook.Worksheets
        lngCnt = lngCnt + 1
        Open (sFilePath & lngCnt & ".csv") For Output As lFnum
        'test that sheet has been used
        Set rng1 = ws.UsedRange
        If Not rng1 Is Nothing Then
            'only multi-cell ranges can be written to a 2D array
            If rng1.Cells.Count > 1 Then
                X = ws.UsedRange.Formula
                For lRow = 1 To UBound(X, 1)
                    strOut = IIf(InStr(X(lRow, 1), strDelim) > 0, """" & X(lRow, 1) & """", X(lRow, 1))
                    For lCol = 2 To UBound(X, 2)
                        'write each line to CSV
                        strOut = strOut & (strDelim & IIf(InStr(X(lRow, lCol), strDelim) > 0, """" & X(lRow, lCol) & """", X(lRow, lCol)))
                    Next lCol
                    Print #lFnum, strOut
                Next lRow
            Else
                Print #lFnum, IIf(InStr(rng1.Formula, strDelim) > 0, """" & rng1.Formula & """", rng1.Formula)
                End If
        End If
        Close lFnum
    Next ws
    MsgBox "Done!", vbOKOnly
    End Sub
    

    【讨论】:

    • 我想我在您之前的一个答案中看到了一种类似的模式,您可以逐行写入文件 - 首先准备字符串中的全部内容然后将其写入一次?
    • @assylias 否 - 原因是您反复连接到整个内容的越来越长的字符串。在我的测试中,这段代码对 1000 行 5 列花费了 0.05 秒,整个内容一次工具 0.07 秒。对于 10,000 条记录,它是 0.2 秒对 8 秒。对于 100,000 条记录,它是 3 秒 v Excel 锁定。
    • 这是一个很棒的解决方案,如果@Tim Williams 解决方案失败,我们最终可能会使用它。
    【解决方案3】:

    作为最后一个解决方案的替代方案,您可以替换文件系统对象和文本流。 检查writing to a text file上的此链接

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-04
      • 2015-01-22
      • 2023-03-23
      • 1970-01-01
      相关资源
      最近更新 更多