AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 11.04.2017, 15:30   #1  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Мультипаспорт записи
Вниманию участников форума предлагается утилита «Мультипаспорт записи», в дальнейшем именуемая как «мультипаспорт», предоставляет возможности для редактирования данных в полях на формах Аксапты. Она не замещает имеющийся «Паспорт записи» и используется независимо от него.

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

В прилагаемой документации описаны основные приемы работы с мультипаспортом.

Во вложении описание утилиты и проекты для Аксапты версий 2012, 2009 и 3.0. Переносить нужно все объекты в проектах кроме одного - они не затрагивают стандартный функционал. Класс SysSetupFormRun переносить целиком не нужно. Достаточно добавить строку следующую строку кода перед непосредственным вызовом super() в методе task().
X++:
if (!zRecordInfo::recordInfoOverloadButton(_p1, this))
Миниатюры
Нажмите на изображение для увеличения
Название: Пример.jpg
Просмотров: 631
Размер:	260.4 Кб
ID:	11338  
Вложения
Тип файла: docx Мультипаспорт.docx (574.8 Кб, 313 просмотров)
Тип файла: xpo SharedProject_zMultiPassport_AX2012.xpo (195.5 Кб, 427 просмотров)
Тип файла: xpo SharedProject_zMultiPassport_AX2009.xpo (180.5 Кб, 610 просмотров)
Тип файла: xpo zMultiPassport_AX30.xpo (261.9 Кб, 446 просмотров)

Последний раз редактировалось sukhanchik; 21.04.2017 в 18:46.
За это сообщение автора поблагодарили: bitter (1), raz (10), Logger (10), S.Kuskov (10), KiselevSA (5), Dron AKA andy (5), sukhanchik (10), ivas (3), MazZzDaI (1), trud (5), rumpleteazer (1), Dumfag (1), imir (2).
Старый 11.04.2017, 16:00   #2  
bitter is offline
bitter
Участник
 
15 / 19 (1) ++
Регистрация: 12.04.2015
За это сообщение автора поблагодарили: Ace of Database (1).
Старый 11.04.2017, 22:59   #3  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Прошу модераторов поправить мое первое сообщение.
Поправка: в классе SysSetupFormRun надо перед непосредственным вызовом super() в методе task() добавить следующую строку кода
X++:
if (!zRecordInfo::recordInfoOverloadButton(_p1, this))
В исходном сообщении я пропустил восклицательный знак отрицания перед словом "zRecordInfo". Эта ошибка приводит к очень интересным эффектам, которые мешают работе мультипаспорта. В прилагаемых проектах такой ошибки нет. Ошибка есть только в тексте первого сообщения.

**sukhanchik** Поправлено

Последний раз редактировалось sukhanchik; 21.04.2017 в 18:46.
Старый 12.04.2017, 10:30   #4  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Исправил один баг для AX3.0. В новых версиях этот баг уже учтен, а в АЗ.0 он в тех же местах не воспроизводился. Но сегодня воспроизвелся на форме "Налоговые операции", которая открывается по кнопке "Разнесенные налоги" на журнале накладных. Патч во вложении.
Вложения
Тип файла: xpo zMultiPassport_AX30.xpo (261.9 Кб, 437 просмотров)
Старый 13.04.2017, 09:42   #5  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Сегодня встретилась форма, на которой программно дизэйблится источник данных. Из-за этого не работало массовое изменение в строках документа на сильно модифицированной форме закупок.
Чтобы не включать в сгенерированный мультипаспортом запрос задизэйбленные источники, надо добавить в классе zRecordInfo в методе fillQueryTreeQueryDatasource в самую первую строку кода после декларации переменных вставить следующий код:
X++:
    if (!queryBuildDatasource.enabled())
        return;
Когда накопится несколько новых поправок, выложу патч в проектах.

PS: прошу прощение за слово "дизэйблится"
Старый 17.04.2017, 14:28   #6  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,039 / 1633 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
Когда накопится несколько новых поправок, выложу патч в проектах.
Сделайте лучше проект на GitHub ну и с переводом на английский
Старый 17.04.2017, 15:05   #7  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Я как раз сейчас в гитхабе лазию. Меня заставила перейти туда вот такая штука:
http://plnkr.co/edit/?p=catalogue
Пытаюсь сделать оффлайн html-редактор документов Аксапты. Но до этого еще далеко.
А какие бонусы мне может дать проект на GitHub с переводом на английский?
Старый 19.04.2017, 15:11   #8  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Выяснилось, что в Аксапте неправильно работает метод SysQuery::countTotal().
Из-за этого при установленных галках "Выполнить для всех записей текущего родителя" или "Выполнить для всех записей, отображаемых на форме" мультипаспорт подвисал, пока этот метод не подсчитает все записи во всех таблицах запроса.
Я это сразу не заметил, так как в основном тестировал на той Аксапте, где метод SysQuery::countTotal() уже был переделан умельцами.

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

Чтобы у вас в мультипаспорте плавно работал прогресс-бар при массовом изменении данных, а также чтобы перед массовым изменением данных мультипаспорт не подвисал, то произведите два следущих изменения:
1) В класс SysQuery добавьте следующий метод
X++:
client static int countPrimClient(Query _query)
{
    Query                   countQuery;
    QueryRun                countQueryRun;
    QueryBuildDataSource    qbds;
    QueryBuildFieldList     qbfl;
    Common                  common;
    int                     counter;
    int                     loops;
    int                     iGrp;
    int                     k
  ;
    countQueryRun   = new QueryRun(_query);
    countQuery      = countQueryRun.query();
    for (k = 1; k <= countQuery.dataSourceCount();k++)
    {
        qbds = countQuery.dataSourceNo(k);
        qbds.update(false);
        iGrp +=(qbds.orderMode()==orderMode::GroupBy); // SHiSHok.fix
        //qbds.sortClear(); // Вот этот метод сильно мешал!
        qbfl = qbds.fields();
        qbfl.dynamic(false);
        qbfl.clearFieldList();
        qbfl.addField(FieldNum(Common,recId),SelectionField::COUNT);
    }

    countQueryRun   = new QueryRun(countQuery);
    while (countQueryRun.next())
    {
        common  = countQueryRun.getNo(1);
        counter += common.recId;
        loops++;
    }
//    return [counter,((loops > 1)? loops : counter)];
    return counter;
}
2) на форме zRecordInfo в источнике данных zRecordInfoTmp в методе writeForAll
строку кода
X++:
p.setTotal(SysQuery::countTotal(queryRun));
замените на
X++:
p.setTotal(SysQuery::countPrimClient(query));
Спасибо участнику SHiSHok !
Количество строк в Query
Старый 21.04.2017, 13:01   #9  
imir is offline
imir
Участник
 
159 / 161 (6) ++++++
Регистрация: 28.05.2010
В 12-шке На сложных формах типа договоров поставщиков валится с ошибками типа поле не было явным образом выбрано


Название: Снимок.PNG
Просмотров: 2046

Размер: 19.1 Кб
За это сообщение автора поблагодарили: Ace of Database (2).
Старый 21.04.2017, 14:50   #10  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Я понял, это таблицы с иерархией.
В таблице PurchAgreementHeaderExt_RU нет поля relationType. Но оно есть в базовой таблице AgreementHeaderExt_RU.
Буду думать, как из этого можно сварить суп.

Точнее, этого поля даже в базовой таблице нет в AOT, но оно есть физически в базе SQL
Можно выполнить такой запрос SQL
select relationType, * from AGREEMENTHEADEREXT_RU

Последний раз редактировалось Ace of Database; 21.04.2017 в 14:53.
Старый 21.04.2017, 15:38   #11  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Цитата:
Сообщение от imir Посмотреть сообщение
В 12-шке На сложных формах типа договоров поставщиков валится с ошибками типа поле не было явным образом выбрано
Ловите патч для AX2012
Вложения
Тип файла: xpo Table_zRecordInfoTmp.xpo (25.0 Кб, 369 просмотров)
За это сообщение автора поблагодарили: Pustik (12).
Старый 24.04.2017, 10:54   #12  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Продолжение темы с наследуемыми таблицами в AX2012.
Во вложении патч, который исправляет проблему того, что в мультипаспорте не были видны поля из иерархических таблиц (например, не было видно поля "Дата" договора).
В стандартном паспорте такие поля тоже не видны, а в мультипаспорте - теперь видны! Еще один повод использовать мультипаспорт
Есть следующие особенности для наследуемых таблиц:
1) Если поменять через мультипаспорт дату или сумму договора, то эти поля перерисуются на стандартной форме не в момент сохранения записи в мультипаспорта, а только после того как вы закроете мультипаспорт. Обычные поля перерисовываются сразу после сохранения в мультипаспорте. При множественном изменении данных записи перерисовываются сразу и для суммы и для даты договора.
2) Поле "Классификатор договора" мультипаспорт отображает, но не может определить его в тот момент, когда вы нажимаете клавиши ALT+1 для активации мультипаспорта при фокусе ввода, находящемся в этом поле. Мультипаспорт не позиционируется на это поле и выдает инфолог "Фокус не был установлен на выбранное поле. Найдите поле вручную." Ищите это поле в мультипаспорте вручную

Также в этот патч включено исправление для подсчета количества изменяемых записей при множественном изменении данных (смотрите на четыре сообщения выше от этого сообщения). Класс SysQuery.
Вложения
Тип файла: xpo SharedProject_zMutiliPassportPatch_TableHierarchy.xpo (288.7 Кб, 591 просмотров)

Последний раз редактировалось Ace of Database; 24.04.2017 в 10:58.
За это сообщение автора поблагодарили: KiselevSA (5).
Старый 15.05.2017, 15:20   #13  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Все обновления по утилите "Мультипаспорт" теперь буду выкладывать в моем блоге
http://aceofdatabase.blogspot.com/

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

В свободное время буду выкладывать туда свои утилиты. У меня их примерно около пяти.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 15.05.2017, 16:09   #14  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
может все же лучше выкладывать проекты на github?

добавил в импорт блогов. спасибо.
__________________
полезное на axForum, github, vk, coub.
Старый 15.05.2017, 16:40   #15  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Цитата:
Сообщение от mazzy Посмотреть сообщение
может все же лучше выкладывать проекты на github?

добавил в импорт блогов. спасибо.
Хорошо, попробую через GitHub, раз это актуально.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
За это сообщение автора поблагодарили: mazzy (2).
Старый 06.06.2017, 14:59   #16  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Выложил проект для AX2012 на GitHub
https://github.com/farmer1357/AX2012...rt-Project.git

Использовал для экспорта проекта вот эту штуку
https://community.dynamics.com/ax/b/...namics-ax-2012
Чтобы она у меня заработала, прописал корректный путь к файлу Git.exe в методе classDeclaration класса Git
X++:
class Git
{
    #localmacro.git
        @'C:\Program Files\Git\bin\git.exe'
    #endmacro

    #localmacro.TortoiseGit
        @'C:\Program Files\TortoiseGit\bin\TortoiseGitProc.exe'
    #endmacro
}
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
За это сообщение автора поблагодарили: mazzy (2), Logger (2).
Старый 08.06.2017, 12:52   #17  
mdanko2000 is offline
mdanko2000
Участник
 
44 / 40 (2) +++
Регистрация: 21.04.2014
Добрый день!

Для поля с ExtendedDataType==PackedQueryRun вылетает ошибка.

PHP код:
static zRecordInfoTmp fillForRecord(Common recordzRecordInfoTmp _zRecordInfoTmp nullstr _dsName ""int _dsNum 0int _repeatCount 1)
{
.............................
 else if (
dictField.type() != Types::Container)
                {
здесь  -->     zRecordInfoTmp.FieldValue strfmt("%1"record.(fieldid2ext(dictField.id(), j))); 
                }
.....................

Тип надо приводить к базовым типам:
PHP код:
  baseType    = (extendedTypeName2IdИМЯ_ТИПА )<<16+11 )& 0xffff
или использовать
PHP код:
  dictField.basetype() 
как-то так

Последний раз редактировалось mdanko2000; 08.06.2017 в 13:20. Причина: дополнил
За это сообщение автора поблагодарили: Ace of Database (2).
Старый 08.06.2017, 14:36   #18  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
877 / 649 (23) +++++++
Регистрация: 14.10.2004
Цитата:
Сообщение от mdanko2000 Посмотреть сообщение
Добрый день!

Для поля с ExtendedDataType==PackedQueryRun вылетает ошибка.

как-то так
А как таблица называется? Чтобы на ней потренироваться.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 08.06.2017, 14:49   #19  
mdanko2000 is offline
mdanko2000
Участник
 
44 / 40 (2) +++
Регистрация: 21.04.2014
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
А как таблица называется? Чтобы на ней потренироваться.
Не думаю что это поможет , таблица называется ExportXMLExcelMainTable.

Я у себя поменял dictField.Type() на dictField.baseType() и всё заработало.

Ну и как пожелание, при переходе по дереву таблиц может имеет смысл фильтровать данные в гриде для текущей таблицы ?
Старый 29.03.2022, 09:30   #20  
oleggy is offline
oleggy
Участник
 
276 / 36 (2) +++
Регистрация: 03.12.2019
Адрес: Россия
Таблица: zRecordInfoTmp
Метод: zRecordInfoTmp

X++:
static zRecordInfoTmp fillForRecord(Common record, zRecordInfoTmp _zRecordInfoTmp = null, str _dsName = "", int _dsNum = 0, int _repeatCount = 1)
{
    zRecordInfoTmp          zRecordInfoTmp;
    DictTable               dictTable;
    DictField               dictField;
    int                     fieldCnt;
    int                     i;
    int                     j;
    int                     arraySize;
    str                     ts;
    ;
    if (_zRecordInfoTmp)
        zRecordInfoTmp = _zRecordInfoTmp;

    dictTable = new DictTable(record.TableId);
    fieldCnt  = dictTable.fieldCnt();

    for (i = 1; i <= fieldCnt; i++)
    {
        dictField = dictTable.fieldObject(dictTable.fieldCnt2Id(i));
        arraySize = dictField.arraySize();
        for (j = 1; j <= arraySize; j++)
        {
            if (dictField.isSql())
            {
                //w(dictField.);
                zRecordInfoTmp.clear();
                zRecordInfoTmp.FormDatasourceNum = _dsNum;
                zRecordInfoTmp.FormDatasourceName = _dsName;
                zRecordInfoTmp.RefRecId = record.RecId;
                zRecordInfoTmp.TableName = dictTable.name();
                if (_dsName && _repeatCount > 1)
                    zRecordInfoTmp.TableName += strfmt(" [%1]", _dsName);
                zRecordInfoTmp.RefTableId = dictTable.id();
                zRecordInfoTmp.RefFieldName = dictField.name(DbBackEnd::Native, j) + (arraySize > 1 ? strFmt('[%1]', j) : "");
                zRecordInfoTmp.RefFieldId = dictField.id();
                zRecordInfoTmp.FieldArrayIdx = j;
                zRecordInfoTmp.FieldLabel = dictField.label(j);

                if (dictField.type() == Types::Time)
                {
                    zRecordInfoTmp.FieldValue = time2str(record.(fieldid2ext(dictField.id(), j)), 1, 1);
                }
                else if (dictField.type() != Types::Container 
                        && dictField.baseType() != Types::Container // <------  fix
                        ) 
                {
                    ts = strfmt("%1", dictField.type());
                    zRecordInfoTmp.FieldValue = strfmt("%1", record.(fieldid2ext(dictField.id(), j)));
                }
                else
                {
                    zRecordInfoTmp.FieldValue = "[Container]";
                }
                zRecordInfoTmp.insert();
            }
        }
    }
    return zRecordInfoTmp;
}


Если имеется таблица у которой поле является EDT который в свою очередь является производным от Extends который в свою очередь с типом Container. Тогда вылетает ошибка.

Последний раз редактировалось oleggy; 29.03.2022 в 09:34.
За это сообщение автора поблагодарили: S.Kuskov (2).
Теги
github

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Ошибка записи в SalesParmSubLine FrolovAndy DAX: Программирование 2 09.01.2018 15:48
Dax12 форма ListPage: как скрыть/отобразить MenuItemButton без смены фокуса записи в гриде Aquarius DAX: Программирование 10 30.11.2016 14:36
Как лучше хранить ссылки на записи - (RefTableId, Company, RefRecId) mazzy DAX: Программирование 41 08.07.2011 13:18
ALEG: Доступны записи тренингов по Microsoft Dynamics NAV Blog bot DAX Blogs 0 21.03.2007 15:00
Автоматическое увеличение значения поля при создании новой записи. sguryev DAX: Программирование 3 06.02.2003 14:00

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 09:57.