|
29.01.2010, 10:16 | #1 |
Moderator
|
Что попадает в буфер обмена при стандартном копировании строк grid'а?
Всем привет!
Если не все, то очень многие, наверное, замечали, что при копировании из grid'а и последующей вставке в Excel на рабочем листе обнаруживаются колонки, отсутствующие в гриде. Отсюда вопрос: по каким принципам формируется список и порядок этих выводимых колонок? Чисто по ощущениям мне показалось следующее: вначале идут все видимые в гриде колонки с учетом пользовательских настроек, а затем оставшиеся поля датасорса грида, причем в порядке, отличном от порядка следования полей в базовой таблице. Интересно, каком? Насколько мне известно, копирование грида - это системная функция и код ее для изучения, к сожалению, недоступен. Кто что знает об этом? Заранее спасибо всем откликнувшимся. Надо мне это для решения следующей задачки. Есть грид, который пользователи благополучно стандартно копируют в Excel и там развлекаются (наверное, тоже стандартно ). Но к форме недавно добавился еще один датасорс, данные которого нужно отобразить в стиле перекрестной таблицы Excel. Столбцы этой "перекрестной таблицы" теоретически можно добавить в грид, создав соответствующие дисплей-методы, но в этом случае форма тихо умирает еще при открытии. Поэтому я сделал отдельную выгрузку "перекрестной таблицы" по кнопке и рекомендовал пользователям "приставлять" ее уже в Excel к данным грида. Им показалось это слишком сложным - отсортировать два диапазона и расположить рядом на рабочем листе - и они желают, чтобы по кнопке вылезало всё сразу. Все видимые колонки грида я могу выгрузить, потому что могу их получить программно. Вопрос - как быть с невидимыми? |
|
29.01.2010, 10:23 | #2 |
Участник
|
По-моему, попадает содержимое полей, привязанных к контролам на форме, которые могут быть видны пользователю
PS Порядок - как расположены контролы на форме.
__________________
Axapta v.3.0 sp5 kr2 Последний раз редактировалось AndyD; 29.01.2010 в 10:28. |
|
|
За это сообщение автора поблагодарили: Gustav (1). |
29.01.2010, 11:06 | #3 |
Боец
|
Так напишите свой обработчик экспорта в эксель, вместо стандартного. Нужно только формат сохранения в буффер обмена выяснить, и заталкивать в него что угодно.
Вот, например, можно посмотреть, что сохраняется при стандартном 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 |
Member
|
По-моему, контролы (поля, а с 3.0 сп3 и display-методы) грида + контролы со всех остальных закладок.
__________________
С уважением, glibs® |
|
|
За это сообщение автора поблагодарили: Gustav (1). |
29.01.2010, 20:47 | #5 |
Moderator
|
Немного сумбурно, но всё же завершу трудовую неделю на мажорной ноте. Потом неспешно покомментирую.
В общем, прислушавшись к коллегам, родил получение состава и порядка колонок - вроде, правильно. Ковырялся с достаточно сложной формой, поэтому наступил, как мне кажется, уже на все возможные грабли. Но дальнейшие исследования всячески приветствуются, поэтому желающие могут поучаствовать в небольшом эксперименте. Для участия надо:
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))); } }
Последний раз редактировалось Gustav; 29.01.2010 в 23:33. |
|
|
За это сообщение автора поблагодарили: mazzy (2), EVGL (2), lev (2), Player1 (1). |
01.02.2010, 06:40 | #6 |
Axapta Retail User
|
Axapta 3.0 sp3. Все успешно.
|
|
|
За это сообщение автора поблагодарили: Gustav (1). |
03.03.2013, 11:06 | #7 |
Участник
|
видимость лучше проверять двумя условиями
X++: if (control.isVisible() ||
control.userHide()) |
|