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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 29.02.2008, 18:16   #1  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1147 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Gustav: Unsorted, или Записки DAX-дилетанта - II
И снова здравствуйте!
Позвольте начать процесс экспериментального бложения.
"Ноги" растут отсюда: Эксперимент: создан раздел Blog'и

Первые несколько постов этой ветки-блога некоторое время будут в состоянии "under construction". Поэтому приношу свои извинения за возможные ваши пожимания плечами. - уже все активно задействованы
За это сообщение автора поблагодарили: belugin (7), Kabardian (4).
Старый 29.02.2008, 18:17   #2  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1147 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
СОДЕРЖАНИЕ ЭТОГО "БЛОГА"

2008-02-29: Трамплин в код из инфолога (SysInfoAction_Editor)

2008-03-11: Преодоление принципиальных RLS-заблуждений

2008-03-13: SysRecordLevelSecurityWizard: Настройка RLS для неотображаемой таблицы

2008-03-24: Аналог excel'ной функции TRIM

2008-06-27: Подручные средства для облегчения создания рутинных фрагментов кода

2008-06-27: Прямоугольные блочные операции в редакторе кода X++

2008-08-14: Автонумерация полей при обмене значениями с записеподобными структурами

2008-09-08: Изготовление связанных тестовых копий форм журналов и форм строк журналов

2008-10-06: Визуальная имитация раннего связывания COM-объектов

2008-12-04: Критерии запроса: ловушка перечисления через запятую

2008-12-29: Excel: шаблон XLT vs псевдошаблон XLS

2009-05-20: Проблемы при создании наследников класса RunBaseBatch

Последний раз редактировалось Gustav; 20.05.2009 в 13:27.
Старый 29.02.2008, 18:18   #3  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1147 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Иногда бывает нужно найти собственное сообщение, про которое помнишь, что писал, но когда именно, а также название темы - вспомнить трудно. Если за сообщение поблагодарили (хотя как об этом помнить?), то появляется шанс найти его среди "Полученных отзывов" (т.е. перерывая ограниченное количество информации), в противном случае рост утомительности поиска прямо пропорционален росту количества опубликованных мною сообщений (в самом удручающем случае это будет визуальный перебор всех сообщений).

Принимая все это во внимание, я решил "завязывать" в этом сообщении узелки на память (с краткими комментариями), чтобы, если и придется искать что-то утомительно, то, по крайней мере, без повторных поисков в дальнейшем.


ССЫЛКИ НА МОИ СООБЩЕНИЯ ВНЕ ЭТОГО "БЛОГА" (или на темы с моими сообщениями) - интересные мне и может быть кому-нибудь еще

* ColorFillCells в Excel документе --- табличка представления цветов для ColorIndex в Excel через параметры функции RGB для Color
* Быстрый способ вывода данных в Excel с картинками --- вывод в Excel 400 фрагментов экрана
* Запустить метод контрола
* Как проинициализировать COM уже запущенным приложением (Excel)? --- как влезть в уже работающий скрытый экземпляр Excel
* Копирование колонок Excel --- "Очередное разглагольство про Excel": букмарки и т.п.
* Можно ли в SELECT использовать критерия вида "10..20" --- про макросы #sqlBetween и #sqlIn, SQL_Imitation
* переделать запрос sql --- хорошая памятка про Query касаемо расширенных диапазонов, двойных кавычек и имени датасорса по умолчанию с суффиксом "_1"
* Пользовательский генератор строк-перечислений для критерия запроса в Axapta
* Пользовательский генератор строк-перечислений...- 2: Доп.вкладка для SysQueryForm
* Помогите сделать действие в Excel через COM --- интересный диалог с Иваном Кашперуком про структуру в Excel; вопросы региональных настроек по части формул
* снятие данных с GRID
* Форматирование на Excel --- сплошная сетка на некоторый диапазон кладётся дух захватывающе просто + там чуть ниже ссылка на BorderAround
* Функция, вычисляющая разницу между датами. --- возвращает контейнер из семи значений: 1) полные годы разницы - от 0 до бесконечности; 2) полные месяцы (свыше полных лет) - от 0 до 11; 3) дни неполного месяца (свыше полных месяцев) - от 0 до 30; 4) недели месяца (свыше полных месяцев) - от 0 до 4; 5) дни неполной недели (свыше полных недель) - от 0 до 6; 6) общей кол-во дней разности - от от 0 до бесконечности; 7) дни неполного года - от 0 до 365.


Информация по форуму:

* http://www.axforum.info/forums/member.php?u=5597&pp=500 --- мой профиль без деления таблиц отзывов на страницы
* Возможность доступа к сообщениям и репутациям пользователя за произвольный период

* С моим участием (по не более 500 первых в выборке по возрастанию даты: последнего сообщения в теме - для "тем", своего сообщения - для "сообщений")...
...за последние 5 лет : темы сообщения
...за последние 4 года: темы сообщения
...за последние 3 года: темы сообщения
...за последние 2 года: темы сообщения
...за последний 1 год : темы сообщения

Последний раз редактировалось Gustav; 13.03.2010 в 21:24. Причина: update again
Старый 29.02.2008, 18:19   #4  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1147 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Трамплин в код из инфолога (SysInfoAction_Editor)
Почитываю книгу Microsoft Dynamics AX 4.0 (на русском языке). Выборочно, отдельными главами. Недавно прочитал 14-ю - "Отражение". После прочтения в голове хорошо и понятно выстроились все 3 API (UtilElements, Dict... и TreeNode AOT), которые раньше постигал урывками и бессистемно. Признаться, совсем доселе не приходилось возиться с UtilElements, а тут набросал джобик, повыводил в инфолог всякие списки последних модифицированных объектов - хорошо!

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

У меня есть несколько джобов, предназначенных для нужд конкретных пользователей по конкретным задачам, причем для удобства распознавания я включаю (вкратце) фамилию пользователя и название задачи в идентификатор джоба. И вот мне нужно было посмотреть какие изменения были внесены за последний месяц в джобы для пользователя Ивановой:
X++:
static void Job_Unsorted_8229(Args _args)
{
    UtilElements    utilElements;
;
    while select Name from utilElements
        where utilElements.RecordType == UtilElementType::Job
           && utilElements.Name like '*Ivanova*'
           && utilElements.ModifiedDate >= today()-30
    {
        info( utilElements.Name, '',
              SysInfoAction_Editor::newOpen( strfmt(@'\Jobs\%1', 
                                             utilElements.Name ) ));
    }
}
Приведенный код вывел мне в инфолог фактически меню-навигатор: список нужных мне в данный момент джобов и возможность двойным щелчком открыть любой из них в редакторе кода.

P.S. По поводу буквального перевода "отражения" (reflection). Вроде, в отечественной литературе по Java, о тесном родстве с которой принято говорить при упоминании об X++, имеется устойчивый, обычно непереводимый, термин "рефлексия" (из серии: "файл", а не "реестр", "подшивка", "напильник"...). Ну, да ладно, "отражение" тоже понятно

P.S. от 08.12.2008. Версия джоба с использованием формы запроса:
X++:
static void Job_Unsorted_8229_Query(Args _args)
{
    UtilElements            utilElements;
 
    Query                   query = new Query();
    QueryBuildDatasource    qbds  = new QueryBuildDatasource() ;
    QueryRun                qr;
    ;
 
    qbds = query.addDataSource(tablenum(UtilElements));
 
    qbds.addRange(fieldnum(UtilElements, RecordType))
        .value(queryValue(UtilElementType::Job));
 
    qbds.addRange(fieldnum(UtilElements, Name))
        .value('*Ivanova*');
 
    qbds.addRange(fieldnum(UtilElements, ModifiedDate))
        .value(strFmt('%1..',date2StrXpp( today()-30 )));
 
    qbds.addSortField(fieldnum(UtilElements, ModifiedDate), 
        SortOrder::Ascending);
 
 
    qr = new QueryRun(query);
 
    // qr.userUpdate(false);
    if (qr.prompt())
    {
        while (qr.next())
        {
            utilElements = qr.getNo(1);
 
            info( strfmt('%1 -- %2', utilElements.ModifiedDate, 
                                     utilElements.Name),
                  '',
                  SysInfoAction_Editor::newOpen( strfmt(@'\Jobs\%1',
                                                 utilElements.Name) ));
        }
    }
}
Старый 29.02.2008, 18:33   #5  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,039 / 2170 (81) +++++++++
Регистрация: 16.01.2004
Адрес: Москва
Наверное, лучше посты сделать отдельными темами, а не все в одну кучу....
За это сообщение автора поблагодарили: MikeR (5).
Старый 29.02.2008, 18:43   #6  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1147 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Цитата:
Сообщение от belugin Посмотреть сообщение
Наверное, лучше посты сделать отдельными темами, а не все в одну кучу....
Максим, ближайшее время покажет... Если наполнение будет лавинообразным, то приму меры - по мере возникновения, так сказать.
Старый 29.02.2008, 19:14   #7  
kashperuk is offline
kashperuk
Senior SDE, Dynamics AX
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,353 / 2050 (77) +++++++++
Регистрация: 30.05.2004
Адрес: Копенгаген, Дания
Цитата:
Сообщение от Gustav Посмотреть сообщение
P.S. По поводу буквального перевода "отражения" (reflection). Вроде, в отечественной литературе по Java, о тесном родстве с которой принято говорить при упоминании об X++, имеется устойчивый, обычно непереводимый, термин "рефлексия" (из серии: "файл", а не "реестр", "подшивка", "напильник"...). Ну, да ладно, "отражение" тоже понятно
Долго думал над этим термином. Кого уже только не спрашивал.
Мнения знатоков разошлись.

Да и что говорить, только что опять полез гуглить - вот 2 ссылки на один и тот же сайт про Java, с двумя разными переводами

http://www.javable.com/javaworld/tips/118_tt/ -- здесь отражение
http://www.javable.com/tutorials/fesunov/lesson22/ -- здесь рефлексия.

По шарпу вроде чаще таки использовалось отражение.
А рефлексия - не нравится мне это слово. Мне напоминает болезнь какую-то по звучанию
Старый 29.02.2008, 19:30   #8  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,039 / 2170 (81) +++++++++
Регистрация: 16.01.2004
Адрес: Москва
Оно примерно то же значит.
http://ru.wikipedia.org/wiki/Рефлексия

Афористическое определение рефлексии звучит так: «Рефлексия есть мысль, направленная на мысль» (или «направленная на саму себя»). И это определение не совсем точно, поскольку суть рефлексии не в том, что она есть мысль, а в самой обращенности на себя. Более верным, является следующее определение: Рефлексия есть обращенность сознания на себя. В смысле этого определения, мысль, речь, воображение и др. способы сознательной деятельности могут быть рефлективными, если c помощью них обращаются на самих себя.

БСЭ: «Содержание рефлексии определено предметно-чувственной деятельностью: рефлексия в конечном счёте есть осознание практики, предметного мира культуры. В этом смысле рефлексия есть метод философии, а диалектика — рефле
Старый 29.02.2008, 19:35   #9  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,039 / 2170 (81) +++++++++
Регистрация: 16.01.2004
Адрес: Москва
Цитата:
Сообщение от Gustav Посмотреть сообщение
Максим, ближайшее время покажет... Если наполнение будет лавинообразным, то приму меры - по мере возникновения, так сказать.
Дело не в наполнении скорее, а в комментировании.
Старый 11.03.2008, 19:38   #10  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1147 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Преодоление принципиальных RLS-заблуждений
Недавно я сам давал совет про ограничение доступа на уровне записей, где излагал некоторую ситуацию, реализованную в нашей инсталляции Аксапты (3.0 SP4, приложение GMCS):
Цитата:
Сообщение от Gustav Посмотреть сообщение
Администрирование \ Настройки \ Контроль доступа \ Доступ на уровне записей \ Ctrl+N

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

У меня сделано следующим образом. Есть общая группа, назовем ее "ВсеНоменклатурщики", в которую входят все подобные пользователи. Этой группе прописаны общие права для всех пользователей, но на таблицу "Картотека номенклатуры" выставлен полный запрет.

С другой стороны есть группы "Номенклатурщики1" и "Номенклатурщики2", у которых полный запрет прописан на всё, кроме таблицы "Картотека номенклатуры". На эту таблицу прописан полный доступ.

Каждый пользователь входит в одну из этих групп и в общую.

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

Что же неверного было в моих представлениях? А вот что: я наивно полагал, что приоритет имеет собственно доступ, а настройки RLS как бы вторичны и следуют за этим доступом, т.е. если пользователь, скажем, входит в 2 группы и у одной группы настроен RLS и уровень доступа - "Просмотр", а у другой - RLS нет и уровень доступа "Полный доступ", то пользователь получает "максимальный доступ" 2-й группы, т.е. полный доступ без RLS (масла в огонь здесь еще подливала ситуация, когда у первой группы есть RLS и доступ "Нет доступа" - тогда пользователь действительно получает полный доступ без RLS, правда, как выясняется, совсем по другой причине).

Дальше - больше! Похоже, что я совсем не одинок в своих заблуждениях. Не знаю, настраивали ли когда-нибудь самостоятельно RLS авторы оригинала книги Microsoft Dynamics AX 4.0 (или не барское это дело ), но читаем следующее:
Цитата:
(в английской версии):

Important. If an application role that uses multiple user groups has record-level security applied on a certain table within a company account, maximum access is given to the role. For example, if one user group has no record-level security for the Customer table and another user group allows users to see only a subset of the customers, the user will have access to all customers.

(и перевод - в русском издании, на странице 363):

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

В общем, прозрение таково: доступ и RLS - являются понятиями как бы независимо параллельными. Вначале системой для пользователя выбирается максимальный доступ из всех групп (пока без учета RLS). И далее, если хотя бы у одной группы есть RLS, то эта RLS применяется. Если одна группа - "Просмотр" + RLS, а другая "Полный доступ" без RLS, то у пользователя будет "Полный доступ" + RLS. В случае нескольких групп с разными настройками RLS отдельные фильтры RLS от разных групп для одного пользователя объединяются в SQL-предложении WHERE при помощи операции ИЛИ (OR).

Дошёл я до этого, спустя несколько недель после моего совета, когда мне пришлось решать иную, я бы сказал, обратную задачу: нужно было не "дать некоторым, запретив остальным", а "ограничить некоторых, не трогая остальных". Речь шла о справочнике "Код складского журнала" (таблица InventJournalName), который у нас содержит 7 записей, определяющих типы складских журналов. Некая складская роль "Кладовщик" у нас состоит из нескольких групп, настройки каждой из которых достаточно многообразны. Новой группе людей нужно было дать возможность создавать журналы только двух типов из семи, при всём при том, что все остальные настройки, определяемые по совокупности нескольких групп, для роли "Кладовщик" должны были остаться такими, как были. С кислым выражением лица накануне 8 марта я думал о том, как мне придется закрывать у всех уже ранее настроенных групп роли доступ к таблице InventJournalName, после чего создавать и заполнять две новые группы - "Все 7" и "Только 2", с содроганием думая о возможной перспективе возникновения необходимости ограничения доступа к еще какой-нибудь таблице, когда опять придётся изменять настройку уже существующих групп...

К счастью, всё прояснилось до практических телодвижений и ничего из ранее сформированных групп трогать не пришлось. Была создана группа "Только 2" с указанными RLS-ограничениями на таблицу InventJournalName, которая была назначена новым людям в дополнение к остальным (стандартным) группам роли "Кладовщик".

Ниже в качестве узелков на память я привожу несколько особенно помогших мне цитат из материалов некоторых наших уважаемых участников форума и свои скромные, в основном поддакивающие, комментарии.
Цитата:
http://erpkb.com/Axapta/DostupNaUrovneZapisejj - belugin
:
Чтобы настроенный RLS заработал, надо, чтобы у группы был хоть какой-то доступ к таблице.
Да, хотя бы "Просмотр", лишь бы не "Нет доступа"! В данном случае вариант "Нет доступа" не следует считать наиминимальнейшим уровнем доступа, а следует считать полным, не принимаемым ни в какое внимание, осутствием доступа.

Цитата:
http://axapta.mazzy.ru/lib/rls_setup/ - mazzy
:
RLS в Аксапте работает совместно с системой настройки обычных прав. Это значит, что для того, чтобы ограничить доступ к тому или иному полю таблицы, необходимо настроить обычные права на эти таблицу. Задача RLS - незаметно для пользователя отфильтровать записи.
...
Настройка ограничения прав на уровне записей сводится к определению фильтров на те или иные таблицы для разных групп пользователей. Если пользователь входит в несколько групп, то фильтры объединяются по условию ИЛИ.
...
Axapta смотрит на обычные права доступа. И, если право доступа есть, то смотрит в настройки RLS. Если для данной группы и данной таблицы настроек RLS нет, то Аксапта показывает все записи из таблицы.
Цитата:
http://forum.mazzy.ru/index.php?s=&s...ndpost&p=15230 - glibs
:
Не знаю, новость ли это для остальных, но приятная. Если у пользователя нет доступа к определенному значению из таблицы на уовне RLS, то validate relation-а на таблице в lookup срабатывает корректно. Т.е. если есть две группы клиентов Х и У, я могу видеть только группу Х, то создать запись в таблице клиентов и вручную ввести группу У система не позволяет. Раньше с этим были проблемы.
Для меня - очень приятная! Я был в шорах предубежденности, что даже если значение не показывается в выпадающем списке, то его можно прописать вручную или вставить копированием - возможно, я как раз и начитался информации про версию 2.5?
За это сообщение автора поблагодарили: GLU (1), Logger (3), gl00mie (5).
Старый 13.03.2008, 17:41   #11  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1147 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
SysRecordLevelSecurityWizard: Настройка RLS для неотображаемой таблицы
ПРОБЛЕМА:

Необходимо для заданной группы прав настроить RLS на таблицу "Коды журналов ОС", которой нет в списке таблиц, отображаемых в Мастере. Таблица "Коды журналов ОС" в нашем сильноэксклюзивном приложении от компании GMCS называется GM_RAssetJournalName.

РЕЦЕПТ:

1. Открываем форму "Доступ на уровне записей" (SysRecordLevelSecurity), до которой предварительно добираемся по меню Ax 3.0: Администрирование \Настройки \Контроль доступа \Доступ на уровне записей.

2. Находясь в гриде, жмем Ctrl+N и создаем при помощи Мастера запись для заданной группы и какой-нибудь произвольной таблицы, которая нам не нужна, но которая видна в списке Мастера, например, "Модели учета" - RAssetStandardTable (она видна в раскрытом узле "СНГ Основные средства" после включения опции "Показать все таблицы").

3. Закончив шаги Мастера, выходим из формы "Доступ на уровне записей", не настраивая для созданной записи никаких фильтров (т.е. не пользуемся кнопкой "Запрос").

4. В таблице SysRecordLevelSecurity в нужной записи меняем код "ненужной" таблицы на код требуемой таблицы любым удобным способом - вручную (через Обозреватель таблицы или средствами СУБД) или при помощи элементарного джоба:
X++:
static void Job_UpdateRLSrecord(Args _args)
{
    SysRecordLevelSecurity sysRLS;
    ;
    ttsbegin;

    select forupdate sysRLS
        where sysRLS.companyId == curExt()
           && sysRLS.groupId == '<наша группа прав>'
           && sysRLS.tabId == tablenum(RAssetStandardTable);

    sysRLS.tabId = tablenum(GM_RAssetJournalName);
    sysRLS.update();

    ttscommit;
}
5. Снова открываем форму "Доступ на уровне записей", находим нужную запись - видим в колонке "Название таблицы", что таблица благополучно поменялась.

6. Нажимаем кнопку "Запрос" и выполняем требуемую настройку фильтра для нашей таблицы.

7. "Захардкодиваем" код нашей таблицы в метод buildTableTree формы SysRecordLevelSecurityWizard. Это необходимо для того, чтобы возможные последующие настройки RLS для данной группы прав не снесли нашу, с таким трудом вживленную, таблицу. Для этого меняем условие в IF - тупо, зато быстро, расширяя его на ИЛИ с нашей таблицей:
c
X++:
if (dictTable &&
    dictTable.allowSecuritySetup() &&
    (dictTable.tableGroup() == TableGroup::Main ||
     tableSelection.selection() ||
     tableIds.in(tableId)) &&
     (domainAccess || SysRecordLevelSecurityWizard::tableAllowed(tableId)))
на
X++:
if (
   (dictTable &&
    dictTable.allowSecuritySetup() &&
    (dictTable.tableGroup() == TableGroup::Main ||
     tableSelection.selection() ||
     tableIds.in(tableId)) &&
     (domainAccess || SysRecordLevelSecurityWizard::tableAllowed(tableId)))
   ||
   tableId == tablenum(GM_RAssetJournalName)
   )
Подобным образом надо будет расширять условие при добавлении в RLS каждой новой неотображаемой таблицы. Если таких таблиц станет много и надоест каждый раз править метод, то, может, будет иметь смысл вставить в условие глобальный макрос, расширяемый по мере необходимости, или читать коды "исключительных" таблиц из какой-нибудь специальной настроечной таблицы.

ИСТОЧНИКИ (ВДОХНОВЕНИЯ):

Еще по поводу QueryBuildRange()
Коды аналитики
Старый 24.03.2008, 18:49   #12  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1147 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Аналог excel'ной функции TRIM
В Excel есть замечательная функция рабочего листа TRIM (в русской версии - СЖПРОБЕЛЫ). Она не только удаляет ведущие и концевые пробелы, как это делают функции strLTrim и strRTrim в X++ (или LTrim и RTrim в VBA, Oracle и т.д.), но и оставляет между словами только по одному пробелу, например:
Код:
TRIM(" Доход   за   первый    квартал   ") равняется "Доход за первый квартал".
Сегодня я понял, что чувствую себя в Аксапте очень неуютно без подобной функции. И, поскольку ничего подходящиего ни среди системных функций, ни среди методов класса Global я не нашёл, то слепил свою собственную:
X++:
static str trimLikeExcel(str _sourceString)
{
    // имитация табличной функции TRIM из Excel
    // удаляем пробелы до тех пор, пока между словами не останется только по одному пробелу
    str strTmp;
    int lenPrev, lenCurr;
    ;

    strTmp = strLRTrim(_sourceString);
    lenCurr = strLen(strTmp);
    do
    {
        lenPrev = lenCurr;
        strTmp = strReplace(strTmp, '  ', ' '); // многократная замена 2-х пробелов на 1
        lenCurr = strLen(strTmp);
    }
    while (lenCurr != lenPrev);

    return strTmp;
}
Функцию можно поместить в класс Global или в какой-нибудь собственный класс-набор статических методов (а-ля "персональный Global").

Кстати, имеющаяся в VBA и Oracle функция Trim действует не более, чем как метод класса Global strLRTrim (т.е. просто выполняет оба действия - "левое" и "правое" - одновременно). Пробелы же между словами, которых может быть более одного, она не трогает.

Коллеги, возможно, кто-то видит не столь очевидную, но более эффективную, комбинацию иных текстовых функций для достижения такого же результата - пожалуйста, делитесь соображениями, с удовольствием послушаю.
Старый 24.03.2008, 19:01   #13  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,039 / 2170 (81) +++++++++
Регистрация: 16.01.2004
Адрес: Москва
X++:
    TextBuffer buf = new TextBuffer();
;
    buf.setText(' I  do ');
    buf.replace('  +', ' ');
    info(strFmt("'%1'", strLRTrim(buf.getText())));
За это сообщение автора поблагодарили: Gustav (5), alex55 (1).
Старый 24.03.2008, 19:43   #14  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1147 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Макс, большое спасибо за наводку! Уже нашёл очень полезную ветку: Функция, которая убирает перевод каретки в строке. и пошёл читать справку к функции match про регулярные выражения.

"Хорошо! "Стамбул - город контрастов". А объявление перепишем:" (с)
X++:
static str trimLikeExcel(str _sourceString)
{
    TextBuffer buf = new TextBuffer();
    ;
    buf.setText(_sourceString);
    buf.replace('  +', ' ');
    return strLRTrim(buf.getText());
}
P.S. Не надо ли добавить еще строку textBuffer.regularExpressions(true); , как это сделано в упомянутой полезной ветке в примере у Максима Горбунова?
Старый 24.03.2008, 22:24   #16  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,039 / 2170 (81) +++++++++
Регистрация: 16.01.2004
Адрес: Москва
Цитата:
Сообщение от Gustav Посмотреть сообщение
P.S. Не надо ли добавить еще строку textBuffer.regularExpressions(true); , как это сделано в упомянутой полезной ветке в примере у Максима Горбунова?
Оно по умолчанию тру
Старый 27.06.2008, 13:08   #17  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1147 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Подручные средства для облегчения создания рутинных фрагментов кода
Во загнул, скажете, но на самом деле все очень просто. То тут, то там приходится выписывать последовательности операторов присваивания для перевалки данных из одного места в другое, например, пересылать значения из несвязанных контролов формы в поля таблицы. Для оформления подобных операций желательно иметь выстроенный список полей с одной и с другой стороны, которые в коде необходимо "совместить" друг с другом посредством знака равенства.

Такое совмещение можно приготовить в любом редакторе текста, позволяющем блочные вставки, например, в MultiEdit или в текстовом редакторе программы FAR (выделение прямоугольника при помощи Alt+стрелка), и затем вставить в текст конкретного метода в Axapta. Еще проще подготовить присваивания при помощи таблиц Excel, вставив наборы полей в соседние колонки, связав их формулами и наконец скопировав вычисленные значения формул в код X++.

Пусть, например, имееется набор полей таблицы:
Table1.StrField1
Table1.StrField2
Table1.StrField3

и набор контролов формы (подразумевается AutoDeclaration = Yes):
StringEditControl1
StringEditControl2
StringEditControl3

Допустим, что код должен выглядеть следующим образом:
Table1.Field1 = StringEditControl1.valueStr();
Table1.Field2 = StringEditControl2.valueStr();
Table1.Field3 = StringEditControl3.valueStr();

Создадим эти операторы присваивания при помощи Excel. Для этого:
- скопируем набор полей в столбец A Excel, начиная с ячейки A1;
- скопируем набор контролов в столбец B Excel, начиная с ячейки B1;
- в ячейку C1 введем формулу: =A1 & " = " & B1 & ".valueStr();" и распространим ее вниз копированием на все необходимые строки;
- далее из столбца C забираем строки кода X++ для вставки в Axapta.

Всё неплохо. Дело осталось за малым - автоматизировать получение самих списков полей (не вручную их же набирать в самом деле! ).

Вот два коротеньких джобика, которые могут помочь в этом. Первый - получение списка полей таблицы:
X++:
static void Job_getTableFieldList(Args _args)
{
    str         tableName = 'RAssetTable'; // подставь здесь свою таблицу
    treeNode    treeNode = new xInfo()
                            .rootNode()
                            .AOTfindChild('Data Dictionary')
                            .AOTfindChild('Tables')
                            .AOTfindChild( tableName )
                            .AOTfindChild('Fields');
    ;
    treeNode = treeNode.AOTfirstChild();
    while ( treeNode )
    {
        info( strfmt('%1.%2', tableName, treeNode.treeNodeName()) );
        treeNode = treeNode.AOTnextSibling();
    }
}
Из инфолога список забираем операцией "Копировать как список в буфер обмена" и вставляем в Excel. Очевидно, что если табличная переменная в коде отличается от имени исходной таблицы, то достаточно соответствующим образом подправить параметры вызова функции strfmt. Например: strfmt('%1.%2', 'myTable', treeNode.treeNodeName()). Можно еще сразу включить знак равенства: '%1.%2 = ' (чтобы упростить формулу Excel или вообще обойтись без нее, если используется редактор с блочными вставками ).

Второй джоб - получение списка контролов формы:
X++:
static void Job_getFormControlList(Args _args)
{
    str         formName = 'RAssetTable';  // подставь здесь свою форму
    int         row, hLevel; // служебные поля на случай вывода сквозной нумерации строк или уровней иерархии
    TreeNode    treeNode = new xInfo()
                            .rootNode()
                            .AOTfindChild('Forms')
                            .AOTfindChild( formName )
                            .AOTfindChild('Designs')
                            .AOTfindChild('Design');
    str controlType;
    str controlName;

    void nextNode( treeNode _tn)
    {
        ;
        hLevel++;
        _tn = _tn.AOTfirstChild();
        while (_tn )
        {
            if (strscan(_tn.treeNodeName(), ':', 1, 10000))
            {
                row++;
                [controlType, controlName] = str2con(_tn.treeNodeName(), ':');

                if (substr(controlType,1,1)=='[') // Tab, TabPage, Group, Grid, ButtonGroup
                {
                    controlType = substr(controlType, 2, strlen(controlType)  );
                    controlName = substr(controlName, 1, strlen(controlName)-1);
                }
                info( strfmt('%1.valueStr();', controlName) );
            }
            nextNode(_tn );
            _tn = _tn.AOTnextSibling();
        }
        hLevel--;
    }
    ;
    nextNode( treeNode );
}
В целях примера к имени контрола при выводе в инфолог сразу добавлена подстрока '.valueStr();'.
Старый 27.06.2008, 13:23   #18  
kashperuk is offline
kashperuk
Senior SDE, Dynamics AX
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,353 / 2050 (77) +++++++++
Регистрация: 30.05.2004
Адрес: Копенгаген, Дания
Ну, с TreeNode ты конечно зря так, ну да ладно.
Вот еще посмотреть можно схожую функциональность:
http://kashperuk.blogspot.com/2007/0...d-another.html
Старый 27.06.2008, 15:20   #19  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1147 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Прямоугольные блочные операции в редакторе кода X++
Цитата:
Сообщение от kashperuk Посмотреть сообщение
Ну, с TreeNode ты конечно зря так, ну да ладно.
Да вот именно!
Спасибо за твою ссылку.

Очередное прозрение! По ходу обнаружил блочные операции и в редакторе кода X++ в пункте меню "Правка" (как полезно иногда более пристально приглядеться к тому, чем пользуешься третий год!).

Однако способы использования этих команд либо тривиальны, либо неочевидны. Так абсолютно не допёр смысл команды "Выделить область" (ALT+A). Что она делает-то и как увидеть ее эффект? Команды "Выделить строку" (ALT+L) и "Оменить выделение" (ALT+U) вполне можно и мышкой более традиционно выполнить.

А вот команда "Выделить колонку" (ALT+O) как раз оказалась ключом к блокам. Чтобы выделить прямоугольный блок текста в редакторе кода X++ надо:
1.Щелкнуть мышкой в левом верхнем углу будущего блока (левее первого символа).
2.Удерживая Shift, щелкнуть мышкой в правом нижнем углу будущего блока (правее последнего символа).
3.Нажать ALT+O (т.е. выполнить команду "Выделить колонку").

Далее с выделенным прямоугольником можно выполнять стандартные операции вырезки, копирования, удаления. Для вставки в новое место нужно соответственно позиционировать курсор и выполнить стандартную команду Вставка. Блок будет вставлен прямоугольником правее и ниже точки вставки, раздвигая (а не забивая) символы тех строк, которые покрывает прямоугольный блок. НО! Если вы захотите вставить прямоугольный блок между существующими строчками, то перед вставкой необходимо будет сначала создать клавишей Enter достаточное кол-во пустых строк.

P.S. Имеется продолжение темы, начиная с сообщения 182133.
Старый 27.06.2008, 16:03   #20  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,039 / 2170 (81) +++++++++
Регистрация: 16.01.2004
Адрес: Москва
Мой воариант:
1. Испотьзуюя табакс копируем имена полей в буыер обмена
2. Испоььзуя поиск и замену с регекспами меняем ^(.*)$ на table.$1 = control$2,value() или как-то так
Теги
excel, rls, полезное, blog, axapta

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
dax-lessons: Generate XML Documentation Files for a project - DAX 2009 Blog bot DAX Blogs 0 08.08.2008 19:06
dax-lessons: Active directory in Axapta Blog bot DAX Blogs 0 27.08.2007 23:00
Kashperuk Ivan: AxPaint - make your DAX look cool :) Blog bot DAX Blogs 0 26.06.2007 21:00
Kashperuk Ivan: (DAX 3.0) SysExportDialog form extension Blog bot DAX Blogs 1 15.05.2007 19:16
Kashperuk Ivan: Two very useful projects for DAX Blog bot DAX Blogs 0 20.04.2007 01:14
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 22:33.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.