2014-08-28 3 views
4

У меня есть 2 вопроса, первый из них касается формулы excel, которую я не могу реплицировать в VBA, хотя я использовал макрос записи для извлечения формулы, второй - потому что я не мог решить мой первый вопрос и об эффективности кода: основном в клетке П2 я кладу формулу первенствовать:Альтернатива использованию цикла для ускорения работы кода

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

им делать это для связки стран.

, а затем я выполняю назначение ячейки автозаполнения в своей второй строке до последней строки с данными на моем листе, чтобы получить результат. Основная проблема заключается в том, что в 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 строк .... 5мин до процесса 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 

Если первенствовать formulat не работает в VBA, как я могу код эффективным и быстрым способом, чтобы получить те страны, по крайней мере, 20k строк без необходимости ждать и получить результат почти мгновенно, как для режима автоматической заливки формулы excel.

Большое спасибо оптоволоконный ryour помощь Оливье

ответ

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 

Прежде всего, если вы получаете доступ значение в диапазоне очень часто не имеют доступа к объекту диапазона каждый раз. Это очень медленно. Сохраните его значение во временную переменную и получите доступ к этой переменной. И еще лучше - сохраните весь диапазон, который вы просматриваете в переменной массива, а затем пропустите этот массив.

Во-вторых, если случаи являются взаимоисключающими, не просто написать тонну Если заявления - использование Если ... ELSEIF ...

и т.д. Таким образом, это не нужно проверьте каждое другое условие, если оно уже найдено совпадающее. В приведенном выше коде я только что использовал для этого вариант утверждения для выбора.

Проверьте, скоро ли это ускорится. Это не так, вы можете попробовать добавить возможные короткие коды в Scripting.Dictionary как ключи и замены (например, «НИДЕРЛАНДЫ») в качестве значений. Словарь поиска очень быстрый.

И если это еще медленнее, вы всегда можете использовать WorksheetFormula.something для доступа к функциям листа в VBA.

+0

Точно, что я собирался положить вниз – Tom

+1

Это работает в краткосрочной перспективе, но недостатком является то, что все коды городов и названия стран жестко закодированы! –

+0

@ Jean-FrançoisCorbett Я считаю, что реальным недостатком такого подхода является количество итераций и строк кода. – 2014-08-28 11:07:46

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

Мне нравится подход non vba: P –

+0

++, неплохо, за исключением того, что вы можете переключить свой расчет на руководство с этими 20K строк или скопировать-вставить в качестве значений и заменить оригинал. – 2014-08-28 10:56:43

+1

Если он хочет решить это только с помощью формул excel - почему бы просто не использовать VLOOKUP для этой таблицы поиска? Это должно привести к тому же результату еще проще и, возможно, будет немного быстрее. – Bogey

Смежные вопросы