29.02.2008, 18:16 | #1 |
Moderator
|
Gustav: Unsorted, или Записки DAX-дилетанта - II
И снова здравствуйте!
Позвольте начать процесс экспериментального бложения. "Ноги" растут отсюда: Эксперимент: создан раздел Blog'и |
|
|
За это сообщение автора поблагодарили: belugin (7), Kabardian (4). |
29.02.2008, 18:17 | #2 |
Moderator
|
СОДЕРЖАНИЕ ЭТОГО "БЛОГА"
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 |
Moderator
|
Иногда бывает нужно найти собственное сообщение, про которое помнишь, что писал, но когда именно, а также название темы - вспомнить трудно. Если за сообщение поблагодарили (хотя как об этом помнить?), то появляется шанс найти его среди "Полученных отзывов" (т.е. перерывая ограниченное количество информации), в противном случае рост утомительности поиска прямо пропорционален росту количества опубликованных мною сообщений (в самом удручающем случае это будет визуальный перебор всех сообщений).
Принимая все это во внимание, я решил "завязывать" в этом сообщении узелки на память (с краткими комментариями), чтобы, если и придется искать что-то утомительно, то, по крайней мере, без повторных поисков в дальнейшем. ССЫЛКИ НА МОИ СООБЩЕНИЯ ВНЕ ЭТОГО "БЛОГА" (или на темы с моими сообщениями) - интересные мне и может быть кому-нибудь еще * 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 |
Moderator
|
Трамплин в код из инфолога (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 |
Участник
|
Наверное, лучше посты сделать отдельными темами, а не все в одну кучу....
|
|
|
За это сообщение автора поблагодарили: MikeR (5). |
29.02.2008, 18:43 | #6 |
Moderator
|
|
|
29.02.2008, 19:14 | #7 |
Участник
|
Цитата:
Сообщение от 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 |
Участник
|
Оно примерно то же значит.
http://ru.wikipedia.org/wiki/Рефлексия Афористическое определение рефлексии звучит так: «Рефлексия есть мысль, направленная на мысль» (или «направленная на саму себя»). И это определение не совсем точно, поскольку суть рефлексии не в том, что она есть мысль, а в самой обращенности на себя. Более верным, является следующее определение: Рефлексия есть обращенность сознания на себя. В смысле этого определения, мысль, речь, воображение и др. способы сознательной деятельности могут быть рефлективными, если c помощью них обращаются на самих себя. БСЭ: «Содержание рефлексии определено предметно-чувственной деятельностью: рефлексия в конечном счёте есть осознание практики, предметного мира культуры. В этом смысле рефлексия есть метод философии, а диалектика — рефле |
|
29.02.2008, 19:35 | #9 |
Участник
|
|
|
11.03.2008, 19:38 | #10 |
Moderator
|
Преодоление принципиальных 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 срабатывает корректно. Т.е. если есть две группы клиентов Х и У, я могу видеть только группу Х, то создать запись в таблице клиентов и вручную ввести группу У система не позволяет. Раньше с этим были проблемы. |
|
|
За это сообщение автора поблагодарили: GLU (1), Logger (3), gl00mie (5). |
13.03.2008, 17:41 | #11 |
Moderator
|
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; } 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) ) ИСТОЧНИКИ (ВДОХНОВЕНИЯ): Еще по поводу QueryBuildRange() Коды аналитики |
|
24.03.2008, 18:49 | #12 |
Moderator
|
Аналог excel'ной функции TRIM
В Excel есть замечательная функция рабочего листа TRIM (в русской версии - СЖПРОБЕЛЫ). Она не только удаляет ведущие и концевые пробелы, как это делают функции strLTrim и strRTrim в X++ (или LTrim и RTrim в VBA, Oracle и т.д.), но и оставляет между словами только по одному пробелу, например:
Код: TRIM(" Доход за первый квартал ") равняется "Доход за первый квартал". 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; } Кстати, имеющаяся в VBA и Oracle функция Trim действует не более, чем как метод класса Global strLRTrim (т.е. просто выполняет оба действия - "левое" и "правое" - одновременно). Пробелы же между словами, которых может быть более одного, она не трогает. Коллеги, возможно, кто-то видит не столь очевидную, но более эффективную, комбинацию иных текстовых функций для достижения такого же результата - пожалуйста, делитесь соображениями, с удовольствием послушаю. |
|
24.03.2008, 19:01 | #13 |
Участник
|
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 |
Moderator
|
Макс, большое спасибо за наводку! Уже нашёл очень полезную ветку: Функция, которая убирает перевод каретки в строке. и пошёл читать справку к функции match про регулярные выражения.
"Хорошо! "Стамбул - город контрастов". А объявление перепишем:" (с) X++: static str trimLikeExcel(str _sourceString) { TextBuffer buf = new TextBuffer(); ; buf.setText(_sourceString); buf.replace(' +', ' '); return strLRTrim(buf.getText()); } |
|
24.03.2008, 22:24 | #16 |
Участник
|
|
|
27.06.2008, 13:08 | #17 |
Moderator
|
Подручные средства для облегчения создания рутинных фрагментов кода
Во загнул, скажете, но на самом деле все очень просто. То тут, то там приходится выписывать последовательности операторов присваивания для перевалки данных из одного места в другое, например, пересылать значения из несвязанных контролов формы в поля таблицы. Для оформления подобных операций желательно иметь выстроенный список полей с одной и с другой стороны, которые в коде необходимо "совместить" друг с другом посредством знака равенства.
Такое совмещение можно приготовить в любом редакторе текста, позволяющем блочные вставки, например, в 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(); } } Второй джоб - получение списка контролов формы: 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 ); } |
|
27.06.2008, 13:23 | #18 |
Участник
|
Ну, с TreeNode ты конечно зря так, ну да ладно.
Вот еще посмотреть можно схожую функциональность: http://kashperuk.blogspot.com/2007/0...d-another.html |
|
27.06.2008, 15:20 | #19 |
Moderator
|
Прямоугольные блочные операции в редакторе кода X++
Да вот именно!
Спасибо за твою ссылку. Очередное прозрение! По ходу обнаружил блочные операции и в редакторе кода 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 |
Участник
|
Мой воариант:
1. Испотьзуюя табакс копируем имена полей в буыер обмена 2. Испоььзуя поиск и замену с регекспами меняем ^(.*)$ на table.$1 = control$2,value() или как-то так |
|
Теги |
excel, rls, полезное, blog, axapta |
|
|