Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 使用循环使代码运行更快的替代方法_Excel_For Loop_Vba - Fatal编程技术网

Excel 使用循环使代码运行更快的替代方法

Excel 使用循环使代码运行更快的替代方法,excel,for-loop,vba,Excel,For Loop,Vba,我有两个问题,第一个是关于一个excel公式,我无法在VBA中复制该公式,即使我已使用记录宏检索该公式,第二个问题是因为我无法解决第一个问题,并且是关于代码效率: 基本上,在单元格AR2中,我输入了一个excel公式: IF=(P2="LDN";"UK;IF(P2="MAD";"SPAIN" IF(P2="PRA";"CZECH REPUBLIC";""))))))))) 我为很多国家做这件事 然后我在第二行,直到最后一行,用我的工作表上的数据,做autfill单元格目的地,以得到结果。 主要

我有两个问题,第一个是关于一个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中使用循环来完成它,但是我发现它需要花费很长时间才能得到结果,因为我有将近20k行。。。。用excel公式处理5分钟而不是即时结果: 我的循环代码如下:

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中不起作用,我如何以高效、快速的方式编写代码,以便获得至少20000行的国家/地区,而不必像excel公式自动填充模式那样等待并几乎立即获得结果

非常感谢你的帮助
Olivier

好的,有几个非常简单的建议:

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语句——使用 如果。。。 如果

这样,如果已经找到了匹配的条件,就不需要检查其他条件。在上面的代码中,我刚刚使用了一个selectcase语句

检查一下这是否会加快速度。如果没有,您可以尝试将可能的短代码作为键添加到Scripting.Dictionary中,并将替换项(例如“荷兰”)作为值添加到Scripting.Dictionary中。查字典的速度非常快


如果速度仍然较慢,您可以始终使用WorksheetFormula.something来访问VBA中的工作表函数。

您可以在没有VBA的情况下轻松完成此操作,如下所示;但我还将进一步给出VBA解决方案

不过,首先,我要说的是,硬编码查找数据(即直接在VBA程序中写入城市代码和国家名称)是一种糟糕的做法。这使得人们现在很难阅读和检查它们,而且以后更改它们也很不方便

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

=INDEX($F$4:$F$12,MATCH(A2,$E$4:$E$12,0))
把公式抄下来

如果您真的需要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

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

正是我要说的,这在短期内有效,但缺点是所有的城市代码和国家名称都是硬编码的@Jean-FrançoisCorbett我认为这种方法的真正缺点是迭代和代码行的数量。您好,我认为它仍然有点慢,因为它仍然在为下一个函数使用a。然而,我很想看看如何把字典当作钥匙?我该怎么办?抱歉,我是vbaI的新手,喜欢非vba方法:P++,不错,只是你可能想用这些20K行将计算转换为手动,或者复制粘贴作为值并替换原始值。如果他确实只想用excel公式解决这个问题,为什么不对该查找表使用VLOOKUP呢?这应该会得到同样的结果,甚至更简单,也可能会稍微快一点。@Bogey,因为索引和匹配的组合被证明工作更快。最近一些不成熟的人对我所有的有效答案投了否决票。(眼睛转动着。)我希望串行向下投票算法能抓住他们。