替代使用循环来使代码运行得更快

时间:2014-08-28 10:25:51

标签: excel excel-vba for-loop vba

我有2个问题,第一个是关于一个excel公式,我无法在VBA中复制,即使我已经使用记录宏来检索公式,第二个是因为我无法解决我的问题第一个问题是关于代码效率: 基本上在单元格AR2中我提出了一个excel公式:

IF=(P2="LDN";"UK;IF(P2="MAD";"SPAIN"
IF(P2="PRA";"CZECH REPUBLIC";"")))))))))

我为一群国家做这件事。

然后我在我的第二行上执行autfill单元格目标,直到最后一行包含我的工作表上的数据以获得结果。 主要问题是在excel中它运行良好但是当使用vba记录器在VBA中编码时,我在下面的代码中有错误。虽然我只是复制粘贴vba记录器的结果。 请找到以下代码。

 i = Range("A:A").Find("*", [A1], xlValues, xlWhole, xlByRows, xlPrevious).Row

    Range("AR2").Select
    ActiveCell.FormulaR1C1 = _
        "=IF(RC[-28]=""LDN"",""UK"",IF(RC[-28]=""MAD"",""SPAIN"",IF(RC[-28]=""STO"",""SWEDEN"",IF(RC[-28]=""DUB"",""IRELAND"",IF(RC[-28]=""SAO"",""BRASIL"",IF(RC[-28]=""PAR"",""FRANCE"",IF(RC[-28]=""TOR"",""CANADA"",IF(RC[-28]=""TOK"",""JAPAN"",IF(RC[-28]=""ZUR"",""SWITZERLAND"",IF(RC[-28]=""HKG"",""HONG KONG"",IF(RC[-28]=""HEL"",""FINLAND"",IF(RC[-28]=""MIL"",""ITALY"",IF(R"& _
    ""FRA"",""GERMANY"",IF(RC[-28]=""COP"",""DANEMARK"",IF(RC[-28]=""BRU"",""BELGIUM"",IF(RC[-28]=""AMS"",""NETHERLANDS"",IF(RC[-28]=""SIN"",""SINGAPORE"",IF(RC[-28]=""SEO"",""SOUTH KOREA"",IF(RC[-28]=""OSL"",""NORWAY"",IF(RC[-28]=""LIS"",""PORTUGAL"",IF(RC[-28]=""NYK"",""USA"",IF(RC[-28]=""VIE"",""AUSTRIA"",IF(RC[-28]=""LUX"",""LUXEMBOURG"",IF(RC[-28]=""JOH"",""SOUTH AF"& _
    "(RC[-28]=""MEX"",""MEXICO"",IF(RC[-28]=""SYD"",""AUSTRALIA"",IF(RC[-28]=""TAI"",""TAIWAN"",IF(RC[-28]=""VAR"",""POLAND"",IF(RC[-28]=""BUD"",""HUNGARY"",IF(RC[-28]=""IST"",""TURKEY"",IF(RC[-28]=""BAN"",""INDIA"",IF(RC[-28]=""MOS"",""RUSSIA"",IF(RC[-28]=""TEL"",""ISRAEL"",IF(RC[-28]=""KUA"",""MALAYSIA"",IF(RC[-28]=""ATH"",""GREECE"",IF(RC[-28]     =""PRA"",""CZECH REPUBLIC"& _
    "))))))))))))))))))))))))))))))))))"
Range("AR2").Select
Selection.AutoFill Destination:=Range("AR2:AR" & i)

由于上面的代码没有用,我试图在vba中使用Loop但是我发现需要很长时间才能得到结果,因为我有近20k行.... 5min用excel公式处理即时结果的insteand : 我的循环代码在这里:

For j = 2 To i

If Range("P" & j) = "AMS" Then Range("AR" & j) = "NETHERLANDS"
If Range("P" & j) = "ATH" Then Range("AR" & j) = "GREECE"
If Range("P" & j) = "BAN" Then Range("AR" & j) = "INDIA"
If Range("P" & j) = "BRU" Then Range("AR" & j) = "BELGIUM"
If Range("P" & j) = "BUD" Then Range("AR" & j) = "HUNGARY"
If Range("P" & j) = "COP" Then Range("AR" & j) = "DANEMARK"
.
.
.
.
.

If Range("P" & j) = "VAR" Then Range("AR" & j) = "POLAND"
If Range("P" & j) = "VIE" Then Range("AR" & j) = "AUSTRIA"
If Range("P" & j) = "ZUR" Then Range("AR" & j) = "SWITZERLAND"


Next j

如果excel公式在VBA中不起作用,我怎样才能以高效快捷的方式编码,以便让国家获得至少20k行而无需等待并立即获得结果,例如excel公式自动填充模式。

非常感谢您的帮助 奥利弗

2 个答案:

答案 0 :(得分:4)

如果没有VBA,您可以轻松完成此操作,如下所示;但我还会进一步提供VBA解决方案。

首先,我会说,对您的查询数据进行硬编码(即直接在您的VBA程序中编写城市代码和国家/地区名称)是不好的做法。这使得人们现在很难阅读和检查它们,并且以后不方便更改它们。

在这个示例中,我将所有城市代码和国家/地区名称放在Excel工作表右侧的查找表中(但如果您愿意,可以将其放在其他隐藏工作表中)。然后,为了将A列中列出的城市代码与相应的国家/地区相匹配,我只需使用例如,查找表格中的城市代码即可。在单元格B2中:

=INDEX($F$4:$F$12,MATCH(A2,$E$4:$E$12,0))

将公式完全复制下来。

enter image description here

如果你真的想要VBA,你可以用这么短的代码获得完全相同的结果(在同一位置给出相同的输入和查找表):

Dim i As Long
Dim cityCodes
Dim countryNames
Dim listOfCountryNames
Dim listOfCityCodes

'Read look-up table from sheet.
listOfCityCodes = WorksheetFunction.Transpose(Range("E4:E12").Value)
listOfCountryNames = WorksheetFunction.Transpose(Range("F4:F12").Value)

'Read the input city codes from sheet to array
cityCodes = Range("A2:A9").Value
'Make a blank array of same size to receive the corresponding country names
ReDim countryNames(LBound(cityCodes, 1) To UBound(cityCodes, 1), _
    LBound(cityCodes, 2) To UBound(cityCodes, 2))

'Lookup individual country names one by one, write them in array
For i = LBound(cityCodes, 1) To UBound(cityCodes, 1)
    countryNames(i, 1) = listOfCountryNames( _
        WorksheetFunction.Match(cityCodes(i, 1), listOfCityCodes, 0))
Next i

'Write country names from array to sheet
Range("B2:B9").Value = countryNames

你会注意到我从工作表到数组一次读取所有内容,然后在这些数组中进行所有操作,最后写回到工作表。这比逐个执行单个单元中的读/写操作要快得多。

答案 1 :(得分:0)

好的,一些非常简单的建议:

Dim vals() As Variant
vals = Range("P1:P1000")  ' Substitute with the range you're looking at

Dim i As Integer
Dim val As String

For i = LBound(vals, 1) To UBound(vals, 1)
    val = CStr(vals(i, 1))

    Select Case val
        Case "AMS"
            Range("AR" & i + some_fixed_offset_if_needed) = "NETHERLANDS"
        Case "AR":
            ' .....
        ' Case .....
    End Select
Next i

首先,如果您经常访问范围的值,请不要每次都访问范围对象。这很慢。将其值保存到临时变量,然后访问该变量。 更好的是 - 保存您在数组变量中查看的整个范围,然后遍历该数组。

其次,如果案件是相互排斥的,不要只写大量的If语句 - 使用 如果... ElseIf ...

等。这样,如果已经找到匹配的条件,则不需要检查所有其他条件。在上面的代码中,我刚刚为此目的使用了一个select case语句。

检查是否加快了一点。它不是,您可以尝试将可能的短代码添加到Scripting.Dictionary作为键,并将替换(例如“NETHERLANDS”)作为值。字典查找速度非常快。

如果仍然比较慢,您可以随时使用WorksheetFormula.something来访问VBA中的工作表函数。