我有两个excel文件。
第一个excel文件包含Person Name和Total Days Present列 实施例
PersonName TotalDays
xyz
abcd
另一个excel文件包含人名,日期和状态(存在/不存在)。
PersonName Date Status
xyz 1/1/2011 Present
xyz 1/1/2011 Present
我需要将类似的日期状态分组为一个,并将它们计算在第一个excel文件中进行更新。
我在第一个文件中有大约100行,其中第二个文件中有20,000行,我需要检查。因此,为了加快速度,我将第二个文件中的所有行加载到一个数组中并读取它们以计算每个条目是否正常工作。
问题是,在Windows中占用大量内存所以很多应用程序会自动打开并且系统几乎挂起。
在没有内存问题和快速处理的情况下,是否有任何替代方法可以实现我遇到了Scripting.Dictionary,但不确定它是否需要更少的内存。
修改 我尝试使用redim保留和20,000个大小的静态数组,在这两种情况下都会出现同样的问题。
修改
lblStatus.Caption = "Loading to memory"
Dim ArrAuditData() As AData
Dim TotalLookUpCount As Integer
For J = 1 To 50000
If lookUpRange.Cells(J, cmbChoice.ListIndex) = "Fail" Then
ReDim Preserve ArrAuditData(J) As AData
ArrAuditData(TotalLookUpCount).AuditType = lookUpRange.Cells(J, cmdAudit2.ListIndex)
ArrAuditData(TotalLookUpCount).TransTime = lookUpRange.Cells(J, cmbChoice.ListIndex - 1)
ArrAuditData(TotalLookUpCount).AuditValue = lookUpRange.Cells(J, cmbChoice.ListIndex)
ArrAuditData(TotalLookUpCount).Slno = lookUpRange.Cells(J, 0)
TotalLookUpCount = TotalLookUpCount + 1
ElseIf lookUpRange.Cells(J, cmbChoice.ListIndex) = "" And J > 4 Then Exit For
End If
DoEvents
Next
答案 0 :(得分:5)
包含4个变体的20,000个元素的数组每个将占用不到2 MB的RAM。我不认为记忆与你的问题有任何关系 - 除非你碰巧使用的是具有2 MB RAM或类似东西的旧计算机。
您的代码如此繁重的一个更可能的原因是您正在循环遍历单元格。 VBA和Excel工作表数据之间的每次通信都会产生很大的开销,当您一次引用一个单元格时,这会增加。在您的情况下,您的循环最多可以执行200,000个单独的单元格引用。
相反,您应该将所有数据一次加载到Variant
数组中,然后遍历该数组,如下所示。这明显更快(即使这使用更多内存,而不是更少;但同样,我不认为内存是你的问题)。
lblStatus.Caption = "Loading to memory"
Dim ArrAuditData() As AData
Dim varTemp As Variant
Dim TotalLookUpCount As Integer
' Load everything into a Variant array.
varTemp = lookUpRange
ReDim ArrAuditData(1 To UBound(varTemp, 1)) As AData
For J = 1 To UBound(varTemp, 1)
If varTemp(J, cmbChoice.ListIndex) = "Fail" Then
ArrAuditData(TotalLookUpCount).AuditType = varTemp(J, cmdAudit2.ListIndex)
ArrAuditData(TotalLookUpCount).TransTime = varTemp(J, cmbChoice.ListIndex - 1)
ArrAuditData(TotalLookUpCount).AuditValue = varTemp(J, cmbChoice.ListIndex)
ArrAuditData(TotalLookUpCount).Slno = varTemp(J, 0)
TotalLookUpCount = TotalLookUpCount + 1
ElseIf varTemp(J, cmbChoice.ListIndex) = "" And J > 4 Then
Exit For
End If
DoEvents
Next
ReDim Preserve ArrAuditData(TotalLookUpCount) As AData
如需进一步阅读,请查看这篇旧的但仍然相关的文章:http://www.avdf.com/apr98/art_ot003.html
如果您仍然认为RAM是问题,那么请向我们展示AData
类型声明。
编辑:此外,永远不要{@ 1}}在这样的循环中! ReDim Preserve
是一项非常昂贵的操作,很少需要在任何给定的数组上进行多次操作。这样做20,000次会降低你的代码速度。在这里,我将它从循环中取出,并在最后使用它一次以修剪掉未使用的元素。 (注意我最初ReDim Preserve
如何编辑数组以适应最大可能的元素数。)
答案 1 :(得分:3)
我建议采用不同的方法。
如果我正确地解释了这个问题:
我将使用的方法是使用COUNTIF(或者如果你使用Excel 2007或更高版本的COUNTIFS)
假设
Excel 2007或2010的解决方案
=COUNTIFS(file2.xlsx!StatusData[Name],[Name],file2.xlsx!StatusData[Status],StatusReport[[#Headers],[Present]])
=COUNTIFS(file2.xlsx!StatusData[Name],[Name],file2.xlsx!StatusData[Status],StatusReport[[#Headers],[Absent]])
Excel 2003解决方案
在file2 StatusData表中添加一个额外的列D(称之为代码)
=Sheet1!$A2&"_"&Sheet1!$C2
file1单元格B2
=COUNTIF([file2.xls]Sheet1!$D:$D,Sheet2!$A2&"_"&Sheet2!$B$1)
=COUNTIF([file2.xls]Sheet1!$D:$D,Sheet2!$A2&"_"&Sheet2!$C$1)
注意:虽然这些公式给出了相同的结果,但是COUNTIFS + Table在2010年引用了版本,如果快得多,那就不好笑了(我在几秒钟内测试了大约300,000行的更新)。