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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 29.01.2010, 10:16   #1  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
? Что попадает в буфер обмена при стандартном копировании строк grid'а?
Всем привет!

Если не все, то очень многие, наверное, замечали, что при копировании из grid'а и последующей вставке в Excel на рабочем листе обнаруживаются колонки, отсутствующие в гриде.

Отсюда вопрос: по каким принципам формируется список и порядок этих выводимых колонок? Чисто по ощущениям мне показалось следующее: вначале идут все видимые в гриде колонки с учетом пользовательских настроек, а затем оставшиеся поля датасорса грида, причем в порядке, отличном от порядка следования полей в базовой таблице. Интересно, каком? Насколько мне известно, копирование грида - это системная функция и код ее для изучения, к сожалению, недоступен.

Кто что знает об этом? Заранее спасибо всем откликнувшимся.

Надо мне это для решения следующей задачки. Есть грид, который пользователи благополучно стандартно копируют в Excel и там развлекаются (наверное, тоже стандартно ). Но к форме недавно добавился еще один датасорс, данные которого нужно отобразить в стиле перекрестной таблицы Excel. Столбцы этой "перекрестной таблицы" теоретически можно добавить в грид, создав соответствующие дисплей-методы, но в этом случае форма тихо умирает еще при открытии. Поэтому я сделал отдельную выгрузку "перекрестной таблицы" по кнопке и рекомендовал пользователям "приставлять" ее уже в Excel к данным грида. Им показалось это слишком сложным - отсортировать два диапазона и расположить рядом на рабочем листе - и они желают, чтобы по кнопке вылезало всё сразу. Все видимые колонки грида я могу выгрузить, потому что могу их получить программно. Вопрос - как быть с невидимыми?
Старый 29.01.2010, 10:23   #2  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
По-моему, попадает содержимое полей, привязанных к контролам на форме, которые могут быть видны пользователю

PS Порядок - как расположены контролы на форме.
__________________
Axapta v.3.0 sp5 kr2

Последний раз редактировалось AndyD; 29.01.2010 в 10:28.
За это сообщение автора поблагодарили: Gustav (1).
Старый 29.01.2010, 11:06   #3  
DSPIC is offline
DSPIC
Боец
 
1,077 / 1243 (44) ++++++++
Регистрация: 11.04.2008
Так напишите свой обработчик экспорта в эксель, вместо стандартного. Нужно только формат сохранения в буффер обмена выяснить, и заталкивать в него что угодно.
Вот, например, можно посмотреть, что сохраняется при стандартном Ctrl+C на гриде:
X++:
static void ClipboardGridTest(Args _args)
{
    TextBuffer  tb;
    ;

    tb = new TextBuffer();

    tb.fromClipboard();

    tb.toFile(@"C:\ClipboardGridTest");
}
За это сообщение автора поблагодарили: Gustav (1), alex55 (1).
Старый 29.01.2010, 13:55   #4  
glibs is offline
glibs
Member
Сотрудники компании It Box
Most Valuable Professional
Лучший по профессии 2011
Лучший по профессии 2009
 
4,942 / 911 (40) +++++++
Регистрация: 10.06.2002
Адрес: I am from Kyiv, Ukraine. Now I am in Moscow. For private contacts: glibs@hotmail.com
По-моему, контролы (поля, а с 3.0 сп3 и display-методы) грида + контролы со всех остальных закладок.
__________________
С уважением,
glibs®
За это сообщение автора поблагодарили: Gustav (1).
Старый 29.01.2010, 20:47   #5  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Немного сумбурно, но всё же завершу трудовую неделю на мажорной ноте. Потом неспешно покомментирую.

В общем, прислушавшись к коллегам, родил получение состава и порядка колонок - вроде, правильно. Ковырялся с достаточно сложной формой, поэтому наступил, как мне кажется, уже на все возможные грабли.

Но дальнейшие исследования всячески приветствуются, поэтому желающие могут поучаствовать в небольшом эксперименте.

Для участия надо:
  1. открыть любую форму с гридом и желательно большим количеством закладок
  2. выделить несколько строк грида, скопировать и вставить в Excel
  3. не закрывая форму с гридом, открыть окно с кодом джоба, подправив gridName
  4. "макнуть" мышку в форму, вернуться в джоб и нажать F5 (см.комментарии в джобе)
  5. получившийся список меток скопировать из инфолога в Excel на отдельный лист
  6. "развернуть" вертикальный список горизонтально при помощи команды Специальная вставка \ Транспонировать
  7. сравнить названия колонок из грида и из моего списка, расположив обе строки на одном листе Excel
  8. сообщить в ветку об успехе или неудаче
Вот мой джоб:
X++:
static void Job2192_exportGridColumnOrder(Args _args)
{
    // перед запуском ткнуть мышкой в желаемую форму,
    // затем ткнуть в текст этого джоба и нажать F5
    // (для наглядности лучше сначала закрыть (или свернуть) все ненужные окна,
    // а оставшиеся открытые расположить мозаикой)

    str     gridName = 'RequestList';  // ПОДПРАВЬ ДЛЯ СВОЕЙ ФОРМЫ ИМЯ ИССЛЕДУЕМОГО ГРИДА!
    FormRun formRun;

    FormGridControl grid;
    FormDataSource  gridDataSource;

    int j, k, m;
    Map colNames  = new Map(Types::String, Types::Integer);
    Map colLabels = new Map(Types::Integer, Types::String);

    boolean hasClassMethod(Object _obj, str _methodName)
    {   // функция заимствована у Russland'а
        ClassId         classId      = classIdGet(_obj);
        SysDictClass    sysDictClass = new sysDictClass(classId);
        ;
        return sysDictClass.hasObjectMethod(_methodName);
    }

    void nextControl(Object _obj)
    {
        Object      control;
        int         i;
        DictField   dictField;
        DictType    dictType;
        DictMethod  dictMethod;

        str         columnLabel;
        str         columnName;
        ;

        for(i=1; i<=_obj.controlCount(); i++)
        {
            control = _obj.controlNum(i);

            if (hasClassMethod(control, 'dataSource') &&
                hasClassMethod(control, 'dataField' ) &&
                hasClassMethod(control, 'dataMethod'))
            {
                if (!control.isContainer()  &&
                     control.isVisible()    &&
                     control.dataSource() == gridDataSource.id())
                {
                    if (!control.dataMethod())
                    {
                        dictField = new DictField(gridDataSource.table(), control.dataField());
                        dictType  = new DictType (dictField.typeId());

                        columnLabel = 
                            control.label() ? control.label()
                                            : dictField.label() ? dictField.label()
                                                                : dictType.label();
                        columnName  = dictField.name();
                    }
                    else
                    {
                        // обращение с dictMethod заимствовано у EVGL
                        dictMethod = new DictMethod(UtilElementType::TableInstanceMethod, gridDataSource.table(), control.dataMethod());
                        dictType   = new DictType(dictMethod.returnId());

                        columnLabel =
                            control.label() ? control.label()
                                            : (dictMethod.returnType()==Types::UserType) ? dictType.label() 
                                                                                         : dictMethod.name();
                        m++;
                        columnName = strFmt('%1(%2)', control.dataMethod(), m);
                    }

                    if (! colNames.exists(columnName))
                    {
                        k++;
                        colNames.insert(columnName, k);
                        colLabels.insert(k, columnLabel);
                    }
                }
            }

            if(control.isContainer())
            {
                nextControl(control);
            }
        }
    }
    ;

    formRun = infolog.parmLastActivatedForm().object();

    grid = formRun.design().controlName(gridName);

    // ищем датасорс грида
    for (j=1; j<=formRun.dataSourceCount(); j++)
    {
        if (formRun.dataSource(j).id() == grid.dataSource())
        {
            gridDataSource = formRun.dataSource(j);
            break;
        }
    }

    k = 0; // счетчик уникальных имен
    m = 0; // счетчик дисплей-методов
    nextControl(formRun.design());  

    for (k=1;k<=colNames.elements();k++)
    {
        info(strFmt('%1 -- %2', k, colLabels.lookup(k)));
    }
}
P.S. Теперь несколько тезисов по теме русским бытовым языком:
  1. После копировании строк грида и последующей вставки в Excel выводятся столбцы, соответствующие всем видимым (visible=Yes) управляющим элементам ("контролам") формы, у которых в свойстве dataSource указан датасоурс копируемого грида.
    .
  2. Порядок следования колонок в Excel определяется порядком рекурсивного перебора контролов работающей (перебор по AOT не годится!) формы (см. джоб) по всем вкладкам, начиная с первой (обычно это вкладка "Обзор", на которой расположен сам грид). То, что первыми идут колонки самого грида - не более, чем следствие того, что грид расположен именно на первой вкладке. Перетащите вкладку "Обзор" в конец набора вкладок - и колонки ее грида станут последними на листе Excel.
    .
  3. Копируются данные контролов, соответствующих как полям датасорса, так и дисплей-методам базовой таблицы (у меня Axapta 3.0 sp4, со слов glibs'а вывод дисплей-методов появился с версии 3.0 sp3).
    .
  4. Если одно и то же поле выводится на форму несколько раз, то в Excel попадает только самый первый по порядку перебора контрол с этим полем. Оставшиеся контролы с этим полем не выводятся, даже если имеют различные метки (становящиеся в Excel названиями колонок).
    .
  5. В отличие от полей, контролы, ссылающиеся на один и тот же дисплей-метод, выводятся в Excel все (а не только самый первый). Не знаю, фича это или бага, но это так.
    .
  6. Видимость (visible) проверяется непосредственно по самому контролу. Если контрол входит в группу и имеет visible=Yes, а у группы стоит visible=No, то контрол не виден на форме, НО (!) появляется в Excel!
    .
  7. Пока не проверял контролы с разными ключами безопасности. Надеюсь, там всё хорошо.

Последний раз редактировалось Gustav; 29.01.2010 в 23:33.
За это сообщение автора поблагодарили: mazzy (2), EVGL (2), lev (2), Player1 (1).
Старый 01.02.2010, 06:40   #6  
ViV is offline
ViV
Axapta Retail User
Самостоятельные клиенты AX
Axapta Retail User
 
200 / 79 (3) ++++
Регистрация: 14.09.2005
Axapta 3.0 sp3. Все успешно.
За это сообщение автора поблагодарили: Gustav (1).
Старый 03.03.2013, 11:06   #7  
Player1 is offline
Player1
Участник
Самостоятельные клиенты AX
 
306 / 137 (5) +++++
Регистрация: 21.04.2008
видимость лучше проверять двумя условиями
X++:
if (control.isVisible() ||
            control.userHide())
Теги
grid, буфер обмена, полезное, clipboard

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
фильтр на копировании в буфер обмена Nikolaich DAX: Программирование 15 26.02.2009 21:10
Тормозит копирование строк в буфер обмена ivas DAX: Программирование 20 21.08.2007 15:05
Кол-во выделенных строк в Grid Bigzone DAX: Программирование 3 19.10.2006 12:47
Не копирует из display-метода в буфер обмена akvi DAX: Программирование 6 08.12.2005 13:14
Крякозяблики при копировании через буфер обмена kalex DAX: Администрирование 1 13.10.2004 12:36

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

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

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