Excel сложные формулы vba

На чтение 4 мин. Просмотров 33.1k.

Итог: ознакомьтесь с 3 советами по написанию и созданию формул в макросах VBA с помощью этой статьи и видео.

Уровень мастерства: Средний

Автоматизировать написание формул

Написание формул может быть одной из самых трудоемких частей
вашей еженедельной или ежемесячной задачи Excel. Если вы работаете над
автоматизацией этого процесса с помощью макроса, вы можете попросить VBA
написать формулу и ввести ее в ячейки.

Поначалу написание формул в VBA может быть немного сложнее,
поэтому вот три совета, которые помогут сэкономить время и упростить процесс.

Совет № 1: Свойство Formula

Свойство Formula является членом объекта Range в VBA. Мы можем использовать его для установки / создания формулы для отдельной ячейки или диапазона ячеек.

Есть несколько требований к значению формулы, которые мы устанавливаем с помощью свойства Formula:

  1. Формула представляет собой строку текста, заключенную в кавычки. Значение формулы должно начинаться и заканчиваться кавычками.
  2. Строка формулы должна начинаться со знака равенства = после первой кавычки.

Вот простой пример формулы в макросе.

Sub Formula_Property()

  ' Формула представляет собой строку текста, заключенную в кавычки
  ' Начинается со знака =
  Range("B10").Formula = "=SUM(B4:B9)"

End Sub

Свойство Formula также можно использовать для чтения существующей формулы в ячейке.

Совет № 2: Используйте Macro Recorder

Если ваши формулы более сложные или содержат специальные
символы, их будет сложнее написать в VBA. К счастью, мы можем использовать
рекордер макросов, чтобы создать код для нас.

Create Formula VBA code with the Macro Recorder

Вот шаги по созданию кода свойства формулы с помощью средства записи макросов.

  1. Включите средство записи макросов (вкладка «Разработчик»> «Запись макроса»)
  2. Введите формулу или отредактируйте существующую формулу.
  3. Нажмите Enter, чтобы ввести формулу.
  4. Код создается в макросе.

Если ваша формула содержит кавычки или символы амперсанда, макрос записи будет учитывать это. Он создает все подстроки и правильно упаковывает все в кавычки. Вот пример.

Sub Macro10()
' Используйте средство записи макросов для создания кода для сложных формул с
' специальны символы и относительные ссылки

  ActiveCell.FormulaR1C1 = "=""Total Sales: "" & TEXT(R[-5]C,""$#,###"")"
    
End Sub

Совет № 3: Нотация формулы стиля R1C1

Если вы используете средство записи макросов для формул, вы
заметите, что он создает код со свойством FormulaR1C1.

Нотация стиля R1C1 позволяет нам создавать как относительные (A1), абсолютные ($A$1), так и смешанные ($A1, A$1) ссылки в нашем макрокоде.

R1C1 обозначает строки и столбцы.

Относительные ссылки

Для относительных ссылок мы указываем количество строк и
столбцов, которые мы хотим сместить от ячейки, в которой находится формула.
Количество строк и столбцов указывается в квадратных скобках.

Следующее создаст ссылку на ячейку, которая на 3 строки выше
и на 2 строки справа от ячейки, содержащей формулу.

Отрицательные числа идут вверх по строкам и столбцам слева.

Положительные числа идут вниз по строкам и столбцам справа.

Абсолютные ссылки

Мы также можем использовать нотацию R1C1 для абсолютных ссылок. Обычно это выглядит как $A$2.

Для абсолютных ссылок мы НЕ используем квадратные скобки. Следующее создаст прямую ссылку на ячейку $A$2, строка 2, столбец 1

При создании смешанных ссылок относительный номер строки или
столбца будет зависеть от того, в какой ячейке находится формула.

Проще всего использовать макро-рекордер, чтобы понять это.

Свойство FormulaR1C1 и свойство формулы

Свойство FormulaR1C1 считывает нотацию R1C1 и создает
правильные ссылки в ячейках. Если вы используете обычное свойство Formula с
нотацией R1C1, то VBA попытается вставить эти буквы в формулу, что, вероятно,
приведет к ошибке формулы.

Поэтому используйте свойство Formula, если ваш код содержит
ссылки на ячейки ($ A $ 1), свойство FormulaR1C1, когда вам нужны относительные
ссылки, которые применяются к нескольким ячейкам или зависят от того, где
введена формула.

Если ваша электронная таблица изменяется в зависимости от
условий вне вашего контроля, таких как новые столбцы или строки данных,
импортируемые из источника данных, то относительные ссылки и нотация стиля
R1C1, вероятно, будут наилучшими.

Я надеюсь, что эти советы помогут. Пожалуйста, оставьте
комментарий ниже с вопросами или предложениями.

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

#1

11.11.2017 04:17:55

Здравствуйте! Попытаюсь максимально подробно объяснить чего хочу, т.к. нет возможности вставить пример.
Есть динамическая таблица на листе, в которой закрашиваются ячейки в зависимости от выбранного имени таблицы (закраска ячеек происходит при выборе имени таблицы). Имена таблиц вместе со значениями, указывающими какую ячейку выбранной таблицы в какой цвет залить хранятся в базе на другом листе. Есть ячейки, в которых выводится процент ячеек, залитых определенным цветом. Вначале я создал массив на отдельном листе , в  нем получилось много ячеек с длинными формулами, и общий результат вычислений в этом массиве выводился в ячейки на листе вместе с таблицей. Вот пример формулы одной из ячеек массива с множеством условий:

Скрытый текст

Для увеличения скорости обработки данных  решил перенести все вычисления в vba, а только в ячейки выводить общий результат.
Создал функцию в vba, в которую попытался запихнуть такую длинную формулу:

Код
Option explicit
Function Test()
Test=Evaluate("="длинная формула в англ. варианте"")
End Function 

Не получилось, думаю из-за того, что в скобках стоит ограничение на 255 символов.
Подскажите метод чтобы можно было впихнуть всю формулу не разбивая ее на множество функций. Заранее благодарен.

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

#2

11.11.2017 06:59:02

Разделил формулу на несколько коротких функций, и когда пытаюсь вызвать одну функцию из другой, вместо значения получаю «Error 2015» (Stack Overflow).
Вот пример вызываемой функции:

Код
Function L1B1Pos()
L1B1Pos = Evaluate("=MyPos()&"".""&NLHE.FR!C8&"".""&NLHE.FR!F2&"".""&LST2Pos()&"".""&LST3Pos()&"".""&SSPos()")
End Function

А в этой функции я ее вызываю и получаю ошибку:

Код
Function L1T()
L1T = Evaluate("=IF(NLHE.FR!C1=1,L1B1Pos())")
End Function

По отдельности вызываемая функция нормально работает, и вызывающая тоже, если вместо «L1B1Pos()» подставить другую функцию с более коротким выражением.

Изменено: OSA91311.11.2017 07:06:19

 

Лучше бы файл приложили с примером.
А так — …
1. можно посоветовать посмотреть в сторону объекта Application.WorksheetFunction
2. Ваша задача скорее всего имеет более лаконичное решение, чем конструкция со вложенными ЕСЛИ().

Прикрепленные файлы

  • Книга1.xlsm (13.89 КБ)

Изменено: Михаил Лебедев11.11.2017 07:29:46

Всё сложное — не нужно. Всё нужное — просто /М. Т. Калашников/

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

Спасибо, попробую убрать функцию «ЕСЛИ» в формулах.

 

Казанский

Пользователь

Сообщений: 8839
Регистрация: 11.01.2013

#5

11.11.2017 14:10:07

OSA913, если рассмотреть первый фрагмент формулы, добавив перенос строки (Alt+Enter внутри ячейки)

Код
=ЕСЛИ(NLHE.FR!$C$1=1;
ЕСЛИ(NLHE.FR!$B$1=1;NLHE.FR!$B$8;
ЕСЛИ(NLHE.FR!$B$1=2;NLHE.FR!$B$9;
ЕСЛИ(NLHE.FR!$B$1=3;NLHE.FR!$B$10;
ЕСЛИ(NLHE.FR!$B$1=4;NLHE.FR!$B$11;
ЕСЛИ(NLHE.FR!$B$1=5;NLHE.FR!$B$12;
ЕСЛИ(NLHE.FR!$B$1=6;NLHE.FR!$B$13;
ЕСЛИ(NLHE.FR!$B$1=7;NLHE.FR!$B$14;
ЕСЛИ(NLHE.FR!$B$1=8;NLHE.FR!$B$15)))))))))

, то видно, что фрагмент можно упростить:

Код
=ЕСЛИ(NLHE.FR!$C$1=1;ИНДЕКС(NLHE.FR!$B$8:$B$15;NLHE.FR!B1))

Видимо, и дальше так же.

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

#6

12.11.2017 00:26:20

Спасибо, можно ли как нибудь сократить формулу такого плана?

Код
=ЕСЛИОШИБКА(ЕСЛИ(NLHE.FR!$C$1=1;
ЕСЛИ(ИЛИ(ИНДЕКС(BASE!B:B;ПОИСКПОЗ(NLHE.FR!$C$6&"|"&$K$1;BASE!$A:$A;0))=
{"13995347|13995347";"12611584|12611584";"13020235|13020235";"13995347|12611584";"12611584|13995347";"13995347|13020235";"13020235|13995347";"12611584|13020235";"13020235|12611584"});6;
ЕСЛИ(И(ИЛИ(ИНДЕКС(BASE!B:B;ПОИСКПОЗ(NLHE.FR!$C$6&"|"&$K$1;BASE!$A:$A;0))<>
{"13995347|13995347";"12611584|12611584";"13020235|13020235";"13995347|12611584";"12611584|13995347";"13995347|13020235";"13020235|13995347";"12611584|13020235";"13020235|12611584"});
ЕСЛИ(НЕ(И(ЕОШ(НАЙТИ({"13995347";"12611584";"13020235"};
ИНДЕКС(BASE!B:B;ПОИСКПОЗ(NLHE.FR!$C$6&"|"&$K$1;BASE!$A:$A;0))))));3));3));
ЕСЛИ(NLHE.FR!$C$1>1;
ЕСЛИ(ИНДЕКС(BASE!B:B;ПОИСКПОЗ(NLHE.FR!$C$6&"|"&$K$43;BASE!$A:$A;0))="5296274|5296274";6;
ЕСЛИ(И(ИНДЕКС(BASE!B:B;ПОИСКПОЗ(NLHE.FR!$C$6&"|"&$K$43;BASE!$A:$A;0))<>"5296274|5296274";
ЕСЛИ(НАЙТИ("5296274";ИНДЕКС(BASE!B:B;ПОИСКПОЗ(NLHE.FR!$C$6&"|"&$K$43;BASE!$A:$A;0)));3));3));
ЕСЛИ(И(NLHE.FR!$B$1<>9;NLHE.FR!$D$1>=1);ЕСЛИ(ИНДЕКС(BASE!B:B;ПОИСКПОЗ(NLHE.FR!$C$6&"|"&$K$85;BASE!$A:$A;0))="5296274|5296274";6;
ЕСЛИ(И(ИНДЕКС(BASE!B:B;ПОИСКПОЗ(NLHE.FR!$C$6&"|"&$K$85;BASE!$A:$A;0))<>"5296274|5296274";
ЕСЛИ(НАЙТИ("5296274";ИНДЕКС(BASE!B:B;ПОИСКПОЗ(NLHE.FR!$C$6&"|"&$K$85;BASE!$A:$A;0)));3));3));"")));"")

Изменено: OSA91312.11.2017 10:38:59

 

Можно, наверно. Если файл-пример приложете.

Всё сложное — не нужно. Всё нужное — просто /М. Т. Калашников/

 

Sanja

Пользователь

Сообщений: 14838
Регистрация: 10.01.2013

#8

13.11.2017 09:49:21

Цитата
OSA913 написал: сократить формулу такого плана

От формул ТАКОГО плана нужно совсем отказываться, тем более, что макросы применяете.
Но без файла-примера, увы…

Согласие есть продукт при полном непротивлении сторон.

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

В ячейке Е8 формула, которая проверяет в базе в первом столбце текущее имя таблицы. Если находит проверяет ячейку в строке соответствующую ячейке в таблице на наличие значений которые указаны в формуле, и в зависимости от значений возвращает в ячейку либо 3 либо 6 либо «». Имя таблицы берется из функции «L1_T()» .
Помогите эту формулу превратить в функцию vba.

 

Sanja

Пользователь

Сообщений: 14838
Регистрация: 10.01.2013

#10

13.11.2017 16:59:32

Цитата
OSA913 написал: и в зависимости от значений возвращает…

Каковы эти зависимости? Почему сейчас в целевой ячейке 6, а не 3?

Цитата
OSA913 написал: проверяет в базе в первом столбце текущее имя таблицы

Т.е. в этом первом столбце возможно несколько имен таблиц? Имя листа всегда совпадает с именем таблицы? Нужно ли оно вообще?

Согласие есть продукт при полном непротивлении сторон.

 

Крутая формула, OSA913 :)
Вы уверены, что она у Вас правильно считает? /Если уверены, тогда можно смело браться за ее оптимизацию.
Лично я — не уверен. Например, вот этот кусок формулы
…ИЛИ(ИНДЕКС(BASE!B:B;ПОИСКПОЗ($C$6&»|»&L1_T();BASE!$A:$A;0))<>
{«13995347|13995347″;»12611584|12611584″;»13020235|13020235″;»13995347|12611584″;»12611584|13995347″;»13995347|13020235″;»13020235|13995347″;»12611584|13020235″;»13020235|12611584»})
— всегда будет возвращать ИСТИНА, т.к. ПОИСКПОЗ() возвращает всего одно значение, которое сравнивается с несколькими разными значениями (теми, что в фигурных скобках). И если это значение не будет равно хотя бы одному из тех, что в фигурных скобках, функция ИЛИ() вернет ИСТИНА. А то, что ОДНО значение не может одновременно равняться нескольким РАЗНЫМ значениям — ОЧЕВИДНО.
Значит кусок вашего уравнения можно смело заменить на просто ИСТИНА.

А зачем в формуле ссылки на ячейки К43 и К85? Они же — пустые!

Такое ощущение, что Вы просто всем голову морочите :) Я угадал? Не надеюсь, что это не может быть не так, так как Вы не пытаетесь не думать.

PS

Вот это
ЕСЛИ(ИЛИ(ИНДЕКС(BASE!B:B;ПОИСКПОЗ($D$6;BASE!$A:$A;0))=
{«13995347|13995347″;»12611584|12611584″;»13020235|13020235″;»13995347|12611584″;»12611584|13995347″;»13995347|13020235″;»13020235|13995347″;»12611584|13020235″;»13020235|12611584»});[длиннющий набор функций];6)

можно смело заменить на вот это
ЕСЛИ(ЕНД(ПОИСКПОЗ($D$6;BASE!$A:$A;0));6;[длиннющий набор функций])

, где в D6 стоит =C6&»|»&L1_T()

Изменено: Михаил Лебедев13.11.2017 18:36:32

Всё сложное — не нужно. Всё нужное — просто /М. Т. Калашников/

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

#12

13.11.2017 18:09:27

Цитата
Sanja написал:
Каковы эти зависимости? Почему сейчас в целевой ячейке 6, а не 3?

Значения эти идентичны коду цвета, делятся вертикальной чертой т.к. есть возможность заливки ячейки двумя цветами с градиентом, если код по обе стороны черты одинаковый, тогда ячейка заливается одним цветом.   При первом условии (С1=1) если в ячейке 2 кода 3х первых оттенков синих цветов

Скриншот

, тогда ячейка принимает значение равное 6, если содержиться только один цвет синего оттенка, тогда =3, если нет такого цвета, тогда «».

Цитата
Sanja написал:
Т.е. в этом первом столбце возможно несколько имен таблиц? Имя листа всегда совпадает с именем таблицы? Нужно ли оно вообще?

Да это база в которой хранятся имена таблиц и она пополняется. Имя листа нужно, потому что есть другие таблицы на других листах, а базу у них одна.
П.С: Конкретно для ячейки в приложенном примере в базе проверяется ячейка столбца В.

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

#13

13.11.2017 18:25:31

Цитата
Михаил Лебедев написал:
Лично я — не уверен. Например, вот этот кусок формулы
…ИЛИ(ИНДЕКС(BASE!B:B;ПОИСКПОЗ($C$6&»|»&L1_T();BASE!$A:$A;0))<>
{«13995347|13995347″;»12611584|12611584″;»13020235|13020235″;»13995347|12611584″;»12611584|13995347″;»13995347|13020235″;»13020235|13995347″;»12611584|13020235″;»13020235|12611584»})
— всегда будет возвращать ИСТИНА, т.к. ПОИСКПОЗ() возвращает всего одно значение, которое сравнивается с несколькими разными значениями (теми, что в фигурных скобках). И если это значение не будет равно хотя бы одному из тех, что в фигурных скобках, функция ИЛИ() вернет ИСТИНА. А то, что ОДНО значение не может одновременно равняться нескольким РАЗНЫМ значениям — ОЧЕВИДНО.
Значит кусок вашего уравнения можно смело заменить на просто ИСТИНА.

Проверял считало вроде правильно, это условие-если ячейка не содержит не одной из комбинаций в которых присутствует два из трех оттенков синего цвета. Возможно ее можно как то упростить..

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

#14

13.11.2017 18:28:27

Цитата
Михаил Лебедев написал:
А зачем в формуле ссылки на ячейки К43 и К85? Они же — пустые!

Это были ссылки на ячейки с формулами. Я забыл заменить их ссылкой на функцию. Сейчас поправлю.

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

 

Михаил Лебедев

Пользователь

Сообщений: 2855
Регистрация: 17.01.2013

#16

13.11.2017 18:39:43

Цитата
OSA913 написал:
Сейчас поправлю.

Я откорректировал свое предыдущее сообщение, добавил вопросы (не ожидал, что Вы так быстро отзовётесь :) )

Всё сложное — не нужно. Всё нужное — просто /М. Т. Калашников/

 

Михаил Лебедев

Пользователь

Сообщений: 2855
Регистрация: 17.01.2013

#17

13.11.2017 18:46:16

Цитата
OSA913 написал:
Проверял считало вроде правильно

Ответьте себе на вопросы:
1. Сколько аргументов возвращает =ПОИСКПОЗ() ?

Всё сложное — не нужно. Всё нужное — просто /М. Т. Калашников/

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

Вставил в пример еще одну таблицу, при выборе которой в ячейке становится значение равное 3. Для этого в ячейке С1 нужно поменять 1 на 2.

 

Михаил Лебедев

Пользователь

Сообщений: 2855
Регистрация: 17.01.2013

#19

13.11.2017 18:58:07

Цитата
OSA913 написал:
Исправил

Нет, не исправили. Чему равно К85 ?

Изменено: Михаил Лебедев13.11.2017 19:14:44

Всё сложное — не нужно. Всё нужное — просто /М. Т. Калашников/

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

На счет последнего аргумента ПОИСКПОЗ не уверен нужен ли он. В D6 не получится поставить функцию т.к. этих функций 9 штук , и будет 9 ячеек с разными результатами вычислений. K85 поправил.

 

Михаил Лебедев

Пользователь

Сообщений: 2855
Регистрация: 17.01.2013

#21

14.11.2017 08:45:19

Цитата
OSA913 написал:
В D6 не получится поставить функцию т.к. этих функций 9 штук , и будет 9 ячеек с разными результатами вычислений.

??? Диаметр окружности примерно равен 2-м радиусам, поскольку число ПИ() — бесконечно.

Всё сложное — не нужно. Всё нужное — просто /М. Т. Калашников/

 

Михаил Лебедев

Пользователь

Сообщений: 2855
Регистрация: 17.01.2013

#22

14.11.2017 11:10:17

Цитата
OSA913 написал:
При первом условии (С1=1) если в ячейке 2 кода 3х первых оттенков синих цветов…, тогда ячейка принимает значение равное 6, если содержится только один цвет синего оттенка, тогда =3, если нет такого цвета, тогда «».

Вот — как Вы и написали. Что должно происходить при других значениях С1 ?

Прикрепленные файлы

  • Файл пример NEW.xlsm (20.93 КБ)

Всё сложное — не нужно. Всё нужное — просто /М. Т. Калашников/

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

Здравствуйте! При С1>1, если ячейка в базе содержит 2 кода зеленого цвета, тогда значение равно 6, если ячейка в базе содержит только 1 код зеленого, тогда значение равно 3. И 3е условие, когда B1 не равно 9 и D1 не равно 0- получилось точно таким же как и второе. Я когда объединял  3 формулы в одну пропустил этот момент. тогда по логике его можно добавить ко второму условию и формула станет еще меньше.

 

Вы мой пример посмотрели? То, что надо? Попробуйте то же самое сделать для «кода зеленого цвета» сами. Если моя формула — это то, что надо, я могу показать, как ее перенести в VBA. Но это уже завтра, скорее всего.

Всё сложное — не нужно. Всё нужное — просто /М. Т. Калашников/

 

Михаил Лебедев

Пользователь

Сообщений: 2855
Регистрация: 17.01.2013

#25

14.11.2017 13:17:45

Цитата
OSA913 написал:
И 3е условие, когда B1 не равно 9 и D1 не равно 0- получилось точно таким же как и второе

Вот это — непонятно.

Всё сложное — не нужно. Всё нужное — просто /М. Т. Калашников/

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

#26

14.11.2017 13:43:14

Да, Спасибо большое, то что нужно, и хотелось бы ее перенести в код. Единственное, если так возможно  

Код
=$C$6&"|"&L1_T()

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

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

#27

14.11.2017 13:49:52

Цитата
Михаил Лебедев написал:
Вот это — непонятно.

При B1=9 и D1<>0 , если в таблице встретятся ячейки с зеленым цветом нужно чтобы его не подсчитывало.

Изменено: OSA91314.11.2017 13:53:00

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

Ссылку на функцию в формуле теперь увидел, с этим порядок. Нашел несоответствие- поставил в базе синий вместе с голубым, а в ячейке 3 вместо 6. Любое сочетание двух синих оттенков в ячейке должно давать 6. И поставил голубой в сочетании вместе с белым — показывает 6, а надо 3. Извините что не сразу проверил, но все равно Спасибо что помогаете)

 

Михаил Лебедев

Пользователь

Сообщений: 2855
Регистрация: 17.01.2013

#29

15.11.2017 05:02:34

Цитата
OSA913 написал:
…если в ячейке 2 кода 3х первых оттенков синих цветов…
…Любое сочетание двух синих оттенков в ячейке должно давать 6…

ОК.

Прикрепленные файлы

  • Файл пример NEW.xlsm (20.06 КБ)

Изменено: Михаил Лебедев15.11.2017 05:21:52

Всё сложное — не нужно. Всё нужное — просто /М. Т. Калашников/

 

OSA913

Пользователь

Сообщений: 248
Регистрация: 03.01.2016

#30

15.11.2017 05:36:34

Ну да  12611584|12611584 должно быть 6. Так же 13995347|12611584 или 13995347|13020235 должно быть 6. Т.е. Любая комбинация двух цветов с синим оттенком(их всего три: светло-синий, синий и голубой). А комбинация какого нибудь одного из этих 3х синих цветов с каким нибудь другим цветом (не синего оттенка)- это 3. Иначе- «».

Вставка сложных формул в макрос

alex808

Дата: Понедельник, 29.08.2016, 15:23 |
Сообщение № 1

Группа: Пользователи

Ранг: Новичок

Сообщений: 47


Репутация:

0

±

Замечаний:
0% ±


Excel 2007

Добрый день, подскажите пожалуйста. Встал вопрос о вставке макросом формул исходя из количества аргументов… Написал вот такой код..При этом первые три формулы встают, а четвертая по (Х), что длинная ругается. Может кто видит ошибку?
[vba]

Код

Sub Макрос11()

Sheets(«пересчет»).Range(«U2:U» & Cells(Rows.Count, 6).End(xlUp).Row).FormulaR1C1 = «=RC[-2]-RC[+11]-RC[+14]»

Sheets(«пересчет»).Range(«V2:V» & Cells(Rows.Count, 6).End(xlUp).Row).FormulaR1C1 = «=RC[-3]»

Sheets(«пересчет»).Range(«W2:W» & Cells(Rows.Count, 6).End(xlUp).Row).FormulaR1C1 = «=RC[-5]*RC[-1]/100»

Sheets(«пересчет»).Range(«X2:X» & Cells(Rows.Count, 6).End(xlUp).Row).FormulaR1C1 = «=IF(RC[+44]=»»менеджерская «»,IF(AND(ISNUMBER(IF(ISNUMBER(VLOOKUP((ROUNDDOWN(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!R8C3:R8C9,0),FALSE)),VLOOKUP((ROUNDDOWN(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[+44]),матрица!R8C3:R8C9,0),FALSE),»»нет нижней КВ»»)),ISNUMBER((IF(ISNUMBER(VLOOKUP((ROUNDUP(RC[-3],0)),матрица!R10C3:» & _
        «ATCH(CONCATENATE(RC[-20],RC[+44]),матрица!R8C3:R8C9,0),FALSE)),VLOOKUP((ROUNDUP(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!R8C3:R8C9,0),FALSE),»»нет нижней КВ»»)))),VLOOKUP(ROUNDDOWN(RC[-3],0),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[+44]),матрица!R8C3:R8C9,0),FALSE)+(RC[-3]-(ROUNDDOWN(RC[-3],0)))*(VLOOKUP((ROUNDUP(RC[-3],0)),ма» & _
        «C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[+44]),матрица!R8C3:R8C9,0),FALSE)-VLOOKUP((ROUNDDOWN(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[+44]),матрица!R8C3:R8C9,0),FALSE)),»»нет данных для расчета»»),IF(RC[+44]=»»агентская «»,IF(AND(ISNUMBER(IF(ISNUMBER(VLOOKUP((ROUNDDOWN(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[+44]),матрица!R8C3:R8C» & _
        «E)),VLOOKUP((ROUNDDOWN(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[+44]),матрица!R8C3:R8C9,0),FALSE),»»нет нижней КВ»»)),ISNUMBER((IF(ISNUMBER(VLOOKUP((ROUNDUP(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[+44]),матрица!R8C3:R8C9,0),FALSE)),VLOOKUP((ROUNDUP(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[+44]),матрица!R8C3:R» & _
        «LSE),»»нет нижней КВ»»)))),VLOOKUP(ROUNDDOWN(RC[-3],0),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[+44]),матрица!R8C3:R8C9,0),FALSE)+(RC[-3]-(ROUNDDOWN(RC[-3],0)))*(VLOOKUP((ROUNDUP(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[+44]),матрица!R8C3:R8C9,0),FALSE)-VLOOKUP((ROUNDDOWN(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[+44]),ма» & _
        «3:R8C9,0),FALSE)),»»нет данных для расчета»»),0))»

End Sub

[/vba]
сама формула выглядет так:

Код

=ЕСЛИ(RC[44]=»менеджерская «;ЕСЛИ(И(ЕЧИСЛО(ЕСЛИ(ЕЧИСЛО(ВПР((ОКРУГЛВНИЗ(RC[-3];0));матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ));ВПР((ОКРУГЛВНИЗ(RC[-3];0));матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ);»нет нижней КВ»));ЕЧИСЛО((ЕСЛИ(ЕЧИСЛО(ВПР((ОКРУГЛВВЕРХ(RC[-3];0));матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ));ВПР((ОКРУГЛВВЕРХ(RC[-3];0));матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ);»нет нижней КВ»))));ВПР(ОКРУГЛВНИЗ(RC[-3];0);матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ)+(RC[-3]-(ОКРУГЛВНИЗ(RC[-3];0)))*(ВПР((ОКРУГЛВВЕРХ(RC[-3];0));матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ)-ВПР((ОКРУГЛВНИЗ(RC[-3];0));матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ));»нет данных для расчета»);ЕСЛИ(RC[44]=»агентская «;ЕСЛИ(И(ЕЧИСЛО(ЕСЛИ(ЕЧИСЛО(ВПР((ОКРУГЛВНИЗ(RC[-3];0));матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ));ВПР((ОКРУГЛВНИЗ(RC[-3];0));матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ);»нет нижней КВ»));ЕЧИСЛО((ЕСЛИ(ЕЧИСЛО(ВПР((ОКРУГЛВВЕРХ(RC[-3];0));матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ));ВПР((ОКРУГЛВВЕРХ(RC[-3];0));матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ);»нет нижней КВ»))));ВПР(ОКРУГЛВНИЗ(RC[-3];0);матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ)+(RC[-3]-(ОКРУГЛВНИЗ(RC[-3];0)))*(ВПР((ОКРУГЛВВЕРХ(RC[-3];0));матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ)-ВПР((ОКРУГЛВНИЗ(RC[-3];0));матрица!R10C3:R109C9;ПОИСКПОЗ(СЦЕПИТЬ(RC[-20];RC[44]);матрица!R8C3:R8C9;0);ЛОЖЬ));»нет данных для расчета»);0))

Сообщение отредактировал alex808Понедельник, 29.08.2016, 15:51

 

Ответить

sboy

Дата: Понедельник, 29.08.2016, 16:01 |
Сообщение № 2

Группа: Друзья

Ранг: Участник клуба

Сообщений: 2566


Репутация:

724

±

Замечаний:
0% ±


Excel 2010

Добрый день.
Посмотрите в переносах строки

матрица!R10C3:» & _
        «ATCH

матрица!R8C3:R8C» & _
        «E))

матрица!R8C3:R» & _
        «LSE)


Яндекс: 410016850021169

 

Ответить

sboy

Дата: Понедельник, 29.08.2016, 16:03 |
Сообщение № 3

Группа: Друзья

Ранг: Участник клуба

Сообщений: 2566


Репутация:

724

±

Замечаний:
0% ±


Excel 2010

Формула конечно зверь)
Если решили применять VBA, может имеет смысл расчеты перенести, чтоб не нагружать файл такими монстрами?


Яндекс: 410016850021169

 

Ответить

alex808

Дата: Понедельник, 29.08.2016, 16:20 |
Сообщение № 4

Группа: Пользователи

Ранг: Новичок

Сообщений: 47


Репутация:

0

±

Замечаний:
0% ±


Excel 2007

Посмотрите в переносах строки

Спасибо, я в экселе и тем более в VBA профан…Я сначала записал формулу в ячейку через рекодер, а потом просто скопировал получившийся вид… Вы хотите сказать, что при переносе в коду формула была деформирована и ее нужно восстановить? Я признаться, ничего про это не знаю. Что характерно, то что при записи макрос отрабатывает и подтягивает правильное значение, а при повторном нажатии уже ругается.

Формула конечно зверь)
Если решили применять VBA, может имеет смысл расчеты перенести, чтоб не нагружать файл такими монстрами?

Я понимаю, что такая тяжелая формула затормозит расчет, но моя цель вставить ее строк на 50-100, ибо расчеты нужны для формирования понимания работы расчетов по базе для формирования ТЗ. Я даже пытался дать задание специалисту, но практически сразу понял, что на его конкретные вопросы мне ответить будет нечего, вот и решил хотя бы усеченно «прожить» формирование базы хотя бы в усеченной форме

 

Ответить

sboy

Дата: Понедельник, 29.08.2016, 16:30 |
Сообщение № 5

Группа: Друзья

Ранг: Участник клуба

Сообщений: 2566


Репутация:

724

±

Замечаний:
0% ±


Excel 2010

Вы хотите сказать, что при переносе в коду формула была деформирована и ее нужно восстановить

Или да, или деформировалась при копировании сюда на форум.
Можно попробовать заменить в макросе все FormulaR1C1 на FormulaLocal. И Формулы скопируйте как есть (по-русски) не через запись рекодером.


Яндекс: 410016850021169

 

Ответить

Udik

Дата: Понедельник, 29.08.2016, 16:37 |
Сообщение № 6

Группа: Друзья

Ранг: Старожил

Сообщений: 1588


Репутация:

192

±

Замечаний:
0% ±


Excel 2016 х 64

Разбираться с этим монстром нет желания, но при любом разделении строки должно стоять & _ А у Вас, то просто обрыв
[vba]

Код

IF(RC[+44]=»»агентская
«»

[/vba]
то тире
[vba][/vba]
Может это только на сайте так, тогда нужен файл


вот вам барабан
яд 41001231307558 wm R419131876897
udik1968@gmail.com

 

Ответить

alex808

Дата: Понедельник, 29.08.2016, 16:40 |
Сообщение № 7

Группа: Пользователи

Ранг: Новичок

Сообщений: 47


Репутация:

0

±

Замечаний:
0% ±


Excel 2007

Разбираться с этим монстром нет желания, но при любом разделении строки должно стоять & _ А у Вас, то просто обрыв

Спасибо буду разбираться….не смогу урежу файл и выложу

 

Ответить

Gustav

Дата: Понедельник, 29.08.2016, 16:47 |
Сообщение № 8

Группа: Друзья

Ранг: Старожил

Сообщений: 2398


Репутация:

985

±

Замечаний:
0% ±


начинал с Excel 4.0, видел 2.1

Есть мнение, что деформация произошла при записи макрорекордером. Как-то он подозрительно (примерно так же) порезал у меня на строчки со съеданием нескольких концевых символов — видимо, подошёл к собственному пределу, но как-то корявенько…

Я попробовал другой путь — скопировал текст формулы на английском языке в OneNote, там подвигал границы и подобрал приемлемый размер текстового фрейма. В местах визуальных концов строки принудительно нажал Enter. Далее взял полученный текст в Блокнот, удвоил внутри текста все двойные кавычки при помощи «Найти и заменить». Затем добавил по двойной кавычке в конец каждой строки и в начало каждой строки вставил фрагмент: vb = vb & «. Получился следующий код для создания формулы:

[vba]

Код

Sub insertBigFormula()
    Dim vb As String

            vb = vb & «=IF(RC[44]=»»менеджерская «»,IF(AND(ISNUMBER(IF(ISNUMBER(VLOOKUP((ROUNDDOWN(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!»
    vb = vb & «R8C3:R8C9,0),FALSE)),VLOOKUP((ROUNDDOWN(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!R8C3:R8C9,0),FALSE),»»нет нижней «
    vb = vb & «КВ»»)),ISNUMBER((IF(ISNUMBER(VLOOKUP((ROUNDUP(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!»
    vb = vb & «R8C3:R8C9,0),FALSE)),VLOOKUP((ROUNDUP(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!R8C3:R8C9,0),FALSE),»»нет нижней «
    vb = vb & «КВ»»)))),VLOOKUP(ROUNDDOWN(RC[-3],0),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!R8C3:R8C9,0),FALSE)+(RC[-3]-«
    vb = vb & «(ROUNDDOWN(RC[-3],0)))*(VLOOKUP((ROUNDUP(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!R8C3:R8C9,0),FALSE)-«
    vb = vb & «VLOOKUP((ROUNDDOWN(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!R8C3:R8C9,0),FALSE)),»»нет данных для расчета»»),IF(RC[44]=»»агентская «
    vb = vb & «»»,IF(AND(ISNUMBER(IF(ISNUMBER(VLOOKUP((ROUNDDOWN(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!»
    vb = vb & «R8C3:R8C9,0),FALSE)),VLOOKUP((ROUNDDOWN(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!R8C3:R8C9,0),FALSE),»»нет нижней «
    vb = vb & «КВ»»)),ISNUMBER((IF(ISNUMBER(VLOOKUP((ROUNDUP(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!»
    vb = vb & «R8C3:R8C9,0),FALSE)),VLOOKUP((ROUNDUP(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!R8C3:R8C9,0),FALSE),»»нет нижней «
    vb = vb & «КВ»»)))),VLOOKUP(ROUNDDOWN(RC[-3],0),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!R8C3:R8C9,0),FALSE)+(RC[-3]-«
    vb = vb & «(ROUNDDOWN(RC[-3],0)))*(VLOOKUP((ROUNDUP(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!R8C3:R8C9,0),FALSE)-«
    vb = vb & «VLOOKUP((ROUNDDOWN(RC[-3],0)),матрица!R10C3:R109C9,MATCH(CONCATENATE(RC[-20],RC[44]),матрица!R8C3:R8C9,0),FALSE)),»»нет данных для расчета»»),0))»

            ActiveCell.FormulaR1C1 = vb
End Sub

[/vba]


МОИ: Ник, Tip box: 41001663842605

 

Ответить

alex808

Дата: Понедельник, 29.08.2016, 18:07 |
Сообщение № 9

Группа: Пользователи

Ранг: Новичок

Сообщений: 47


Репутация:

0

±

Замечаний:
0% ±


Excel 2007

Есть мнение, что деформация произошла при записи макрорекордером. Как-то он подозрительно (примерно так же) порезал у меня на строчки со съеданием нескольких концевых символов — видимо, подошёл к собственному пределу, но как-то корявенько…

Да именно так и произошло…Взял Ваш подход, чуток подправил для интервала, чтобы заполнил все ячейки в столбце и все заработало!!! Большое Вам и всем спасибо за подсказки и потраченное время!

 

Ответить

Время на прочтение
4 мин

Количество просмотров 28K

VBA – очень полезная вещь. Можно консолидировать данные из многих файлов и обрабатывать большие объемы информации с использованием интересных алгоритмов. Например, макрос Nodupes. Он использует возникающую в процессе выполнения кода ошибку как проверку наличия элемента в формируемой коллекции. Есть макросы, использующие рекурсию для формирования всех возможных комбинаций и перестановок.

Но я бы хотел показать несколько примеров использования стандартных функций листа программы Excel. Достаточно часто приходится городить огород из формул, чтобы вытащить из ячеек нужный текст или числа. Происходит это как правило из-за неверного представления данных. Числа — это числа, текст — это текст, не надо их смешивать. Даты (и время) это числа, с которыми можно и нужно производить вычисления. Не надо путать 14.03.2018 с 14 марта 2018 г. Второе это только пользовательский формат даты [$-F800], то, что мы видим в ячейке, а в строке формул будет 14.03.2018. И хватит об этом.

1. Допустим у вас есть таблица с временами начала и окончания каких-то событий, например, телефонных разговоров.

На рисунке часть таблицы _t2. Необходимо вычислить максимальное одновременное количество событий. Для этого есть такая формула:

=МАКС(МУМНОЖ((_t2[start]>=ТРАНСП(_t2[start]))*(_t2[start]<=ТРАНСП(_t2[end]));СТРОКА(_t2[start])^0))
Или в английской локали
=MAX(MMULT((_t2[start]>=TRANSPOSE(_t2[start]))*(_t2[start]<=TRANSPOSE(_t2[end])),ROW(_t2[start])^0))

Формула массивная, ввод подтверждается одновременным нажатием кнопок Control, Shift, Enter (CSE). В строке формул будет видно, что формула в фигурных скобках. МУМНОЖ делает виртуальную матрицу размером число строк таблица на число строк таблицы, в строках которой результаты вычисления, как если бы в строки таблицы была введена следующая формула (для второй строки) =СУММПРОИЗВ(Ч((C$2:C2>A2)))/ =SUMPRODUCT(N((C$2:C2>A2))), и протянуть на всю таблицу.

2. То же самое, но посложнее. Кроме начала и окончания есть количество агрегатов или отдаваемая/получаемая мощность. Необходимо определить максимальную мощность в какой-то момент времени.

Часть таблицы _t1:

И сама формула:

=МАКС(МУМНОЖ((ТРАНСП(_t1[start]*1440)<=СТРОКА(1:1436)-1)*(ТРАНСП(_t1[stop]*1440)>=СТРОКА(1:1436)-1);_t1[power]))
=MAX(MMULT((TRANSPOSE(_t1[start]*1440)<=ROW(1:1436)-1)*(TRANSPOSE(_t1[stop]*1440)>=ROW(1:1436)-1),_t1[power]))

Поскольку время — это доля единицы, умножаем значения на количество минут в сутках, чтобы получить целые числа. И второй аргумент МУМНОЖ – столбец значений мощности. В первом случае был сформирован столбец единиц.

3. Слева в таблице представлены суммы, соответствующие определенным интервалам. Необходимо вычислить суммы по месяцам. Предполагается, что суммы распределены равномерно внутри своих интервалов.

В столбце Н первые числа месяцев, в столбце I следующие формулы:

=СУММ(_tis[sum per day]*ЕСЛИОШИБКА((ЕСЛИ(КОНМЕСЯЦА(H3;0)>_tis[end];_tis[end];КОНМЕСЯЦА(H3;0))-ЕСЛИ(H3>_tis[start];H3;_tis[start])+1)^0,5;)^2)
=SUM(_tis[sum per day]*IFERROR((IF(EOMONTH(H3,0)>_tis[end],_tis[end],EOMONTH(H3,0))-IF(H3>_tis[start],H3,_tis[start])+1)^0.5,)^2)

Формулы массивные. Можно было бы использовать СУММПРОИЗВ/SUMPRODUCT, но ЕСЛИОШИБКА не работает без массивного ввода. Также, к сожалению, МАКС и МИН не могут сформировать виртуальный массив значений. Поэтому для вычисления частей интервалов, приходящихся на месяц, используется ЕСЛИ. Так как полученные части могут быть отрицательными, искусственно вызывается ошибка (квадратный корень из отрицательного числа приводит к ней). В исходной таблице можно было обойтись без столбцов длительности интервала и дневной суммы. Формула стала бы немного длиннее.

4. Небольшое развлечение. Сколько в году может быть счастливых пятниц?

Количество пятниц:

=СУММПРОИЗВ((ДЕНЬ(СТРОКА(ИНДЕКС(A:A;B2):ИНДЕКС(A:A;C2)))=13)*(ДЕНЬНЕД(СТРОКА(ИНДЕКС(A:A;B2):ИНДЕКС(A:A;C2));2)=5))
=SUMPRODUCT((DAY(ROW(INDEX(A:A,B2):INDEX(A:A,C2)))=13)*(WEEKDAY(ROW(INDEX(A:A,B2):INDEX(A:A,C2)),2)=5))

Даты пятниц:

=ЕСЛИОШИБКА(АГРЕГАТ(15;6;СТРОКА(ИНДЕКС($A:$A;$B2):ИНДЕКС($A:$A;$C2))/(ДЕНЬ(СТРОКА(ИНДЕКС($A:$A;$B2):ИНДЕКС(A:A;$C2)))=13)/(ДЕНЬНЕД(СТРОКА(ИНДЕКС($A:$A;$B2):ИНДЕКС($A:$A;$C2));2)=5);СТОЛБЕЦ(A$2));"")
=IFERROR(AGGREGATE(15,6,ROW(INDEX($A:$A,$B2):INDEX($A:$A,$C2))/(DAY(ROW(INDEX($A:$A,$B2):INDEX(A:A,$C2)))=13)/(WEEKDAY(ROW(INDEX($A:$A,$B2):INDEX($A:$A,$C2)),2)=5),COLUMN(A$2)),"")

Это очень хорошо (здесь), что первая строка листа соответствует 01.01.1901. Поэтому достаточно легко сформировать массив дат года с помощью ИНДЕКС и СТРОКА и считать только пятницы тринадцатое.

5. Размер процентной ставки, зависящей от суммы, встречается достаточно часто. Если пользоваться ими неправильно, то график полученных сумм будет такой как красный график ниже:

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

Для таких исходных данных:

Формула:

=ВПР(A3;tbl;2)*(A3-ВПР(A3;tbl;1))+СУММПРОИЗВ(ЕСЛИОШИБКА((tbl[limit]<=A3)*(tbl[limit]-СМЕЩ(tbl[limit];-1;))*СМЕЩ(tbl[rate];-1;);))
=VLOOKUP(A3,tbl,2)*(A3-VLOOKUP(A3,tbl,1))+SUMPRODUCT(IFERROR((tbl[limit]<=A3)*(tbl[limit]-OFFSET(tbl[limit],-1,))*OFFSET(tbl[rate],-1,),))

Формула массивная. В А3 – сумма, для которой нужно вычислить проценты. Исходные данные –tbl.
И, напоследок, кредитная линия с изменяемой процентной ставкой. Формула для расчета суммы процентов в зависимости от дат/сумм траншей/возвратов.

История кредита:

Изменение ставки:

=ЕСЛИ(B1=0;СУММ(ЕСЛИОШИБКА(ПРОСМОТР(_d;_s[[date]:[rate]]);)*ТРАНСП(B5:B16)*ИНДЕКС((_d>ТРАНСП(A5:A16))*(_d<=A2);;)*1/(365+(ОСТАТ(ГОД(_d);4)=0)))-СУММ(ЕСЛИОШИБКА(ПРОСМОТР(_d;_s[[date]:[rate]]);)*ТРАНСП(D5:D16)*ИНДЕКС((_d>ТРАНСП(C5:C16))*(_d<=A2);;)*1/(365+(ОСТАТ(ГОД(_d);4)=0)));)
=IF(B1=0,SUM(IFERROR(LOOKUP(_d,_s[[date]:[rate]]),)*TRANSPOSE(B5:B16)*INDEX((_d>TRANSPOSE(A5:A16))*(_d<=A2),,)*1/(365+(MOD(YEAR(_d),4)=0)))-SUM(IFERROR(LOOKUP(_d,_s[[date]:[rate]]),)*TRANSPOSE(D5:D16)*INDEX((_d>TRANSPOSE(C5:C16))*(_d<=A2),,)*1/(365+(MOD(YEAR(_d),4)=0))),)

Формула массивная. Считает проценты по дням, учитывает високосные года.

Спасибо за внимание!

Вставка формулы со ссылками в стиле A1 и R1C1 в ячейку (диапазон) из кода VBA Excel. Свойства Range.FormulaLocal и Range.FormulaR1C1Local.

Свойство Range.FormulaLocal

FormulaLocal — это свойство объекта Range, которое возвращает или задает формулу на языке пользователя, используя ссылки в стиле A1.

В качестве примера будем использовать диапазон A1:E10, заполненный числами, которые необходимо сложить построчно и результат отобразить в столбце F:

Примеры вставки формул суммирования в ячейку F1:

Range(«F1»).FormulaLocal = «=СУММ(A1:E1)»

Range(«F1»).FormulaLocal = «=СУММ(A1;B1;C1;D1;E1)»

Пример вставки формул суммирования со ссылками в стиле A1 в диапазон F1:F10:

Sub Primer1()

Dim i As Byte

    For i = 1 To 10

        Range(«F» & i).FormulaLocal = «=СУММ(A» & i & «:E» & i & «)»

    Next

End Sub

В этой статье я не рассматриваю свойство Range.Formula, но если вы решите его применить для вставки формулы в ячейку, используйте англоязычные функции, а в качестве разделителей аргументов — запятые (,) вместо точек с запятой (;):

Range(«F1»).Formula = «=SUM(A1,B1,C1,D1,E1)»

После вставки формула автоматически преобразуется в локальную (на языке пользователя).

Свойство Range.FormulaR1C1Local

FormulaR1C1Local — это свойство объекта Range, которое возвращает или задает формулу на языке пользователя, используя ссылки в стиле R1C1.

Формулы со ссылками в стиле R1C1 можно вставлять в ячейки рабочей книги Excel, в которой по умолчанию установлены ссылки в стиле A1. Вставленные ссылки в стиле R1C1 будут автоматически преобразованы в ссылки в стиле A1.

Примеры вставки формул суммирования со ссылками в стиле R1C1 в ячейку F1 (для той же таблицы):

‘Абсолютные ссылки в стиле R1C1:

Range(«F1»).FormulaR1C1Local = «=СУММ(R1C1:R1C5)»

Range(«F1»).FormulaR1C1Local = «=СУММ(R1C1;R1C2;R1C3;R1C4;R1C5)»

‘Ссылки в стиле R1C1, абсолютные по столбцам и относительные по строкам:

Range(«F1»).FormulaR1C1Local = «=СУММ(RC1:RC5)»

Range(«F1»).FormulaR1C1Local = «=СУММ(RC1;RC2;RC3;RC4;RC5)»

‘Относительные ссылки в стиле R1C1:

Range(«F1»).FormulaR1C1Local = «=СУММ(RC[-5]:RC[-1])»

Range(«F2»).FormulaR1C1Local = «=СУММ(RC[-5];RC[-4];RC[-3];RC[-2];RC[-1])»

Пример вставки формул суммирования со ссылками в стиле R1C1 в диапазон F1:F10:

‘Ссылки в стиле R1C1, абсолютные по столбцам и относительные по строкам:

Range(«F1:F10»).FormulaR1C1Local = «=СУММ(RC1:RC5)»

‘Относительные ссылки в стиле R1C1:

Range(«F1:F10»).FormulaR1C1Local = «=СУММ(RC[-5]:RC[-1])»

Так как формулы с относительными ссылками и относительными по строкам ссылками в стиле R1C1 для всех ячеек столбца F одинаковы, их можно вставить сразу, без использования цикла, во весь диапазон.


In this Article

  • Formulas in VBA
  • Macro Recorder and Cell Formulas
  • VBA FormulaR1C1 Property
    • Absolute References
    • Relative References
    • Mixed References
  • VBA Formula Property
  • VBA Formula Tips
    • Formula With Variable
    • Formula Quotations
    • Assign Cell Formula to String Variable
    • Different Ways to Add Formulas to a Cell
    • Refresh Formulas

This tutorial will teach you how to create cell formulas using VBA.

Formulas in VBA

Using VBA, you can write formulas directly to Ranges or Cells in Excel. It looks like this:

Sub Formula_Example()

    'Assign a hard-coded formula to a single cell
    Range("b3").Formula = "=b1+b2"
    
    'Assign a flexible formula to a range of cells
    Range("d1:d100").FormulaR1C1 = "=RC2+RC3"

End Sub

There are two Range properties you will need to know:

  • .Formula – Creates an exact formula (hard-coded cell references). Good for adding a formula to a single cell.
  • .FormulaR1C1 – Creates a flexible formula. Good for adding formulas to a range of cells where cell references should change.

For simple formulas, it’s fine to use the .Formula Property.  However, for everything else, we recommend using the Macro Recorder

Macro Recorder and Cell Formulas

The Macro Recorder is our go-to tool for writing cell formulas with VBA.  You can simply:

  • Start recording
  • Type the formula (with relative / absolute references as needed) into the cell & press enter
  • Stop recording
  • Open VBA and review the formula, adapting as needed and copying+pasting the code where needed.

I find it’s much easier to enter a formula into a cell than to type the corresponding formula in VBA.

vba formula formular1c1

Notice a couple of things:

  • The Macro Recorder will always use the .FormulaR1C1 property
  • The Macro Recorder recognizes Absolute vs. Relative Cell References

VBA FormulaR1C1 Property

The FormulaR1C1 property uses R1C1-style cell referencing (as opposed to the standard A1-style you are accustomed to seeing in Excel).

Here are some examples:

Sub FormulaR1C1_Examples()

    'Reference D5 (Absolute)
    '=$D$5
    Range("a1").FormulaR1C1 = "=R5C4"
    
    'Reference D5 (Relative) from cell A1
    '=D5
    Range("a1").FormulaR1C1 = "=R[4]C[3]"
    
    'Reference D5 (Absolute Row, Relative Column) from cell A1
    '=D$5
    Range("a1").FormulaR1C1 = "=R5C[3]"
    
    'Reference D5 (Relative Row, Absolute Column) from cell A1
    '=$D5
    Range("a1").FormulaR1C1 = "=R[4]C4"

End Sub

Notice that the R1C1-style cell referencing allows you to set absolute or relative references.

Absolute References

In standard A1 notation an absolute reference looks like this: “=$C$2”.  In R1C1 notation it looks like this: “=R2C3”.

To create an Absolute cell reference using R1C1-style type:

  • R + Row number
  • C + Column number

Example:  R2C3 would represent cell $C$2 (C is the 3rd column).

    'Reference D5 (Absolute)
    '=$D$5
    Range("a1").FormulaR1C1 = "=R5C4"

Relative References

Relative cell references are cell references that “move” when the formula is moved.

In standard A1 notation they look like this: “=C2”. In R1C1 notation, you use brackets [] to offset the cell reference from the current cell.

Example: Entering formula “=R[1]C[1]” in cell B3 would reference cell D4 (the cell 1 row below and 1 column to the right of the formula cell).

Use negative numbers to reference cells above or to the left of the current cell.

    'Reference D5 (Relative) from cell A1
    '=D5
    Range("a1").FormulaR1C1 = "=R[4]C[3]"

Mixed References

Cell references can be partially relative and partially absolute.  Example:

    'Reference D5 (Relative Row, Absolute Column) from cell A1
    '=$D5
    Range("a1").FormulaR1C1 = "=R[4]C4"

VBA Coding Made Easy

Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!

automacro

Learn More

VBA Formula Property

When setting formulas with the .Formula Property you will always use A1-style notation.  You enter the formula just like you would in an Excel cell, except surrounded by quotations:

    'Assign a hard-coded formula to a single cell
    Range("b3").Formula = "=b1+b2"

VBA Formula Tips

Formula With Variable

When working with Formulas in VBA, it’s very common to want to use variables within the cell formulas.  To use variables, you use & to combine the variables with the rest of the formula string. Example:

Sub Formula_Variable()
    Dim colNum As Long
    colNum = 4

    Range("a1").FormulaR1C1 = "=R1C" & colNum & "+R2C" & colNum

End Sub

VBA Programming | Code Generator does work for you!

Formula Quotations

If you need to add a quotation (“) within a formula, enter the quotation twice (“”):

vba formula quotations

Sub Macro2()
    Range("B3").FormulaR1C1 = "=TEXT(RC[-1],""mm/dd/yyyy"")"
End Sub

A single quotation (“) signifies to VBA the end of a string of text. Whereas a double quotation (“”) is treated like a quotation within the string of text.

Similarly, use 3 quotation marks (“””) to surround a string with a quotation mark (“)

MsgBox """Use 3 to surround a string with quotes"""
' This will print <"Use 3 to surround a string with quotes"> immediate window

Assign Cell Formula to String Variable

We can read the formula in a given cell or range and assign it to a string variable:

'Assign Cell Formula to Variable
Dim strFormula as String
strFormula = Range("B1").Formula

Different Ways to Add Formulas to a Cell

Here are a few more examples for how to assign a formula to a cell:

  1. Directly Assign Formula
  2. Define a String Variable Containing the Formula
  3. Use Variables to Create Formula
Sub MoreFormulaExamples ()
' Alternate ways to add SUM formula
' to cell B1
'
  Dim strFormula as String
  Dim cell as Range
  dim fromRow as long, toRow as long

  Set cell = Range("B1")

  ' Directly assigning a String
  cell.Formula = "=SUM(A1:A10)"

  ' Storing string to a variable
  ' and assigning to "Formula" property
  strFormula = "=SUM(A1:A10)"
  cell.Formula = strFormula

  ' Using variables to build a string 
  ' and assigning it to "Formula" property
  fromRow = 1
  toRow   = 10
  strFormula = "=SUM(A" & fromValue & ":A" & toValue & ")
  cell.Formula = strFormula
End Sub

Refresh Formulas

As a reminder, to refresh formulas, you can use the Calculate command:

Calculate

To refresh single formula, range, or entire worksheet use .Calculate instead:

Sheets("Sheet1").Range("a1:a10").Calculate

Всем доброго времени суток

как в IF прописать формулу с несколькими условиями

пример
Sub Test()
Dim r As Byte
Dim c As Byte
For r = 4  To 9
For c = 4 To 31
If Cells(r, c) условие под звездочкой
Next c
Next r

End Sub

уcловие для IF
если произведение строка*деньнедели кратное 8; тогда столбец+день(сегодня())+строка() и ячейку закрасить желтым; иначе строка()*столбец()


Почитайте Хэлп
Но в общем, сложная схема Ифа така:


Sub Test2()
    If условие_1 = Критерий_1 Then
        MsgBox "Критерий_1"
        If условие_1_1 = Критерий_1_1 Then
            MsgBox "Критерий_1_1"
        ElseIf условие_1_2 = Критерий_1_2 Then
            MsgBox "Критерий_1_2"
        Else
            MsgBox "Критерий_1 выполняется не полностью"
        End If
    ElseIf условие_2 = Критерий_2 Then
        MsgBox "Критерий2_"
    Else
        MsgBox "Критерии не выполняются"
    End If
End Sub

Ничто не обходится нам так дешево и не ценится так дорого, как вежливость…  Мигель Сервантес де Сааведра


boa , здравствуйте

Цитата: boa от 02.12.2017, 19:46
Почитайте Хэлп

пока  изучал макросы методом тыка,  я еще что-то понимал…
После прочтения помощи оказалось что я все делал неправильно. а по правильному у меня ничего не получается …

спасибо за оперативный ответ и подробное описание
Но на данном уровне моих знаний это все равно что первокласснику дать «Капитал» читать …

Записал макрос макрокодером
получилось так

Range("D4").Select
    ActiveCell.FormulaR1C1 = _
        "=IF(ROW()*WEEKDAY(TODAY(),2)/8=INT(ROW()*WEEKDAY(TODAY(),2)/8),COLUMN()+DAY(TODAY()+ROW()),ROW()*(COLUMN()))"

попытка загнать все это в ячейку
IF Cells (r, c) = IF(ROW()*WEEKDAY(TODAY(),2)/8=INT(ROW()*WEEKDAY(TODAY(),2)/8),COLUMN()+DAY(TODAY()+ROW()),ROW()*(COLUMN()))
Машина отказывается  работать с этой белебердой !
Не могли бы вы написать конкретный код под мои требования


Забудьте о ЕСЛИ и объясните ЗАДАЧУ, а не выбранный способ решения.
И предложите название темы, отражающее суть задачи.


vikttur, здравствуйте

Цитата: vikttur от 02.12.2017, 21:31
и объясните ЗАДАЧУ

Если опускать все тонкости, то конечная цель: научиться работать в среде VBA
А то что написано в стартовом топике — это не задача, а «предисловие»

Цитироватьа не выбранный способ решения.

Если у Вас лично или на форуме имеется список в котором отмечаются решенные/нерешенные вопросы, тогда эту задачу можно отмечать птичкой, потому что решение этой задачи имеется .
Я его предоставил вместе с вопросом (см.файл)
Но это решение на формулах и условном форматировании.
Мне бы хотелось получить такой же ответ но через макросы.
Я допускаю что Вы и/или другие форумчане можете предложить не один и не два макроса с правильным и красивым решением.
Но мое серое вещество не сможет воспринять ту информацию ввиду отсутствия знаний.
Поэтому мне не надо «КРАСИВЫЙ» ответ. Мне надо «ПОНЯТНОЕ» решение
На сегодняшний день IF— это мой спасательный круг
Если по каким-то причинам ответ не может быть предоставлен в том виде в каком я хочу — тогда могу убрать часть условий

ЦитироватьИ предложите название темы, отражающее суть задачи

Это самый сложный (для меня) пункт Вашего поста
Может быть так?
Как записать IF, при условии что ИСТИНА и ЛОЖЬ задаются математическим решением и при этом ответ тоже должен исходить из формулы


Название темы заменил.

Цитироватьможете предложить не один и не два макроса с правильным и красивым решением.

Вам дали в руку карту с отмеченным маршрутом. Задание: достичь конечной точки, оптимизировав маршрут. Но главное условие — от указанной нитки не отклоняться.
Так и здесь. Прошу улучшить, но от формулы шаг влево, шаг вправо — расстрел :)

ЦитироватьНа сегодняшний день IF- это мой спасательный круг

Код получается более структурирован и читабелен, если вместо многих условных операторов применяется *Select Case/End Select*. Часто каскад If можно заменить поиском или циклами.

Цитироватьрешение этой задачи имеется

Отлично. Для решения конкретной задачи (не об операторах и формулах) создайте новую тему, опишите ЗАДАЧУ так, как будто Excel Вы и в глаза не видели.


Для вызова с листа в ячейке напишите формулу «=condition()»


Option Explicit

Sub test()
Dim r&: r = 3
Dim c&: c = 3
    If Cells(r, c) = condition(r, c) Then MsgBox "Получилось"
End Sub

Function condition(Optional iRow&, Optional iCol&)
'"=IF(ROW()*WEEKDAY(TODAY(),2)/8=INT(ROW()*WEEKDAY(TODAY(),2)/8),COLUMN()+DAY(TODAY()+ROW()),ROW()*(COLUMN()))"

Dim MyDate As Date: MyDate = Date
' если функцию планируете вызывать не с листа, то функции надо передавать значения iCol и iRow
' Caller является объектом Range, т.е ссылкой на ячейку, из которой вызвана функция пользователя
    If iCol = 0 Then iCol = Application.Caller.Column
    If iRow = 0 Then iRow = Application.Caller.Row

        If iRow * Weekday(MyDate, vbMonday) / 8 = Int(iRow * Weekday(MyDate, vbMonday) / 8) Then
        condition = iCol + Day(MyDate + iRow)
    Else
        condition = iCol * iRow
    End If
End Function

Ничто не обходится нам так дешево и не ценится так дорого, как вежливость…  Мигель Сервантес де Сааведра


0mega, добрый день!
Давненько не встречались! Вижу, Вы уже к макросам подобрались и не пишете свое «sub — no». Поздравляю.
По поводу

Цитата: 0mega от 02.12.2017, 21:09
Range("D4").Select
    ActiveCell.FormulaR1C1 = _
        "=IF(ROW()*WEEKDAY(TODAY(),2)/8=INT(ROW()*WEEKDAY(TODAY(),2)/8),COLUMN()+DAY(TODAY()+ROW()),ROW()*(COLUMN()))"

попытка загнать все это в ячейку
IF Cells (r, c) = IF(ROW()*WEEKDAY(TODAY(),2)/8=INT(ROW()*WEEKDAY(TODAY(),2)/8),COLUMN()+DAY(TODAY()+ROW()),ROW()*(COLUMN()))

— Вы просто неверно загоняете. Нужно именно так, как Вам рекодер написал. Вот так

Cells (r, c).FormulaR1C1 = _
        "=IF(ROW()*WEEKDAY(TODAY(),2)/8=INT(ROW()*WEEKDAY(TODAY(),2)/8),COLUMN()+DAY(TODAY()+ROW()),ROW()*(COLUMN()))"

Абсолютно согласен с Виктором в части оптимизации. Но и с Вами тоже согласен — помню свои муки в начальной стадии изучения VBA и прекрасно понимаю Ваше желание сделать не так, как нужно, а так, как понятнее.
Думаю, что этот код затруднений у Вас не вызовет, тем более, что я комментарии туда написал

Sub Test()
    Application.ScreenUpdating = 0 'Отключаем обновление экрана
    d_ = Weekday(Date, 2) 'день недели https://msdn.microsoft.com/ru-ru/VBA/Language-Reference-VBA/articles/weekday-function
    den_ = Day(Date) 'сегодняшний день
    For r_ = 4 To 31 'цикл по строкам
        If r_ * d_ Mod 8 = 0 Then 'если остаток от деления = 0
        'https://msdn.microsoft.com/ru-ru/vba/language-reference-vba/articles/mod-operator
            '2 строки ниже пишем ДО цикла по столбцам, они одинаковы для любого столбца строки r_
            n_ = den_ + r_ 'день + строка
            Cells(r_, 4).Resize(1, 6).Interior.Color = 65535 'красим 6 ячеек вправо от ячейки строка r_, столбец 4
            For c_ = 4 To 9 'цикл по столбцам
               Cells(r_, c_) = c_ + n_ 'каждая ячейка равна столбец + n_
            Next c_ 'конец цикла по столбцам
        Else 'если остаток от деления НЕ = 0
            For c_ = 4 To 9 'цикл по столбцам
               Cells(r_, c_) = c_ * r_ 'каждая ячейка равна столбец * строку
            Next c_ 'конец цикла по столбцам
        End If 'конец условия if
    Next r_ 'конец цикла по строкам
    Application.ScreenUpdating = 1 'Включаем обновление экрана
End Sub

Скажи мне, кудесник, любимец ба’гов…

Яндекс-деньги: 41001632713405
Webmoney: R289877159277; Z102172301748; E177867141995


Кстати, повторяющиеся формулы, да бы исключить ошибки, лучше создавать в Менеджере имен(Ctrl+F3) и потом в ячейку вставлять только имя созданной формулы

Ничто не обходится нам так дешево и не ценится так дорого, как вежливость…  Мигель Сервантес де Сааведра


boa , спасибо за иллюстрацию
скорее всего будут вопросы и я их задам, но _Вoroda_  предоставил более понятный (для меня ) ответ


_Boroda_ , здравствовать

Цитата: _Boroda_ от 03.12.2017, 14:05
0mega, добрый день!
Давненько не встречались! Вижу, Вы уже к макросам подобрались и не пишете свое «sub — no». Поздравляю.

Немного «тесновато «мне стало среди формул…

Александр, что значит нижнее подчеркивание справа от переменной (d_ ,  r_ ,  c_ … ) ?


Ничего. Я так делаю просто для того, чтобы гарантированно не обозвать переменную тем именем, которое уже есть внутри VBA — их же там туча немереная и все запомнить я ну никак не могу (да и зачем)

Скажи мне, кудесник, любимец ба’гов…

Яндекс-деньги: 41001632713405
Webmoney: R289877159277; Z102172301748; E177867141995


Привет подводным лодкам! :)
Часто проще и удобнее вместо If-Then использовать select case условие, в частности

select case true
case Cells(r, c) = произведение строка*деньнедели кратное 8
тогда столбец+день(сегодня())+строка() и ячейку закрасить желтым
case какое-то другое выполняющееся условие
тут действие при другом выполняющемся условии
case else ' когда никакие условия не выполнились
строка()*столбец()
end select

При первом совпавшем условии дальнейшие проверки не производятся!

webmoney: E265281470651 Z422237915069 R41892628200


Цитата: Hugo121 от 08.12.2017, 15:37
Часто проще и удобнее вместо If-Then использовать select case условие, в частности

Об этом уже писал vikttur в данной теме… :-

Цитата: vikttur от 03.12.2017, 11:28
Код получается более структурирован и читабелен, если вместо многих условных операторов применяется *Select Case/End Select*. Часто каскад If можно заменить поиском или циклами.

З.Ы. Если б все рисовали одинаково, то мир бы не увидел шедевров

Ничто не обходится нам так дешево и не ценится так дорого, как вежливость…  Мигель Сервантес де Сааведра


Про select case true многие не знают, и в шпаргалках редко упоминается.

webmoney: E265281470651 Z422237915069 R41892628200


Цитата: Hugo121 от 08.12.2017, 15:37
Привет подводным лодкам! :)

Игорь , здравствуйте
хех …  максимум 2 , но большая вероятность что Вы единственный,  кто знает о подводных лодках.
Остальные, очевидно , предполагагают что  два однополчанина вспоминают службу на форуме excel  ?!

Цитата: Hugo121 от 08.12.2017, 15:37

Часто проще и удобнее вместо If-Then использовать select case условие, в частности

При первом совпавшем условии дальнейшие проверки не производятся!

сейчас для меня это очень сложно .
Поскольку живого преподавателя рядом нет, то  единственная «палочка-выручалочка» — это маросы вытягивать из формул.
тем не менее, спасибо за подсказку .
Ковырнул изюм …
Но только неизвесно когда этот я буду печь свои булочки с Вашим изюмом


Понравилась статья? Поделить с друзьями:

А вот еще интересные статьи:

  • Excel сложные таблицы практическая работа
  • Excel сложные практические работы
  • Excel сложные логические выражения
  • Excel сложные вложенные функции
  • Excel сложное условное форматирование

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии