2013-10-08 4 views
5

Это странно ... Кто-то знает или может понять, почему это происходит?Странное поведение при назначении массива VBA формулам диапазона excel

В прошлом мне удалось присвоить массив формул диапазону Excel (Пример быстрого назначения:Range("A1:A1000") = ArrayOfFormulas). Он работал отлично и БЫСТРО (оченьБЫСТРО) по сравнению с назначения по ячейкам (Пример клеточной клетки:. Range("A" & i).Formula=ArrayOfFormula(i) внутри цикла медленный!).

Я работаю с Excel 2013 сейчас, и при попытке присвоить формулы, хранящиеся в массиве строк, в диапазон excel, он не работает (Эксел показывает формулировку, но не вычисляет как левую часть на картинке ниже), к сожалению, я не могу получить старый код для сравнения. Например, следующий код показывает «= 1 + 2» вместо «3» в диапазоне от A1 до A1000.

Sub AssignFormulas_1() 
    Dim i as Long 
    Dim FORML_ARRAY(1 To 1000, 1 To 1) As String 
    For i = 1 To 1000 
     FORML_ARRAY(i, 1) = "=1+2" 
    Next i 
    Range("A1:A1000").Formula = FORML_ARRAY '<- Don't work as formula 
              ' It put the value! 
End Sub 

Однако, когда я не использую массив формул работать нормально (все ячейки показывает, «3» вместо «= 1 + 2» в соответствии с правой части рисунка ниже). Вот код:

Sub AssignFormulas_2() 
    Dim i as Long 
    Dim FORML_SINGLE As String 
    FORML_SINGLE = "=1+2" 
    Range("A1:A1000").Formula = FORML_SINGLE '<- works ok, not practical for my 
              ' real life case as I need 
              ' different formula for each cell. 
End Sub 

Следующий код работы также хорошо (В данном случае я задаю формул по ячейкам, так является более гибким, но sloooowly для больших формул).

Sub AssignFormulas_3() 
    Dim i as Long 
    Dim FORML_ARRAY(1 To 1000, 1 To 1) As String 
    For i = 1 To 1000 
     FORML_ARRAY(i, 1) = "=1+2" 
     Range("A1:A" & i).Formula = FORML_ARRAY(i, 1) '<- works ok, but slowly 
    Next i 
End Sub 

Изображения с выходом всех выше кода:

Example of result wrong (left) and correct (right)


Примечание: Клетки правильно отформатированные как число, а не текст!

+0

Нет 2013, чтобы проверить, но я нашел [этот документ MSDN] (http://msdn.microsoft.com/en-us/library/ff837104.aspx), которые могут быть полезны. – Passerby

+0

@Passerby, спасибо, но FormulaArray() предназначен для чего-то другого. Он предназначен для работы с матрицами или массивами Excel, но не для массива VBA. Используя FormulaArray(), вы получите в своей ячейке формулу '{= Sum (A1: A3)}', а не '= Sum (A1: A3)'. –

+0

Из любопытства, Когда это когда-нибудь будет практичным? Ваше время тратится на заполнение массива формулой, чтобы написать формулы в диапазон, который затем должен быть рассчитан?!?! Почему бы не просто заполнить диапазон формулами? Или делать вычисления в массиве и заполнять диапазон вычислениями? Какую причину у вас есть для вас, не говоря о том, что он ошибается, просто пытаясь понять, почему. Просто кажется, что в то время, которое вы сделали бы, чтобы заполнить массив, который вы могли бы выполнять вычисление (быстрее, чем позволить вычислениям), ИЛИ чтобы вы могли полностью пропустить массив и просто добавить формулы напрямую. – user2140261

ответ

6

Ваш первый код должен работать.
Вместо объявления его как строки, объявите его как вариант.

Так изменить свою декларацию от этого:

Dim FORML_ARRAY(1 To 1000, 1 To 1) As String 

к этому:

Dim FORML_ARRAY(1 To 1000, 1 To 1) As Variant 

У меня нет никакой возможности пробовать его на Excel 2013, но он должен работать.
Надеюсь.

+1

+ 1 Когда массив объявлен как вариант, он будет работать :) –

+0

+1 Это работает в Excel 2013. Для соображений безопасности типа я предпочитаю использовать более узкий тип, который я планирую использовать. В этом случае строка является правильным типом для обработки формулы Excel. Мне не нравится, что VBA нажимает мой вариант использования, но я не думаю, что в этом случае нечего делать ... –

+0

@ L42, Спасибо! Очень странно, что функции # 2 и # 3 действительно работают, в этом случае объявление Variant не требуется (я все еще могу использовать объявление строки). Ты знаешь почему?? –

3

Интересный вопрос. Я никогда раньше не использовал эту функцию.

Ваш первый имеет тот же результат для меня в 2010 и 2013 годах - столбец, содержащий строку "=1+2". Я изменил FORML_ARRAY от строки до Variant и работает как и ожидалось.Для пущей я изменил формулу, чтобы включить i и он по-прежнему заполняет ряд с формулами:

Sub AssignFormulas_1() 
    Dim i As Long 
    Dim FORML_ARRAY(1 To 1000, 1 To 1) As Variant 'changed to Variant 
    For i = 1 To 1000 
     FORML_ARRAY(i, 1) = "=" & i & "+2" 'changed 1 to i - still works 
    Next i 
    Range("A1:A1000").Formula = FORML_ARRAY 
End Sub 
+0

+ 1 Когда массив объявлен как вариант, он будет работать :) –

+0

@Doug, Спасибо! Очень странно, что функции # 2 и # 3 действительно работают, в этом случае объявление Variant не требуется (я все еще могу использовать объявление String). Ты знаешь почему?? Как вы определяете решение для функции # 1 (prof и error)? Вы никогда не пробовали? Сделайте некоторые тесты производительности, это действительно заставляет ваш VBA-код летать, когда вам нужно работать с большим количеством ячеек! –

+1

Хотя я не заполнял формулы таким образом, я много сделал с диапазонами и массивами, и, основываясь на этом опыте, просто решил, что «Вариант» будет работать. Я тестировал его сначала в 2010 году, а затем в 2013 году, с теми же результатами для обоих. –

2

Просто, чтобы добавить еще один вариант, причина, как вы сказали, что вы предпочли бы затемнить ваш массив правильно, с этим вы можете, это добавляет 1/250-й секунды к OVERALL Sub (не за цикл), но позволит вам уменьшить ваш массив в виде строки.

Sub AssignFormulas_2() 
    Dim i As Long 

    Dim FORML_ARRAY(1 To 1000, 1 To 1) As String 

    For i = 1 To 1000 
     FORML_ARRAY(i, 1) = "= " & i & " + 2" 
    Next i 

    Range("A1:A1000").Formula = FORML_ARRAY '<- Don't work as formula 
              ' It put the value! 

    Range("A1:A1000").Value = Range("A1:A1000").Value 
End Sub 

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

Примечание: Этот ответ не предназначен, чтобы быть лучшим ответом, как принято отвечать, это медленнее, ответ и больше альтернативы; чтобы ответить на запрос, что вы хотите уменьшить размер строки.

UPDATE: Этот метод будет разделить разницу между принятым ответом и описанным выше способом. Это добавит только 1/500-й секунды к времени выполнения sub.

Sub AssignFormulas_Transpose() 
    Dim i As Long 

    Dim FORML_ARRAY(1 To 1000) As String 
    For i = 1 To 1000 
     FORML_ARRAY(i) = "= " & i & " + 2" 
    Next i 

    Range("A1:A1000").Formula = Application.Transpose(FORML_ARRAY) '<- Don't work as formula 
                    ' It put the value! 
End Sub 
+0

Спасибо, но TextToColumns ** не будет работать ** для всех случаев. Если текст формулы содержит «,» или «;», он может разбить формулу на ячейку справа, нарушая решение. Для меня это разрывает сделку. –

+0

Можете ли вы заменить свое решение и использовать «Range (« A1: A1000 »). Value = Range (« A1: A1000 »). Value' вместо TextToColumns? Это сделает трюк TextToColumns, не разбивайте формулу в любом случае, и я считаю, что это намного быстрее! –

+0

Обновлен ответ. Это намного быстрее, чем TextToColumns, я собирался предложить установить TextToColumns по ширине на максимальный размер ячейки, разделив без разделителя, но значение будет быстрее, а для записи это всего лишь 1/250th второго медленнее, чем использование альтернативного массива. – user2140261

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