2012-02-14 85 views
1

我将展示一些人为的例子,请耐心等待。应用函数后保持单元格文本格式化

我们的产品利用CSV文件创建过渡数据,在Excel用户界面和Java程序之间发送数据,并将其转移到SQL后端。我们有一个VBA脚本,可按以下顺序处理所有Excel工作:

在单个Excel文档中将所有8个CSV文件加载到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,15,654”这些单元格始终显示为文本。但是,有一个边缘情况,其中单元格可能是漂亮的打印数字,例如“10,456,345”Excel将在评估所有函数后将这些数字转换为数字单元格,并删除所有逗号。尽管文档中的20,000行左右是正确的,但这影响了4行左右,从而打破了整个系统。

有没有办法触发Excel来评估从CSV的功能,而不必完全从VBA中更改单元格格式?由于Java CSV生成器由不同的部门处理,因此将格式从CSV更改为SYLK不是一种选择。

+0

是否指CSV文件包含Excel公式(例如,“= R1C1”或“= A1”)? – assylias 2012-02-14 16:47:03

+0

您是否尝试过使用'r.NumberFormat =“@”'将单元格定义为文本? – 2012-02-14 16:52:12

+0

@assylias是的,它包含Excel公式。 Java程序根据需要生成正确的公式,并在正确的位置生成CSV文件。 r.Formulas = r.Formulas触发它们进行评估。 – Reivax 2012-02-14 18:02:01

回答

1

您可以将所有单元格的格式设置为文本(Cells.NumberFormat =“@”),然后遍历它们并在以'='开头的单元格上使用您的代码。 如果性能是一个问题,您应该将工作表内容放入数组中,在数组上工作并将其放回工作表。 如果您发布更多的代码和示例数据,人们将能够仔细观察。

EDIT

例如,把下列值在列A(从A1到A4) “工作表Sheet” 的,具有文本格式:

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 
+0

将其推入数组可能更具可管理性。数组大小有上限吗?我知道有字符串长度。 – Reivax 2012-02-16 16:16:42

+0

我不认为有VBA限制(请参阅http://support.microsoft.com/default.aspx?scid=kb;en-us;177991),它很可能会受到您的内存限制。例如,您可以存储数百万个数字。 – assylias 2012-02-16 16:21:37

+0

我个人尝试尽可能多地对阵列进行处理,因为我一般一次处理100k ++记录,并且它显着提高了性能。因此,一个典型的工作流程将是:将数据从工作表读取到数组中,处理数据并将结果放入另一个数组,将该新数组复制到目标工作表。 – assylias 2012-02-16 16:24:47

1

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

我创建了一个包含26,000个值的工作表:包含逗号和公式的字符串,数字,日期,数字。

我跑超过上述片一个环路,它的内码是:

 ValueCell = .Cells(RowCrnt, ColCrnt).Formula 
    If IsNumeric(Replace(ValueCell, ",", "")) Then 
     .Cells(RowCrnt, ColCrnt).Formula = Replace(ValueCell, ",", "|") 
    End If 

.Cells(RowCrnt, ColCrnt).Formula得到式如果单元包含一个或值,如果它没有。如果删除的任何逗号的值或公式是数字,我用管道替换任何逗号。

26,000个细胞需要59秒。这是否与每500行多出45秒有利?

“1,2,3,15,654”的任何值现在都是“1 | 2 | 3 | 15 | 654”,但我认为这不是问题。如果你有嵌套的字符串,比如“ab,cd,ef”,它们仍然会包含逗号。也许测试一个领先的“=”来消除公式并自动替换其他所有的逗号将是一种可能性。

以下代码需要78秒才能运行26,000个单元。

 ValueCell = .Cells(RowCrnt, ColCrnt).Formula 
    If Left(ValueCell, 1) <> "=" Then 
     .Cells(RowCrnt, ColCrnt).Formula = Replace(ValueCell, ",", "|") 
    End If 

希望这可以帮助,如果只是给你新的想法。

+0

这是一个很好的解决方案。我们在整个工作簿上的总运行时间是5秒,而不是每500行5秒。除了编号问题外,它的编程非常好。一分钟内可能无法交付。使用替代分隔符可能是可以接受的,我会看看是否可以让其他团队将嵌套CSV中的逗号更改为半色或其他合理的可压缩字符。或者,也许可以让CSV生成器/解析仅使用分号作为嵌套分隔符。 – Reivax 2012-02-16 16:21:25

0

我提出一个替代方案,更简单的方法:

你有没有考虑直接从Java程序写入到一个Excel电子表格,例如使用Apache POI?对我来说,这比整个CSV公式业务要简单得多,不太容易出错,并且不易出错。

+0

是的,我有,但任务是没有开源工具。尽管如此,这是一项愚蠢而可怕的要求。 – Reivax 2012-02-16 16:16:04

+0

那么,只要它被编译,它就不再是开源的了......这是多么荒谬的要求。这就像要求代码写入时没有字母“e”一样荒谬。 – 2012-02-17 02:18:18

+0

思想是社区驱动意味着没有支持,也没有人确保没有任何漏洞。我的推理是开源是确保没有漏洞的唯一途径,但这不是管理层的看法。显然,他们希望有人分配责任,如果他们需要。使用POI库就属于这种情况。 MySQL也是如此,但Oracle是允许的。 – Reivax 2012-02-21 19:28:18