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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 24.03.2008, 19:43   #1  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Макс, большое спасибо за наводку! Уже нашёл очень полезную ветку: Функция, которая убирает перевод каретки в строке. и пошёл читать справку к функции 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   #2  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от Gustav Посмотреть сообщение
P.S. Не надо ли добавить еще строку textBuffer.regularExpressions(true); , как это сделано в упомянутой полезной ветке в примере у Максима Горбунова?
Оно по умолчанию тру
Старый 27.06.2008, 13:08   #3  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Подручные средства для облегчения создания рутинных фрагментов кода
Во загнул, скажете, но на самом деле все очень просто. То тут, то там приходится выписывать последовательности операторов присваивания для перевалки данных из одного места в другое, например, пересылать значения из несвязанных контролов формы в поля таблицы. Для оформления подобных операций желательно иметь выстроенный список полей с одной и с другой стороны, которые в коде необходимо "совместить" друг с другом посредством знака равенства.

Такое совмещение можно приготовить в любом редакторе текста, позволяющем блочные вставки, например, в 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();'.
Старый 09.09.2008, 11:40   #4  
AlGol is offline
AlGol
Участник
 
277 / 93 (4) ++++
Регистрация: 24.12.2001
Адрес: Тверь.
Цитата:
Сообщение от Gustav Посмотреть сообщение
получение списка полей таблицы
В версии 4.0 получение списка полей таблицы есть в стандартной функциональности.
- В форме с нужной записью, заходим в паспорт записи (правый клик/ паспорт записи).
- нажимаем кнопку Сценарий.

Остается только вставить текст в нужное место.

2Gustav
При вставке получаем следующий код:
X++:
    CustTable.AccountNum = "000001_039";
    CustTable.Name = "ООО """;
    CustTable.Address = "180000, Светлово, ул. Пермяковская, д.21";
    CustTable.Phone = "45254565";
    CustTable.TeleFax = "";
    CustTable.InvoiceAccount = "";
...
    CustTable.MultiDiscPct = 0.00;
    CustTable.EndDiscPct = 0.00;
    CustTable.RContractDimension = NoYes::Yes;
    CustTable.insert();

Последний раз редактировалось AlGol; 22.09.2008 в 11:40.
За это сообщение автора поблагодарили: Lemming (1), Gustav (3).
Старый 06.10.2008, 17:01   #5  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Визуальная имитация раннего связывания COM-объектов
Известно, что с COM-объектами Аксапта работает через позднее связывание. Это означает, что при портировании в Х++, например, кода VBA из Excel, нам придется расписать отдельными операторами X++ все точки, разделяющие объекты в операторах VBA.

Допустим, у нас есть такой код VBA, созданный макрорекордером и нами слегка подправленный, который в Excel записывает значение 123 в ячейку C2 активного листа активной книги, затем делает шрифт этой ячейки жирным ("болдит") и, наконец, заливает ячейку светложелтым цветом:

Код:
 
Sub Macro1()
    Range("C2").FormulaR1C1 = "123"
    Range("C2").Font.Bold = True
    Range("C2").Interior.ColorIndex = 36 'Light Yellow  
End Sub
Чтобы воспроизвести его в Аксапте, нужно будет (помимо полного квалифицирования объекта Range от объекта Application) расписать все точки между объектами и методами. Получится примерно так:
X++:
{
    COM application;
    COM workbook = SysExcelApplication::construct().workbooks().add().comObject();
    COM range;
    COM font;
    COM interior;
    ;

    application = workbook.Parent();
    application.Visible(true);

    range = application.Range('C2');

    range.FormulaR1C1(123);

    font = range.Font();
    font.Bold(true);

    interior = range.Interior();
    interior.ColorIndex(36);
}
Нам приходится выделять специальные переменные для промежуточных объектов - font и interior. Хотя наша цель лишь заболдить и закрасить ячейку, и больше эти объекты нам не понадобятся.

Вместо нескольких таких переменных, истинный объектный смысл каждой из которых нас в данном случае мало интересует, можно использовать одну фиктивную. Обычно я называю ее comTemp - для акцентирования ее "временности" и "промежуточности". С такой "болван"-переменной можно написать операции следующим образом:
X++:
    COM comTemp;
    ..........

    comTemp = range.Font();
    comTemp . Bold(true);

    comTemp = range.Interior();
    comTemp . ColorIndex(36);
Часто в случае только двух точек можно исхитриться записать их в одной строке вообще без промежуточной переменной:
X++:
    COM::createFromObject( range.Font()).Bold( true );
    COM::createFromObject( range.Interior()).ColorIndex(36);
Если не обращать внимания на устрашающие начала операторов с вызова статического метода COM::createFromObject, то получается почти как на VBA. Но, к сожалению, таким двоеточием всё и ограничивается. Использовать более двух точек не получится даже вложенными друг в друга вызовами COM::createFromObject или COM::createFromVariant (последний иногда бывает нужен для выделения COM-объекта из свойства Item, например, при обращении к одной ячейке листа через семейство Cells). Попытка сконструировать такое вложение вызовет ошибку компиляции.

Таким образом, для реализации следующего "многоточечного" оператора VBA:
Код:
 
Application.ActiveWorkbook.Worksheets.Item(1).Cells.Item(2,3).Font.Bold = True
в X++ нам потребуются примерно такие строчки:
X++:
    comTemp = application.ActiveWorkbook();
    comTemp = comTemp.Worksheets();
    comTemp = comTemp.Item(1);
    comTemp = comTemp.Cells();
    comTemp = COM::createFromVariant(comTemp.Item(2,3));
    comTemp = comTemp.Font();
    comTemp.Bold(true);
И чисто визуально это иногда удручает.

В целях "борьбы" с описанным явлением я наваял совсем небольшой метод, с использованием функции runbuf, который позволяет существенно сократить количество строк код и придать вызову внешнюю похожесть на оператор VBA:
X++:
{
    COM application;
    COM workbook = SysExcelApplication::construct().workbooks().add().comObject();
    COM range;
    COM comTemp;
    ;

    application = workbook.Parent();
    application.Visible(true);

    range = application.Range('C2');

    range.FormulaR1C1(123);

    comTemp = comEarlyBindingImitation( application,
    'ActiveWorkbook()','Worksheets()','Item(1)','Cells()','~Item(2,3)','Font()');
    comTemp.Bold(true);
}
Текст статического метода comEarlyBindingImitation - для помещения в Global или аналогичный по смыслу класс:
X++:
static COM comEarlyBindingImitation( COM _com0,
                                     str _com1 = '',
                                     str _com2 = '',
                                     str _com3 = '',
                                     str _com4 = '',
                                     str _com5 = '',
                                     str _com6 = '',
                                     str _com7 = '',
                                     str _com8 = '')
{
    str myjob;

    str getSourcePart(str _com = '')
    {
        if (_com)
            if (subStr(_com,1,1) != '~')
                return strFmt('c=c.%1; ', _com);
            else
                return strFmt('c=COM::createFromVariant(c.%1); ', 
                       subStr(_com,2,strLen(_com)-1));
        else
            return '';
    }
;
    myjob = 'COM comEaBIm(COM _com0) {COM c;; c = _com0; ';
    myjob += getSourcePart(_com1);
    myjob += getSourcePart(_com2);
    myjob += getSourcePart(_com3);
    myjob += getSourcePart(_com4);
    myjob += getSourcePart(_com5);
    myjob += getSourcePart(_com6);
    myjob += getSourcePart(_com7);
    myjob += getSourcePart(_com8);
    myjob += 'return c; }';

    return runbuf(myjob, _com0);
}
Не обошлось без минимального "встроенного языка" метода Тильда в строке ~Item(2,3) означает, что к Item(2,3) надо применить COM::createFromVariant. Знаю об этом из личного опыта по работе с объектами Range('...').Item(i, j) и Cells().Item(i, j).

Интересно, что терминальные свойства (типа Bold или ColorIndex) можно тоже включить в это "раннее связывание" и тогда вообще обойтись одним оператором для одной операции. Следующие два оператора работают как надо:
X++:
    comEarlyBindingImitation(application,
        'Range("C2")','Font()','Bold(true)');

    comEarlyBindingImitation(application,
        'Range("C2")','Interior()','ColorIndex(36)');
За это сообщение автора поблагодарили: kashperuk (3), aidsua (1).
Теги
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, время: 02:33.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.