Excel 应用函数后保留单元格文本格式

Excel 应用函数后保留单元格文本格式,excel,vba,format,Excel,Vba,Format,我将展示一个有点做作的例子,所以请容忍它 我们的产品使用CSV文件作为过渡数据,在Excel用户界面之间发送数据,使用Java程序进行操作并将其传输到SQL后端。我们有一个VBA脚本,它按以下顺序处理所有Excel工作: 将所有8个CSV文件加载到单个Excel文档中的8个工作表中。然后迭代数据批次,执行以下操作: 'Loop over data: Dim r As Range ... r.NumberFormat = "General" r.Formula =

我将展示一个有点做作的例子,所以请容忍它

我们的产品使用CSV文件作为过渡数据,在Excel用户界面之间发送数据,使用Java程序进行操作并将其传输到SQL后端。我们有一个VBA脚本,它按以下顺序处理所有Excel工作:

将所有8个CSV文件加载到单个Excel文档中的8个工作表中。然后迭代数据批次,执行以下操作:

'Loop over data:
    Dim r As Range
    ...
    r.NumberFormat = "General"
    r.Formula = r.Formula
'End loop
这会导致整个工作表填充CSV数据,数字单元格显示文本,Excel公式保持未计算状态。运行r.Formula=r.Formula将触发所有函数进行正确计算。唯一的问题是数字格式

CSV文件有时包含嵌套的CSV。例如,单个单元格可能包含“1,2,3,15654”,这些单元格始终显示为文本。但是,有一种边缘情况,其中单元格可以是漂亮的打印数字,例如“10456345”Excel将在评估所有函数后将这些数字转换为数字单元格,并去掉所有逗号。虽然文档中大约20000行在其他方面是正确的,但影响的4行左右会破坏整个系统


是否有一种方法可以触发Excel从CSV计算函数,而不完全从VBA更改单元格格式?将格式从CSV更改为SYLK不是一个选项,因为Java CSV生成器由另一个部门处理。

您可以在所有单元格(cells.NumberFormat=“@”)上将格式转换为文本,然后在其上循环,并在以“=”开头的单元格上使用代码。 如果绩效是一个问题,您应该将工作表内容放入数组中,处理该数组并将其放回工作表。 如果您发布更多的代码和示例数据,人们将能够更仔细地查看

编辑

例如,将以下值放入“Sheet1”的A列(从A1到A4),并使用文本格式:

13246
13564,4654,4565
654
=A1+A3
并使用以下代码:

Sub test()

    Dim a As Variant
    Dim result As Variant

    a = Sheets("Sheet1").UsedRange
    ReDim result(1 To UBound(a, 1), 1 To UBound(a, 2)) As Variant

    For i = 1 To UBound(a, 1)
      For j = 1 To UBound(a, 2)
        If Left(a(i, j), 1) = "=" Then
          result(i, j) = a(i, j)
        Else
          result(i, j) = "'" & a(i, j)
        End If
      Next j
    Next i

    Sheets("Sheet1").Cells(1, 2).Resize(UBound(result, 1), UBound(result, 2)) = result

End Sub
结果放在B列中,为:

13246
13564,4654,4565
654
13900

我有一种可能适合的替代技术

我创建了一个包含26000个值的工作表:字符串、数字、日期、嵌入逗号和公式的数字

我在上面的表单上运行了一个循环,其内部代码是:

     ValueCell = .Cells(RowCrnt, ColCrnt).Formula
     If IsNumeric(Replace(ValueCell, ",", "")) Then
       .Cells(RowCrnt, ColCrnt).Formula = Replace(ValueCell, ",", "|")
     End If
.Cells(RowCrnt,ColCrnt).Formula
如果单元格包含公式,则给出公式;如果单元格不包含公式,则给出值。如果删除了任何逗号的值或公式是数值,我将用管道替换任何逗号

对于26000个细胞,这需要59秒。这与您每500行额外的45秒相比是否有利

任何像“1,2,3,15654”这样的值现在都是“1 | 2 | 3 | 15 | 654”,但我认为这不是问题。如果您有嵌套字符串,例如“ab,cd,ef”,它们仍然会包含逗号。也许可以测试前导“=”来消除公式并自动替换所有其他内容中的逗号

以下代码在26000个单元格上运行了78秒

     ValueCell = .Cells(RowCrnt, ColCrnt).Formula
     If Left(ValueCell, 1) <> "=" Then
       .Cells(RowCrnt, ColCrnt).Formula = Replace(ValueCell, ",", "|")
     End If
ValueCell=.Cells(rowcrn,ColCrnt).Formula
如果左(ValueCell,1)“=”则
.Cells(RowCrnt,ColCrnt).Formula=Replace(ValueCell,“,”,“|”)
如果结束

希望这能给你带来新的想法。

我建议一种更直接的替代方法:


您是否考虑过直接从Java程序编写Excel电子表格,例如使用?在我看来,这将比整个CSV业务中的公式更简单、更不做作、更不容易出错

您的意思是您的CSV文件包含Excel公式(例如“=R1C1”或“=A1”)?您是否尝试过将单元格定义为文本的
r.NumberFormat=“@”
。@assylas是的,它包含Excel公式。Java程序根据需要生成正确的公式,并在正确的位置生成CSV文件。r、 Formulas=r。Formulas会触发它们求值。@TonyDallimore是,这会导致包含公式的单元格不求值。我不希望每次只检查一个单元格,因为它会将宏执行时间从~5秒拖到~50秒。这就是为什么我一次分批做500行。是的,我做过,但授权没有开源工具。一个愚蠢的可怕的需求,但仍然是一个需求。好吧,一旦它被编译,它就不再是开源的了。。。多么荒谬的要求啊。这就像要求代码中没有字母“e”一样荒谬。这种想法是,社区驱动意味着没有支持,也没有人保证没有漏洞。我的理由是,开源是确保没有漏洞的唯一方法,但这不是管理层的意见。显然,如果他们需要的话,他们希望有人来责怪他们。使用POI库属于这一类。MySQL也是如此,但Oracle是被允许的。但是,对于一些员工(一个社区的人)编写的、可能明年就不在这里工作的本土肮脏黑客,支持甚至更少!更不用说保证这些黑客没有漏洞了。那为什么要跟黑客一起去?!唉。管理层。让他们沉溺于内容的自欺欺人中。将其放入数组可能更易于管理。数组大小是否有上限?我知道字符串长度是有限制的。我不认为VBA有限制(请参阅),它很可能会受到内存的限制。例如,您可以存储数百万个数字而不会出现任何问题。我个人尝试尽可能多地对数组进行处理,因为我通常一次处理100k++记录,这样可以显著提高性能。因此,典型的工作流程是:将数据从工作表读取到数组中,处理数据并将结果放入另一个数组中,将新数组复制到目标工作表中。顺便说一句,如果您可以发布一些代码和示例文件,您可以得到更具体的答案……将数据移动到数组中大大加快了速度