1. Обязательно представиться на русском языке кириллицей (заполнить поле "Имя").
  2. Фиктивные имена мы не приветствуем. Ивановых и Пупкиных здесь уже достаточно.
  3. Не писать свой вопрос в первую попавшуюся тему - вместо этого создать новую тему.
  4. За поиск, предложение и обсуждение пиратского ПО и средств взлома - бан без предупреждения.
  5. Рекламу и частные объявления "куплю/продам/есть халтура" мы не размещаем ни на каких условиях.
  6. Перед тем как что-то написать - читать здесь и здесь, а студентам - обязательно здесь.
  7. Не надо писать в ЛС администраторам свои технические вопросы. Администраторы форума отлично знают как работает форум, а не все-все контроллеры, о которых тут пишут.

Операции в отчетах

Сценарии / Модули API

Модератор: специалисты Eplan

Ответить

Автор темы
Hurog
здесь недавно
здесь недавно
Сообщения: 6
Зарегистрирован: 04 ноя 2019, 14:05
Имя: Павел
Страна: Казахстан
город/регион: Караганда
Благодарил (а): 6 раз
Поблагодарили: 3 раза

Операции в отчетах

Сообщение Hurog »

Доброго дня!
Решил освоить операции в отчётах. Есть задача, в таблице схемы автоматизации нарисовать кружки на соответствующих позиция по свойствам дискретных/аналоговых входов/выходов. Для того чтобы нарисовать круг требуется указать его месторасположение (страница и координаты).
Возникли пара вопросов:
1) Подскажите, как в операции обратиться к месторасположению текста заполнителя, которым она вызывается?
2)И можно ли в операцию передать, на какое свойство она должна сейчас смотреть? Т.е. не писать операцию отдельно для аналоговых входов, отдельно для выходов, а принимать это свойство из вызова операции.
Аватара пользователя

Barmaley4
знаток Eplan
знаток Eplan
Сообщения: 50
Зарегистрирован: 30 окт 2018, 09:17
Имя: Павел
Страна: РФ
город/регион: Москва
Благодарил (а): 2 раза
Поблагодарили: 50 раз

Операции в отчетах

Сообщение Barmaley4 »

Сомневаюсь, что в форме отчёта можно выполнить операцию в элементе "графика", вроде такое только с текстом заполнителем можно делать.
Я вижу 2 подхода к решению этого вопроса:
1) использовать вместо кружка букву О и выводить её в отдельный текст заполнитель
2) проходиться по сгенерированным отчётам после завершения генерации отчёта и ставить Circle по фиксированному отступу от ОУ в строке. Естественно нужно будет во время генерации отчёта составлять массив сгенерированных значений для последующего поиска содержимого в PlaceHolderText на странице отчёта.

Автор темы
Hurog
здесь недавно
здесь недавно
Сообщения: 6
Зарегистрирован: 04 ноя 2019, 14:05
Имя: Павел
Страна: Казахстан
город/регион: Караганда
Благодарил (а): 6 раз
Поблагодарили: 3 раза

Операции в отчетах

Сообщение Hurog »

Barmaley4 писал(а): 05 окт 2021, 14:28 операцию в элементе "графика", вроде такое только с текстом заполнителем можно делать.
Я и хочу в тексте заполнителе вызывать операцию, которая рисует кружок. Но мне надо в Arc.Create(Page) передать страницу и в Arc.SetCircle(PointD) вставить координаты, по которым вставляется текст заполнитель, который вызвал эту операцию.
Такое возможно?
Аватара пользователя

Barmaley4
знаток Eplan
знаток Eplan
Сообщения: 50
Зарегистрирован: 30 окт 2018, 09:17
Имя: Павел
Страна: РФ
город/регион: Москва
Благодарил (а): 2 раза
Поблагодарили: 50 раз

Операции в отчетах

Сообщение Barmaley4 »

В штатном функционале работы с кастомными отчётами такой функции нет. Теоритически можно конечно вызывать запрос у проекта страниц во время каждой операции, и выбирать оттуда все групповые спецификации или какая там форма выбрана, но тут есть 2 нюанса:
1. Я предполагаю, что страница отчёта создаётся как Page.Create только после заполнения данных на этой странице, а следовательно вряд ли получится получить её как объект для вставки графики (только как незаконченный инстанс) прямо с первой операции в тексте заполнителе.
2. Плохая идея лезть во внутренние процессы системных экшенов, т.к. форма и области данных рисуются той же графикой, генерация новых областей может быть воспринята не корректно если появятся новые объекты типа графика, т.к. они могут сбить внутренний механизм добавления новых областей данных после операции относительно уже сгенерированых областей данных.

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

Автор темы
Hurog
здесь недавно
здесь недавно
Сообщения: 6
Зарегистрирован: 04 ноя 2019, 14:05
Имя: Павел
Страна: Казахстан
город/регион: Караганда
Благодарил (а): 6 раз
Поблагодарили: 3 раза

Операции в отчетах

Сообщение Hurog »

Значит буду копать в этом направлении. Спасибо. :thankyou:

Евгений Кузнецов
здесь недавно
здесь недавно
Сообщения: 72
Зарегистрирован: 01 окт 2009, 15:57
Имя: Евгений К.
Благодарил (а): 15 раз
Поблагодарили: 2 раза

Операции в отчетах

Сообщение Евгений Кузнецов »

Увы, ничего не могу подсказать по теме, но поражен обсуждаемыми вопросами и тем, как коллеги расширяют функциональность.
@Hurog - опубликуете финальный результат?
@Barmaley4 - не могли бы Вы показать свои наработки посредством API?
Спасибо.

Автор темы
Hurog
здесь недавно
здесь недавно
Сообщения: 6
Зарегистрирован: 04 ноя 2019, 14:05
Имя: Павел
Страна: Казахстан
город/регион: Караганда
Благодарил (а): 6 раз
Поблагодарили: 3 раза

Операции в отчетах

Сообщение Hurog »

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

Из относительно работающего сделал пока такое:

Код: Выделить всё

using System;
using System.Windows.Forms;
using Eplan.EplApi.DataModel;
using Eplan.EplApi.ApplicationFramework;
using Eplan.EplApi.HEServices;
using Eplan.EplApi.DataModel.Topology;

namespace Eplan.EplAddIn.EplanCnC
{
    class CTopoCalc
    {
        public class Action_Test : IEplAction
        {
            public bool OnRegister(ref string Name, ref int Ordinal)
            {
                Name = "CTopoCalc";
                Ordinal = 20;
                MessageBox.Show("Command CTopoCalc registred", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return true;
            }
            public bool Execute(ActionCallingContext oActionCallingContext)
            {
                using (LockingStep oLS = new LockingStep())
                {   //... доступ к данным P8 ...
                    SelectionSet selectionSet = new SelectionSet(); //объявляем набор выбора объектов
                    StorableObject[] storableObjects = selectionSet.Selection; //заносим все объекты в обрабатываемые объекты
                    if (storableObjects.Length == 0) //проверяем выбраны ли объекты
                    {
                        MessageBox.Show("Не выбран сегмент", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return true;
                    }
                    if (storableObjects.Length != 0) //если объекты выбранны
                    {
                        foreach (StorableObject sp in storableObjects) // перебор каждого объекта из обрабатываемых объектов
                        {
                            if (sp is Segment) //если объект является сегментом
                            {
                            SegmentPropertyList spList = ((Segment)sp).Properties; //создаём лист свойств сегмента текущего обрабатываемого объекта
                               Article mArticle = ((Segment)sp).ArticleReferences[0].Article; // объявляем основным обрабатываем изделие на нулевой позиции
                                uint uintDevCount = Convert.ToUInt32((spList.CABLINGSEGMENT_LENGTH_AUTO + 0.499) / ((mArticle.Properties.ARTICLE_DELIVERYLENGTH) / 1000))+1; //подсчёт колличества изделий для заказа
                                ((Segment)sp).Properties.FUNC_ARTICLE_COUNT[1] = uintDevCount; // присвоение колличества изделий на первой позиции
                                Article.Accessory[] accessories = mArticle.ArticleAccessories; //создание списка принадлежностей для первого изделия списка
                                for (int i=0; i <= accessories.Length -1 ; i++ ) //начинается цикл присвоения изделий из списка принадлежностей
                                {
                                    if (accessories[i].Name.Length != 0) // если изделие в списке принадлежностей названо
                                    {
                                        bool tag = true; // объявляем переменную индикации наличия изделия из списка принадлежностей в списке изделий
                                        foreach (ArticleReference references in ((Segment)sp).ArticleReferences) // для каждой ссылки изделия с писке ссылок изделий
                                        {
                                            if (references.PartNr == accessories[i].Name) // если изделие уже имеется в списке индикатор скидывается на 0
                                            {
                                                tag = false; 
                                            }
                                        }
                                        if (tag) // если изделий не было в списке
                                        {
                                            if (i == 0) // если изделие первое в списке принадлежностей. первые в списках принадлежностей должны распологаться лотки
                                            {
                                                ((Segment)sp).AddArticleReference(accessories[i].Name, "1", uintDevCount); // создание ссылки в списке изделий
                                            }
                                            else
                                            {
                                                ((Segment)sp).AddArticleReference(accessories[i].Name, "1", (uintDevCount * 2 + 1)); // создание ссылки в списке изделий
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                return true;
            }
            public void GetActionProperties(ref ActionProperties actionProperties)
            {

            }
        }
    }
}
Считает количество условно лотков для заказа по длине выбранного сегмента маршрутизации. Так же добавляет принадлежности и их количество из списка принадлежностей изделия, которое было назначено на сегмент маршрутизации.
Комментарии, рекомендации и пожелания приветствуются.
Последний раз редактировалось Hurog 08 окт 2021, 14:19, всего редактировалось 1 раз.

Евгений Кузнецов
здесь недавно
здесь недавно
Сообщения: 72
Зарегистрирован: 01 окт 2009, 15:57
Имя: Евгений К.
Благодарил (а): 15 раз
Поблагодарили: 2 раза

Операции в отчетах

Сообщение Евгений Кузнецов »

Hurog, чего-то не хватает - сценарий не компилируется.
Аватара пользователя

Barmaley4
знаток Eplan
знаток Eplan
Сообщения: 50
Зарегистрирован: 30 окт 2018, 09:17
Имя: Павел
Страна: РФ
город/регион: Москва
Благодарил (а): 2 раза
Поблагодарили: 50 раз

Операции в отчетах

Сообщение Barmaley4 »

Hurog, что за форматированный текст в форме? Нужно редактировать именно форму через api? Или речь идёт про сгенерированный лист отчёта в проекте? Если отчёт сгенерирован, то узнать из каких свойств был составлен текст отчёта не получится, операция завершена и страница просто из палочек и текста, без ссылок на исходные объекты.

По поводу сценария: очень замудрёно напишет, нужно существенно упрощать:

Код: Выделить всё

public bool Execute(ActionCallingContext oActionCallingContext)
        {
            SelectionSet selectionSet = new SelectionSet(); //объявляем набор выбора объектов
            var selection = selectionSet.Selection;
            if (selection.Length == 0)
            {
                MessageBox.Show("Не выбран сегмент", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return true;
            }

            try
            {
                using (new LockingStep())
                {
                    selection.First().Project.LockAllObjects(); // Блокировка всего проекта, на всякий случай

                    foreach (Segment sp in (selection.Where(s => s is Segment).Select(s => s as Segment)))
                    {
                        SegmentPropertyList spList = sp.Properties; //создаём лист свойств сегмента текущего обрабатываемого объекта
                        Article mArticle = sp.ArticleReferences[0].Article; // объявляем основным обрабатываем изделие на нулевой позиции
                        uint uintDevCount = Convert.ToUInt32((spList.CABLINGSEGMENT_LENGTH_AUTO + 0.499) / ((mArticle.Properties.ARTICLE_DELIVERYLENGTH) / 1000)) + 1; //подсчёт колличества изделий для заказа
                        sp.Properties.FUNC_ARTICLE_COUNT[1] = uintDevCount; // присвоение колличества изделий на первой позиции
                        Article.Accessory[] accessories = mArticle.ArticleAccessories; //создание списка принадлежностей для первого изделия списка

                        for (int i = 0; i <= accessories.Length - 1; i++) //начинается цикл присвоения изделий из списка принадлежностей
                        {
                            if (accessories[i].Name.Length != 0) // если изделие в списке принадлежностей названо
                            {
                                //проверка наличия изделия из списка принадлежностей в списке изделий
                                if (sp.ArticleReferences.Any(r => r.PartNr == accessories[i].Name))
                                {
                                    //если первое
                                    uint ammount = uintDevCount;
                                    if (i > 0) // если не первое
                                        ammount = uintDevCount * 2 + 1;

                                    sp.AddArticleReference(accessories[i].Name, "1", ammount); // создание ссылки в списке изделий

                                }
                            }
                        }

                    }



                }
            }
            catch (Exception ex)
            { MessageBox.Show($"Сбой сценария: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); }

            return true;
        }

Madwolf
знаток Eplan
знаток Eplan
Сообщения: 1455
Зарегистрирован: 17 окт 2012, 11:24
Имя: Виталий
Страна: Беларусь
город/регион: Минск
Благодарил (а): 61 раз
Поблагодарили: 181 раз

Операции в отчетах

Сообщение Madwolf »

API Reports Modification Interface читаем.
Там мы получаем ID объектов на 3-м этапе (тексты заполнители), а на 4-м этапе получаем уже страницы которые появляются в отчёте. Так вот на 4-м этапе, получаем страницу, ищем на ней объекты из этапа 3 по их ID, смотрим координаты и добавляем что нужно.

Автор темы
Hurog
здесь недавно
здесь недавно
Сообщения: 6
Зарегистрирован: 04 ноя 2019, 14:05
Имя: Павел
Страна: Казахстан
город/регион: Караганда
Благодарил (а): 6 раз
Поблагодарили: 3 раза

Операции в отчетах

Сообщение Hurog »

Barmaley4, спасибо, попробую.
Barmaley4 писал(а): 26 окт 2021, 10:55 Hurog, что за форматированный текст в форме?

Это такой текст.
Изображение
И вот интересно как достучаться до этих отображаемых свойств?
И ещё вопрос, как обратиться к пользовательским свойствам, созданным в базе данных изделий через "Конфигурировать свойства"?
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Аватара пользователя

Barmaley4
знаток Eplan
знаток Eplan
Сообщения: 50
Зарегистрирован: 30 окт 2018, 09:17
Имя: Павел
Страна: РФ
город/регион: Москва
Благодарил (а): 2 раза
Поблагодарили: 50 раз

Операции в отчетах

Сообщение Barmaley4 »

Hurog писал(а): 17 ноя 2021, 12:26 И вот интересно как достучаться до этих отображаемых свойств?
В данном случае это Текст-заполнитель, то есть это именно отдельный текст, который был создан во время создания отчёта, он уже не имеет связи со свойствами на основании каких был сгененерирован. Если изменить свойства, то текст заполнитель изменится только после генерации или обновлении отчёта.
Можно конечно получить его как объект API текст заполнитель, и вносить туда произвольные значения текста, но лучше это контролировать во время выполнения генерации отчёта посредством модификаторов отчёта через api..
Hurog писал(а): 17 ноя 2021, 12:26 И ещё вопрос, как обратиться к пользовательским свойствам, созданным в базе данных изделий через "Конфигурировать свойства"?
Вроде как во всех моделях объектах (Проект, страница, функция) есть свойства пользователя, которые доступны через геттер/сеттер

Код: Выделить всё

Function F = new Function();
string mydata = Func.Project.Properties.get_PROJ_CUSTOM_SUPPLEMENTARYFIELD03(0);
так же можно обращаться по идентифицирующему имени к свойству

Код: Выделить всё

Function F = new Function();
Func.Properties["EPLAN.Function.UserSupplementaryField10"] = "la la ley";
Ответить

Вернуться в «Eplan API»