Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam

Топ прошлой недели

  • Oskanov Oskanov 8 постов
  • alekseyJHL alekseyJHL 6 постов
  • XpyMy XpyMy 1 пост
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Новости Пикабу Помощь Кодекс Пикабу Реклама О компании
Команда Пикабу Награды Контакты О проекте Зал славы
Промокоды Скидки Работа Курсы Блоги
Купоны Biggeek Купоны AliExpress Купоны М.Видео Купоны YandexTravel Купоны Lamoda
Мобильное приложение

Vba

С этим тегом используют

Microsoft Excel Excel Макрос Программирование Помощь Microsoft Word Без рейтинга Все
164 поста сначала свежее
81
bighouse.live
bighouse.live
3 года назад
MS, Libreoffice & Google docs
Серия Оцифровка

Excel. Долгая дорога оцифровки. Часть 7. Автоматическое создание макроса функции с использованием кусочной интерполяции⁠⁠

По аналогии с Excel. Долгая дорога оцифровки. Часть 4. Макрос по созданию макросов апроксимации простых графиков полиномом  и Excel. Долгая дорога оцифровки. Часть 6. Кусочная интерполяция не сложно выполняется макрос по созданию макросов оцифровки простых графиков с использованием кусочной интерполяции.

Excel. Долгая дорога оцифровки. Часть 7. Автоматическое создание макроса функции с использованием кусочной интерполяции Microsoft Excel, Vba, Плюшка, Длиннопост

Описание вводимых данных аналогично ранее изложенному.

Если ещё немного развить тему, то и макрос создания макросов функции с двумя аргументами не проблема:

Excel. Долгая дорога оцифровки. Часть 7. Автоматическое создание макроса функции с использованием кусочной интерполяции Microsoft Excel, Vba, Плюшка, Длиннопост

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


Основное нововведение - определение количества графиков. Если вспомните ещё в Excel. Долгая дорога оцифровки. Часть 2. Забираем данные с листа я писал, что что "снятие точек производить от меньшего Х к большему. При наличии диаграммы зависимости от двух аргументов типаY(X1, X2) начиная с графика меньшего Х2. С обязательным условием - каждая следующая линия должна начинаться с Х меньшего, чем закончилась предыдущая.". И теперь можно этим воспользоваться - определить количество переходов на новую линию по уменьшению Х по сравнению с предыдущим.


For i = 2 To xVal.Count

If i = xVal.Count Then

Nkon(Ndiap) = i

End If

If xVal.Rows(i) < xVal.Rows(i - 1) Then

Nkon(Ndiap) = i - 1

Ndiap = Ndiap + 1

Nna4(Ndiap) = i

End If

Next i


Ну а дальше просто - перебираем поочерёдно все диапазоны, для каждого определяем уравнение апроксимации...


Результирующий макрос будет иметь вид:


' Поправки Сербия Панчево Страница 34 из 77 Нижний рисунок

Public Function ТЭХ_ПТ80_Рис3(ByRef Go As Single, ByRef CkH As Single) As Single

Dim krit_kriv As Variant

krit_kriv = array(2.96,3.06,3.15)

Dim kriv As Variant

kriv = Array(-0.00271242 * Go + 0.100817, _

-0.00252906 * Go + 0.230858, _

0.000276671 * Go ^ 2 -0.203078 * Go + 31.5862)

ТЭХ_ПТ80_Рис3= kus_interp(krit_kriv, kriv, CkH, 2)

End Function


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


Давайте так, чтобы не утомлять читателя выкопировкой текстовок макросов - выкладываю сие для свободной скачки/использования/модернизации


Если возникнут вопросы как сие работает, распишу. Если у кого то что то не заработает - обращайтесь, посмотрю.


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

Excel. Долгая дорога оцифровки. Часть 7. Автоматическое создание макроса функции с использованием кусочной интерполяции Microsoft Excel, Vba, Плюшка, Длиннопост

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


Например диаграмма с несколькими независимыми графиками типа такой. Можно либо сделать 3 независимых макроса, либо один с выбором графика.

Excel. Долгая дорога оцифровки. Часть 7. Автоматическое создание макроса функции с использованием кусочной интерполяции Microsoft Excel, Vba, Плюшка, Длиннопост

С помощью автоматического создания макросов

Excel. Долгая дорога оцифровки. Часть 7. Автоматическое создание макроса функции с использованием кусочной интерполяции Microsoft Excel, Vba, Плюшка, Длиннопост

Позволит получить (текстовка от графика отличного от представленного выше рисунка)


' ТЭХ ПТ80 Рис.3 Давление в отборах при конденсационном режиме [МПа]

Public Function ТЭХ_ПТ80_Рис3(ByRef Go As Single, ByRef Название_графика As Variant) As Variant

Dim krit_graph As Variant

krit_graph = array(1,2,3)

Select Case Название_графика

Case krit_graph(0)

ТЭХ_ПТ80_Рис3 = -0.0027124 * Go ^ 1 + 0.10082

Case krit_graph(1)

ТЭХ_ПТ80_Рис3 = -0.0025397 * Go ^ 1 + 0.23509

Case krit_graph(2)

ТЭХ_ПТ80_Рис3 = -0.0026659 * Go ^ 1 + 0.4529

Case Else

ТЭХ_ПТ80_Рис3 = 999999999999999

End Select

End Function


При желании указывать название графика правится krit_graph = array("Go","Qo","qt").


Ну и гораздо более сложноподчинённые, например что реализовано у меня:

Создание макроса для варианта когда критерий зависит от своего критерия
Excel. Долгая дорога оцифровки. Часть 7. Автоматическое создание макроса функции с использованием кусочной интерполяции Microsoft Excel, Vba, Плюшка, Длиннопост

Диаграммы режимов ПТ типа ПТ-80

Excel. Долгая дорога оцифровки. Часть 7. Автоматическое создание макроса функции с использованием кусочной интерполяции Microsoft Excel, Vba, Плюшка, Длиннопост

Диаграммы режимов типа Т-250

Excel. Долгая дорога оцифровки. Часть 7. Автоматическое создание макроса функции с использованием кусочной интерполяции Microsoft Excel, Vba, Плюшка, Длиннопост

Нормативной температуры сетевого подогревателя.

Excel. Долгая дорога оцифровки. Часть 7. Автоматическое создание макроса функции с использованием кусочной интерполяции Microsoft Excel, Vba, Плюшка, Длиннопост

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


Из того на что стоит обратить внимание, или маленькие лайфхаки:

1. Не всегда есть разметка осей. Например на диаграмме на последнем скрине вертикальная ось не размечена. Но она в данном случае не нужно. Важно иметь одинаковое значение для левого и правого графиков. Как правило я принимаю в качестве минимального значения оси - 0, в качестве максимального - число клеток (например 12-ть).

2. Внимание! Ось Х не обязательно горизонтальная при "снятии точек"! Например на диаграмме на последнем скрине  для правого графика удобно взять в качестве оси Х вертикальную ось а в качестве Y - горизонтальную. Тогда результат обработки левой номограммы будет сразу выступать в качестве аргумента для правой номограммы.

3. Есть варианты оцифровки, когда лучше привязываться не к значениям осей, а к клеточкам :) Да, звучит дико, но иногда проще внести пересчёт внутри макроса, чем реализовать оцифровку по данным осей.  Например диаграмма ниже - обратите внимание, что вертикальная ось не обозначена, зато горизонтальная в левой диаграмме разбита на 3 участка с разным масштабом.

Excel. Долгая дорога оцифровки. Часть 7. Автоматическое создание макроса функции с использованием кусочной интерполяции Microsoft Excel, Vba, Плюшка, Длиннопост

Упд. Вспомнил ещё про важную часть - обратные функции. Т.е. есть макрос (готовый!), который по известным Х1, Х2... находит Y. Иногда требуется с использованием данного макроса и известных Y и X1 найти X2... Но об этом в следующий раз. А то и так пост разросся.

Показать полностью 9
[моё] Microsoft Excel Vba Плюшка Длиннопост
2
44
bighouse.live
bighouse.live
3 года назад
MS, Libreoffice & Google docs
Серия Оцифровка

Excel. Долгая дорога оцифровки. Часть 6. Кусочная интерполяция⁠⁠

Ну теперь пора перейти именно к интерполяции исходных данных. Итак, я напомню - у нас был лист с распечатанным графиком, мы его отсканировали, получили набор точек ХY и... имеем вот такую (в лучшем случае) картину (см.первый скрин). Т.е. по данному набору точек невозможно сделать корректную апроксимацию полиномом.

Excel. Долгая дорога оцифровки. Часть 6. Кусочная интерполяция Microsoft Excel, Vba, Плюшка, Длиннопост

Выходом из данной ситуации является разбиение данных на несколько частей, в данном случае 2 с общей точкой Do=428, создание кусучнозаданной функции (ЕСЛИ меньше 428 одна функция, если больше - вторая функция). Но так в данном случае, а если надо сделать два, три...и больше разбиений? Кропотливая работа. Но зачем, если можно заставить Excel в автоматическом режиме выбирать малое количество точек и проводить через них интерполяционную функцию.

Отчасти кусочную интерполяцию показывал в прошлом посте серии ( Excel. Долгая дорога оцифровки. Часть 5. Создание пользовательской функции для двух аргументов. Ручной вариант ) при поиске решения между заданных критериев.


Как простые варианты рассмотрим кусочную интерполяцию по двум и по четырём точкам для заданных ниже данных.

Excel. Долгая дорога оцифровки. Часть 6. Кусочная интерполяция Microsoft Excel, Vba, Плюшка, Длиннопост

Допустим нужно определить значение Y при X = 2.5.

При кусочной интерполяции по двум точкам используются две ближайшие заданные точки к X = 2.5. , т.е. 2 и 3, через данные точки провидится линия,и по ней находится Y при X = 2.5..

Excel. Долгая дорога оцифровки. Часть 6. Кусочная интерполяция Microsoft Excel, Vba, Плюшка, Длиннопост

При кусочной интерполяции по четырём точкам используются две ближайшие заданные точки к X = 2.5. справа и две две ближайшие заданные точки к X = 2.5. слева, т.е. 1 и 2 и 3 и 4, через данные точки провидится кривая (полином 3-й степени),и по ней находится Y при X = 2.5.

Это справедливо для данных за 2-й и перед предпоследней известной точкой. Для данных отрезков и для экстраполяции использую линейную интерполяцию (по 2-м точкам).

Excel. Долгая дорога оцифровки. Часть 6. Кусочная интерполяция Microsoft Excel, Vba, Плюшка, Длиннопост

Как видно использование кусочной интерполяции по 4-м точкам (голубая линия)немного сглаживает итоговую функцию, что позволяет снимать при оцифровке чуть меньше точек :) .

Вообще правило такое, в зависимости от вида графика:

Excel. Долгая дорога оцифровки. Часть 6. Кусочная интерполяция Microsoft Excel, Vba, Плюшка, Длиннопост

Ну и собственно с помощью чего сие выполняется:


Макрос кусочной интерполяции при использовании данных с листа

======

' Интерполяция по 2-м, 3-м или 4-м ближайшим (до и после) к заданной (Xisk) точке

' В подпрограмму передаются все заданные точки

' Интерполяция происходит косочно, по количеству заданных точек с учётом расположения заданного Х

' Данные из листа Excel.

Public Function kus_interp_Ex(Xt As Range, Yt As Range, Xisk As Single, Optional ByVal toch As Integer = 2) As Variant

Dim i As Long

Dim xd() As Double

Dim yd() As Double

Dim cd() As Double

' toch - указание поиска решения с использованием количества точек (2, 3, 4).

Select Case toch

Case 2 ' Уравнение а·х+b

kus_interp_Ex = linterp(Xt.Rows(Xt.Count - 1), Xt.Rows(Xt.Count), Yt.Rows(Xt.Count - 1), Yt.Rows(Xt.Count), Xisk)

For i = 1 To Xt.Count - 1

If Xisk < Xt.Rows(i + 1) Then

kus_interp_Ex = linterp(Xt.Rows(i), Xt.Rows(i + 1), Yt.Rows(i), Yt.Rows(i + 1), Xisk)

Exit For

End If

Next i

Case 3 ' Уравнение а·х^2+b·x+c Интерполяция по принципу х1 Х х2 х3

kus_interp_Ex = kubterp(Xt.Rows(Xt.Count - 2), Xt.Rows(Xt.Count - 1), Xt.Rows(Xt.Count), _

Yt.Rows(Xt.Count - 2), Yt.Rows(Xt.Count - 1), Yt.Rows(Xt.Count), Xisk)

For i = 1 To Xt.Count - 2

If Xisk < Xt.Rows(i + 1) Then

kus_interp_Ex = kubterp(Xt.Rows(i), Xt.Rows(i + 1), Xt.Rows(i + 2), _

Yt.Rows(i), Yt.Rows(i + 1), Yt.Rows(i + 2), Xisk)

Exit For

End If

Next i

Case 4 ' Уравнение а·х^3+b·x^2+c·x+d Интерполяция по принципу х1 х2 X х3 x4

ReDim xd(1 To 4) As Double

ReDim yd(1 To 4) As Double

If Xisk < Xt.Rows(2) Then ' Экстраполяция ДО и интерполяция ДО второй известной точки - линейна

kus_interp_Ex = linterp(Xt.Rows(1), Xt.Rows(2), Yt.Rows(1), Yt.Rows(2), Xisk)

Else

If Xisk >= Xt.Rows(Xt.Count - 1) Then ' Экстраполяция ЗА и интерполяция ПОСЛЕ второй известной точки - линейна

kus_interp_Ex = linterp(Xt.Rows(Xt.Count - 1), Xt.Rows(Xt.Count), Yt.Rows(Xt.Count - 1), Yt.Rows(Xt.Count), Xisk)

Else ' Между ними считаю по интерполяции полиномом с расположением заданного икса между двух пар точек

For i = 3 To Xt.Count - 1

If Xisk < Xt.Rows(i) Then

xd(1) = Xt.Rows(i - 2): xd(2) = Xt.Rows(i - 1): xd(3) = Xt.Rows(i): xd(4) = Xt.Rows(i + 1)

yd(1) = Yt.Rows(i - 2): yd(2) = Yt.Rows(i - 1): yd(3) = Yt.Rows(i): yd(4) = Yt.Rows(i + 1)

Linia_trenda yd, xd, 3, cd

kus_interp_Ex = cd(1) * Xisk ^ 3 + cd(2) * Xisk ^ 2 + cd(3) * Xisk ^ 1 + cd(4)

Exit For

End If

Next i

End If

End If

Case Else

End Select

End Function

======

Входные данные:

Xt - Столбец исходных Х

Yt  - Столбец исходных Y

Xisk  - X при котором требуется определить Y

toch - количество используемых точек при интерполяции.


Наблюдательный заметит, что в макросе присутствует и интерполяция с использованием 3-х точек. (0_о)


Дополнительная функция, требуемая для макроса кусочной интерполяции - определение коэффициентов полинома линии тренда:


======

' Проведение интерполяции с использованием функционала Excel

' На выходе - коэффициенты полинома. Число точек должно быть минимум на одну больше, чем степень полинома.

' Данные берутся из программы

Public Sub Linia_trenda(ByRef Y() As Double, ByRef x() As Double, ByVal PolyStep As Integer, ByRef c() As Double, Optional ByRef r2 As Double)

Dim stepen As Long

' Ввожу проверку не превышения степени массива

If (UBound(Y) - LBound(Y) - 1) < PolyStep Then

stepen = UBound(Y) - LBound(Y)

Else

stepen = PolyStep

End If

' Объявляю переменные, создаю матрицы под размер данных и степень полинома.

Dim X1() As Double, Y1() As Double

ReDim X1(LBound(Y) To UBound(Y), 1 To stepen) As Double

ReDim Y1(LBound(Y) To UBound(Y), 1 To 1) As Double

ReDim c(1 To stepen + 1) As Double

' Заполню массив Х в соответствии со степенью уравнения.

For i = LBound(x) To UBound(x)

Y1(i, 1) = Y(i)

X1(i, 1) = x(i)

For N = 2 To stepen

X1(i, N) = X1(i, 1) ^ N

Next N

Next i

' Нахожу уравнение.

Dim Coefs As Variant

Coefs = WorksheetFunction.LinEst(Y1, X1, True, True)

' Вытаскиваю коэффициенты полинома.

For i = 1 To stepen + 1

c(i) = Coefs(1, i)

Next i

' Вытаскиваю величину достоверности апроксимации.

r2 = Coefs(3, 1)

End Sub

======

Макрос linterp был представлен в прошлый раз.


Одним из замечательных применений кусочной интерполяции является возможность автоматического создания макросов функций без проблем с невозможностью достоверной апроксимации исходных данных вот в таком виде:


' Поправки Сербия Панчево Страница 39 из 77

Public Function ТЭХ_ПТ80_Рис3(ByRef Go As Single) As Variant

Dim Xt As Variant

Dim Yt As Variant

Xt = Array(13.0042194092827, 13.4767932489451, 14.0675105485232)

Yt = Array(-6.38888888888889E-02, -6.38888888888889E-02, -0.06875)

ТЭХ_ПТ80_Рис3 = kus_interp(Xt, Yt, Go, 4, 2)

End Function


Учтите что kus_interp при использовании данных с листа и из макроса отличаются...

Но об этом в следующий раз.


===========================

Планы на будущее

1. Часть 7. Автоматическое создание макроса функции с использованием кусочной интерполяции.

2. Построим поиск решения.

3. Строим график функции.

Показать полностью 5
[моё] Microsoft Excel Vba Плюшка Длиннопост
9
168
bighouse.live
bighouse.live
3 года назад
MS, Libreoffice & Google docs

Базы данных в Excel. Или ВПР по неограниченному количеству условий⁠⁠

Ответ на пост из соседней темы о ВПР по 2-м условиям.

Довольно часто я встречаю решения выполнения поиска в таблице по двум/трём условиям с применением ВПР/ГПР. Подчас решения очень интересные. Однако что ВПР, что ГПР выдают только одно значение, и решения не масштабируемы. А что делать если необходимо из массива выбрать всю строку, которая будет подчиняться набору критериев?

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

Итак, есть некая таблица и необходимо из неё выбрать все строки подчиняющиеся неким условиям.

Ход поиска однотипен:

1. Столбцы исходной таблицы имеют уникальные заголовки.

2. Для выборки из данной таблицы создаём таблицу условий. При этом заголовок таблицы условий должен совпадать с названием столбца из исходной таблицы, по которому будет проходить выборка. Если выборка по одному столбцу, но по нескольким условиям, то можно написать всё в один столбец (см.скрин ниже). Если условия по нескольким столбцам - по одному условию на столбец, наименования столбцов могут повторяться.

3. Затем переходим в вкладку "Данные" - "Сортировка и фильтр" - "Дополнительно". В открывшемся окне

3.1. отмечаем "скопировать результат в новое место". В этом случае исходная таблица не изменится.

3.2. Исходный диапазон - таблица исходная, вместе с шапкой

3.3. Диапазон условий - таблица условий, вместе с шапкой

3.4. Адрес ячейки с которой будет заполняться итоговая таблица согласно выборки.

Итоговая таблица при этом никак не связана с исходной. И с ней можно проводить любые операции.

Базы данных в Excel. Или ВПР по неограниченному количеству условий Microsoft Excel, Vba, Плюшка, Длиннопост

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

=====

Sub Выборка()

Range("B3:B37").AdvancedFilter Action:=xlFilterCopy, _

CriteriaRange:=Range("I3:I6"), _

CopyToRange:=Range("K3"), _

Unique:=False

End Sub

=====

где

Range("B3:B37") - исходная таблица

Range("I3:I6") - таблица критериев

Range("K3") - начало вывода результирующей таблицы


Соответственно можно повесить выполнением макроса на кнопку, менять условия и получать новые выборки.


Вызов функции выборки:

AdvancedFilter (Действие, CriteriaRange, CopyToRange, Уникальный)

Базы данных в Excel. Или ВПР по неограниченному количеству условий Microsoft Excel, Vba, Плюшка, Длиннопост

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

Базы данных в Excel. Или ВПР по неограниченному количеству условий Microsoft Excel, Vba, Плюшка, Длиннопост

Например, если я хочу просуммировать все значения из столбца "Продажи" с учётом того, что они проводились в марте, и контактов было от 35...36, то я создаю таблицу критериев (см.скрин ниже) и в любой ячейке листа формулу  =БДСУММ(B6:G21;F6;B2:В3)

где

B6:G21 - Диапазон исходной таблицы, включая заголовок;

F6 - по какому столбцу буду суммировать;

B2:D3 - при каких условиях суммировать.

Базы данных в Excel. Или ВПР по неограниченному количеству условий Microsoft Excel, Vba, Плюшка, Длиннопост

Да, сейчас это можно заменить на СУММЕСЛИ, но если будет больше условий? А если суммируется при сложных условиях содержания ячеек?

Насколько способ с использованием баз нагляднее, не так ли?

Варианты задания условий при этом поражают разнообразием. Не всегда можно сходу подобрать условия для СУММЕСЛИ, а тут это просто содержание одной ячейки.

Базы данных в Excel. Или ВПР по неограниченному количеству условий Microsoft Excel, Vba, Плюшка, Длиннопост

Ну и естественно умные таблицы используются без проблем

Базы данных в Excel. Или ВПР по неограниченному количеству условий Microsoft Excel, Vba, Плюшка, Длиннопост

==================


Рассмотрим ещё один метод  поиска значения по 2-м, 3-м и более критериям без применение ВПР.

Для сокращения пишу для умной таблицы. К тому же она масштабируема, так что добавление участника не приведёт к необходимости корректировки формулы.

Допустим есть таблица исходных данных (Таблица1), в корой представлены список  сотрудников (столбец Name) с датой их приёма на работу (Start) увольнения с должности (Stop) и названием должности (Role). При этом если человек принят, но ещё не уволился, то его ячейка Stop пустая. Нужно найти должность человека (F3) на какую то дату (F4). Попробуйте это через ВПР прописать ради интереса. А вот так делается без ВПР:

Базы данных в Excel. Или ВПР по неограниченному количеству условий Microsoft Excel, Vba, Плюшка, Длиннопост

В ячейке F6 собственно формула поиска.

=ЕСЛИОШИБКА(ПРОСМОТР(2;1/(Таблица1[Name]=F3)/(Таблица1[Start]<=F4)/((Таблица1[Stop]="")+(Таблица1[Stop]>=F4));Таблица1[Role]);"нет данных")


Разберём структуру поиска и задания условий:

Таблица1[Name]=F3 - совпадение имени

Таблица1[Start]<=F4 - дата зачисления на работу меньше даты поиска

(Таблица1[Stop]="")+(Таблица1[Stop]>=F4) - дата поиска или меньше даты увольнения или дата увольнения пустая.

Таблица1[Role] - вывод ячейки для которой все три условия истина.


Как видно формула легко масштабируется под любое количество условий.


Ну вот как то так.

Этим постом я хотел показать, что применение ВПР(ГПР) не всегда оправдано (хотя несомненно знание этих функций обязательно), и есть более простые и лёгкие способы.

Показать полностью 7
[моё] Microsoft Excel Vba Плюшка Длиннопост
17
25
bighouse.live
bighouse.live
3 года назад
MS, Libreoffice & Google docs
Серия Оцифровка

Excel. Долгая дорога оцифровки. Часть 5. Создание пользовательской функции для двух аргументов. Ручной вариант⁠⁠

Итак, если понятно как получить уравнение по имеющемуся графику одного аргумента, то перейдём к следующему этапу: Созданию макроса-функции по диаграмме двух аргументов или Y=f(X1,X2). Внешний вид таких диаграмм на скрине ниже.

Excel. Долгая дорога оцифровки. Часть 5. Создание пользовательской функции для двух аргументов. Ручной вариант Microsoft Excel, Vba, Плюшка, Длиннопост

Так повелось, что для удобства я называю второй аргумент критерием. Просто кроме зависимости от одного или двух аргументов существуют варианты зависимости от трёх и четырёх аргументов. У меня на практике доходило до пяти... Но для всех таких диаграмм была, как правило, общая ось Х.

В данном случае имеется зависимость от двух аргументов (Go, Qт). При этом для второго аргумента есть 10 критериев (Qт = 0, 20…180).

Решение происходит в два этапа:

Этап 1: для каждого критерия прописывается значение критерия и уравнение линии (не обязательно прямой как в данном примере), соответствующей критерию.

Этап 2: производится проверка перебором соотношения заданного критерия и имеющихся. Как только соотношение krit_kriv(i) Krit < krit_kriv(i + 1) выполняется, происходит поиск значения функции с использованием линейной (в данном случае) интерполяции (или просто через пропорцию) по точкам Y(Xзад, krit_kriv(i)) и Y(Xзад, krit_kriv(i+1.))


Т.е. например нужно определить значение при Gо=400 и Qт = 30. Соответственно я понимаю что искомое находится между критериями Qт = 20 и Qт = 40. Нахожу при данных критериях и при Go = 400 значения Gцнд. И через пропорцию определяю каким будет значение при Qт = 30.


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

=====

' Функция линейной интерполяции по двум точкам методом пропорции

' Необходимое условие X1 < X2

Public Function linterp(ByVal X1 As Single, ByVal X2 As Single, ByVal Y1 As Single, ByVal Y2 As Single, ByVal X As Single) As Single

If X2 = X1 Then X2 = X1 + X1 / 10000# ' Убираем совпадение иксов

linterp = Y2 - ((Y2 - Y1) / (X2 - X1)) * (X2 - X)

End Function

=====

Ну и собственно макрос


' Программа является унифицированной для минимизации изменений.

Public Function ris_71(x As Single, Krit As Single) As Single

Dim kriv() As Single ' объявляем динамический массив

Dim krit_kriv() As Single ' объявляем динамический массив

Dim N_kriv As Integer, i As Integer ' объявляем тип числа уравнений

N_kriv = 10 ' ВВОДИМ число кривых

ReDim kriv(1 To N_kriv) ' Изменяем размер массива в соответствии с числом кривых.

ReDim krit_kriv(1 To N_kriv) ' Изменяем размер массива в соответствии с числом кривых

' требование - рост критериев должен быть по нарастающей. Критерий - это второй аргумент функции.

' ВВОДИМ критерии с первой по последнюю кривую в порядке возрастания

krit_kriv(1) = 0#

krit_kriv(2) = 20#

krit_kriv(3) = 40#

krit_kriv(4) = 60#

krit_kriv(5) = 80#

krit_kriv(6) = 100#

krit_kriv(7) = 120#

krit_kriv(8) = 140#

krit_kriv(9) = 160#

krit_kriv(10) = 180#

' ВВОДИМ уравнения кривых в соответствии с критериями

kriv(1) = 0.7324 * x - 1.576 ' соответствует krit_kriv(1) = 0# и т.д.

kriv(2) = 0.7343 * x - 30.41

kriv(3) = 0.7574 * x - 68.76

kriv(4) = 0.7536 * x - 102.2

kriv(5) = 0.756 * x - 142.9

kriv(6) = 0.7311 * x - 173.1

kriv(7) = 0.7582 * x - 221.6

kriv(8) = 0.7461 * x - 260.2

kriv(9) = 0.7894 * x - 323#

kriv(10) = 0.7798 * x - 357.2

If Krit > krit_kriv(N_kriv) Then

' предварительный расчёт результата если критерий больше максимального имеющегося

ris_71 = linterp(krit_kriv(N_kriv - 1), krit_kriv(N_kriv), _

kriv(N_kriv - 1), kriv(N_kriv), Krit)

Else

' проверка положения критерия относительно имеющихся кривых, и проведение линейной аппроксимации.

For i = 1 To N_kriv - 1

If Krit <= krit_kriv(i + 1) Then

ris_71 = linterp(krit_kriv(i), krit_kriv(i + 1), _

kriv(i), kriv(i + 1), Krit)

Exit For

End If

Next i

End If

End Function


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


Т.е. для нового графика потребуется
1. Заменить название. Внимание - менять по всему макросу.

2. Указать количество критериев.

3. Указать значения критериев

4. Указать уравнения описывающие критерии.

Показать полностью 1
[моё] Microsoft Excel Vba Плюшка Длиннопост
9
70
bighouse.live
bighouse.live
3 года назад
MS, Libreoffice & Google docs
Серия Оцифровка

Excel. Долгая дорога оцифровки. Часть 4.  Макрос по созданию макросов апроксимации простых графиков полиномом⁠⁠

"Позабыты хлопоты, остановлен бег, Вкалывают роботы, счастлив человек!"(с)ПЭ

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

Всё базируется на трёх китах:

1. Унификация.

2. Результатом действия макроса может являться текст;

3. В текстовых переменных можно использовать спец символы:

3.1. Знак возврата каретки. vbCr она же символ Chr(13);

3.2. Знак перевода строки. vbLf она же символ Chr(10);

3.3. Символ объёдинения &.

Excel. Долгая дорога оцифровки. Часть 4.  Макрос по созданию макросов апроксимации простых графиков полиномом Microsoft Excel, Vba, Прост, Длиннопост

Ну а теперь пройдём все шаги вместе.


В прошлом посте я говорил про макрос расчёта на основании построения тренда.


====

' Апроксимация полиномом для всего массива исходных данных

' В подпрограмму передаются все заданные точки и апроксимация ведётся по всем точкам!

' Данные из листа Excel

Public Function polinomEx_all(xVal As Range, yVal As Range, x As Single, Optional stepen As Long = 2) As Variant

Dim i As Integer

' Проверка требования "число элементов массива на 1 больше чем степень полинома"

If xVal.Count < stepen + 1 Then

stepen = xVal.Count - 1

End If

polinomEx_all = 0#


Select Case stepen


Case 1 ' Уравнение а·х+b

For i = 1 To stepen + 1

polinomEx_all = polinomEx_all + (x ^ (stepen + 1 - i)) * Application.Index(WorksheetFunction.LinEst(yVal, xVal, True, True), 1, i)

Next i


Case 2 ' Уравнение а·х^2+b·x+c

For i = 1 To stepen + 1

polinomEx_all = polinomEx_all + _

(x ^ (stepen + 1 - i)) * Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2)), True, True), 1, i)

Next i


Case 3 ' Уравнение а·х^3+b·x^2+c·x+d

For i = 1 To stepen + 1

polinomEx_all = polinomEx_all + _

(x ^ (stepen + 1 - i)) * Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2, 3)), True, True), 1, i)

Next i


Case 4 ' Уравнение а·х^4+b·x^3+c·x^2+d·x+e

For i = 1 To stepen + 1

polinomEx_all = polinomEx_all + _

(x ^ (stepen + 1 - i)) * Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2, 3, 4)), True, True), 1, i)

Next i


Case 5 ' Уравнение а·х^5+b·x^4+c·x^3+d·x^2+e·x+f

For i = 1 To stepen + 1

polinomEx_all = polinomEx_all + _

(x ^ (stepen + 1 - i)) * Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2, 3, 4, 5)), True, True), 1, i)

Next i


Case 6 ' Уравнение а·х^6+b·x^5+c·x^4+d·x^3+e·x^2+f·x+g

For i = 1 To stepen + 1

polinomEx_all = polinomEx_all + _

(x ^ (stepen + 1 - i)) * Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2, 3, 4, 5, 6)), True, True), 1, i)

Next i


Case 7 ' Уравнение а·х^7+b·x^6+c·x^5+d·x^4+e·x^3+f·x^2+g·x+h

For i = 1 To stepen + 1

polinomEx_all = polinomEx_all + _

(x ^ (stepen + 1 - i)) * Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2, 3, 4, 5, 6, 7)), True, True), 1, i)

Next i

Case Else

End Select

End Function

====

Как видно - ничего сложного в этом макросе нет. В соответствии с заявленной степенью полинома происходит перемножение заданного Х в соответствующей степени на соответствующий коэффициент полинома. Коэф-ты вычисляются точно так же как вычислялись на листе экселя.

Т.е.

WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2, 3, 4)), True, True)

полностью совпадает с

ЛИНЕЙН(Y; X{1;2;3;4}; True; True)


Ну а теперь просто заменим расчёт на составление текстовой переменной

=====

' Апроксимация полиномом для всего массива исходных данных

' В подпрограмму передаются все заданные точки и апроксимация ведётся по всем точкам!

' Данные из листа Excel

' Результат работы программы - текст (уравнение полинома)

Public Function polinomExStr(ByVal xVal As Range, ByVal yVal As Range, Optional stepen As Long = 2) As Variant

' Проверка требования "число элементов массива на 1 больше чем степень полинома"

Dim i As Integer

If xVal.Count < stepen + 1 Then

stepen = xVal.Count - 1

End If

polinomExStr = ""


Select Case stepen


Case 1 ' Уравнение а·x+c

For i = 1 To 2

polinomExStr = polinomExStr & " + X ^ " & (2 - i) & " * " _

& Format(Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1)), True, True), 1, i), "0.###E+")

Next i


Case 2 ' Уравнение а·х^2+b·x+c

For i = 1 To 3

polinomExStr = polinomExStr & " + X ^ " & (3 - i) & " * " _

& Format(Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2)), True, True), 1, i), "0.###E+")

Next i


Case 3 ' Уравнение а·х^3+b·x^2+c·x+d

For i = 1 To 4

polinomExStr = polinomExStr & " + X ^ " & (4 - i) & " * " _

& Format(Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2, 3)), True, True), 1, i), "0.###E+")

Next i


Case 4 ' Уравнение а·х^4+b·x^3+c·x^2+d·x+e

For i = 1 To 5

polinomExStr = polinomExStr & " + X ^ " & (5 - i) & " * " _

& Format(Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2, 3, 4)), True, True), 1, i), "0.###E+")

Next i


Case 5 ' Уравнение а·х^5+b·x^4+c·x^3+d·x^2+e·x+f

For i = 1 To 6

polinomExStr = polinomExStr & " + X ^ " & (6 - i) & " * " _

& Format(Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2, 3, 4, 5)), True, True), 1, i), "0.###E+")

Next i


Case 6 ' Уравнение а·х^6+b·x^5+c·x^4+d·x^3+e·x^2+f·x+g

For i = 1 To 7

polinomExStr = polinomExStr & " + X ^ " & (7 - i) & " * " _

& Format(Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2, 3, 4, 5, 6)), True, True), 1, i), "0.###E+")

Next i


Case 7 ' Уравнение а·х^7+b·x^6+c·x^5+d·x^4+e·x^3+f·x^2+g·x+h

For i = 1 To 8

polinomExStr = polinomExStr & " + X ^ " & (8 - i) & " * " _

& Format(Application.Index(WorksheetFunction.LinEst(yVal, Application.Power(xVal, Array(1, 2, 3, 4, 5, 6, 7)), True, True), 1, i), "0.###E+")

Next i

Case Else

End Select

End Function

=====


Ну или немного в другом виде с учётом ряда особенностей и модификаций

=====

' Программа формирования текста макроса для функции одного уравнения

Public Function fun_macros_Y(xVal As Range, yVal As Range, PolyStep As Long, _

Optional Name_f As String = "Nomogramma", _

Optional Opisanie As String = " Уравнение ", _

Optional NameX As String = "Xisk") As Variant

Dim j As Long

Dim N As Long

Dim k As Long

Dim stepen As Long

Dim xn() As Double ' заявляем массив X

Dim yn() As Double ' заявляем массив Y

Dim c() As Double ' заявляем массив c - коэффециенты уравнения полинома

fun_macros_Y = "" & Chr(10) & "' " & Opisanie & Chr(10)

fun_macros_Y = fun_macros_Y & "Public Function " & Name_f & "(ByRef " & NameX & " As Single) As Variant" & Chr(10)

Dim Nna4 As Long 'Номер начала диапазона.

Dim Nkon As Long 'Номер конца диапазона.

Nna4 = 1

Nkon = xVal.Count

' Проверяем на соответствие число элементов участка степени полинома

If (Nkon - Nna4) < PolyStep Then

stepen = (Nkon - Nna4)

Else

stepen = PolyStep

End If

' Заполняем матрицы участка

ReDim xn(1 To (Nkon - Nna4 + 1), 1 To stepen)

ReDim yn(1 To (Nkon - Nna4 + 1), 1 To 1)

ReDim c(1 To stepen + 1) As Double

For j = 1 To (Nkon - Nna4 + 1)

xn(j, 1) = xVal.Rows(j + Nna4 - 1)

For N = 2 To stepen

xn(j, N) = xn(j, 1) ^ N

Next N

yn(j, 1) = yVal.Rows(j + Nna4 - 1)

Next j

' Делаем расчёт и вывод.

fun_macros_Y = fun_macros_Y & Name_f & " = "

For k = 1 To stepen + 1 Step 1

c(k) = Format(Application.Index(WorksheetFunction.LinEst(yn, xn, True, True), 1, k), "0.####E+")


If c(k) >= 0 And k > 1 Then

fun_macros_Y = fun_macros_Y & " + " & c(k)

Else

fun_macros_Y = fun_macros_Y & c(k)

End If


If (stepen + 1 - k) > 0 Then

fun_macros_Y = fun_macros_Y & " * " & NameX & " ^ " & (stepen + 1 - k) & " "

End If

Next k


fun_macros_Y = fun_macros_Y & Chr(10) & "End Function" & Chr(10)

End Function

=====


Макрос ждёт в качестве вводных данных:

xVal - столбец известных Х

yVal - столбец известных Y

PolyStep - желаемую степень уравнения. Если точек будет меньше чем требуется для степени - на уменьшится

Name_f - название получаемого макроса. Опционально. Если не задать будет Nomogramma

Opisanie - описание получаемого макроса. Опционально. Если не задать будет Уравнение

NameX - название/имя аргумента. Опционально. Если не задать будет Xisk


Вызов макроса:

=ПОДСТАВИТЬ(fun_macros_Y(X; Y; 3; "fun_пример"; "Пример создания макроса"; "Go");",";".")


=ПОДСТАВИТЬ( ;",";".") требуется для замены запятых на точки. Иначе будет казус - VBA в качестве разделителя целой и дробной части использует точку, а в текстом виде (по крайней мере в рус.экселе) разделитель запятая.

Обратите внимание, что

"fun_пример"; "Пример создания макроса"; "Go" - текстовые, т.е. заключаются в кавычки

"fun_пример";  "Go" - должны соответствовать требованиям к переменным. Т.е. не должны содержать пробелов, не должны совпадать с имеющимися переменными или названиями ячеек/диапазонов.


Результатом выполнения макроса будет (поставил 3-ю степень чтобы результат влез в окно поста):

"

' Пример создания простого макроса

Public Function fun_Wтф(ByRef Go As Single) As Variant

fun_Wтф = 0.00000056401 * Go ^ 3 -0.001952 * Go ^ 2 + 1.3842 * Go ^ 1 + 25.341

End Function

"

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


Если есть желание повысить количество знаков коэффициентов - правим формат "0.####E+"


Для ускорения работы у меня собраны листы/шаблоны позволяющие не лезть в заполнение вызова макросов.

Вызов макроса для данного случая у меня выглядит так (в Е9):

=ПОДСТАВИТЬ(fun_macros_Y(B3:ДВССЫЛ("B"&E4);C3:ДВССЫЛ("C"&E4);M7;E7;G5;G7);",";".")

Excel. Долгая дорога оцифровки. Часть 4.  Макрос по созданию макросов апроксимации простых графиков полиномом Microsoft Excel, Vba, Прост, Длиннопост

Как заполнены дополнительные столбцы А, D и ячейки Е4 и т.д. видно на скрине.

Столбец А - контроль верности снятия данных (по возрастанию Х).

Столбец D - подсчёт снятых точек.

В итоге выполнение/изготовление макроса для меня сводится в вставке исходных данных начиная с ячейки В3, и затем жёлтых полей ввода описания, ввода названия новой функции и аргумента, выбора степени. Т.е. занимает не более минуты.


Для наблюдательных - присутствующие в макросе Dim Nna4 As Long 'Номер начала диапазона.

Dim Nkon As Long 'Номер конца диапазона.

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


Для продвинутых - да, можно обойтись без доп.столбцов А и D, да и E4 лишнее. И то и другое можно реализовать в макросе, но...но данный лист был так сформирован на основании удобства для меня - могу оперативно проверить правильность и полноту вставки исходных данных, отсутствие сбоев "снятия" точек с картинки при массовой оцифровке. И вообще - "работает? Стабильно? Без сбоев? Не трожь!" (с)Анекдот. Вам ничто не мешает сделать иначе.


=========

dixi


Краткий план:

Теория вкратце [ Часть 1. ]

Забираем данные с листа. [ Часть 2. ]

Апроксимация простых графиков полиномом средствами Excel [ Часть 3.]

Макрос по созданию макросов апроксимации простых графиков полиномом [ Часть 4.] Этот пост

Апроксимация графиков двух аргументов полиномом [ Часть 5.]

Кусочная интерполяция простых графиков [ Часть 6.]

Показать полностью 1
[моё] Microsoft Excel Vba Прост Длиннопост
8
46
bighouse.live
bighouse.live
3 года назад
MS, Libreoffice & Google docs
Серия Оцифровка

Excel. Долгая дорога оцифровки. Часть 3. Апроксимация простых графиков полиномом средствами Excel⁠⁠

Итак, мы имеем набор точек XY и нам требуется определить значение между заданными (опорными) точками. Начнём с самого простого варианта - набор точек позволяет найти уравнение полиномиального вида, которое с достаточной нам точностью описывает поведение функции с учётом имеющихся точек. Это будет в 90% апроксимация т.к. помним про погрешности связанные со снятием точек. Т.е. значения полученные по данной функции будут отличаться от заданных изначально. Кроме вариантов при степени полинома на 1 меньше количества точек (например полином 5-й степени, а известных точек 6-ть).

Excel. Долгая дорога оцифровки. Часть 3. Апроксимация простых графиков полиномом средствами Excel Microsoft Excel, Vba, Прост, Длиннопост

Стоит учитывать, что описанный ниже способ подходит только в ограниченном количестве случаев:

- требует заказчик;

- зависимость явно полиномиальная.

Итак, в общем случае всё сводится к пяти шагам:

1. По имеющимся данным построить точечный график.

2. По построенным точкам выполнить построение линии тренда.

3. Подобрать степень полиномиальной зависимости таким образом, чтобы внешний вид (прохождение около/через заданные точки) соответствовал изначальному графику (тот что был на картинке). Проверить, возможно полином не лучший вариант.

4. Отобразить уравнение линии тренда на диаграмме и, если зависимость полиномиальная, становить формат чисел "Экспоненциальный" Число знаков - не менее 3х знаков.

5. Скопировать полученное уравнение и использовать в дальнейшем.

Excel. Долгая дорога оцифровки. Часть 3. Апроксимация простых графиков полиномом средствами Excel Microsoft Excel, Vba, Прост, Длиннопост

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

Ещё одно заблуждение - "чем больше степень полинома, тем точнее". К сожалению, если по оси Х значения в десятках тысяч, а по оси Y в единицах фактически не реально найти полином выше 5-й степени. Точнее определить с достаточной достоверностью его коэффициенты (просто не хватает 15-ти знаков).

Определение коэффициентов полинома.

Как видно на скриншоте выше извлечение коэффициентов полинома происходит совсем не сложно.

=ИНДЕКС(ЛИНЕЙН(F4:F13;E4:E13^{1;2;3;4;5;6});1;7)

где {1;2;3;4;5;6} - степень полинома, 7 - порядковый номер коэффициента.

И об этом написано в многих местах. Но вот то что не написано - извлечённые таким способом иногда не совсем соответствуют коэф-ам уравнения на диаграмме, а иногда совсем не соответствуют.

Excel. Долгая дорога оцифровки. Часть 3. Апроксимация простых графиков полиномом средствами Excel Microsoft Excel, Vba, Прост, Длиннопост

Это внутренняя математика Excel и  может быть вызвано целым рядом причин. Основные:

- Значительный разрыв исходных данных. Например есть несколько сот снятых точек от 0 до 10, затем отсутствие снятых точек от 10 до 20, затем несколько сот точек с 20 до 50.

- Значительные степени чисел (как на скрине выше).

Выходом из данной ситуации является следующий макрос-костыль который забирает данные из указанного диапазона ( в примере - "B2:B6"  Данные Х  и "C2:C6" -  Данные Y), строит график, на графике строит линию тренда с заявленной степенью (в примере вторая - Order = 2), копирует строку уравнения, распарсивает её и выкидывает в столбец (  в примере - начиная с ячейки E2 и вниз) коэффициенты полин.уравнения. Построенный график удаляется...


Sub Polynomial()

Dim rX As Range

Dim rY As Range

Dim rOut As Range

Dim dataLabelText As String

Dim coefficients As Variant

Set rX = ActiveSheet.Range("B2:B6") ' Данные Х

Set rY = ActiveSheet.Range("C2:C6") ' Данные Y

Set rOut = ActiveSheet.Range("E2") ' Место выгрузки коэф-в

dataLabelText = Извлечение_Полинома(rX, rY)

coefficients = Извлечение_коэффициентов(dataLabelText)

With rOut.Resize(UBound(coefficients, 1) + 1, UBound(coefficients, 2))

'назначаем формат для избежания ошибок при вставке получившихся формул

.NumberFormat = "#.####E+00"

.Value = coefficients

End WithEnd Sub


Private Function Извлечение_коэффициентов(dataLabelText As String) As Variant

Dim i As Integer

Dim rez() As Variant, txt As Variant

txt = Split(dataLabelText, "x")

ReDim rez(LBound(txt) To UBound(txt), 1 To 2)

For i = LBound(txt) To UBound(txt)

txt(i) = Right(txt(i), IIf(i = LBound(txt), (Len(txt(i)) - 2), (Len(txt(i)) - 1)))

rez(i, 1) = i: rez(i, 2) = txt(i)

Next i

Извлечение_коэффициентов = rez

End Function


Function Извлечение_Полинома(rX As Range, rY As Range) As String

Dim MyChart As Chart

Dim text As String

Dim dt As Date

Set MyChart = ActiveSheet.Shapes.AddChart2(, , , , 450, 300).Chart

With MyChart

.SeriesCollection.NewSeries

.SeriesCollection(1).XValues = rX

.SeriesCollection(1).Values = rY

.ChartType = xlXYScatter

.FullSeriesCollection(1).Trendlines.Add

With .FullSeriesCollection(1).Trendlines(1)

.Type = xlPolynomial

.Order = 2 ' Указываем степень полинома

.DisplayEquation = True

.DataLabel.NumberFormat = "#.####E+00"

dt = Now

DoEvents ' Задержка. См. ниже

DoEvents ' Задержка. См. ниже

Do

If .DataLabel.text <> "" Then Exit Do

If dt < Now - TimeSerial(0, 1, 0) Then Exit Do

For i = 1 To 100: DoEvents: Next

Loop

text = .DataLabel.text

End With

End With

Извлечение_Полинома = text

MyChart.Parent.Delete

End Function


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


Быстрое определение искомого Y по заданному X.

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

Excel. Долгая дорога оцифровки. Часть 3. Апроксимация простых графиков полиномом средствами Excel Microsoft Excel, Vba, Прост, Длиннопост

Сокращённый вид макроса за авторством БМВ расположен ниже. Расширенный частично на скрине выше. Он понадобится нам в следующем посте, когда будем делать макрос по созданию макросов ), и там будет представлен полностю.


Public Function polinomEx(xVal As Range, yVal As Range, X As Single, stepen As Integer)

Dim I As Integer

Dim Seria

Seria = Array(1, 2, 3, 4, 5, 6, 7)

If stepen > 7 Then stepen = 7

If xVal.Count < stepen + 1 Then stepen = xVal.Count - 1

polinomEx = 0#

ReDim Preserve Seria(stepen - 1)

For I = 1 To stepen + 1

polinomEx = polinomEx + _

(X ^ (stepen + 1 - I)) * _

Application.Index(WorksheetFunction.LinEst(yVal, _

IIf(stepen = 1, xVal, Application.Power(xVal, Seria)), _

True, True), 1, I)

Next I

End Function

Excel. Долгая дорога оцифровки. Часть 3. Апроксимация простых графиков полиномом средствами Excel Microsoft Excel, Vba, Прост, Длиннопост

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


И да, все заметили что посредством макроса есть возможность построить полином 7-й степени, тогда как линия тренда позволяет выполнять это только до 6-й?


Дальнейшее использование уравнения апроксимации.

Существует всего два подхода:

- Хранить исходные данные на листе. Или в виде таблицы, или в виде уравнения в ячейке.

- Хранить уравнение в виде макроса.


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


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

===========

Краткий план:

Теория вкратце [ Часть 1. ]

Забираем данные с листа. [ Часть 2. ]

Апроксимация простых графиков полиномом средствами Excel [ Часть 3.] Этот пост

Макрос по созданию макросов апроксимации простых графиков полиномом [ Часть 4.]

Апроксимация графиков двух аргументов полиномом [ Часть 5.]

Кусочная интерполяция простых графиков [ Часть 6.]

Показать полностью 4
[моё] Microsoft Excel Vba Прост Длиннопост
1
72
bighouse.live
bighouse.live
3 года назад
MS, Libreoffice & Google docs
Серия Оцифровка

Excel. Долгая дорога оцифровки. Часть 2. Забираем данные с листа⁠⁠

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

Первым этапом оцифровки будет получение набора данных XY соответствующих имеющейся кривой.

Excel. Долгая дорога оцифровки. Часть 2. Забираем данные с листа Microsoft Excel, Vba, Прост, Длиннопост

Некоторые РД (документация заводов-изготовителей, НТД, ТЭХ, ТНХ и т.д) предоставляют функции/уравнения, соответствующие графикам/номограммам. Однако стоит знать, что иногда предоставленная функция может не соответствовать предоставленному графику и требует проверки.

До проведения "снятия" точек требуется обработать отсканированный (если он таковой) график. А именно:

- максимально уменьшить искажения типа "горб" или "рыбий глаз. Т.е. сделать все вертикальные и горизонтальные линии параллельными между собой соответственно.

- максимально сделать перпендикулярными вертикальную и горизонтальную оси.

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


В далёком прошлом помню варианты "снятия" точек путём вставки картинки в автокад, простановки точек, их переписывания и пересчёта... Сейчас же при отсутствии функций-зависимостей следует воспользоваться программой Graph2Digit, GetData Graph Digitizer или аналогичной. GetData Graph Digitizer продаётся за денежку, но т.к. я начинал работать с ней, она установлена у меня на работе (а у нас нельзя самому ставить софт), то показывать буду на ней. Но тут скорее дело привычки, и пары удобств, которых не помню в Graph2Digit - типа возможности снятия точек с нескольких линий.

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

Excel. Долгая дорога оцифровки. Часть 2. Забираем данные с листа Microsoft Excel, Vba, Прост, Длиннопост

Для желающих - выбираем язык программы.

Excel. Долгая дорога оцифровки. Часть 2. Забираем данные с листа Microsoft Excel, Vba, Прост, Длиннопост

1. Установить оси. Потребуется установить точки минимального Х, максимального Х, минимального У, максимального У. При этом, как видно на скриншоте выше, достаточно установить точки там, где заведомо известны значения. Например максимальный Х задан как 400, хотя график продолжается и далее - значение по осям будут пересчитаны соответственно.

2. Ручная простановка точек. В ручном режиме наводится на место снятия точки, при этом в увеличенном виде это место отображается справа в нижнем углу, и ЛКМ фиксируем точку. Все снятые точки отображаются в таблице справа.

3. Копирование снятых точек в буфер обмена. В дальнейшем "снятые" точки копируются в лист Excel, и с ними производятся различные манипуляции.



Это был описаны основные действия при ручном снятии.

Основные вопросы:

Насколько часто требуется производить "снятие" точек? Вопрос сложный... Но из опыта - линия, что связывает две проставленные точки, в идеале должна находиться внутри линии графика.

Что делать, если был не верно указан диапазон (например вместо Хмакс=1000 записали Хмакс=100)? Ничего страшного. Точки заново расставлять вдоль линии не надо, достаточно зайти в "Текущее состояние" - "Параметры" и задать правильное параметров осей.

Excel. Долгая дорога оцифровки. Часть 2. Забираем данные с листа Microsoft Excel, Vba, Прост, Длиннопост

Несколько советов:

- сохранять поле снятых точек. т.е. файл *.gdw. В дальнейшем, если обнаружится не верное отображение точек, легко проверить правильность указания осей. Дело в том, что если график один, то точки снимаются внимательно, и аккуратно. А когда ставится на поток, по 50 графиков в час, то бывают и плюхи...

- выставлять следующие настройки (в дальнейшем облегчат автоматическое получение макросов):

Excel. Долгая дорога оцифровки. Часть 2. Забираем данные с листа Microsoft Excel, Vba, Прост, Длиннопост

- немного забегая вперёд (постов эдак на 4). снятие точек производить от меньшего Х к большему. При наличии диаграммы зависимости от двух аргументов типаY(X1, X2) начиная с графика меньшего Х2.Т.е. см.диаграмму внизу - имеется зависимость qт(Nт,Qт). Снятие точек начинаем с Qт=0, Nт = 40... 120, затем с Qт=20, Nт = 40... 120 и т.д. С обязательным условием - каждая следующая линия должна начинаться с Х меньшего, чем закончилась предыдущая... Может немного сумбурно, но если понятней по видео, то вот - https://youtu.be/AXnTdHlmn34

- Нужно помнить, что погрешность оцифровки составляет толщину линии, и для вертикальных участков кривых может достигать 2%. Дополнительная погрешность вызывается искривлением графика при печати/сканировании. Поэтому точки, полученные в результате такого снятия можно, и подчас нужно, редактировать. Например, если Вы точно знаете что при Х=10 Y должен ровняться 20, а по снятым данным выходит 19.95, то или производится правка данной точки (заменяется на 20), или все точки поднимаются на 0,05 (+0,05).

При этом точность определения значений с помощью линейки и карандаша заведомо ниже, чем при использовании интерполированных кривых.

===========

Краткий план:

Теория вкратце [ Часть 1. ]

Забираем данные с листа. [ Часть 2. ] Этот пост

Апроксимация простых графиков полиномом средствами Excel [ Часть 3.]

Макрос по созданию макросов апроксимации  простых графиков полиномом [ Часть 4.]

Апроксимация графиков двух аргументов полиномом [ Часть 5.]

Кусочная интерполяция простых графиков  [ Часть 6.]

....

Показать полностью 4
[моё] Microsoft Excel Vba Прост Длиннопост
0
31
bighouse.live
bighouse.live
3 года назад
MS, Libreoffice & Google docs

Прореживание маркеров⁠⁠

Избыточное количество данных одного графика диаграммы приводит к трудности использования маркеров для обозначения линии. При этом отказываются от маркеров, применяют пунктирные/штрихпунктирные линии, выполняют выноски/подписи и т.д. Однако есть способ проще - провести "прополку" маркеров. Разница отчётливо видна на скриншоте:

Прореживание маркеров Microsoft Excel, Vba, Плюшка, Длиннопост

Для этого можно воспользоваться макросом:

' ===========================

Sub Прореживание_маркеров()

' Активируем диаграмму

ActiveSheet.ChartObjects("Прореживание_после").Activate

' Перебор по всем графикам диаграммы

For k = 1 To ActiveChart.FullSeriesCollection.Count

' Удаляем маркеры на линии за исключением указанного шага

For i = 1 To ActiveChart.SeriesCollection(k).Points.Count

If (i Mod 9) <> 0 Then

ActiveChart.FullSeriesCollection(k).Points(i).MarkerStyle = -4142

End If

Next i

Next k

End Sub

' ===========================

где:

"Прореживание_после" - название диаграммы

"i Mod 9" - указание частоты оставленных маркеров. В данном примере остаётся каждый 9-й маркер, начиная с 9-го.

Из минусов можно отметить необходимость выставления всех маркеров перед каждым прореживанием.


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

' ===========================

Sub Прореживание_маркеров_2()

' Активируем диаграмму

ActiveSheet.ChartObjects("Прореживание_после").Activate

' Перебор по всем графикам диаграммы

For k = 1 To ActiveChart.FullSeriesCollection.Count

' Удаляем все маркеры на линии

For i = 1 To ActiveChart.SeriesCollection(k).Points.Count

ActiveChart.FullSeriesCollection(k).Points(i).Select

Selection.MarkerStyle = -4142

Next i

' Выставляем маркеры с требуемым шагом.

For i = 1 To ActiveChart.SeriesCollection(k).Points.Count Step 9 ' Указываем частоту маркеров

ActiveChart.FullSeriesCollection(k).Points(i).Select

With Selection

' Тип маркеров будет разным для каждой линии (если линий до 9-ти)

' Если линий более 9-ти, то можно указывать заливки/границы маркера

.MarkerStyle = k

' Указание размера маркера

.MarkerSize = 7 

End With

Next i

Next k

End Sub

' ===========================

Если маркеры двух графиков "налезают" друг на друга, то можно сдвинуть их отображение, например используя номер графика "(i + k * 3)":

' ===========================

Sub Прореживание_маркеров()

' Активируем диаграмму

ActiveSheet.ChartObjects("Прореживание_после").Activate

' Перебор по всем графикам диаграммы

For k = 1 To ActiveChart.FullSeriesCollection.Count

' Удаляем маркеры на линии за исключением указанного шага

For i = 1 To ActiveChart.SeriesCollection(k).Points.Count

If ((i + k * 3) Mod 9) <> 0 Then

ActiveChart.FullSeriesCollection(k).Points(i).MarkerStyle = -4142

End If

Next i

Next k

End Sub

' ===========================

Прореживание маркеров Microsoft Excel, Vba, Плюшка, Длиннопост

dixi.

' ===========================

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

Показать полностью 1
[моё] Microsoft Excel Vba Плюшка Длиннопост
4
Посты не найдены
О Нас
О Пикабу
Контакты
Реклама
Сообщить об ошибке
Сообщить о нарушении законодательства
Отзывы и предложения
Новости Пикабу
RSS
Информация
Помощь
Кодекс Пикабу
Награды
Команда Пикабу
Бан-лист
Конфиденциальность
Правила соцсети
О рекомендациях
Наши проекты
Блоги
Работа
Промокоды
Игры
Скидки
Курсы
Зал славы
Mobile
Мобильное приложение
Партнёры
Промокоды Biggeek
Промокоды Маркет Деливери
Промокоды Яндекс Путешествия
Промокоды М.Видео
Промокоды в Ленте Онлайн
Промокоды Тефаль
Промокоды Сбермаркет
Промокоды Спортмастер
Постила
Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии